-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLevelUp.cs
More file actions
207 lines (177 loc) · 6.93 KB
/
Copy pathLevelUp.cs
File metadata and controls
207 lines (177 loc) · 6.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
using LabApi.Features;
using LabApi.Loader.Features.Plugins;
using LabApi.Features.Console;
using LevelUp.ConfigFiles;
using LevelUp.PlayerData;
using MEC;
using System;
using System.Collections.Generic;
using LabApi.Features.Wrappers;
using LabApi.Loader;
namespace LevelUp;
public class LevelUp : Plugin
{
public override string Author => "Crystal";
public override Version Version { get; } = new Version(1, 0, 0);
public override string Name => "LevelUp";
public override string Description => "一个简单好用的等级插件";
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion); // 插件依赖的 API 版本
public static LevelUp Instance { get; private set; } = null;
public EventHandlers Events { get; } = new();
public LvConfig Config;
public LvTranslations Translation;
public LevelData SavedData;
bool _hasIncorrectConfig = false;
bool _hasIncorrectTranslation = false;
bool _hasIncorrectData = false;
public Dictionary<string, DataTemplates> PlayerDataCache { get; private set; } = new ();
public override void Enable()
{
// 0. 设置实例
Instance = this;
// 2. 加载玩家数据
PlayerDataCache = SavedData.Data;
// 3. 注册所有事件
Events.RegisterAllEvents();
if(_hasIncorrectConfig || _hasIncorrectTranslation || _hasIncorrectData)
{
if (_hasIncorrectConfig)
{
Config = new LvConfig();
}
else if (_hasIncorrectTranslation)
{
Translation = new LvTranslations();
}
else
{
SavedData = new LevelData();
}
Logger.Error("配置文件加载失败。");
}
}
public override void Disable()
{
// 1. 保存玩家数据
SavePlayerData();
PlayerDataCache.Clear();
// 2. 注销所有事件
Events.UnregiserAllEvents();
// 3. 清理实例
Instance = null;
Hints.RemoveAllHints();
}
public override void LoadConfigs()
{
try
{
_hasIncorrectConfig = !this.TryLoadConfig("config.yml", out Config);
_hasIncorrectTranslation = !this.TryLoadConfig("translations.yml", out Translation);
_hasIncorrectData = !this.TryLoadConfig("data.yml", out SavedData);
Logger.Info("配置文件加载完成。");
}
catch (System.Exception ex)
{
Logger.Error($"加载配置文件时发生异常: {ex.Message}");
Logger.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
/// <summary>
/// 保存玩家数据到配置文件
/// </summary>
public void SavePlayerData()
{
try
{
SavedData.Data = PlayerDataCache;
bool ok = this.TrySaveConfig(SavedData, "data.yml");
if (!ok)
{
Logger.Error("保存玩家数据失败!");
}
}
catch (System.Exception ex)
{
Logger.Error($"[Phase 6] 保存玩家数据时发生异常: {ex.Message}");
if (Config.Debug)
Logger.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
/// <summary>
/// Phase 5.2: 计算升级所需经验
/// </summary>
public int CalculateRequiredExp(int currentLevel)
{
switch (Config.formulaNums.CurveType)
{
case ConfigFiles.LevelCurveType.Linear:
// 线性公式: basic + (level - 1) * overflow + extra
return Config.formulaNums.basic +
(currentLevel - 1) * Config.formulaNums.overflow + Config.formulaNums.extra;
case ConfigFiles.LevelCurveType.Exponential:
// 指数公式: basic * (1 + rate)^level
return (int)(Config.formulaNums.basic * System.Math.Pow(1 + Config.formulaNums.ExponentialRate, currentLevel));
case ConfigFiles.LevelCurveType.Custom:
// 自定义公式(未来扩展)
return Config.formulaNums.basic + (currentLevel - 1) * Config.formulaNums.overflow + Config.formulaNums.extra;
default:
return Config.formulaNums.basic + (currentLevel - 1) * Config.formulaNums.overflow + Config.formulaNums.extra;
}
}
/// <summary>
/// 检查并处理玩家升级。
/// </summary>
/// <param name="player">当前玩家</param>
/// <param name="playerData">玩家数据</param>
public void CheckForLevelUp(Player player, DataTemplates playerData)
{
try
{
bool leveledUp = false;
int requiredExp = CalculateRequiredExp(playerData.Level);
// Phase 5.2: 检查等级上限
int maxLevel = Config.formulaNums.MaxLevel;
bool hasMaxLevel = maxLevel > 0;
while (playerData.Experience >= requiredExp && (!hasMaxLevel || playerData.Level < maxLevel))
{
playerData.Level++;
playerData.Experience -= requiredExp;
leveledUp = true;
if (Config.Debug)
Logger.Debug($"玩家 {player.Nickname} 升到了 {playerData.Level} 级!");
string levelUpMessage = Translation.LvlUpMessage
.Replace("{level}", playerData.Level.ToString())
.Replace("{roleColor}", player.RoleBase.RoleColor.ToHex());
player.SendHint(levelUpMessage, Config.showTime.lvlUpTip);
requiredExp = CalculateRequiredExp(playerData.Level);
}
// 如果达到等级上限,清空多余经验
if (hasMaxLevel && playerData.Level >= maxLevel && playerData.Experience >= requiredExp)
{
playerData.Experience = requiredExp - 1; // 保持在满经验但不超过
if (Config.Debug)
Logger.Debug($"玩家 {player.Nickname} 已达到等级上限 {maxLevel}");
}
// 只在升级时才更新名称前缀和HUD
if (leveledUp)
{
// 等级变化时更新名称前缀
Hints.UpdatePlayerNameWithLevelPrefix(player);
// 延迟刷新HUD,让GetLevelHints使用新的数据
Timing.CallDelayed(0.1f, () =>
{
Hints.RemoveLevelHint(player);
Hints.AddLevelHint(player);
});
}
// 即使没有升级,经验值也可能变化,GetLevelHints会智能判断是否需要更新
SavePlayerData();
}
catch (System.Exception ex)
{
Logger.Error($"[Phase 6] 检查玩家 {player?.Nickname} 升级时发生异常: {ex.Message}");
if (Config.Debug)
Logger.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
}