Skip to content

Commit

Permalink
Add new EXM
Browse files Browse the repository at this point in the history
- Implemented the quest "The Dragon Awakened".
- Fixed issues related to random loot rewards.
  • Loading branch information
pacampbell committed Sep 14, 2024
1 parent 1acbf12 commit bf47d37
Show file tree
Hide file tree
Showing 14 changed files with 613 additions and 150 deletions.
9 changes: 8 additions & 1 deletion Arrowgene.Ddon.GameServer/Characters/ExmManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,23 @@ public ulong ExtendTimer(ulong contentId, uint amountInSeconds)
}
}

public void CancelTimer(ulong contentId)
public (TimeSpan Elapsed, TimeSpan MaximumDuration) CancelTimer(ulong contentId)
{
lock (_ContentData)
{
if (_ContentTimers.ContainsKey(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);
}
}
}
Expand Down
51 changes: 28 additions & 23 deletions Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override void Handle(GameClient client, StructurePacket<C2SInstanceEnemyK

// The training room uses special handling to produce enemies that don't exist in the QuestState or InstanceEnemyManager.
// Return an empty response here to not break the rest of the handling.
if (_ignoreKillsInStageIds.Contains(stageId.Id) || packet.Structure.IsNoBattleReward)
if (_ignoreKillsInStageIds.Contains(stageId.Id))
{
client.Send(new S2CInstanceEnemyKillRes());
return;
Expand Down Expand Up @@ -78,28 +78,6 @@ public override void Handle(GameClient client, StructurePacket<C2SInstanceEnemyK
enemyKilled.IsKilled = true;
}

foreach (var partyMemberClient in client.Party.Clients)
{
// If the enemy is quest controlled, then either get from the quest loot drop, or the general one.
List<InstancedGatheringItem> 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<InstancedEnemy> group = client.Party.InstanceEnemyManager.GetInstancedEnemies(stageId);
bool groupDestroyed = group.Where(x => x.IsRequired).All(x => x.IsKilled);
if (groupDestroyed)
Expand Down Expand Up @@ -139,6 +117,33 @@ public override void Handle(GameClient client, StructurePacket<C2SInstanceEnemyK
KillNum = 1
});

if (packet.Structure.IsNoBattleReward)
{
return;
}

foreach (var partyMemberClient in client.Party.Clients)
{
// If the enemy is quest controlled, then either get from the quest loot drop, or the general one.
List<InstancedGatheringItem> 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions Arrowgene.Ddon.GameServer/Handler/QuestPlayEndHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
Expand Down
1 change: 0 additions & 1 deletion Arrowgene.Ddon.GameServer/Quests/GenericQuest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
30 changes: 24 additions & 6 deletions Arrowgene.Ddon.GameServer/Quests/Quest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,17 +381,35 @@ public virtual CDataTimeGainQuestList ToCDataTimeGainQuestList(uint step)
result.Restrictions.Unk5List.Add(new CDataCommonU8() { Value = 2 });
#endif

HashSet<uint> items = new HashSet<uint>();
// 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
});
}
}
}

Expand Down
33 changes: 24 additions & 9 deletions Arrowgene.Ddon.Shared/AssetReader/QuestAssetDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<LootPoolItem>()
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
Expand Down Expand Up @@ -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))
{
Expand Down
84 changes: 0 additions & 84 deletions Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit bf47d37

Please sign in to comment.