@@ -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 ; }
@@ -529,6 +529,24 @@ public HashSet<uint> AreaQuests(QuestAreaId areaId)
529529 }
530530 }
531531
532+ protected virtual uint GetEffectiveAreaRank ( Character character , QuestAreaId areaId )
533+ {
534+ return character . AreaRanks . TryGetValue ( areaId , out var rank ) ? rank . Rank : 0 ;
535+ }
536+
537+ protected Quest RollEligibleQuestVariant ( QuestId questId , Character leaderCharacter )
538+ {
539+ var candidates = QuestManager . GetQuestScheduleIdsForQuestId ( questId )
540+ . Select ( id => QuestManager . GetQuestByScheduleId ( id ) )
541+ . Where ( q => q != null && ! q . OrderConditions . Any ( c => c . Type == QuestOrderConditionType . AreaRank
542+ && ( leaderCharacter == null
543+ || GetEffectiveAreaRank ( leaderCharacter , ( QuestAreaId ) c . Param01 ) < ( uint ) c . Param02 ) ) )
544+ . ToList ( ) ;
545+
546+ if ( candidates . Count == 0 ) return null ;
547+ return candidates [ Random . Shared . Next ( candidates . Count ) ] ;
548+ }
549+
532550 public QuestState GetQuestState ( uint questScheduleId )
533551 {
534552 lock ( ActiveQuests )
@@ -707,14 +725,24 @@ protected PacketQueue SendWalletRewards(DdonGameServer server, GameClient client
707725 return packets ;
708726 }
709727
728+ public virtual void EnforceInitialPoolEligibility ( ) { }
729+
730+ protected virtual Quest RollQuestVariant ( QuestId questId )
731+ {
732+ return QuestManager . RollQuestForQuestId ( questId ) ;
733+ }
734+
710735 public void ResetInstance ( )
711736 {
712737 lock ( ActiveQuests )
713738 {
714739 foreach ( var questId in CompletedWorldQuests )
715740 {
716- var quest = QuestManager . RollQuestForQuestId ( questId ) ;
717- RolledInstanceWorldQuests [ quest . QuestAreaId ] . Add ( quest . QuestScheduleId ) ;
741+ var quest = RollQuestVariant ( questId ) ;
742+ if ( quest != null )
743+ {
744+ RolledInstanceWorldQuests [ quest . QuestAreaId ] . Add ( quest . QuestScheduleId ) ;
745+ }
718746 }
719747 CompletedWorldQuests . Clear ( ) ;
720748 }
@@ -812,6 +840,45 @@ public SharedQuestStateManager(PartyGroup party, DdonGameServer server)
812840 this . Server = server ;
813841 }
814842
843+ public override void EnforceInitialPoolEligibility ( )
844+ {
845+ var leaderCharacter = Party . Leader ? . Client . Character ;
846+ if ( leaderCharacter == null ) return ;
847+
848+ lock ( ActiveQuests )
849+ {
850+ foreach ( var ( areaId , scheduleIds ) in RolledInstanceWorldQuests )
851+ {
852+ var ineligible = scheduleIds
853+ . Select ( id => QuestManager . GetQuestByScheduleId ( id ) )
854+ . Where ( q => q != null && q . OrderConditions . Any ( c => c . Type == QuestOrderConditionType . AreaRank
855+ && GetEffectiveAreaRank ( leaderCharacter , ( QuestAreaId ) c . Param01 ) < ( uint ) c . Param02 ) )
856+ . ToList ( ) ;
857+
858+ foreach ( var quest in ineligible )
859+ {
860+ scheduleIds . Remove ( quest . QuestScheduleId ) ;
861+ var replacement = RollEligibleQuestVariant ( quest . QuestId , leaderCharacter ) ;
862+ if ( replacement != null )
863+ {
864+ scheduleIds . Add ( replacement . QuestScheduleId ) ;
865+ }
866+ }
867+ }
868+ }
869+ }
870+
871+ protected override uint GetEffectiveAreaRank ( Character character , QuestAreaId areaId )
872+ {
873+ if ( ! character . AreaRanks . ContainsKey ( areaId ) ) return 0 ;
874+ return Server . AreaRankManager . GetEffectiveRank ( character , areaId ) ;
875+ }
876+
877+ protected override Quest RollQuestVariant ( QuestId questId )
878+ {
879+ return RollEligibleQuestVariant ( questId , Party . Leader ? . Client . Character ) ;
880+ }
881+
815882 public override bool CompleteQuestProgress ( uint questScheduleId , DbConnection ? connectionIn = null )
816883 {
817884 Quest quest = GetQuest ( questScheduleId ) ;
0 commit comments