diff --git a/EpinelPS/Database/JsonDb.cs b/EpinelPS/Database/JsonDb.cs index 69ac0ac..cafec3a 100644 --- a/EpinelPS/Database/JsonDb.cs +++ b/EpinelPS/Database/JsonDb.cs @@ -78,6 +78,12 @@ namespace EpinelPS.Database /// public long AvailableAt; } + public class ResetableData + { + public int WipeoutCount = 0; + public bool ClearedSimulationRoom = false; + public int InterceptionTickets = 3; + } public class User { // User info @@ -112,6 +118,7 @@ namespace EpinelPS.Database public bool SynchroDeviceUpgraded = false; public int SynchroDeviceLevel = 200; + public ResetableData ResetableData = new(); public List Items = new(); public List Characters = []; public NetWholeUserTeamData RepresentationTeamData = new(); diff --git a/EpinelPS/GameData/GameData.cs b/EpinelPS/GameData/GameData.cs index ce1a883..1cca9f8 100644 --- a/EpinelPS/GameData/GameData.cs +++ b/EpinelPS/GameData/GameData.cs @@ -39,6 +39,7 @@ namespace EpinelPS.StaticInfo public Dictionary SidestoryRewardTable = []; public Dictionary PositionReward = new Dictionary(); public Dictionary FieldItems = []; + public Dictionary OutpostBattle = []; public byte[] Sha256Hash; public int Size; @@ -370,6 +371,12 @@ namespace EpinelPS.StaticInfo { FieldItems.Add(obj.id, obj); } + + var battleOutpostTable = await LoadZip("OutpostBattleTable.json", progress); + foreach (var obj in battleOutpostTable.records) + { + OutpostBattle.Add(obj.id, obj); + } } public MainQuestCompletionRecord? GetMainQuestForStageClearCondition(int stage) diff --git a/EpinelPS/GameData/JsonStaticData.cs b/EpinelPS/GameData/JsonStaticData.cs index 0adcac2..003fe84 100644 --- a/EpinelPS/GameData/JsonStaticData.cs +++ b/EpinelPS/GameData/JsonStaticData.cs @@ -147,4 +147,17 @@ { public List records; } + + public class OutpostBattleTableRecord + { + public int id; + public int credit; + public int character_exp1; + public int character_exp2; + public int user_exp; + } + public class OutpostBattleTable + { + public List records; + } } diff --git a/EpinelPS/LobbyServer/Msgs/Arena/GetArena.cs b/EpinelPS/LobbyServer/Msgs/Arena/GetArena.cs new file mode 100644 index 0000000..e128186 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Arena/GetArena.cs @@ -0,0 +1,22 @@ +using EpinelPS.Utils; +using Google.Protobuf.WellKnownTypes; + +namespace EpinelPS.LobbyServer.Msgs.Arena +{ + [PacketPath("/arena/get")] + public class GetArena : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new ResGetArena(); + response.BanInfo = new NetArenaBanInfo() { Description = "Not Implemented", StartAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow), EndAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow.AddYears(10)) }; + response.User = new NetArenaData() {User = LobbyHandler.CreateWholeUserDataFromDbUser(user) }; + + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Arena/GetArenaBanInfo.cs b/EpinelPS/LobbyServer/Msgs/Arena/GetArenaBanInfo.cs index 3be9dd7..c458494 100644 --- a/EpinelPS/LobbyServer/Msgs/Arena/GetArenaBanInfo.cs +++ b/EpinelPS/LobbyServer/Msgs/Arena/GetArenaBanInfo.cs @@ -1,4 +1,5 @@ using EpinelPS.Utils; +using Google.Protobuf.WellKnownTypes; namespace EpinelPS.LobbyServer.Msgs.Arena { @@ -10,7 +11,9 @@ namespace EpinelPS.LobbyServer.Msgs.Arena var req = await ReadData(); var response = new ResGetArenaBanInfo(); - // TODO + response.RookieArenaBanInfo = new NetArenaBanInfo() { Description = "Not Implemented", StartAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow), EndAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow.AddYears(10)) }; + response.SpecialArenaBanInfo = new NetArenaBanInfo() { Description = "Not Implemented", StartAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow), EndAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow.AddYears(10)) }; + await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Msgs/Arena/GetChampion.cs b/EpinelPS/LobbyServer/Msgs/Arena/GetChampion.cs new file mode 100644 index 0000000..930303e --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Arena/GetChampion.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.WellKnownTypes; + +namespace EpinelPS.LobbyServer.Msgs.Arena +{ + [PacketPath("/arena/champion/get")] + public class GetChampion : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetChampionArena(); + response.Schedule = new NetChampionArenaSchedule(); + + // TODO + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs b/EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs index a1bf61d..4a93c12 100644 --- a/EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs +++ b/EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs @@ -1,4 +1,5 @@ using EpinelPS.Utils; +using Google.Protobuf.WellKnownTypes; namespace EpinelPS.LobbyServer.Msgs.Arena { @@ -10,7 +11,8 @@ namespace EpinelPS.LobbyServer.Msgs.Arena var req = await ReadData(); var response = new ResShowSpecialArenaReward(); - // TODO + response.IsBan = true; + response.BanInfo = new NetArenaBanInfo() { Description = "Not Implemented", StartAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow), EndAt = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow.AddYears(10)) }; await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Msgs/Auth/DoEnterServer.cs b/EpinelPS/LobbyServer/Msgs/Auth/DoEnterServer.cs index 119fc10..b08bf19 100644 --- a/EpinelPS/LobbyServer/Msgs/Auth/DoEnterServer.cs +++ b/EpinelPS/LobbyServer/Msgs/Auth/DoEnterServer.cs @@ -31,7 +31,7 @@ namespace EpinelPS.LobbyServer.Msgs.Auth response.FeatureDataInfo = new NetFeatureDataInfo() { UseFeatureData = true }; response.Identifier = new NetLegacyUserIdentifier() { Server = 21769, Usn = (long)user.ID }; response.ShouldRestartAfter = Duration.FromTimeSpan(TimeSpan.FromSeconds(86400)); - + response.EncryptionToken = ByteString.CopyFromUtf8(rsp.ClientAuthToken); await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/DoWipeout.cs b/EpinelPS/LobbyServer/Msgs/Outpost/DoWipeout.cs index f66d29d..9b6fbd9 100644 --- a/EpinelPS/LobbyServer/Msgs/Outpost/DoWipeout.cs +++ b/EpinelPS/LobbyServer/Msgs/Outpost/DoWipeout.cs @@ -9,8 +9,24 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost { var req = await ReadData(); var response = new ResObtainFastBattleReward(); + var user = GetUser(); - // TODO + if (user.ResetableData.WipeoutCount >= 12) + { + throw new InvalidOperationException("wipeout count cannot exceed 12."); + } + + user.ResetableData.WipeoutCount++; + response.FastBattleCount = user.ResetableData.WipeoutCount; + + response.Reward = NetUtils.GetOutpostReward(user, TimeSpan.FromHours(2)); + NetUtils.RegisterRewardsForUser(user, response.Reward); + + // TODO subtract currency as needed + foreach (var item in user.Currency) + { + response.Currencies.Add(new NetUserCurrencyData() { Type = (int)item.Key, Value = item.Value}); + } await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs index 3d80f7b..1386844 100644 --- a/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs +++ b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs @@ -13,19 +13,26 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost var battleTime = DateTime.UtcNow - user.BattleTime; var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + long overBattleTime = battleTimeMs > 12096000000000 ? battleTimeMs - 12096000000000 : 0; + var response = new ResGetOutpostData { - OutpostBattleLevel = new NetOutpostBattleLevel() { Level = 1 }, + OutpostBattleLevel = user.OutpostBattleLevel, + Jukebox = new() { SelectTid = 5 }, JukeboxV2 = new NetUserJukeboxDataV2() { CommandBgm = new() { Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, JukeboxTableId = 5 } }, BattleTime = 864000000000, - Jukebox = new(), MaxBattleTime = 864000000000, - SkinGroupId = 1000 + SkinGroupId = 1000, }; + // TODO: do not hard code this! + response.Jukebox.List.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + response.JukeboxV2.JukeboxTableIds.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + response.OutpostBattleLevel = user.OutpostBattleLevel; - response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs }; + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs, OverBattleTime = overBattleTime }; + response.Data.Add(new NetUserOutpostData() { SlotId = 1, BuildingId = 22401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); response.Data.Add(new NetUserOutpostData() { SlotId = 4, BuildingId = 22701, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); response.Data.Add(new NetUserOutpostData() { SlotId = 5, BuildingId = 22801, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); @@ -38,6 +45,8 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost response.Data.Add(new NetUserOutpostData() { SlotId = 10, BuildingId = 23501, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); response.Data.Add(new NetUserOutpostData() { SlotId = 38, BuildingId = 33601, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user)); + // TODO await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/ObtainOutpostReward.cs b/EpinelPS/LobbyServer/Msgs/Outpost/ObtainOutpostReward.cs new file mode 100644 index 0000000..2744dca --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Outpost/ObtainOutpostReward.cs @@ -0,0 +1,36 @@ +using EpinelPS.Database; +using EpinelPS.LobbyServer.Msgs.Stage; +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Outpost +{ + [PacketPath("/outpost/obtainoutpostbattlereward")] + public class ObtainOutpostReward : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new ResObtainOutpostBattleReward(); + + + var battleTime = DateTime.UtcNow - user.BattleTime; + var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + long overBattleTime = battleTimeMs > 864000000000 ? battleTimeMs - 864000000000 : 0; + + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = 0, OverBattleTime = 0 }; + response.BattleTime = 0; + response.MaxBattleTime = 864000000000; + + response.Reward = NetUtils.GetOutpostReward(user, battleTime); + NetUtils.RegisterRewardsForUser(user, response.Reward); + + user.BattleTime = DateTime.UtcNow; + + JsonDb.Save(); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/ShowBattleReward.cs b/EpinelPS/LobbyServer/Msgs/Outpost/ShowBattleReward.cs index 822c151..256965c 100644 --- a/EpinelPS/LobbyServer/Msgs/Outpost/ShowBattleReward.cs +++ b/EpinelPS/LobbyServer/Msgs/Outpost/ShowBattleReward.cs @@ -1,4 +1,5 @@ -using EpinelPS.Utils; +using EpinelPS.Database; +using EpinelPS.Utils; namespace EpinelPS.LobbyServer.Msgs.Outpost { @@ -12,13 +13,24 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost var battleTime = DateTime.UtcNow - user.BattleTime; var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + long overBattleTime = battleTimeMs > 864000000000 ? battleTimeMs - 864000000000 : 0; + + // TODO + if (overBattleTime > 864000000000) + overBattleTime = 0; var response = new ResShowOutpostBattleReward(); response.OutpostBattleLevel = user.OutpostBattleLevel; - response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs }; - response.BattleTime = battleTimeMs; + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs, OverBattleTime = 0 }; + + response.BattleTime = 0; + response.FastBattleCount = user.ResetableData.WipeoutCount; response.MaxBattleTime = 864000000000; - response.Reward = new NetRewardData(); + + response.Reward = NetUtils.GetOutpostReward(user, battleTime); + response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user)); + + await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Msgs/Stage/ClearStage.cs b/EpinelPS/LobbyServer/Msgs/Stage/ClearStage.cs index 0a5f5e4..acde6d0 100644 --- a/EpinelPS/LobbyServer/Msgs/Stage/ClearStage.cs +++ b/EpinelPS/LobbyServer/Msgs/Stage/ClearStage.cs @@ -87,7 +87,7 @@ namespace EpinelPS.LobbyServer.Msgs.Stage if (clearedStage.stage_type != "Sub") { // add outpost reward level if unlocked - if (user.MainQuestData.ContainsKey(21)) + if (user.MainQuestData.TryGetValue(21, out bool c)) { user.OutpostBattleLevel.Exp++; if (user.OutpostBattleLevel.Exp >= 5) diff --git a/EpinelPS/Program.cs b/EpinelPS/Program.cs index eb99ce6..3f56912 100644 --- a/EpinelPS/Program.cs +++ b/EpinelPS/Program.cs @@ -396,28 +396,42 @@ namespace EpinelPS response.AddRange(Encoding.UTF8.GetBytes("\r\n")); var bin = await item.ReadAsByteArrayAsync(); - var res = await SendReqLocalAndReadResponseAsync(bin); - - if (res != null) + try { - List ResponseWithBytes = -[ - .. Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\n"), + var res = await SendReqLocalAndReadResponseAsync(bin); + + if (res != null) + { + List ResponseWithBytes = + [ + .. Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\n"), .. Encoding.UTF8.GetBytes($"Content-Type: application/octet-stream+protobuf\r\n"), .. Encoding.UTF8.GetBytes($"Content-Length: {res.Length}\r\n"), .. Encoding.UTF8.GetBytes($"\r\n"), .. res, ]; - response.AddRange([.. ResponseWithBytes]); - } - else - { - List ResponseWithBytes = -[ .. Encoding.UTF8.GetBytes("HTTP/1.1 404 Not Found\r\n"), + response.AddRange([.. ResponseWithBytes]); + } + else + { + List ResponseWithBytes = + [ .. Encoding.UTF8.GetBytes("HTTP/1.1 404 Not Found\r\n"), //.. Encoding.UTF8.GetBytes($"Content-Type: application/octet-stream+protobuf\r\n"), .. Encoding.UTF8.GetBytes($"Content-Length: 0\r\n"), .. Encoding.UTF8.GetBytes($"\r\n"), ]; + response.AddRange([.. ResponseWithBytes]); + } + } + catch + { + List ResponseWithBytes = + [ .. Encoding.UTF8.GetBytes("HTTP/1.1 505 Internal Server Error\r\n"), + //.. Encoding.UTF8.GetBytes($"Content-Type: application/octet-stream+protobuf\r\n"), + .. Encoding.UTF8.GetBytes($"Content-Length: 0\r\n"), + .. Encoding.UTF8.GetBytes($"\r\n"), + ]; + response.AddRange([.. ResponseWithBytes]); } // add boundary, also include http newline if there is binary content diff --git a/EpinelPS/Utils/NetUtils.cs b/EpinelPS/Utils/NetUtils.cs index e6459e2..2c04bd6 100644 --- a/EpinelPS/Utils/NetUtils.cs +++ b/EpinelPS/Utils/NetUtils.cs @@ -1,5 +1,8 @@ using EpinelPS.Database; using EpinelPS.StaticInfo; +using Google.Protobuf.WellKnownTypes; +using System.Collections.Generic; +using static Google.Rpc.Context.AttributeContext.Types; namespace EpinelPS.Utils { @@ -141,5 +144,147 @@ namespace EpinelPS.Utils } return result; } + + private static long CalcOutpostRewardAmount(int value, double ratio, double boost, double elapsedMinutes) + { + double baseValue = value * ratio / 10000.0; + double minuteValue = baseValue + baseValue * boost / 100.0; + + + return (long)Math.Floor(minuteValue * elapsedMinutes); + } + + public static double CalculateBoostValueForOutpost(User user, CurrencyType type) + { + double boost = 1.0; + if (user.CompletedTacticAcademyLessons.Contains(1003) && type == CurrencyType.Gold) + { + boost += .10; + } + + return boost; + } + + public static long GetOutpostRewardAmount(User user, CurrencyType type, double mins, bool includeBoost) + { + var battleData = GameData.Instance.OutpostBattle[user.OutpostBattleLevel.Level]; + + int value = 0; + double ratio = 0; + double boost = 1.0; + if (includeBoost) + boost += CalculateBoostValueForOutpost(user, type); + + switch(type) + { + case CurrencyType.CharacterExp2: + value = battleData.character_exp2; + ratio = 1; + break; + case CurrencyType.CharacterExp: + value = battleData.character_exp1; + ratio = 3; + break; + case CurrencyType.Gold: + value = battleData.credit; + ratio = 3; + break; + case CurrencyType.UserExp: + value = battleData.user_exp; + ratio = 1; + break; + } + return CalcOutpostRewardAmount(value, ratio, boost, mins); + } + + public static NetRewardData GetOutpostReward(User user, TimeSpan duration) + { + //duration = TimeSpan.FromHours(1); + NetRewardData result = new(); + + var battleData = GameData.Instance.OutpostBattle[user.OutpostBattleLevel.Level]; + + result.Currency.Add(new NetCurrencyData() + { + Type = (int)CurrencyType.CharacterExp2, + FinalValue = 0, + Value = CalcOutpostRewardAmount(battleData.character_exp2, 1, 1, duration.TotalMinutes) + }); + + result.Currency.Add(new NetCurrencyData() + { + Type = (int)CurrencyType.CharacterExp, + FinalValue = 0, + Value = CalcOutpostRewardAmount(battleData.character_exp1, 3, 1, duration.TotalMinutes) + }); + + result.Currency.Add(new NetCurrencyData() + { + Type = (int)CurrencyType.Gold, + FinalValue = 0, + Value = CalcOutpostRewardAmount(battleData.credit, 3, 1, duration.TotalMinutes) + }); + + result.Currency.Add(new NetCurrencyData() + { + Type = (int)CurrencyType.UserExp, + FinalValue = 0, + Value = CalcOutpostRewardAmount(battleData.user_exp, 3, 1, duration.TotalMinutes) + }); + + return result; + } + + public static void RegisterRewardsForUser(User user, NetRewardData rewardData) + { + foreach (var item in rewardData.Currency) + { + user.AddCurrency((CurrencyType)item.Type, item.Value); + } + + // TODO: other things that are used by the function above + } + + internal static List GetOutpostTimeReward(User user) + { + List res = new List(); + + var goldBuff = new NetTimeReward() + { + UseId = 1, + ValuePerMinAfterBuff = GetOutpostRewardAmount(user, CurrencyType.Gold, 1, true) * 10000, + ValuePerMinBeforeBuff = GetOutpostRewardAmount(user, CurrencyType.Gold, 1, false) * 10000 + }; + + // goldBuff.Buffs.Add(new NetTimeRewardBuff() { Tid = 110101, FunctionType = 1, SourceType = OutpostBuffSourceType.OutpostBuffSourceTypeTacticAcademy, Value = 1000 }); + + var battleDataBuff = new NetTimeReward() + { + UseId = 2, + ValuePerMinAfterBuff = GetOutpostRewardAmount(user, CurrencyType.CharacterExp, 1, true) * 10000, + ValuePerMinBeforeBuff = GetOutpostRewardAmount(user, CurrencyType.CharacterExp, 1, false) * 10000 + }; + + var xpBuff = new NetTimeReward() + { + UseId = 3, + ValuePerMinAfterBuff = GetOutpostRewardAmount(user, CurrencyType.UserExp, 1, true) * 10000, + ValuePerMinBeforeBuff = GetOutpostRewardAmount(user, CurrencyType.UserExp, 1, false) * 10000 + }; + + var coredustBuff = new NetTimeReward() + { + UseId = 4, + ValuePerMinAfterBuff = GetOutpostRewardAmount(user, CurrencyType.CharacterExp2, 60, true) * 100, + ValuePerMinBeforeBuff = GetOutpostRewardAmount(user, CurrencyType.CharacterExp2, 60, false) * 100 + }; + + res.Add(battleDataBuff); + res.Add(goldBuff); + res.Add(xpBuff); + res.Add(coredustBuff); + + return res; + } } } \ No newline at end of file