@@ -86,9 +86,44 @@ private static void AddQuestToCategory(Quest quest)
8686 gAreaTrialRanks [ quest . QuestAreaId ] = new Dictionary < uint , uint > ( ) ;
8787 }
8888
89- // Nightmarish
90- var requiredRank = quest . ToCDataQuestList ( 0 ) . QuestProcessStateList . First ( ) . CheckCommandList . First ( ) . ResultCommandList . First ( ) . Param02 ;
91- gAreaTrialRanks [ quest . QuestAreaId ] [ quest . QuestScheduleId ] = ( uint ) requiredRank ;
89+ // Search all process states for a CheckAreaRank command rather than assuming
90+ // it is always the very first command — JSON quests and scripted .csx quests
91+ // serialize their process state lists differently, so .First() is unreliable.
92+ var questData = quest . ToCDataQuestList ( 0 ) ;
93+ uint requiredRank = 0 ;
94+ QuestAreaId areaId = quest . QuestAreaId ;
95+ bool found = false ;
96+
97+ foreach ( var processState in questData . QuestProcessStateList )
98+ {
99+ foreach ( var checkCmdGroup in processState . CheckCommandList )
100+ {
101+ foreach ( var cmd in checkCmdGroup . ResultCommandList )
102+ {
103+ if ( cmd . Command == ( ushort ) QuestCheckCommand . CheckAreaRank )
104+ {
105+ requiredRank = ( uint ) cmd . Param02 ;
106+ if ( areaId == QuestAreaId . None )
107+ {
108+ areaId = ( QuestAreaId ) cmd . Param01 ;
109+ }
110+ found = true ;
111+ break ;
112+ }
113+ }
114+ if ( found ) break ;
115+ }
116+ if ( found ) break ;
117+ }
118+
119+ if ( found )
120+ {
121+ if ( ! gAreaTrialRanks . ContainsKey ( areaId ) )
122+ {
123+ gAreaTrialRanks [ areaId ] = new Dictionary < uint , uint > ( ) ;
124+ }
125+ gAreaTrialRanks [ areaId ] [ quest . QuestScheduleId ] = requiredRank ;
126+ }
92127 }
93128 }
94129
@@ -275,18 +310,16 @@ public static HashSet<uint> CollectQuestScheduleIds(GameClient client, StageLayo
275310 public static void PurgeUnstartedTutorialQuests ( GameClient client )
276311 {
277312 var unstartedTutorialQuests = client . QuestState . GetActiveQuestScheduleIds ( )
278- . Where ( x => QuestManager . GetQuestByScheduleId ( x ) . QuestType == QuestType . Tutorial )
279- . Where ( x => QuestManager . GetQuestStateManager ( client , x ) . GetQuestState ( x ) . State == QuestProgressState . Unknown )
280313 . Select ( x => QuestManager . GetQuestByScheduleId ( x ) )
314+ . Where ( x => x != null && x . QuestType == QuestType . Tutorial )
315+ . Where ( x => {
316+ var mgr = QuestManager . GetQuestStateManager ( client , x ) ;
317+ return mgr != null && mgr . GetQuestState ( x . QuestScheduleId ) ? . State == QuestProgressState . Unknown ;
318+ } )
281319 . ToList ( ) ;
282320
283321 foreach ( var quest in unstartedTutorialQuests )
284322 {
285- if ( quest == null )
286- {
287- continue ;
288- }
289-
290323 var questStateManager = QuestManager . GetQuestStateManager ( client , quest ) ;
291324 if ( questStateManager != null )
292325 {
@@ -318,6 +351,16 @@ public static Dictionary<uint,uint> GetAreaTrialRankings(QuestAreaId areaId)
318351 return gAreaTrialRanks [ areaId ] ;
319352 }
320353
354+ public static QuestAreaId GetAreaIdForTrial ( uint questScheduleId )
355+ {
356+ foreach ( var ( areaId , rankings ) in gAreaTrialRanks )
357+ {
358+ if ( rankings . ContainsKey ( questScheduleId ) )
359+ return areaId ;
360+ }
361+ return QuestAreaId . None ;
362+ }
363+
321364 public static uint GetScheduleId ( DdonGameServer server , QuestId questId , uint variantNumber )
322365 {
323366 if ( IsDatabaseManaged ( questId , out uint baseScheduleId ) )
0 commit comments