@@ -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
0 commit comments