Skip to content

Commit 1a79c02

Browse files
committed
feat: Mutually Excluive Quests
Added a mechanism to define lists of world quests where only one can be rolled from at a time in the party.
1 parent ecfeff6 commit 1a79c02

2 files changed

Lines changed: 90 additions & 1 deletion

File tree

Arrowgene.Ddon.GameServer/Quests/QuestStateManager.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public abstract class QuestStateManager
177177
protected Dictionary<uint, QuestState> ActiveQuests { get; set; }
178178
private Dictionary<StageLayoutId, HashSet<uint>> QuestLookupTable { get; set; }
179179
private List<QuestId> CompletedWorldQuests { get; set; }
180-
private Dictionary<QuestAreaId, HashSet<uint>> RolledInstanceWorldQuests { get; set; }
180+
protected Dictionary<QuestAreaId, HashSet<uint>> RolledInstanceWorldQuests { get; set; }
181181

182182
// Deferred Generic Work to be triggered at various points
183183
public Dictionary<QuestProgressWorkType, List<QuestProgressWork>> ProgressWork { get; set; }
@@ -832,10 +832,70 @@ public SharedQuestStateManager(PartyGroup party, DdonGameServer server)
832832
{
833833
this.Party = party;
834834
this.Server = server;
835+
EnforceMutualExclusion();
836+
}
837+
838+
private Dictionary<QuestId, int> BuildMutualExclusionLookup()
839+
{
840+
var lookup = new Dictionary<QuestId, int>();
841+
var groups = Server.GameSettings.GameServerSettings.MutuallyExclusiveWorldQuestGroups;
842+
for (int i = 0; i < groups.Count; i++)
843+
{
844+
foreach (var questId in groups[i])
845+
{
846+
lookup[(QuestId)questId] = i;
847+
}
848+
}
849+
return lookup;
850+
}
851+
852+
private void EnforceMutualExclusion()
853+
{
854+
var lookup = BuildMutualExclusionLookup();
855+
var rolledGroups = new HashSet<int>();
856+
857+
lock (ActiveQuests)
858+
{
859+
foreach (var scheduleIds in RolledInstanceWorldQuests.Values)
860+
{
861+
var toRemove = new List<uint>();
862+
foreach (var scheduleId in scheduleIds)
863+
{
864+
var quest = QuestManager.GetQuestByScheduleId(scheduleId);
865+
if (quest != null && lookup.TryGetValue(quest.QuestId, out int groupIndex))
866+
{
867+
if (!rolledGroups.Add(groupIndex))
868+
{
869+
toRemove.Add(scheduleId);
870+
}
871+
}
872+
}
873+
foreach (var scheduleId in toRemove)
874+
{
875+
scheduleIds.Remove(scheduleId);
876+
}
877+
}
878+
}
835879
}
836880

837881
protected override Quest RollQuestVariant(QuestId questId)
838882
{
883+
var lookup = BuildMutualExclusionLookup();
884+
if (lookup.TryGetValue(questId, out int groupIndex))
885+
{
886+
var groups = Server.GameSettings.GameServerSettings.MutuallyExclusiveWorldQuestGroups;
887+
foreach (var groupQuestId in groups[groupIndex])
888+
{
889+
if ((QuestId)groupQuestId == questId) continue;
890+
foreach (var scheduleIds in RolledInstanceWorldQuests.Values)
891+
{
892+
if (scheduleIds.Any(sid => QuestManager.GetQuestByScheduleId(sid)?.QuestId == (QuestId)groupQuestId))
893+
{
894+
return null;
895+
}
896+
}
897+
}
898+
}
839899
return RollEligibleQuestVariant(questId, Party.Leader?.Client.Character);
840900
}
841901

Arrowgene.Ddon.Server/Settings/GameServerSettings.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,35 @@ public uint AdventureGuideMaxQuestList
257257
}
258258
private const uint _AdventureGuideMaxQuestList = 50;
259259

260+
/// <summary>
261+
/// Groups of mutually exclusive world quest IDs. When rolling world quests for a party,
262+
/// at most one quest from each group will be selected at a time. Use this to prevent
263+
/// conflicting quests from appearing simultaneously. Quest IDs should be specified as
264+
/// uint values (e.g. 21000079).
265+
/// </summary>
266+
[DefaultValue(
267+
"new List<List<uint>>\n" +
268+
"{\n" +
269+
" new List<uint> { 21000079, 21000089 },\n" +
270+
" new List<uint> { 20995009, 21000008 },\n" +
271+
"}"
272+
)]
273+
public List<List<uint>> MutuallyExclusiveWorldQuestGroups
274+
{
275+
set
276+
{
277+
SetSetting("MutuallyExclusiveWorldQuestGroups", value);
278+
}
279+
get
280+
{
281+
return TryGetSetting("MutuallyExclusiveWorldQuestGroups", new List<List<uint>>
282+
{
283+
new List<uint> { 21000079, 21000089 },
284+
new List<uint> { 20995009, 21000008 },
285+
});
286+
}
287+
}
288+
260289
/// <summary>
261290
/// Uses the automatic exp calculation system for all enemies instead of just using the
262291
/// ones marked in quest files.

0 commit comments

Comments
 (0)