diff --git a/EpinelPS/Database/JsonDb.cs b/EpinelPS/Database/JsonDb.cs index 46e4a78..8466baa 100644 --- a/EpinelPS/Database/JsonDb.cs +++ b/EpinelPS/Database/JsonDb.cs @@ -87,6 +87,13 @@ namespace EpinelPS.Database public int WipeoutCount = 0; public bool ClearedSimulationRoom = false; public int InterceptionTickets = 3; + public List CompletedDailyMissions = []; + public int DailyMissionPoints; + } + public class WeeklyResetableData + { + public List CompletedWeeklyMissions = []; + public int WeeklyMissionPoints; } public class OutpostBuffs { @@ -229,6 +236,7 @@ namespace EpinelPS.Database public int SynchroDeviceLevel = 200; public ResetableData ResetableData = new(); + public WeeklyResetableData WeeklyResetableData = new(); public List Items = new(); public List Characters = []; public NetWholeUserTeamData RepresentationTeamData = new(); @@ -272,6 +280,7 @@ namespace EpinelPS.Database public List BondInfo = []; public List Triggers = []; public int LastTriggerId = 1; + public List CompletedAchievements = []; // Event data public Dictionary EventInfo = new(); @@ -284,7 +293,7 @@ namespace EpinelPS.Database Id = LastTriggerId++, Type = type, ConditionId = conditionId, - CreatedAt = DateTime.Now.Ticks, + CreatedAt = DateTime.UtcNow.AddHours(9).Ticks, Value = value }; @@ -319,15 +328,11 @@ namespace EpinelPS.Database public void SetQuest(int tid, bool recievedReward) { - if (MainQuestData.ContainsKey(tid)) + if (!MainQuestData.TryAdd(tid, recievedReward)) { MainQuestData[tid] = recievedReward; return; } - else - { - MainQuestData.Add(tid, recievedReward); - } } public int GenerateUniqueItemId() diff --git a/EpinelPS/GameData/GameData.cs b/EpinelPS/GameData/GameData.cs index eaa980a..ef52d8b 100644 --- a/EpinelPS/GameData/GameData.cs +++ b/EpinelPS/GameData/GameData.cs @@ -65,7 +65,7 @@ namespace EpinelPS.StaticInfo public readonly Dictionary costTable = []; public readonly Dictionary mediasProductTable = []; public readonly Dictionary towerTable = []; - + public readonly Dictionary TriggerTable = []; public byte[] Sha256Hash; @@ -501,6 +501,12 @@ namespace EpinelPS.StaticInfo { this.towerTable.Add(obj.id, obj); } + + var triggerTable = await LoadZip("TriggerTable.json", progress); + foreach (var obj in triggerTable.records) + { + this.TriggerTable.Add(obj.id, obj); + } } public MainQuestCompletionRecord? GetMainQuestForStageClearCondition(int stage) diff --git a/EpinelPS/GameData/JsonStaticData.cs b/EpinelPS/GameData/JsonStaticData.cs index 878e354..70ae09b 100644 --- a/EpinelPS/GameData/JsonStaticData.cs +++ b/EpinelPS/GameData/JsonStaticData.cs @@ -658,4 +658,19 @@ { public List records = []; } + + public class TriggerRecord + { + public int id; + public int condition_id; + public int condition_value; + public int reward_id; + public int point_value; + public bool print_value; + public int before_trigger_id; + } + public class TriggerTable + { + public List records = []; + } } diff --git a/EpinelPS/LobbyServer/Character/LevelUp.cs b/EpinelPS/LobbyServer/Character/LevelUp.cs index 69296c8..13156a6 100644 --- a/EpinelPS/LobbyServer/Character/LevelUp.cs +++ b/EpinelPS/LobbyServer/Character/LevelUp.cs @@ -73,6 +73,8 @@ namespace EpinelPS.LobbyServer.Character break; } } + + user.AddTrigger(TriggerType.CharacterLevelUpCount, 1); JsonDb.Save(); await WriteDataAsync(response); diff --git a/EpinelPS/LobbyServer/Character/SkillLevelUp.cs b/EpinelPS/LobbyServer/Character/SkillLevelUp.cs index 8694f83..cfdc5e7 100644 --- a/EpinelPS/LobbyServer/Character/SkillLevelUp.cs +++ b/EpinelPS/LobbyServer/Character/SkillLevelUp.cs @@ -79,6 +79,11 @@ namespace EpinelPS.LobbyServer.Character newChar.Skill2Lv++; } + if (character.UltimateLevel == 10 && character.Skill1Lvl == 10 && character.Skill2Lvl == 10) + { + user.AddTrigger(TriggerType.CharacterSkillLevelMax, 1); + } + response.Character = newChar; JsonDb.Save(); diff --git a/EpinelPS/LobbyServer/Character/SynchroLevelUp.cs b/EpinelPS/LobbyServer/Character/SynchroLevelUp.cs index 4f18f33..92aee81 100644 --- a/EpinelPS/LobbyServer/Character/SynchroLevelUp.cs +++ b/EpinelPS/LobbyServer/Character/SynchroLevelUp.cs @@ -47,6 +47,8 @@ namespace EpinelPS.LobbyServer.Character } response.SynchroLv = user.SynchroDeviceLevel; + user.AddTrigger(TriggerType.CharacterLevelUpCount, 1); + JsonDb.Save(); await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Character/UpgradeCore.cs b/EpinelPS/LobbyServer/Character/UpgradeCore.cs index 88c9f5c..301494e 100644 --- a/EpinelPS/LobbyServer/Character/UpgradeCore.cs +++ b/EpinelPS/LobbyServer/Character/UpgradeCore.cs @@ -81,6 +81,11 @@ namespace EpinelPS.LobbyServer.Character } } + if (newCharacter.grade_core_id == 103 || newCharacter.grade_core_id == 11 || newCharacter.grade_core_id == 201) + { + user.AddTrigger(TriggerType.CharacterGradeMax, 1); + } + JsonDb.Save(); } } diff --git a/EpinelPS/LobbyServer/Gacha/ExecGacha.cs b/EpinelPS/LobbyServer/Gacha/ExecGacha.cs index 3b9c5d7..716d14d 100644 --- a/EpinelPS/LobbyServer/Gacha/ExecGacha.cs +++ b/EpinelPS/LobbyServer/Gacha/ExecGacha.cs @@ -201,10 +201,19 @@ namespace EpinelPS.LobbyServer.Gacha user.AddBadge(BadgeContents.BadgeContentsNikkeNew, characterData.name_code.ToString()); if (characterData.original_rare == "SSR" || characterData.original_rare == "SR") + { user.BondInfo.Add(new() { NameCode = characterData.name_code, Level = 1 }); + + if (characterData.original_rare == "SSR") + { + user.AddTrigger(TriggerType.ObtainCharacterSSR, 1); + } + } } response.Gacha.Add(gacha); + + user.AddTrigger(TriggerType.GachaCharacter, 1); } response.Reward.Currency.Add(new NetCurrencyData() { Type = (int)CurrencyType.SilverMileageTicket, Value = numberOfPulls }); @@ -212,6 +221,7 @@ namespace EpinelPS.LobbyServer.Gacha user.AddCurrency(CurrencyType.SilverMileageTicket, numberOfPulls); user.GachaTutorialPlayCount++; + JsonDb.Save(); await WriteDataAsync(response); diff --git a/EpinelPS/LobbyServer/Mission/GetAchievementRewardedData.cs b/EpinelPS/LobbyServer/Mission/GetAchievementRewardedData.cs index 8949c95..46a00e4 100644 --- a/EpinelPS/LobbyServer/Mission/GetAchievementRewardedData.cs +++ b/EpinelPS/LobbyServer/Mission/GetAchievementRewardedData.cs @@ -7,11 +7,12 @@ namespace EpinelPS.LobbyServer.Mission { protected override async Task HandleAsync() { - var req = await ReadData(); + await ReadData(); + var user = GetUser(); var response = new ResGetAchievementRewardedData(); - - // TODO + response.Ids.AddRange(user.CompletedAchievements); + await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Mission/ObtainAchievement.cs b/EpinelPS/LobbyServer/Mission/ObtainAchievement.cs new file mode 100644 index 0000000..a5ca168 --- /dev/null +++ b/EpinelPS/LobbyServer/Mission/ObtainAchievement.cs @@ -0,0 +1,36 @@ +using EpinelPS.StaticInfo; +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Mission +{ + [PacketPath("/mission/obtain/achievement")] + public class ObtainAchievement : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new ResObtainAchievementReward(); + + List rewards = new(); + + foreach (var item in req.TidList) + { + if (user.CompletedAchievements.Contains(item)) continue; + + if (!GameData.Instance.TriggerTable.TryGetValue(item, out TriggerRecord? key)) throw new Exception("unknown TID"); + + var rewardRecord = GameData.Instance.GetRewardTableEntry(key.reward_id) ?? throw new Exception("unable to lookup reward"); + + rewards.Add(RewardUtils.RegisterRewardsForUser(user, rewardRecord)); + + user.CompletedAchievements.Add(item); + } + + response.Reward = NetUtils.MergeRewards(rewards, user); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Mission/ObtainDaily.cs b/EpinelPS/LobbyServer/Mission/ObtainDaily.cs index fc6bd87..190f08c 100644 --- a/EpinelPS/LobbyServer/Mission/ObtainDaily.cs +++ b/EpinelPS/LobbyServer/Mission/ObtainDaily.cs @@ -1,3 +1,5 @@ +using EpinelPS.Database; +using EpinelPS.StaticInfo; using EpinelPS.Utils; namespace EpinelPS.LobbyServer.Mission @@ -8,10 +10,49 @@ namespace EpinelPS.LobbyServer.Mission protected override async Task HandleAsync() { var req = await ReadData(); + var user = GetUser(); var response = new ResObtainDailyMissionReward(); - // TODO + List rewards = new(); + + int total_points = 0; + + foreach (var item in req.TidList) + { + if (user.ResetableData.CompletedDailyMissions.Contains(item)) continue; + + if (!GameData.Instance.TriggerTable.TryGetValue(item, out TriggerRecord? key)) throw new Exception("unknown TID"); + + user.ResetableData.CompletedDailyMissions.Add(item); + + if (key.reward_id != 0) + { + // Actual reward + var rewardRecord = GameData.Instance.GetRewardTableEntry(key.reward_id) ?? throw new Exception("unable to lookup reward"); + rewards.Add(RewardUtils.RegisterRewardsForUser(user, rewardRecord)); + } + else + { + // Point reward + + var reward = new NetRewardData(); + + rewards.Add(reward); + + total_points += key.point_value; + } + } + + user.AddTrigger(TriggerType.PointRewardDaily, total_points); + user.ResetableData.DailyMissionPoints += total_points; + + response.Reward = NetUtils.MergeRewards(rewards, user); + response.EventBonusReward = new() { PassPoint = new() }; + response.Reward.PassPoint = new(); + + JsonDb.Save(); + await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Mission/ObtainWeekly.cs b/EpinelPS/LobbyServer/Mission/ObtainWeekly.cs new file mode 100644 index 0000000..981017e --- /dev/null +++ b/EpinelPS/LobbyServer/Mission/ObtainWeekly.cs @@ -0,0 +1,59 @@ +using EpinelPS.Database; +using EpinelPS.StaticInfo; +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Mission +{ + [PacketPath("/mission/obtain/weekly")] + public class ObtainWeekly : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new ResObtainWeeklyMissionReward(); + + List rewards = new(); + + int total_points = 0; + + foreach (var item in req.TidList) + { + if (user.WeeklyResetableData.CompletedWeeklyMissions.Contains(item)) continue; + + if (!GameData.Instance.TriggerTable.TryGetValue(item, out TriggerRecord? key)) throw new Exception("unknown TID"); + + user.WeeklyResetableData.CompletedWeeklyMissions.Add(item); + + if (key.reward_id != 0) + { + // Actual reward + var rewardRecord = GameData.Instance.GetRewardTableEntry(key.reward_id) ?? throw new Exception("unable to lookup reward"); + rewards.Add(RewardUtils.RegisterRewardsForUser(user, rewardRecord)); + } + else + { + // Point reward + + var reward = new NetRewardData(); + + rewards.Add(reward); + + total_points += key.point_value; + } + } + + user.AddTrigger(TriggerType.PointRewardWeekly, total_points); + user.WeeklyResetableData.WeeklyMissionPoints += total_points; + + response.Reward = NetUtils.MergeRewards(rewards, user); + response.EventBonusReward = new() { PassPoint = new() }; + response.Reward.PassPoint = new(); + + JsonDb.Save(); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Mission/Rewards/GetDailyRewards.cs b/EpinelPS/LobbyServer/Mission/Rewards/GetDailyRewards.cs index 3688346..85904d2 100644 --- a/EpinelPS/LobbyServer/Mission/Rewards/GetDailyRewards.cs +++ b/EpinelPS/LobbyServer/Mission/Rewards/GetDailyRewards.cs @@ -7,10 +7,11 @@ namespace EpinelPS.LobbyServer.Mission.Rewards { protected override async Task HandleAsync() { - var req = await ReadData(); + await ReadData(); + var user = GetUser(); - // TODO: implement var response = new ResGetDailyRewardedData(); + response.Ids.Add(user.ResetableData.CompletedDailyMissions); await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Mission/Rewards/GetWeeklyRewards.cs b/EpinelPS/LobbyServer/Mission/Rewards/GetWeeklyRewards.cs index a306e9f..604f39d 100644 --- a/EpinelPS/LobbyServer/Mission/Rewards/GetWeeklyRewards.cs +++ b/EpinelPS/LobbyServer/Mission/Rewards/GetWeeklyRewards.cs @@ -7,10 +7,11 @@ namespace EpinelPS.LobbyServer.Mission.Rewards { protected override async Task HandleAsync() { - var req = await ReadData(); + await ReadData(); + var user = GetUser(); - // TODO: implement var response = new ResGetWeeklyRewardedData(); + response.Ids.Add(user.WeeklyResetableData.CompletedWeeklyMissions); await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Outpost/DoWipeout.cs b/EpinelPS/LobbyServer/Outpost/DoWipeout.cs index 2d4c990..2601368 100644 --- a/EpinelPS/LobbyServer/Outpost/DoWipeout.cs +++ b/EpinelPS/LobbyServer/Outpost/DoWipeout.cs @@ -1,4 +1,5 @@ -using EpinelPS.Utils; +using EpinelPS.Database; +using EpinelPS.Utils; namespace EpinelPS.LobbyServer.Outpost { @@ -28,6 +29,10 @@ namespace EpinelPS.LobbyServer.Outpost response.Currencies.Add(new NetUserCurrencyData() { Type = (int)item.Key, Value = item.Value}); } + user.AddTrigger(StaticInfo.TriggerType.OutpostFastBattleReward, 1); + + JsonDb.Save(); + await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Outpost/ObtainOutpostReward.cs b/EpinelPS/LobbyServer/Outpost/ObtainOutpostReward.cs index 7f188ba..1cab61d 100644 --- a/EpinelPS/LobbyServer/Outpost/ObtainOutpostReward.cs +++ b/EpinelPS/LobbyServer/Outpost/ObtainOutpostReward.cs @@ -27,6 +27,8 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost user.BattleTime = DateTime.UtcNow; + user.AddTrigger(StaticInfo.TriggerType.OutpostBattleReward, 1); + JsonDb.Save(); await WriteDataAsync(response); diff --git a/EpinelPS/LobbyServer/Tower/ClearTower.cs b/EpinelPS/LobbyServer/Tower/ClearTower.cs index 75534fa..72002f4 100644 --- a/EpinelPS/LobbyServer/Tower/ClearTower.cs +++ b/EpinelPS/LobbyServer/Tower/ClearTower.cs @@ -42,6 +42,27 @@ namespace EpinelPS.LobbyServer.Tower user.TowerProgress[TowerType] = record.floor; } + if (record.type == "TETRA") + { + user.AddTrigger(TriggerType.TowerTetraClear, 1); + } + else if (record.type == "ELYSION") + { + user.AddTrigger(TriggerType.TowerElysionClear, 1); + } + else if (record.type == "MISSILIS") + { + user.AddTrigger(TriggerType.TowerMissilisClear, 1); + } + else if (record.type == "PILGRIM") + { + user.AddTrigger(TriggerType.TowerOverspecClear, 1); + } + else if (record.type == "ALL") + { + user.AddTrigger(TriggerType.TowerBasicClear, 1); + } + var reward = GameData.Instance.GetRewardTableEntry(record.reward_id) ?? throw new Exception("failed to get reward"); response.Reward = RewardUtils.RegisterRewardsForUser(user, reward); diff --git a/EpinelPS/LobbyServer/Tower/EnterTower.cs b/EpinelPS/LobbyServer/Tower/EnterTower.cs index 2944710..3154674 100644 --- a/EpinelPS/LobbyServer/Tower/EnterTower.cs +++ b/EpinelPS/LobbyServer/Tower/EnterTower.cs @@ -1,3 +1,4 @@ +using EpinelPS.Database; using EpinelPS.Utils; namespace EpinelPS.LobbyServer.Tower @@ -8,9 +9,14 @@ namespace EpinelPS.LobbyServer.Tower protected override async Task HandleAsync() { var req = await ReadData(); + var user = GetUser(); var response = new ResEnterTower(); + + user.AddTrigger(StaticInfo.TriggerType.TowerAllStart, 1); + JsonDb.Save(); + await WriteDataAsync(response); } } diff --git a/EpinelPS/Utils/NetUtils.cs b/EpinelPS/Utils/NetUtils.cs index 8290467..1bfcd33 100644 --- a/EpinelPS/Utils/NetUtils.cs +++ b/EpinelPS/Utils/NetUtils.cs @@ -132,10 +132,18 @@ namespace EpinelPS.Utils result.UserItems.Add(item); } + foreach (var item in reward.Point) + { + result.Point.Add(item); + } + foreach (var c in reward.Character) { Console.WriteLine("MergeRewards - TODO Character"); } + + if (reward.InfraCoreExp != null) + result.InfraCoreExp = reward.InfraCoreExp; } foreach (var c in currencyDict) @@ -175,7 +183,7 @@ namespace EpinelPS.Utils if (includeBoost) boost += CalculateBoostValueForOutpost(user, type); - switch(type) + switch (type) { case CurrencyType.CharacterExp2: value = battleData.character_exp2; diff --git a/EpinelPS/Utils/RewardUtils.cs b/EpinelPS/Utils/RewardUtils.cs index ba7056b..68f60ed 100644 --- a/EpinelPS/Utils/RewardUtils.cs +++ b/EpinelPS/Utils/RewardUtils.cs @@ -64,7 +64,7 @@ namespace EpinelPS.Utils foreach (var item in rewardData.rewards) { - if (item.reward_id != 0) + if (item.reward_id != 0 || !string.IsNullOrEmpty(item.reward_type)) { if (string.IsNullOrEmpty(item.reward_type) || string.IsNullOrWhiteSpace(item.reward_type)) { } else if (item.reward_type == "Currency") @@ -167,6 +167,15 @@ namespace EpinelPS.Utils user.JukeboxBgm.Add(item.reward_id); } } + else if (item.reward_type == "InfraCoreExp") + { + ret.InfraCoreExp = new NetIncreaseExpData() + { + BeforeLv = user.InfraCoreLvl, + BeforeExp = user.InfraCoreExp, + // TODO + }; + } else { Console.WriteLine("TODO: Reward type " + item.reward_type);