From 005ad80095121c17afd263846650c2ae81281c8f Mon Sep 17 00:00:00 2001 From: Mikhail Date: Mon, 15 Jul 2024 12:18:29 -0400 Subject: [PATCH] properly implement character level up currency is now subtracted --- README.md | 5 ++- nksrv/LobbyServer/Msgs/Character/LevelUp.cs | 39 ++++++++++++++++-- .../LobbyServer/Msgs/User/GetContentsData.cs | 2 +- nksrv/StaticInfo/JsonStaticData.cs | 24 +++++++++++ nksrv/StaticInfo/StaticDataParser.cs | 26 +++++++++--- nksrv/Utils/JsonDb.cs | 41 +++++++++++++++++++ 6 files changed, 126 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2556805..f01b2a0 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,15 @@ Stage, character, outpost and story information is saved and works, as well as p - [X] Profile UI - [X] Open Archives UI - [X] Inventory system + - [X] Character level up + - [ ] Skill level up - [ ] Outpost jukebox / relics saving - [ ] Field obtain object - [ ] Admin panel - [ ] Test hard stage support - [ ] Event system - [ ] Download all game assets ahead of time - - [ ] Level up/skill level up support - - [ ] Basic friend list support / allow using other servers except 127.0.0.1 + - [ ] Basic friend list support - [ ] Aegis Diver minigame, MOG minigame, etc - [ ] Outpost claim rewards - [ ] Daily, weekly missions etc diff --git a/nksrv/LobbyServer/Msgs/Character/LevelUp.cs b/nksrv/LobbyServer/Msgs/Character/LevelUp.cs index e1805aa..6652dfe 100644 --- a/nksrv/LobbyServer/Msgs/Character/LevelUp.cs +++ b/nksrv/LobbyServer/Msgs/Character/LevelUp.cs @@ -1,4 +1,6 @@ -using nksrv.Utils; +using nksrv.StaticInfo; +using nksrv.Utils; +using Swan.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -15,14 +17,40 @@ namespace nksrv.LobbyServer.Msgs.Character var req = await ReadData(); var user = GetUser(); var response = new ResCharacterLevelUp(); + var data = StaticDataParser.Instance.GetCharacterLevelUpData(); foreach (var item in user.Characters.ToArray()) { if (item.Csn == req.Csn) { - item.Level = req.Level; - // TODO: subtract currency + // item.Level = req.Level; + int requiredCredit = 0; + int requiredBattleData = 0; + int requiredCoreDust = 0; + for (int i = item.Level; i < req.Level; i++) + { + var levelUpData = data[i]; + requiredCredit += levelUpData.gold; + requiredBattleData += levelUpData.character_exp; + requiredCoreDust += levelUpData.character_exp2; + } + + if (user.CanSubtractCurrency(CurrencyType.Gold, requiredCredit) && + user.CanSubtractCurrency(CurrencyType.CharacterExp, requiredBattleData) && + user.CanSubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust)) + { + user.SubtractCurrency(CurrencyType.Gold, requiredCredit); + user.SubtractCurrency(CurrencyType.CharacterExp, requiredBattleData); + user.SubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust); + item.Level = req.Level; + } + else + { + // TOOD: log this + Logger.Error("ERROR: Not enough currency for upgrade"); + return; + } response.Character = new() { CostumeId = item.CostumeId, @@ -43,6 +71,11 @@ namespace nksrv.LobbyServer.Msgs.Character response.SynchroStandardCharacters.Add(c.Tid); } + foreach (var currency in user.Currency) + { + response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value }); + } + break; } } diff --git a/nksrv/LobbyServer/Msgs/User/GetContentsData.cs b/nksrv/LobbyServer/Msgs/User/GetContentsData.cs index d642d37..2b3e3d1 100644 --- a/nksrv/LobbyServer/Msgs/User/GetContentsData.cs +++ b/nksrv/LobbyServer/Msgs/User/GetContentsData.cs @@ -27,7 +27,7 @@ namespace nksrv.LobbyServer.Msgs.User // todo tutorial playcount of gacha response.TutorialGachaPlayCount = user.GachaTutorialPlayCount; - await WriteDataAsync(response); + await WriteDataAsync(response); } } } diff --git a/nksrv/StaticInfo/JsonStaticData.cs b/nksrv/StaticInfo/JsonStaticData.cs index aae8d07..17c6085 100644 --- a/nksrv/StaticInfo/JsonStaticData.cs +++ b/nksrv/StaticInfo/JsonStaticData.cs @@ -57,4 +57,28 @@ namespace nksrv.StaticInfo public int NextId; public bool SaveTutorial; } + + public class CharacterLevelData + { + /// + /// level + /// + public int level; + /// + /// can be CharacterLevel or SynchroLevel + /// + public string type = ""; + /// + /// amount of credits required + /// + public int gold = 0; + /// + /// amount of battle data required + /// + public int character_exp = 0; + /// + /// amount of core dust required + /// + public int character_exp2 = 0; + } } diff --git a/nksrv/StaticInfo/StaticDataParser.cs b/nksrv/StaticInfo/StaticDataParser.cs index 900f5db..2355ec6 100644 --- a/nksrv/StaticInfo/StaticDataParser.cs +++ b/nksrv/StaticInfo/StaticDataParser.cs @@ -55,6 +55,7 @@ namespace nksrv.StaticInfo private JArray characterTable; private JArray tutorialTable; private JArray itemEquipTable; + private Dictionary LevelData = []; public byte[] Sha256Hash; public int Size; @@ -230,7 +231,7 @@ namespace nksrv.StaticInfo if (questdata == null) throw new Exception("failed to parse " + entry); var records = (JArray?)questdata["records"]; - if (records == null ) throw new Exception(entry + " is missing records element"); + if (records == null) throw new Exception(entry + " is missing records element"); return records; } @@ -245,6 +246,16 @@ namespace nksrv.StaticInfo characterTable = await LoadZip("CharacterTable.json"); tutorialTable = await LoadZip("ContentsTutorialTable.json"); itemEquipTable = await LoadZip("ItemEquipTable.json"); + var characterLevelTable = await LoadZip("CharacterLevelTable.json"); + + foreach (JToken item in characterLevelTable) + { + var obj = item.ToObject(); + if (obj != null) + LevelData.Add(obj.level, obj); + else + Logger.Warn("failed to read character level table entry"); + } } public MainQuestCompletionData? GetMainQuestForStageClearCondition(int stage) @@ -257,7 +268,7 @@ namespace nksrv.StaticInfo int value = id.ToObject(); if (value == stage) { - MainQuestCompletionData? data = JsonConvert.DeserializeObject(item.ToString()); + MainQuestCompletionData? data = item.ToObject(); if (data == null) throw new Exception("failed to deserialize main quest data item"); return data; } @@ -275,7 +286,7 @@ namespace nksrv.StaticInfo int value = id.ToObject(); if (value == tid) { - MainQuestCompletionData? data = JsonConvert.DeserializeObject(item.ToString()); + MainQuestCompletionData? data = item.ToObject(); if (data == null) throw new Exception("failed to deserialize main quest data item"); return data; } @@ -417,7 +428,7 @@ namespace nksrv.StaticInfo int idValue = id.ToObject(); if (idValue == TableId) { - ClearedTutorialData? data = JsonConvert.DeserializeObject(item.ToString()); + ClearedTutorialData? data = item.ToObject(); if (data == null) throw new Exception("failed to deserialize reward data"); return data; } @@ -454,7 +465,7 @@ namespace nksrv.StaticInfo string mod = normal ? "Normal" : "Hard"; foreach (JObject item in stageDataRecords) { - CampaignStageRecord? data = JsonConvert.DeserializeObject(item.ToString()); + CampaignStageRecord? data = item.ToObject(); if (data == null) throw new Exception("failed to deserialize stage data"); int chVal = data.chapter_id - 1; @@ -465,5 +476,10 @@ namespace nksrv.StaticInfo } } } + + public Dictionary GetCharacterLevelUpData() + { + return LevelData; + } } } diff --git a/nksrv/Utils/JsonDb.cs b/nksrv/Utils/JsonDb.cs index 7d1bc28..eb1d2a0 100644 --- a/nksrv/Utils/JsonDb.cs +++ b/nksrv/Utils/JsonDb.cs @@ -152,6 +152,47 @@ namespace nksrv.Utils return false; } + + public long GetCurrencyVal(CurrencyType type) + { + if (Currency.ContainsKey(type)) + return Currency[type]; + else + { + Currency.Add(type, 0); + return 0; + } + } + public void AddCurrency(CurrencyType type, long val) + { + if (Currency.ContainsKey(type)) Currency[type] += val; + else Currency.Add(type, val); + } + public bool SubtractCurrency(CurrencyType type, long val) + { + if (Currency.ContainsKey(type)) Currency[type] -= val; + else return false; + + if (Currency[type] < 0) + { + Currency[type] += val; + return false; + } + return true; + } + public bool CanSubtractCurrency(CurrencyType type, long val) + { + if (Currency.ContainsKey(type)) + { + if (Currency[type] >= val) return true; + else return false; + } + else + { + if (val == 0) return true; + else return false; + } + } } public class CoreInfo {