diff --git a/Common/Database/Avatar.cs b/Common/Database/Avatar.cs index 9b9862b..cb3829a 100644 --- a/Common/Database/Avatar.cs +++ b/Common/Database/Avatar.cs @@ -1,5 +1,6 @@ using Common.Resources.Proto; using Common.Utils.ExcelReader; +using Newtonsoft.Json; using MongoDB.Bson; using MongoDB.Driver; @@ -11,7 +12,7 @@ namespace Common.Database public static AvatarScheme[] AvatarsFromUid(uint uid) { - return collection.AsQueryable().Where(collection=> collection.OwnerUid == uid).ToArray(); + return collection.AsQueryable().Where(collection => collection.OwnerUid == uid).ToArray(); } public static AvatarScheme Create(int avatarId, uint uid, EquipmentScheme equipment) @@ -40,7 +41,8 @@ namespace Common.Database SubStar = 0, TouchGoodfeel = 0, TodayHasAddGoodfeel = 0, - WeaponUniqueId = weapon.UniqueId + WeaponUniqueId = weapon.UniqueId, + SkillLists = new() }; if(avatarData.AvatarId == 101) @@ -54,18 +56,25 @@ namespace Common.Database avatar.StigmataUniqueId3 = defaultStigmata3.UniqueId; } - avatar.SkillLists.AddRange(avatarData.SkillList.Select(skillId => new AvatarSkill { SkillId = (uint)skillId })); + avatar.SkillLists.AddRange(avatarData.SkillList.Select(skillId => new AvatarScheme.AvatarSkill { SkillId = (uint)skillId })); collection.InsertOne(avatar); return avatar; } - } + public class AvatarScheme : Resources.Proto.Avatar { + public class AvatarSkill : Resources.Proto.AvatarSkill + { + public new List SubSkillLists { get; set; } = new(); + } + public ObjectId Id { get; set; } public uint OwnerUid { get; set; } + public new List SkillLists { get; set; } = new(); + public void Save() { @@ -80,5 +89,39 @@ namespace Common.Database return levelData; } + + public void LevelUpSkill(uint subSkillId, bool isLevelUpAll = false) + { + AvatarSubSkillDataExcel? subSkillData = AvatarSubSkillData.GetInstance().FromId((int)subSkillId); + if (subSkillData is null) + return; + + AvatarSkill? avatarSkill = SkillLists.Where(skill => skill.SkillId == subSkillData.SkillId).FirstOrDefault(); + if(avatarSkill is not null) + { + AvatarSubSkill? avatarSubSkill = avatarSkill.SubSkillLists.FirstOrDefault(skill => skill.SubSkillId == subSkillData.AvatarSubSkillId); + if (avatarSubSkill is not null) + { + if (isLevelUpAll) + { + avatarSubSkill.Level = (uint)subSkillData.MaxLv; + } + else + { + avatarSubSkill.Level++; + } + } + else + { + avatarSkill.SubSkillLists.Add(new() { SubSkillId = (uint)subSkillData.AvatarSubSkillId, Level = 1, IsMask = false }); + } + } + else + { + AvatarSkill newAvatarSkill = new() { SkillId = (uint)subSkillData.SkillId }; + newAvatarSkill.SubSkillLists.Add(new() { SubSkillId = (uint)subSkillData.AvatarSubSkillId, Level = 1, IsMask = false }); + SkillLists.Add(newAvatarSkill); + } + } } } diff --git a/Common/Utils/ExcelReader/AvatarSubSkillData.cs b/Common/Utils/ExcelReader/AvatarSubSkillData.cs new file mode 100644 index 0000000..5fb3db0 --- /dev/null +++ b/Common/Utils/ExcelReader/AvatarSubSkillData.cs @@ -0,0 +1,141 @@ +using Newtonsoft.Json; + +namespace Common.Utils.ExcelReader +{ + public class AvatarSubSkillData : BaseExcelReader + { + public override string FileName { get { return "AvatarSubSkillData.json"; } } + + public AvatarSubSkillDataExcel? FromId(int id) + { + return All.Where(subSkill => subSkill.AvatarSubSkillId == id).FirstOrDefault(); + } + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public partial class AvatarSubSkillDataExcel + { + [JsonProperty("name")] + public HashName Name { get; set; } + + [JsonProperty("info")] + public HashName Info { get; set; } + + [JsonProperty("brief")] + public HashName Brief { get; set; } + + [JsonProperty("showOrder")] + public int ShowOrder { get; set; } + + [JsonProperty("skillId")] + public int SkillId { get; set; } + + [JsonProperty("ignoreLeader")] + public bool IgnoreLeader { get; set; } + + [JsonProperty("iconPath")] + public string IconPath { get; set; } + + [JsonProperty("unlockStar")] + public int UnlockStar { get; set; } + + [JsonProperty("unlockSubStar")] + public int UnlockSubStar { get; set; } + + [JsonProperty("unlockLv")] + public int UnlockLv { get; set; } + + [JsonProperty("unlockLvAdd")] + public int UnlockLvAdd { get; set; } + + [JsonProperty("maxLv")] + public int MaxLv { get; set; } + + [JsonProperty("upLevelSubStarNeedList")] + public UpLevelSubStarNeedList[] UpLevelSubStarNeedList { get; set; } + + [JsonProperty("scoinCalc")] + public bool ScoinCalc { get; set; } + + [JsonProperty("unlockScoin")] + public int UnlockScoin { get; set; } + + [JsonProperty("scoinLvAdd")] + public int ScoinLvAdd { get; set; } + + [JsonProperty("itemType")] + public int ItemType { get; set; } + + [JsonProperty("skillToggle")] + public bool SkillToggle { get; set; } + + [JsonProperty("paramBase_1")] + public double ParamBase1 { get; set; } + + [JsonProperty("paramAdd_1")] + public double ParamAdd1 { get; set; } + + [JsonProperty("paramBase_2")] + public double ParamBase2 { get; set; } + + [JsonProperty("paramAdd_2")] + public double ParamAdd2 { get; set; } + + [JsonProperty("paramBase_3")] + public double ParamBase3 { get; set; } + + [JsonProperty("paramAdd_3")] + public double ParamAdd3 { get; set; } + + [JsonProperty("canTry")] + public bool CanTry { get; set; } + + [JsonProperty("ArtifactSkillID")] + public int ArtifactSkillId { get; set; } + + [JsonProperty("UpLevelArtifactNeedList")] + public UpLevelArtifactNeedList[] UpLevelArtifactNeedList { get; set; } + + [JsonProperty("TagList")] + public TagList[] TagList { get; set; } + + [JsonProperty("DataImpl")] + public object DataImpl { get; set; } + + [JsonProperty("avatarSubSkillId")] + public int AvatarSubSkillId { get; set; } + } + + public partial class TagList + { + [JsonProperty("Strength")] + public int Strength { get; set; } + + [JsonProperty("TagID")] + public int TagId { get; set; } + + [JsonProperty("TagComment")] + public HashName TagComment { get; set; } + } + + public partial class UpLevelArtifactNeedList + { + [JsonProperty("ArtifactLevel")] + public int ArtifactLevel { get; set; } + + [JsonProperty("SubSkillLevel")] + public int SubSkillLevel { get; set; } + } + + public partial class UpLevelSubStarNeedList + { + [JsonProperty("level")] + public int Level { get; set; } + + [JsonProperty("starNeed")] + public int StarNeed { get; set; } + + [JsonProperty("subStarNeed")] + public int SubStarNeed { get; set; } + } +} diff --git a/Common/Utils/ExcelReader/AvatarSubSkillLevelData.cs b/Common/Utils/ExcelReader/AvatarSubSkillLevelData.cs new file mode 100644 index 0000000..2cf6812 --- /dev/null +++ b/Common/Utils/ExcelReader/AvatarSubSkillLevelData.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; + +namespace Common.Utils.ExcelReader +{ + internal class AvatarSubSkillLevelData : BaseExcelReader + { + public override string FileName { get { return "AvatarSubSkillLevelDataV2.json"; } } + + public List FromType(int type) + { + return All.Where(d => d.ItemType == type).ToList(); + } + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public partial class AvatarSubSkillLevelDataExcel + { + [JsonProperty("ItemList_1")] + public AvatarSubSkillLevelItemList[] ItemList1 { get; set; } + + [JsonProperty("DataImpl")] + public object DataImpl { get; set; } + + [JsonProperty("ItemType")] + public int ItemType { get; set; } + + [JsonProperty("SkillLevel")] + public int SkillLevel { get; set; } + } + + public partial class AvatarSubSkillLevelItemList + { + [JsonProperty("itemMetaID")] + public int ItemMetaId { get; set; } + + [JsonProperty("itemNum")] + public int ItemNum { get; set; } + } +} diff --git a/GameServer/Commands/AvatarCommand.cs b/GameServer/Commands/AvatarCommand.cs index cb4c651..d0a1892 100644 --- a/GameServer/Commands/AvatarCommand.cs +++ b/GameServer/Commands/AvatarCommand.cs @@ -53,9 +53,14 @@ namespace PemukulPaku.GameServer.Commands { string action = args[0]; int avatarId = int.Parse(args[1]); - string modType = args[2]; - int value = int.Parse(args[3]); - AvatarScheme? avatar; + string modType = ""; + int value = 0; + if (args.Length > 3) + { + modType = args[2]; + value = int.Parse(args[3]); + } + AvatarScheme? avatar = null; switch (action) { @@ -95,7 +100,7 @@ namespace PemukulPaku.GameServer.Commands avatar.Save(); } else - c.Error("Invalid AvatarScheme in avatar modify command"); + throw new ArgumentException("Avatar not found"); } break; default: diff --git a/GameServer/Handlers/AvatarSubSkillLevelUpReqHandler.cs b/GameServer/Handlers/AvatarSubSkillLevelUpReqHandler.cs new file mode 100644 index 0000000..d910ef0 --- /dev/null +++ b/GameServer/Handlers/AvatarSubSkillLevelUpReqHandler.cs @@ -0,0 +1,28 @@ +using Common.Database; +using Common.Resources.Proto; + +namespace PemukulPaku.GameServer.Handlers +{ + [PacketCmdId(CmdId.AvatarSubSkillLevelUpReq)] + internal class AvatarSubSkillLevelUpReqHandler : IPacketHandler + { + // TODO: Find out how to calculate cost with itemType 0 + public void Handle(Session session, Packet packet) + { + AvatarSubSkillLevelUpReq Data = packet.GetDecodedBody(); + AvatarScheme? avatar = session.Player.AvatarList.FirstOrDefault(avatar => avatar.AvatarId == Data.AvatarId); + AvatarSubSkillLevelUpRsp Rsp = new() { retcode = AvatarSubSkillLevelUpRsp.Retcode.Succ }; + + if (avatar is not null) + { + avatar.LevelUpSkill(Data.SubSkillId, Data.IsLevelUpAll); + session.ProcessPacket(Packet.FromProto(new GetAvatarDataReq() { AvatarIdLists = new uint[] { avatar.AvatarId } }, CmdId.GetAvatarDataReq)); + } + else + { + Rsp.retcode = AvatarSubSkillLevelUpRsp.Retcode.AvatarNotExist; + } + session.Send(Packet.FromProto(Rsp, CmdId.AvatarSubSkillLevelUpRsp)); + } + } +} diff --git a/GameServer/Handlers/GetAvatarDataReqHandler.cs b/GameServer/Handlers/GetAvatarDataReqHandler.cs index b368cd9..db70ec9 100644 --- a/GameServer/Handlers/GetAvatarDataReqHandler.cs +++ b/GameServer/Handlers/GetAvatarDataReqHandler.cs @@ -38,7 +38,12 @@ namespace PemukulPaku.GameServer.Handlers TouchGoodfeel = avatar.TouchGoodfeel, WeaponUniqueId = avatar.WeaponUniqueId }; - a.SkillLists.AddRange(avatar.SkillLists); + a.SkillLists.AddRange(avatar.SkillLists.Select(skill => + { + AvatarSkill avatarSkill = new() { SkillId = skill.SkillId }; + avatarSkill.SubSkillLists.AddRange(skill.SubSkillLists); + return avatarSkill; + })); return a; }); @@ -70,7 +75,12 @@ namespace PemukulPaku.GameServer.Handlers TouchGoodfeel = avatar.TouchGoodfeel, WeaponUniqueId = avatar.WeaponUniqueId }; - a.SkillLists.AddRange(avatar.SkillLists); + a.SkillLists.AddRange(avatar.SkillLists.Select(skill => + { + AvatarSkill avatarSkill = new() { SkillId = skill.SkillId }; + avatarSkill.SubSkillLists.AddRange(skill.SubSkillLists); + return avatarSkill; + })); return a; });