diff --git a/Common/Database/Character/CharacterData.cs b/Common/Database/Character/CharacterData.cs index aeadf46..3cbb890 100644 --- a/Common/Database/Character/CharacterData.cs +++ b/Common/Database/Character/CharacterData.cs @@ -28,6 +28,8 @@ public class CharacterInfo [SugarColumn(IsJson = true)] public List UnlockedSkin { get; set; } = []; [SugarColumn(IsJson = true)] public List Spines { get; set; } = []; [SugarColumn(IsJson = true)] public List Affixs { get; set; } = []; + // Key = EqSlot (= support card Detail), Value = support card UniqueId + [SugarColumn(IsJson = true)] public Dictionary SupportSlots { get; set; } = []; public long Timestamp { get; set; } public uint Count { get; set; } = 1; @@ -55,6 +57,8 @@ public class CharacterInfo proto.Slots[4] = WeaponUniqueId; proto.Slots[5] = SkinId; + foreach (var (slot, uid) in SupportSlots) + proto.Slots[slot] = uid; return proto; } diff --git a/GameServer/Server/CallGS/Handlers/Girl/SupporterCard_Equip.cs b/GameServer/Server/CallGS/Handlers/Girl/SupporterCard_Equip.cs new file mode 100644 index 0000000..b608e4e --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Girl/SupporterCard_Equip.cs @@ -0,0 +1,70 @@ +using MikuSB.Database; +using MikuSB.Proto; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MikuSB.GameServer.Server.CallGS.Handlers.Girl; + +[CallGSApi("SupporterCard_Equip")] +public class SupporterCard_Equip : ICallGSHandler +{ + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var player = connection.Player!; + var req = JsonSerializer.Deserialize(param); + if (req == null || req.CardId == 0 || req.SupportCardUid == 0) + { + await CallGSRouter.SendScript(connection, "Logistics_Equip", "{}"); + return; + } + + var card = player.CharacterManager.GetCharacterByGUID((uint)req.CardId); + if (card == null) + { + await CallGSRouter.SendScript(connection, "Logistics_Equip", "{}"); + return; + } + + var slot = (uint)req.EqSlot; + + // If an existing card is equipped in this slot and bForce is false, ask for confirmation + if (!req.Force && req.CurrentEquippedUid != 0 && card.SupportSlots.TryGetValue(slot, out var existing) && existing != 0) + { + await CallGSRouter.SendScript(connection, "Logistics_Confirm", "{}"); + return; + } + + // Perform equip + card.SupportSlots[slot] = (uint)req.SupportCardUid; + + DatabaseHelper.SaveDatabaseType(player.CharacterManager.CharacterData); + + var sync = new NtfSyncPlayer(); + sync.Items.Add(card.ToProto()); + + // Req_EquipChange (no Model) → Logistics_Change; Req_Equip (has Model) → Logistics_Equip + var responseApi = string.IsNullOrEmpty(req.Model) ? "Logistics_Change" : "Logistics_Equip"; + await CallGSRouter.SendScript(connection, responseApi, "{}", sync); + } +} + +internal sealed class SupporterCardEquipParam +{ + [JsonPropertyName("EqId")] + public int CardId { get; set; } + + [JsonPropertyName("beEqId")] + public int SupportCardUid { get; set; } + + [JsonPropertyName("EqSlot")] + public int EqSlot { get; set; } + + [JsonPropertyName("BEqId")] + public int CurrentEquippedUid { get; set; } + + [JsonPropertyName("bForce")] + public bool Force { get; set; } + + [JsonPropertyName("Model")] + public string? Model { get; set; } +}