From bf47d37024022a2475168548b378f9994b239b6c Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 14 Sep 2024 01:11:31 -0400 Subject: [PATCH] Add new EXM - Implemented the quest "The Dragon Awakened". - Fixed issues related to random loot rewards. --- .../Characters/ExmManager.cs | 9 +- .../Handler/InstanceEnemyKillHandler.cs | 51 +- .../Handler/QuestGetRewardBoxItemHandler.cs | 3 +- .../Handler/QuestPlayEndHandler.cs | 7 +- .../Quests/GenericQuest.cs | 1 - Arrowgene.Ddon.GameServer/Quests/Quest.cs | 30 +- .../AssetReader/QuestAssetDeserializer.cs | 33 +- .../Files/Assets/EnemySpawn.json | 84 --- .../Files/Assets/quests/q00000006.json | 40 +- .../Files/Assets/quests/q50300010.json | 484 ++++++++++++++++++ .../Model/Quest/QuestLootDistribution.cs | 14 + .../Model/Quest/QuestMissionParams.cs | 3 +- .../Model/Quest/QuestRewardType.cs | 2 +- .../Model/Quest/QuestRewards.cs | 2 + 14 files changed, 613 insertions(+), 150 deletions(-) create mode 100644 Arrowgene.Ddon.Shared/Files/Assets/quests/q50300010.json create mode 100644 Arrowgene.Ddon.Shared/Model/Quest/QuestLootDistribution.cs diff --git a/Arrowgene.Ddon.GameServer/Characters/ExmManager.cs b/Arrowgene.Ddon.GameServer/Characters/ExmManager.cs index 3505062b1..00ee11d82 100644 --- a/Arrowgene.Ddon.GameServer/Characters/ExmManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/ExmManager.cs @@ -324,7 +324,7 @@ public ulong ExtendTimer(ulong contentId, uint amountInSeconds) } } - public void CancelTimer(ulong contentId) + public (TimeSpan Elapsed, TimeSpan MaximumDuration) CancelTimer(ulong contentId) { lock (_ContentData) { @@ -332,8 +332,15 @@ public void CancelTimer(ulong contentId) { Logger.Info($"Canceling timer for ContentId={contentId}"); _ContentTimers[contentId].Timer.Dispose(); + + var timerState = _ContentTimers[contentId]; + + TimeSpan elapsed = DateTime.Now.Subtract(timerState.TimeStart); + var results = (elapsed, timerState.Duration); _ContentTimers.Remove(contentId); + return results; } + return (TimeSpan.Zero, TimeSpan.Zero); } } } diff --git a/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs b/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs index 1dd2fec5b..1904cd9c5 100644 --- a/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs @@ -38,7 +38,7 @@ public override void Handle(GameClient client, StructurePacket instancedGatheringItems = IsQuestControlled ? - partyMemberClient.InstanceQuestDropManager.GenerateEnemyLoot(quest, enemyKilled, packet.Structure.LayoutId, packet.Structure.SetId) : - partyMemberClient.InstanceDropItemManager.GetAssets(layoutId, (int)packet.Structure.SetId); - - // If the roll was unlucky, there is a chance that no bag will show. - if (instancedGatheringItems.Count > 0) - { - partyMemberClient.Send(new S2CInstancePopDropItemNtc() - { - LayoutId = packet.Structure.LayoutId, - SetId = packet.Structure.SetId, - MdlType = enemyKilled.DropsTable.MdlType, - PosX = packet.Structure.DropPosX, - PosY = packet.Structure.DropPosY, - PosZ = packet.Structure.DropPosZ - }); - } - } - List group = client.Party.InstanceEnemyManager.GetInstancedEnemies(stageId); bool groupDestroyed = group.Where(x => x.IsRequired).All(x => x.IsKilled); if (groupDestroyed) @@ -139,6 +117,33 @@ public override void Handle(GameClient client, StructurePacket instancedGatheringItems = IsQuestControlled ? + partyMemberClient.InstanceQuestDropManager.GenerateEnemyLoot(quest, enemyKilled, packet.Structure.LayoutId, packet.Structure.SetId) : + partyMemberClient.InstanceDropItemManager.GetAssets(layoutId, (int)packet.Structure.SetId); + + // If the roll was unlucky, there is a chance that no bag will show. + if (instancedGatheringItems.Count > 0) + { + partyMemberClient.Send(new S2CInstancePopDropItemNtc() + { + LayoutId = packet.Structure.LayoutId, + SetId = packet.Structure.SetId, + MdlType = enemyKilled.DropsTable.MdlType, + PosX = packet.Structure.DropPosX, + PosY = packet.Structure.DropPosY, + PosZ = packet.Structure.DropPosZ + }); + } + } + foreach (PartyMember member in client.Party.Members) { if (member.JoinState != JoinState.On) continue; // Only fully joined members get rewards. diff --git a/Arrowgene.Ddon.GameServer/Handler/QuestGetRewardBoxItemHandler.cs b/Arrowgene.Ddon.GameServer/Handler/QuestGetRewardBoxItemHandler.cs index f5c167fa1..4bb4d15d3 100644 --- a/Arrowgene.Ddon.GameServer/Handler/QuestGetRewardBoxItemHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/QuestGetRewardBoxItemHandler.cs @@ -47,7 +47,6 @@ public override S2CQuestGetRewardBoxItemRes Handle(GameClient client, C2SQuestGe UpdateType = 0 }; - foreach (var boxReward in packet.GetRewardBoxItemList) { var reward = rewards.Single(x => x.UID == boxReward.UID); @@ -57,7 +56,7 @@ public override S2CQuestGetRewardBoxItemRes Handle(GameClient client, C2SQuestGe var result = Server.WalletManager.AddToWallet(client.Character, walletType, amount); updateCharacterItemNtc.UpdateWalletList.Add(result); } - else + else if (reward.Num > 0) { var result = Server.ItemManager.AddItem(Server, client.Character, false, reward.ItemId, reward.Num); updateCharacterItemNtc.UpdateItemList.AddRange(result); diff --git a/Arrowgene.Ddon.GameServer/Handler/QuestPlayEndHandler.cs b/Arrowgene.Ddon.GameServer/Handler/QuestPlayEndHandler.cs index e2c568879..d31fada78 100644 --- a/Arrowgene.Ddon.GameServer/Handler/QuestPlayEndHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/QuestPlayEndHandler.cs @@ -2,8 +2,10 @@ using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; +using Arrowgene.Ddon.Shared.Model.Quest; using Arrowgene.Ddon.Shared.Network; using Arrowgene.Logging; +using System.Collections.Generic; namespace Arrowgene.Ddon.GameServer.Handler { @@ -30,12 +32,13 @@ public QuestPlayEndHandler(DdonGameServer server) : base(server) public override S2CQuestPlayEndRes Handle(GameClient client, C2SQuestPlayEndReq request) { var contentId = client.Party.ContentId; - Server.ExmManager.CancelTimer(contentId); + var timeData = Server.ExmManager.CancelTimer(contentId); var quest = Server.ExmManager.GetQuestForContent(contentId); - + var ntc = new S2CQuestPlayEndNtc(); ntc.ContentsPlayEnd.RewardItemDetailList = quest.ToCDataTimeGainQuestList(0).RewardItemDetailList; + ntc.ContentsPlayEnd.PlayTimeMillSec = (uint) timeData.Elapsed.Milliseconds; client.Party.SendToAll(ntc); client.Party.ContentInProgress = false; diff --git a/Arrowgene.Ddon.GameServer/Quests/GenericQuest.cs b/Arrowgene.Ddon.GameServer/Quests/GenericQuest.cs index 0f1327354..a1d4edebb 100644 --- a/Arrowgene.Ddon.GameServer/Quests/GenericQuest.cs +++ b/Arrowgene.Ddon.GameServer/Quests/GenericQuest.cs @@ -35,7 +35,6 @@ public static GenericQuest FromAsset(QuestAssetData questAsset) quest.StageId = questAsset.StageId; quest.MissionParams = questAsset.MissionParams; - foreach (var pointReward in questAsset.PointRewards) { quest.ExpRewards.Add(new CDataQuestExp() diff --git a/Arrowgene.Ddon.GameServer/Quests/Quest.cs b/Arrowgene.Ddon.GameServer/Quests/Quest.cs index 4b7e0b68c..cfd92238f 100644 --- a/Arrowgene.Ddon.GameServer/Quests/Quest.cs +++ b/Arrowgene.Ddon.GameServer/Quests/Quest.cs @@ -381,17 +381,35 @@ public virtual CDataTimeGainQuestList ToCDataTimeGainQuestList(uint step) result.Restrictions.Unk5List.Add(new CDataCommonU8() { Value = 2 }); #endif + HashSet items = new HashSet(); // Rewards for EXM seem to show up independently foreach (var reward in result.Param.FixedRewardItemList) { - for (var i = 0; i < reward.Num; i++) + if (MissionParams.LootDistribution == QuestLootDistribution.TimeBased) { - result.RewardItemDetailList.Add(new CDataRewardItemDetail() + if (!items.Contains(reward.ItemId)) { - ItemId = reward.ItemId, - Num = 1, - Type = 12 - }); + // Show 1 of each item as exact value is unknown + result.RewardItemDetailList.Add(new CDataRewardItemDetail() + { + ItemId = reward.ItemId, + Num = 1, + Type = 12 + }); + items.Add(reward.ItemId); + } + } + else + { + for (var i = 0; i < reward.Num; i++) + { + result.RewardItemDetailList.Add(new CDataRewardItemDetail() + { + ItemId = reward.ItemId, + Num = 1, + Type = 12 + }); + } } } diff --git a/Arrowgene.Ddon.Shared/AssetReader/QuestAssetDeserializer.cs b/Arrowgene.Ddon.Shared/AssetReader/QuestAssetDeserializer.cs index 54c9854bd..cb69806ea 100644 --- a/Arrowgene.Ddon.Shared/AssetReader/QuestAssetDeserializer.cs +++ b/Arrowgene.Ddon.Shared/AssetReader/QuestAssetDeserializer.cs @@ -255,6 +255,7 @@ private void ParseRewards(QuestAssetData assetData, JsonElement quest) case "fixed": case "random": case "select": + case "TimeBased": if (!Enum.TryParse(reward.GetProperty("type").GetString(), true, out QuestRewardType questRewardType)) { continue; @@ -297,17 +298,14 @@ private void ParseRewards(QuestAssetData assetData, JsonElement quest) } else if (questRewardType == QuestRewardType.Fixed) { - var item = reward.GetProperty("loot_pool").EnumerateArray().ToList()[0]; - rewardItem = new QuestFixedRewardItem() + rewardItem = new QuestFixedRewardItem(); + foreach (var item in reward.GetProperty("loot_pool").EnumerateArray()) { - LootPool = new List() + rewardItem.LootPool.Add(new FixedLootPoolItem() { - new FixedLootPoolItem() - { - ItemId = item.GetProperty("item_id").GetUInt32(), - Num = item.GetProperty("num").GetUInt16(), - } - } + ItemId = item.GetProperty("item_id").GetUInt32(), + Num = item.GetProperty("num").GetUInt16(), + }); }; } else @@ -868,6 +866,23 @@ private bool ParseMissionParams(QuestAssetData assetData, JsonElement jMissionPa assetData.MissionParams.SortieMinimum = jMinimumMembers.GetUInt32(); } + assetData.MissionParams.SortieMaximum = 4; + if (jMissionParams.TryGetProperty("minimum_members", out JsonElement jMaximumMembers)) + { + assetData.MissionParams.SortieMaximum = jMaximumMembers.GetUInt32(); + } + + assetData.MissionParams.LootDistribution = QuestLootDistribution.Normal; + if (jMissionParams.TryGetProperty("loot_distribution", out JsonElement jLootDistribution)) + { + if (!Enum.TryParse(jLootDistribution.GetString(), true, out QuestLootDistribution lootDistribution)) + { + Logger.Error("Invalid 'loot_distribution' from ExtremeMission config."); + return false; + } + assetData.MissionParams.LootDistribution = lootDistribution; + } + assetData.MissionParams.PlaytimeInSeconds = 1200; if (jMissionParams.TryGetProperty("playtime", out JsonElement jPlaytime)) { diff --git a/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json b/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json index eb38c8b3e..3737869ff 100644 --- a/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json +++ b/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json @@ -52902,34 +52902,6 @@ 41, "00:00,23:59" ], - [ - 380, - 0, - 3, - 0, - "0x080400", - 2298, - 0, - 100, - 75, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - true, - true, - false, - false, - 0, - 0, - 607000, - 409, - "00:00,23:59" - ], [ 455, 0, @@ -229554,34 +229526,6 @@ 7, "00:00,23:59" ], - [ - 381, - 0, - 2, - 0, - "0x010100", - 2298, - 0, - 100, - 10, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - false, - false, - false, - false, - 0, - 0, - 136, - 7, - "00:00,23:59" - ], [ 442, 0, @@ -240586,34 +240530,6 @@ -1, "00:00,23:59" ], - [ - 620, - 0, - 9, - 0, - "0x015603", - 2659, - 0, - 100, - 48, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - true, - true, - false, - false, - 0, - 0, - 10550, - 341, - "00:00,23:59" - ], [ 616, 0, diff --git a/Arrowgene.Ddon.Shared/Files/Assets/quests/q00000006.json b/Arrowgene.Ddon.Shared/Files/Assets/quests/q00000006.json index b89c2f2b4..bc3b83c2a 100644 --- a/Arrowgene.Ddon.Shared/Files/Assets/quests/q00000006.json +++ b/Arrowgene.Ddon.Shared/Files/Assets/quests/q00000006.json @@ -50,7 +50,7 @@ "id": 67, "group_id": 2 }, - "placement_type": "Manual", + "placement_type": "Manual", "enemies": [ { "enemy_id": "0x015040", @@ -58,39 +58,39 @@ "exp": 4660, "named_enemy_params_id": 141, "is_boss": true, - "index": 6 + "index": 6 }, { "enemy_id": "0x010200", "level": 18, - "named_enemy_params_id": 142, - "index": 3, + "named_enemy_params_id": 142, + "index": 3, "exp": 64, - "index": 4 + "index": 4 }, - { + { "enemy_id": "0x010200", "level": 18, - "named_enemy_params_id": 142, - "index": 3, + "named_enemy_params_id": 142, + "index": 3, "exp": 64, - "index": 10 + "index": 10 }, - { + { "enemy_id": "0x010200", "level": 18, - "named_enemy_params_id": 142, - "index": 3, + "named_enemy_params_id": 142, + "index": 3, "exp": 64, - "index": 11 + "index": 11 }, - { + { "enemy_id": "0x010200", "level": 18, - "named_enemy_params_id": 142, - "index": 3, + "named_enemy_params_id": 142, + "index": 3, "exp": 64, - "index": 12 + "index": 12 } ] } @@ -132,7 +132,7 @@ "stage_id": { "id": 1 }, - "flags": [ + "flags": [ {"type": "QstLayout", "action": "Clear", "value": 977, "comment": "Spawns Gerd and the White Knights outside Glowworm Cave"} ], "event_id": 20 @@ -155,7 +155,7 @@ "stage_id": { "id": 67 }, - "jump_stage_id": { + "jump_stage_id": { "id": 67 }, "start_pos_no": 2, @@ -176,7 +176,7 @@ }, "event_id": 10 }, - { + { "type": "PlayEvent", "stage_id": { "id": 67 diff --git a/Arrowgene.Ddon.Shared/Files/Assets/quests/q50300010.json b/Arrowgene.Ddon.Shared/Files/Assets/quests/q50300010.json new file mode 100644 index 000000000..2cffb05c7 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Files/Assets/quests/q50300010.json @@ -0,0 +1,484 @@ +{ + "state_machine": "GenericStateMachine", + "type": "ExtremeMission", + "comment": "The Dragon Awakened (Grand Mission)", + "quest_id": 50300010, + "base_level": 80, + "minimum_item_rank": 0, + "discoverable": false, + "mission_params": { + "group": 9, + "minimum_members": 1, + "maximum_members": 8, + "playtime": 900, + "solo_only": true, + "max_pawns": 3, + "loot_distribution": "TimeBased", + "phase_groups": [] + }, + "order_conditions": [ + ], + "rewards": [ + { + "type": "random", + "loot_pool": [ + { + "item_id": 15998, + "num": 1, + "chance": 0.35 + }, + { + "item_id": 15998, + "num": 2, + "chance": 0.25 + }, + { + "item_id": 15998, + "num": 4, + "chance": 0.20 + }, + { + "item_id": 15998, + "num": 12, + "chance": 0.15 + }, + { + "item_id": 15998, + "num": 16, + "chance": 0.10 + }, + { + "item_id": 15998, + "num": 20, + "chance": 0.05 + } + ] + }, + { + "type": "random", + "loot_pool": [ + { + "item_id": 15999, + "num": 0, + "chance": 0.35 + }, + { + "item_id": 15999, + "num": 1, + "chance": 0.20 + }, + { + "item_id": 15999, + "num": 2, + "chance": 0.25 + }, + { + "item_id": 15999, + "num": 4, + "chance": 0.20 + }, + { + "item_id": 15999, + "num": 8, + "chance": 0.15 + }, + { + "item_id": 15999, + "num": 10, + "chance": 0.05 + } + ] + }, + { + "type": "random", + "loot_pool": [ + { + "item_id": 16000, + "num": 0, + "chance": 0.60 + }, + { + "item_id": 16000, + "num": 1, + "chance": 0.20 + }, + { + "item_id": 16000, + "num": 2, + "chance": 0.15 + }, + { + "item_id": 16000, + "num": 3, + "chance": 0.05 + } + ] + } + ], + "enemy_groups" : [ + { + "comment": "Boss", + "stage_id": { + "id": 381, + "group_id": 0 + }, + "enemies": [ + { + "comment": "Spirit Dragon Willmia", + "enemy_id": "0x080400", + "level": 80, + "exp": 0, + "is_boss": true, + "named_enemy_params_id": 1707 + } + ] + }, + { + "comment": "Adds (Towers)", + "stage_id": { + "id": 381, + "group_id": 2 + }, + "starting_index": 4, + "enemies": [ + { + "comment": "Dragon Crystal of Evil Sealing", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1710, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Evil Sealing", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1710, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + } + ] + }, + { + "comment": "Adds (Towers)", + "stage_id": { + "id": 381, + "group_id": 2 + }, + "placement_type": "Manual", + "enemies": [ + { + "comment": "Dragon Crystal of Evil Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 11, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Evil Sealing", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 12, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1710, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 15, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sealing", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 16, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1710, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 17, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 18, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 19, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sealing", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 20, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1710, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + }, + { + "comment": "Dragon Crystal of Power Sapping", + "enemy_id": "0x030104", + "level": 80, + "exp": 0, + "index": 21, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1711, + "start_think_tbl_no": 2, + "is_manual_set": true, + "is_required": false, + "repop_count": 50, + "repop_wait_second": 0 + } + ] + }, + { + "comment": "Adds (Gimick)", + "stage_id": { + "id": 381, + "group_id": 1 + }, + "enemies": [ + { + "comment": "Memory of Sighs", + "enemy_id": "0x030105", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1701, + "repop_count": 50, + "repop_wait_second": 45 + }, + { + "comment": "Memory of Sighs", + "enemy_id": "0x030105", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1701, + "repop_count": 50, + "repop_wait_second": 45 + } + ] + }, + { + "comment": "Adds (Gimick)", + "stage_id": { + "id": 381, + "group_id": 1 + }, + "starting_index": 2, + "enemies": [ + { + "comment": "Memory of Sighs", + "enemy_id": "0x030105", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1701, + "repop_count": 50, + "repop_wait_second": 45 + }, + { + "comment": "Memory of Sighs", + "enemy_id": "0x030105", + "level": 80, + "exp": 0, + "enemy_target_types_id": 1, + "named_enemy_params_id": 1701, + "repop_count": 50, + "repop_wait_second": 45 + } + ] + } + ], + "processes": [ + { + "blocks": [ + { + "type": "IsGatherPartyInStage", + "stage_id": { + "id": 381 + } + }, + { + "type": "KillGroup", + "announce_type": "Start", + "groups": [0] + }, + { + "type": "PlayEvent", + "stage_id": { + "id": 381 + }, + "event_id": 5 + } + ] + }, + { + "blocks": [ + { + "type": "Raw", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 80} + ] + }, + { + "comment": "Spawn Crystals", + "type": "SpawnGroup", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 70} + ], + "groups": [3] + }, + { + "type": "DestroyGroup", + "groups": [3] + }, + { + "type": "Raw", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 40} + ] + }, + { + "comment": "Spawn Crystals", + "type": "SpawnGroup", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 30} + ], + "groups": [4] + }, + { + "type": "DestroyGroup", + "groups": [4] + } + ] + }, + { + "blocks": [ + { + "type": "Raw", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 55} + ] + }, + { + "comment": "Spawn Towers", + "type": "KillGroup", + "groups": [1] + }, + { + "type": "Raw", + "check_commands": [ + {"type": "EmHpLess", "Param1": 436, "Param2": 0, "Param3": 0, "Param4": 20} + ] + }, + { + "comment": "Spawn Towers", + "type": "KillGroup", + "groups": [2] + } + ] + } + ] +} diff --git a/Arrowgene.Ddon.Shared/Model/Quest/QuestLootDistribution.cs b/Arrowgene.Ddon.Shared/Model/Quest/QuestLootDistribution.cs new file mode 100644 index 000000000..d66d08c19 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Model/Quest/QuestLootDistribution.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Arrowgene.Ddon.Shared.Model.Quest +{ + public enum QuestLootDistribution + { + Normal, + TimeBased + } +} diff --git a/Arrowgene.Ddon.Shared/Model/Quest/QuestMissionParams.cs b/Arrowgene.Ddon.Shared/Model/Quest/QuestMissionParams.cs index f82d4c264..17ceb21b4 100644 --- a/Arrowgene.Ddon.Shared/Model/Quest/QuestMissionParams.cs +++ b/Arrowgene.Ddon.Shared/Model/Quest/QuestMissionParams.cs @@ -16,14 +16,15 @@ public QuestMissionParams() } public uint SortieMinimum { get; set; } + public uint SortieMaximum { get; set; } public uint PlaytimeInSeconds { get; set; } public bool IsSolo { get; set; } public uint MaxPawns { get; set; } // public bool SupportPawnAllowed { get; set; } Is in symbol but doesn't seem to work? public bool ArmorAllowed { get; set; } public bool JewelryAllowed { get; set; } - public uint Group { get; set; } public List QuestPhaseGroupIdList { get; set; } + public QuestLootDistribution LootDistribution { get; set; } } } diff --git a/Arrowgene.Ddon.Shared/Model/Quest/QuestRewardType.cs b/Arrowgene.Ddon.Shared/Model/Quest/QuestRewardType.cs index 1f56a4a8b..9c21a4195 100644 --- a/Arrowgene.Ddon.Shared/Model/Quest/QuestRewardType.cs +++ b/Arrowgene.Ddon.Shared/Model/Quest/QuestRewardType.cs @@ -23,6 +23,6 @@ public enum QuestRewardType : uint FixedSecond = 12, FixedMemberFirst = 13, ProgressBonus = 14, - Num = 15 + Num = 15, } } diff --git a/Arrowgene.Ddon.Shared/Model/Quest/QuestRewards.cs b/Arrowgene.Ddon.Shared/Model/Quest/QuestRewards.cs index 928637ae2..e54db6719 100644 --- a/Arrowgene.Ddon.Shared/Model/Quest/QuestRewards.cs +++ b/Arrowgene.Ddon.Shared/Model/Quest/QuestRewards.cs @@ -118,6 +118,7 @@ public CDataRewardBoxItem AsCDataRewardBoxItem() var item = LootPool[ItemIndex]; return new CDataRewardBoxItem() { + UID = item.GetUID(), ItemId = item.ItemId, Num = item.Num, Type = (byte)RewardType @@ -129,6 +130,7 @@ public CDataRewardBoxItem AsCDataRewardBoxItem(int index) var item = LootPool[index]; return new CDataRewardBoxItem() { + UID = item.GetUID(), ItemId = item.ItemId, Num = item.Num, Type = (byte)RewardType