Files
MikuSB/GameServer/Server/CallGS/Handlers/SupporterCard/SupporterCard_Upgrade.cs
2026-04-28 16:12:02 +09:00

120 lines
3.9 KiB
C#

using MikuSB.Data;
using MikuSB.Database;
using MikuSB.Proto;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MikuSB.GameServer.Server.CallGS.Handlers.SupporterCard;
[CallGSApi("SupporterCard_Upgrade")]
public class SupporterCard_Upgrade : ICallGSHandler
{
public async Task Handle(Connection connection, string param, ushort seqNo)
{
var player = connection.Player!;
var req = JsonSerializer.Deserialize<SupporterCardUpgradeParam>(param);
if (req == null || req.SupportCardUid == 0 || req.Materials == null || req.Materials.Count == 0)
{
await CallGSRouter.SendScript(connection, "Logistics_Upgrade", "{}");
return;
}
var supportCard = player.InventoryManager.InventoryData.Items.GetValueOrDefault((uint)req.SupportCardUid);
if (supportCard == null)
{
await CallGSRouter.SendScript(connection, "Logistics_Upgrade", "{}");
return;
}
var supportCardExcel = GameData.SupportCardData.FirstOrDefault(x => x.TemplateId == supportCard.TemplateId);
var maxLevel = supportCardExcel?.MaxLevel ?? 10;
// Validate all materials exist with sufficient count
foreach (var mat in req.Materials)
{
var item = player.InventoryManager.InventoryData.Items.GetValueOrDefault((uint)mat.Id);
if (item == null || item.ItemCount < mat.Num)
{
await CallGSRouter.SendScript(connection, "Logistics_Upgrade", "{}");
return;
}
}
// Consume materials and accumulate exp
var syncItems = new List<Item>();
uint gainedExp = 0;
foreach (var mat in req.Materials)
{
var item = player.InventoryManager.InventoryData.Items[(uint)mat.Id];
// Look up ProvideExp: check SupportCardData first, then SuppliesData
uint provideExp = 0;
var scExcel = GameData.SupportCardData.FirstOrDefault(x => x.TemplateId == item.TemplateId);
if (scExcel != null)
provideExp = scExcel.ProvideExp;
else if (GameData.SuppliesData.TryGetValue((uint)item.TemplateId, out var supExcel))
provideExp = supExcel.ProvideExp;
gainedExp += provideExp * (uint)mat.Num;
item.ItemCount -= (uint)mat.Num;
var proto = item.ToProto();
if (item.ItemCount == 0)
{
player.InventoryManager.InventoryData.Items.Remove(item.UniqueId);
proto.Count = 0;
}
syncItems.Add(proto);
}
// Apply exp and level up
supportCard.Exp += gainedExp;
while (supportCard.Level < maxLevel)
{
var expNeeded = GetExpNeeded(supportCard.Level + 1);
if (expNeeded == 0 || supportCard.Exp < expNeeded) break;
supportCard.Exp -= expNeeded;
supportCard.Level++;
}
if (supportCard.Level >= maxLevel)
{
supportCard.Exp = 0;
supportCard.Level = maxLevel;
}
syncItems.Add(supportCard.ToProto());
DatabaseHelper.SaveDatabaseType(player.InventoryManager.InventoryData);
var sync = new NtfSyncPlayer();
sync.Items.AddRange(syncItems);
await CallGSRouter.SendScript(connection, "Logistics_Upgrade", "{}", sync);
}
private static uint GetExpNeeded(uint level)
{
if (GameData.UpgradeExpData.TryGetValue((int)level, out var row))
return row.SusNeedExp;
return 0;
}
}
internal sealed class SupporterCardUpgradeParam
{
[JsonPropertyName("Id")]
public int SupportCardUid { get; set; }
[JsonPropertyName("tbMaterials")]
public List<UpgradeMaterial> Materials { get; set; } = [];
}
internal sealed class UpgradeMaterial
{
[JsonPropertyName("Id")]
public int Id { get; set; }
[JsonPropertyName("Num")]
public uint Num { get; set; }
}