diff --git a/AscNet.Common/Database/Character.cs b/AscNet.Common/Database/Character.cs index 77b64be3..436380a6 100644 --- a/AscNet.Common/Database/Character.cs +++ b/AscNet.Common/Database/Character.cs @@ -77,7 +77,7 @@ namespace AscNet.Common.Database throw new ServerCodeException("Character already obtained!", 20009022); } - NotifyCharacterDataList.CharacterData characterData = new() + CharacterData characterData = new() { Id = (uint)character.Id, Level = 1, @@ -100,7 +100,7 @@ namespace AscNet.Common.Database }; // TODO: Don't do the ToString, query skill properly pls. - characterData.SkillList.AddRange(characterSkill.SkillGroupId.Take(8).Select(x => new NotifyCharacterDataList.CharacterData.CharacterSkill() + characterData.SkillList.AddRange(characterSkill.SkillGroupId.Take(8).Select(x => new CharacterSkill() { Id = uint.Parse(x.ToString().Take(6).ToArray()), Level = 1 @@ -121,7 +121,7 @@ namespace AscNet.Common.Database return ret; } - public NotifyCharacterDataList.CharacterData? AddCharacterExp(int characterId, int exp, int maxLvl = 0) + public CharacterData? AddCharacterExp(int characterId, int exp, int maxLvl = 0) { var characterData = TableReaderV2.Parse().FirstOrDefault(x => x.Id == characterId); var character = Characters.FirstOrDefault(x => x.Id == characterId); @@ -153,7 +153,7 @@ namespace AscNet.Common.Database return character; } - public UpgradeCharacterSkillResult UpgradeCharacterSkillGroup(uint skillGroupId, int count) + public UpgradeCharacterSkillResult UpgradeCharacterSkillGroup(int skillGroupId, int count) { List affectedCharacters = new(); int totalCoinCost = 0; @@ -257,7 +257,7 @@ namespace AscNet.Common.Database [BsonElement("characters")] [BsonRequired] - public List Characters { get; set; } + public List Characters { get; set; } [BsonElement("equips")] [BsonRequired] @@ -307,7 +307,7 @@ namespace AscNet.Common.Database public struct AddCharacterRet { - public NotifyCharacterDataList.CharacterData Character { get; set; } + public CharacterData Character { get; set; } public EquipData Equip { get; set; } public FashionList Fashion { get; set; } } diff --git a/AscNet.Common/MsgPack/Types.cs b/AscNet.Common/MsgPack/Types.cs index 2ac923d3..d4e0f56d 100644 --- a/AscNet.Common/MsgPack/Types.cs +++ b/AscNet.Common/MsgPack/Types.cs @@ -2503,7 +2503,7 @@ namespace AscNet.Common.MsgPack [global::MessagePack.MessagePackObject(true)] public class CharacterUpgradeSkillGroupRequest { - public UInt32 SkillGroupId { get; set; } + public Int32 SkillGroupId { get; set; } public Int32 Count { get; set; } } @@ -2513,44 +2513,44 @@ namespace AscNet.Common.MsgPack public List UnlockChallengeStages { get; set; } = new(); } + [global::MessagePack.MessagePackObject(true)] + public class CharacterSkill + { + public UInt32 Id { get; set; } + public Int32 Level { get; set; } + } + + [global::MessagePack.MessagePackObject(true)] + public class CharacterData + { + public UInt32 Id { get; set; } + public Int32 Level { get; set; } + public UInt32 Exp { get; set; } + public Int32 Quality { get; set; } + public Int32 InitQuality { get; set; } + public Int32 Star { get; set; } + public Int32 Grade { get; set; } + public List SkillList { get; set; } = new(); + public List EnhanceSkillList { get; set; } = new(); + public UInt32 FashionId { get; set; } + public Int64 CreateTime { get; set; } + public Int32 TrustLv { get; set; } + public Int32 TrustExp { get; set; } + public Int32 Ability { get; set; } + public Int32 LiberateLv { get; set; } + + [global::MessagePack.MessagePackObject(true)] + public class CharacterHead + { + public UInt32 HeadFashionId { get; set; } + public Int32 HeadFashionType { get; set; } + } + public CharacterHead CharacterHeadInfo { get; set; } + } + [global::MessagePack.MessagePackObject(true)] public class NotifyCharacterDataList { - [global::MessagePack.MessagePackObject(true)] - public class CharacterData - { - public UInt32 Id { get; set; } - public Int32 Level { get; set; } - public UInt32 Exp { get; set; } - public Int32 Quality { get; set; } - public Int32 InitQuality { get; set; } - public Int32 Star { get; set; } - public Int32 Grade { get; set; } - [global::MessagePack.MessagePackObject(true)] - public class CharacterSkill - { - public UInt32 Id { get; set; } - public Int32 Level { get; set; } - } - - public List SkillList { get; set; } = new(); - public List EnhanceSkillList { get; set; } = new(); - public UInt32 FashionId { get; set; } - public Int64 CreateTime { get; set; } - public Int32 TrustLv { get; set; } - public Int32 TrustExp { get; set; } - public Int32 Ability { get; set; } - public Int32 LiberateLv { get; set; } - [global::MessagePack.MessagePackObject(true)] - public class CharacterHead - { - public UInt32 HeadFashionId { get; set; } - public Int32 HeadFashionType { get; set; } - } - - public CharacterHead CharacterHeadInfo { get; set; } - } - public List CharacterDataList { get; set; } = new(); } diff --git a/AscNet.GameServer/Handlers/CharacterModule.cs b/AscNet.GameServer/Handlers/CharacterModule.cs index 06476d21..dbe1bb02 100644 --- a/AscNet.GameServer/Handlers/CharacterModule.cs +++ b/AscNet.GameServer/Handlers/CharacterModule.cs @@ -9,11 +9,37 @@ using AscNet.Common; using AscNet.Table.V2.share.character.quality; using MongoDB.Driver.Linq; using AscNet.Table.V2.share.character.skill; +using AscNet.Table.V2.share.character.enhanceskill; namespace AscNet.GameServer.Handlers { #region MsgPackScheme #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + [MessagePackObject(true)] + public class CharacterUpgradeEnhanceSkillRequest + { + public int Count; + public int SkillGroupId; + } + + [MessagePackObject(true)] + public class CharacterUpgradeEnhanceSkillResponse + { + public int Code; + } + + [MessagePackObject(true)] + public class CharacterUnlockEnhanceSkillRequest + { + public int SkillGroupId; + } + + [MessagePackObject(true)] + public class CharacterUnlockEnhanceSkillResponse + { + public int Code; + } + [MessagePackObject(true)] public class CharacterLevelUpRequest { @@ -291,7 +317,7 @@ namespace AscNet.GameServer.Handlers var affectedChars = TableReaderV2.Parse().Where(x => x.SkillGroupId.Contains(request.SkillGroupId)).Select(x => x.CharacterId); foreach (var character in session.character.Characters.Where(x => affectedChars.Any(y => y == x.Id))) { - character.SkillList.AddRange(TableReaderV2.Parse().Where(x => x.Id == request.SkillGroupId).SelectMany(x => x.SkillId).Select(x => new NotifyCharacterDataList.CharacterData.CharacterSkill() { Id = (uint)x, Level = 1 })); + character.SkillList.AddRange(TableReaderV2.Parse().Where(x => x.Id == request.SkillGroupId).SelectMany(x => x.SkillId).Select(x => new CharacterSkill() { Id = (uint)x, Level = 1 })); notifyCharacterData.CharacterDataList.Add(character); } session.SendPush(notifyCharacterData); @@ -321,6 +347,88 @@ namespace AscNet.GameServer.Handlers session.SendResponse(new CharacterUpgradeSkillGroupResponse(), packet.Id); } + [RequestPacketHandler("CharacterUnlockEnhanceSkillRequest")] + public static void CharacterUnlockEnhanceSkillRequestHandler(Session session, Packet.Request packet) + { + CharacterUnlockEnhanceSkillRequest request = packet.Deserialize(); + + var enhanceSkillIds = TableReaderV2.Parse().Where(x => x.Id == request.SkillGroupId).SelectMany(x => x.SkillId); + + NotifyItemDataList notifyItemData = new(); + NotifyCharacterDataList notifyCharacterData = new(); + foreach (var enhanceSkillId in enhanceSkillIds) + { + var affectedChars = TableReaderV2.Parse().Where(x => x.SkillGroupId.Contains(request.SkillGroupId)).Select(x => x.CharacterId).ToList(); + foreach (var character in session.character.Characters.Where(x => affectedChars.Contains((int)x.Id))) + { + if (character.EnhanceSkillList.Any(x => x.Id == enhanceSkillId)) + { + // CharacterSkillUnlocked + session.SendResponse(new CharacterUnlockEnhanceSkillResponse() { Code = 20009047 }, packet.Id); + return; + } + character.EnhanceSkillList.Add(new() + { + Id = (uint)enhanceSkillId, + Level = 1 + }); + notifyCharacterData.CharacterDataList.Add(character); + } + + EnhanceSkillUpgradeTable? upgradeTable = TableReaderV2.Parse().Find(x => x.SkillId == enhanceSkillId && x.Level == 0); + if (upgradeTable is null) + continue; + + for (int i = 0; i < Math.Min(upgradeTable.CostItem.Count, upgradeTable.CostItemCount.Count); i++) + { + notifyItemData.ItemDataList.Add(session.inventory.Do(upgradeTable.CostItem[i], upgradeTable.CostItemCount[i] * -1)); + } + } + session.SendPush(notifyItemData); + session.SendPush(notifyCharacterData); + + session.SendResponse(new CharacterUnlockEnhanceSkillResponse(), packet.Id); + } + + [RequestPacketHandler("CharacterUpgradeEnhanceSkillRequest")] + public static void CharacterUpgradeEnhanceSkillRequestHandler(Session session, Packet.Request packet) + { + CharacterUpgradeEnhanceSkillRequest request = packet.Deserialize(); + + var enhanceSkillIds = TableReaderV2.Parse().Where(x => x.Id == request.SkillGroupId).SelectMany(x => x.SkillId); + + NotifyItemDataList notifyItemData = new(); + NotifyCharacterDataList notifyCharacterData = new(); + foreach (var enhanceSkillId in enhanceSkillIds) + { + foreach (var character in session.character.Characters.Where(x => x.EnhanceSkillList.Any(x => x.Id == enhanceSkillId))) + { + for (int j = 0; j < request.Count; j++) + { + var skill = character.EnhanceSkillList.Find(x => x.Id == enhanceSkillId); + if (skill is not null) + { + EnhanceSkillUpgradeTable? upgradeTable = TableReaderV2.Parse().Find(x => x.SkillId == enhanceSkillId && x.Level == skill.Level); + skill.Level++; + if (upgradeTable is null) + continue; + + for (int i = 0; i < Math.Min(upgradeTable.CostItem.Count, upgradeTable.CostItemCount.Count); i++) + { + notifyItemData.ItemDataList.Add(session.inventory.Do(upgradeTable.CostItem[i], upgradeTable.CostItemCount[i] * -1)); + } + } + } + + notifyCharacterData.CharacterDataList.Add(character); + } + } + session.SendPush(notifyItemData); + session.SendPush(notifyCharacterData); + + session.SendResponse(new CharacterUpgradeEnhanceSkillResponse(), packet.Id); + } + [RequestPacketHandler("CharacterExchangeRequest")] public static void CharacterExchangeRequestHandler(Session session, Packet.Request packet) { @@ -350,7 +458,7 @@ namespace AscNet.GameServer.Handlers } NotifyItemDataList notifyItemData = new(); - // idk if it's always 50, please investigate later... + // TODO: idk if it's always 50, please investigate later... notifyItemData.ItemDataList.Add(session.inventory.Do(characterData.ItemId, 50 * -1)); session.SendPush(notifyItemData); diff --git a/AscNet.GameServer/Handlers/EquipModule.cs b/AscNet.GameServer/Handlers/EquipModule.cs index 4e73b864..3060c67a 100644 --- a/AscNet.GameServer/Handlers/EquipModule.cs +++ b/AscNet.GameServer/Handlers/EquipModule.cs @@ -255,7 +255,7 @@ namespace AscNet.GameServer.Handlers session.SendResponse(new EquipTakeOffResponse(), packet.Id); } - // TODO: Swapping equip resonance is broken! + // TODO: Swapping equip resonance is broken, this is only partially implemented! [RequestPacketHandler("EquipResonanceRequest")] public static void EquipResonanceRequestHandler(Session session, Packet.Request packet) { diff --git a/AscNet.GameServer/Handlers/FightModule.cs b/AscNet.GameServer/Handlers/FightModule.cs index 95993272..ae404679 100644 --- a/AscNet.GameServer/Handlers/FightModule.cs +++ b/AscNet.GameServer/Handlers/FightModule.cs @@ -1,6 +1,5 @@ using AscNet.Common.Database; using AscNet.Common.MsgPack; -using static AscNet.Common.MsgPack.NotifyCharacterDataList; using AscNet.Common.Util; using AscNet.Common; using AscNet.Table.V2.share.fuben; @@ -249,7 +248,7 @@ namespace AscNet.GameServer.Handlers InitQuality = robot.CharacterQuality, Star = robot.CharacterStar, Grade = robot.CharacterGrade, - SkillList = skills.Where(x => !robot.RemoveSkillId.Contains(x)).Select(x => new CharacterData.CharacterSkill() { Id = (uint)x, Level = Math.Min(robot.SkillLevel, TableReaderV2.Parse().OrderByDescending(x => x.Level).FirstOrDefault(y => y.SkillId == x)?.Level ?? 1) }).ToList(), + SkillList = skills.Where(x => !robot.RemoveSkillId.Contains(x)).Select(x => new CharacterSkill() { Id = (uint)x, Level = Math.Min(robot.SkillLevel, TableReaderV2.Parse().OrderByDescending(x => x.Level).FirstOrDefault(y => y.SkillId == x)?.Level ?? 1) }).ToList(), FashionId = (uint)robot.FashionId, CreateTime = 0, TrustLv = 1, diff --git a/AscNet.GameServer/Handlers/PhotographModule.cs b/AscNet.GameServer/Handlers/PhotographModule.cs index 7c35c2e3..64acf4cc 100644 --- a/AscNet.GameServer/Handlers/PhotographModule.cs +++ b/AscNet.GameServer/Handlers/PhotographModule.cs @@ -38,7 +38,7 @@ namespace AscNet.GameServer.Handlers session.player.PlayerData.DisplayCharIdList.Add(request.CharId); } - NotifyCharacterDataList.CharacterData? character = session.character.Characters.Find(x => x.Id == request.CharId); + CharacterData? character = session.character.Characters.Find(x => x.Id == request.CharId); if (character is not null && character.FashionId != request.FashionId && TableReaderV2.Parse().Any(x => x.CharacterId == request.CharId && x.Id == request.FashionId)) { character.FashionId = (uint)request.FashionId;