HtmlPage[] ExtractFollowingPages(HtmlPage page, int pageIndex, HtmlPage[] allPages) { if (pageIndex < 0) throw new ArgumentException("pageIndex"); List<HtmlPage> followingPages = new List<HtmlPage>(0); if (page.Selects == null || pageIndex >= allPages.Length - 1) return followingPages.ToArray(); foreach (SelectsAct action in page.Selects) { if (String.IsNullOrEmpty(action.href)) continue; string nextPageName = action.ActionName; if (nextPageName == null) continue; HtmlPage nextPage = allPages.Where(p => p != null && p.name == nextPageName) .FirstOrDefault(); if (nextPage == null) { // doesn't match nextPage = allPages.Where(p => p != null && p.name.StartsWith(nextPageName)) .FirstOrDefault(); } if (nextPage != null) { int nextPageIdx = Array.IndexOf(allPages, nextPage); if (nextPageIdx == pageIndex + 2) { // theres's a page between, check if it has only a "finish_dialog" action HtmlPage skippedPage = allPages[pageIndex + 1]; if (skippedPage != null && skippedPage.Selects != null) { string name = skippedPage.Selects[0].ActionName; if (name == "finish_dialog") { // add the skipped page before // TODO: check for being non-referenced by other pages? followingPages.Add(skippedPage); allPages[pageIndex + 1] = null; } } } followingPages.Add(nextPage); // remove, so if other pages back-referencing it, the page won't be picked up again allPages[nextPageIdx] = null; followingPages.AddRange(ExtractFollowingPages(nextPage, nextPageIdx, allPages)); } else if (nextPageName == "check_user_has_quest_item") { // add the next page which is displayed when the check fails // make sure it has "finish_dialog" button // Add to select3 --> select3_1 etc. instead ?? // it also can contain "setpro" button !!! int addedCount = 0; string lastAddedPageName = String.Empty; for (int i = pageIndex + 1; i < allPages.Length; i++) { HtmlPage pageAfter = allPages[i]; if (pageAfter == null) continue; bool canClose = pageAfter.Selects == null || pageAfter.name == "user_item_ok" || pageAfter.name == "user_item_fail"; if (!canClose && pageAfter.Selects.Length == 1) { string pgAct = pageAfter.Selects[0].ActionName; canClose = pgAct == "finish_dialog" || pgAct.StartsWith("setpro"); } if (canClose || pageAfter.name.StartsWith(page.name) || addedCount > 0 && pageAfter.name.StartsWith(lastAddedPageName)) { followingPages.Add(pageAfter); allPages[i] = null; addedCount++; lastAddedPageName = pageAfter.name; if (!canClose || pageAfter.name == "user_item_ok" || pageAfter.name == "user_item_fail") { followingPages.AddRange(ExtractFollowingPages(pageAfter, i + 1, allPages)); } if (addedCount == 2) // added Accept and Deny pages break; } } } } return followingPages.ToArray(); }