1 // Copyright (C) 2013, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
16 using System.Collections.Generic;
\r
17 using System.Drawing;
\r
19 using System.Windows.Forms;
\r
20 using System.Xml.Serialization;
\r
21 using KancolleSniffer.Util;
\r
22 using static System.Math;
\r
24 namespace KancolleSniffer.Model
\r
26 public class QuestStatus
\r
28 public int Id { get; set; }
\r
29 public int Category { get; set; }
\r
30 public string Name { get; set; }
\r
31 public string Detail { get; set; }
\r
32 public int[] Material { get; set; }
\r
33 public int Progress { get; set; }
\r
36 public QuestCount Count { get; set; }
\r
39 public Color Color { get; set; }
\r
41 public string ToToolTip() =>
\r
43 (Material == null || Material.All(x => x == 0)
\r
45 : "\r\n" + string.Join(" ",
\r
46 new[] {"燃", "弾", "鋼", "ボ", "建造", "修復", "開発", "改修"}
\r
47 .Zip(Material, (m, num) => num == 0 ? "" : m + num)
\r
48 .Where(s => !string.IsNullOrEmpty(s))));
\r
51 public enum QuestInterval
\r
53 // ReSharper disable once UnusedMember.Global
\r
61 public class QuestSpec
\r
63 public QuestInterval Interval { get; set; }
\r
64 public int Max { get; set; }
\r
65 public int[] MaxArray { get; set; }
\r
66 public bool AdjustCount { get; set; } = true;
\r
67 public int Shift { get; set; }
\r
68 public int[] Material { get; set; }
\r
71 public class QuestSortie : QuestSpec
\r
73 public string Rank { get; set; }
\r
74 public int[] Maps { get; set; }
\r
76 public static int CompareRank(string a, string b)
\r
78 const string ranks = "SABCDE";
\r
79 return ranks.IndexOf(a, StringComparison.Ordinal) -
\r
80 ranks.IndexOf(b, StringComparison.Ordinal);
\r
83 public bool Check(string rank, int map, bool boss)
\r
85 return (Rank == null || CompareRank(rank, Rank) <= 0) &&
\r
86 (Maps == null || Maps.Contains(map) && boss);
\r
90 public class QuestEnemyType : QuestSpec
\r
92 public int[] EnemyType { get; set; } = new int[0];
\r
94 public int CountResult(IEnumerable<ShipStatus> enemyResult) =>
\r
95 enemyResult.Count(ship => ship.NowHp == 0 && EnemyType.Contains(ship.Spec.ShipType));
\r
98 public class QuestPractice : QuestSpec
\r
100 public bool Win { get; set; }
\r
101 public bool Check(string rank) => !Win || QuestSortie.CompareRank(rank, "B") <= 0;
\r
104 public class QuestMission : QuestSpec
\r
106 public int[] Ids { get; set; }
\r
107 public bool Check(int id) => Ids == null || Ids.Contains(id);
\r
110 public class QuestDestroyItem : QuestSpec
\r
112 public int[] Types { get; set; }
\r
113 public int[] Ids { get; set; }
\r
115 public bool Count(QuestCount count, ItemSpec[] specs)
\r
117 if (count.NowArray == null)
\r
119 var num = specs.Count(spec => Types?.Contains(spec.Type) ?? (Ids?.Contains(spec.Id) ?? true));
\r
123 if (Types == null && Ids == null)
\r
125 var result = false;
\r
126 for (var i = 0; i < count.NowArray.Length; i++)
\r
128 var num = specs.Count(spec => Types != null ? Types[i] == spec.Type : Ids[i] == spec.Id);
\r
129 count.NowArray[i] += num;
\r
137 public class QuestPowerUp : QuestSpec
\r
141 public class QuestCount
\r
143 public int Id { get; set; }
\r
144 public int Now { get; set; }
\r
145 public int[] NowArray { get; set; }
\r
148 public QuestSpec Spec { get; set; }
\r
150 public bool AdjustCount(int progress)
\r
152 if (!Spec.AdjustCount)
\r
154 if (NowArray != null)
\r
156 if (progress != 100)
\r
158 NowArray = NowArray.Zip(Spec.MaxArray, Max).ToArray();
\r
177 var now = Now + Spec.Shift;
\r
178 var max = Spec.Max + Spec.Shift;
\r
179 var low = (int)Ceiling(max * progress / 100.0);
\r
180 if (low >= max && progress != 100)
\r
182 var high = (int)Ceiling(max * next / 100.0);
\r
185 Now = low - Spec.Shift;
\r
190 Now = high - 1 - Spec.Shift;
\r
196 public override string ToString()
\r
198 if (Id == 426 || Id == 854 || Id == 873 || Id == 888 || Id == 894)
\r
199 return $"{NowArray.Count(n => n >= 1)}/{Spec.MaxArray.Length}";
\r
200 return NowArray != null
\r
201 ? string.Join(" ", NowArray.Zip(Spec.MaxArray, (n, m) => $"{n}/{m}"))
\r
202 : $"{Now}/{Spec.Max}";
\r
205 public string ToToolTip()
\r
210 return string.Join(" ",
\r
211 new[] {"警備任務", "対潜警戒任務", "海上護衛任務", "強硬偵察任務"}
\r
212 .Zip(NowArray, (mission, n) => n >= 1 ? mission : "")
\r
213 .Where(s => !string.IsNullOrEmpty(s)));
\r
215 return string.Join(" ",
\r
216 new[] {"対潜警戒任務", "海峡警備行動", "長時間対潜警戒"}.Zip(NowArray, (mission, n) => n >= 1 ? mission + n : "")
\r
217 .Where(s => !string.IsNullOrEmpty(s)));
\r
219 return string.Join(" ",
\r
220 new[] {"2-4", "6-1", "6-3", "6-4"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")
\r
221 .Where(s => !string.IsNullOrEmpty(s)));
\r
223 return string.Join(" ",
\r
224 new[] {"3-1", "3-2", "3-3"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")
\r
225 .Where(s => !string.IsNullOrEmpty(s)));
\r
227 return string.Join(" ",
\r
228 new[] {"5-1", "5-3", "5-4"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")
\r
229 .Where(s => !string.IsNullOrEmpty(s)));
\r
231 return string.Join(" ",
\r
232 new[] {"艦戦", "艦爆", "艦攻", "水偵"}.Zip(NowArray, (type, n) => n >= 1 ? type + n : "")
\r
233 .Where(s => !string.IsNullOrEmpty(s)));
\r
235 return string.Join(" ",
\r
236 new[] {"1-5", "7-1", "7-2G", "7-2M"}.Zip(NowArray, (map, n) => n >= 1 ? $"{map}:{n}" : "")
\r
237 .Where(s => !string.IsNullOrEmpty(s)));
\r
239 return string.Join(" ",
\r
240 new[] {"1-3", "1-4", "2-1", "2-2", "2-3"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")
\r
241 .Where(s => !string.IsNullOrEmpty(s)));
\r
246 public bool Cleared => NowArray?.Zip(Spec.MaxArray, (n, m) => n >= m).All(x => x) ?? Spec.Max != 0 && Now >= Spec.Max;
\r
249 public class QuestInfo : IHaveState
\r
251 private readonly SortedDictionary<int, QuestStatus> _quests = new SortedDictionary<int, QuestStatus>();
\r
252 private readonly QuestCountList _countList = new QuestCountList();
\r
253 private readonly ItemInfo _itemInfo;
\r
254 private readonly BattleInfo _battleInfo;
\r
255 private readonly Func<DateTime> _nowFunc = () => DateTime.Now;
\r
256 private DateTime _lastReset;
\r
257 private IEnumerable<QuestStatus> _clearedQuest = new List<QuestStatus>();
\r
259 private readonly Color[] _color =
\r
261 Color.FromArgb(60, 141, 76), Color.FromArgb(232, 57, 41), Color.FromArgb(136, 204, 120),
\r
262 Color.FromArgb(52, 147, 185), Color.FromArgb(220, 198, 126), Color.FromArgb(168, 111, 76),
\r
263 Color.FromArgb(200, 148, 231), Color.FromArgb(232, 57, 41)
\r
266 public int AcceptMax { get; set; } = 5;
\r
268 public QuestStatus[] Quests => _quests.Values.ToArray();
\r
270 public QuestInfo(ItemInfo itemInfo, BattleInfo battleInfo, Func<DateTime> nowFunc = null)
\r
272 _itemInfo = itemInfo;
\r
273 _battleInfo = battleInfo;
\r
274 if (nowFunc != null)
\r
275 _nowFunc = nowFunc;
\r
278 public void GetNotifications(out string[] notify, out string[] stop)
\r
280 var cleared = _quests.Values.Where(q => q.Count.Cleared).ToArray();
\r
281 notify = cleared.Except(_clearedQuest, new QuestComparer()).Select(q => q.Name).ToArray();
\r
282 stop = _clearedQuest.Except(cleared, new QuestComparer()).Select(q => q.Name).ToArray();
\r
283 _clearedQuest = cleared;
\r
286 private class QuestComparer : IEqualityComparer<QuestStatus>
\r
288 public bool Equals(QuestStatus x, QuestStatus y)
\r
290 return x?.Id == y?.Id;
\r
293 public int GetHashCode(QuestStatus obj)
\r
299 public void InspectQuestList(dynamic json)
\r
302 if (json.api_list == null)
\r
304 for (var i = 0; i < 2; i++)
\r
306 foreach (var entry in json.api_list)
\r
308 if (entry is double) // -1の場合がある。
\r
311 var id = (int)entry.api_no;
\r
312 var state = (int)entry.api_state;
\r
313 var progress = (int)entry.api_progress_flag;
\r
314 var cat = (int)entry.api_category;
\r
315 var name = (string)entry.api_title;
\r
316 var detail = ((string)entry.api_detail).Replace("<br>", "\r\n");
\r
317 var material = (int[])entry.api_get_material;
\r
333 if (_quests.Remove(id))
\r
340 AddQuest(id, cat, name, detail, material, progress, true);
\r
344 if (_quests.Count <= AcceptMax)
\r
347 * ほかのPCで任務を達成した場合、任務が消えずに受領した任務の数が_questCountを超えることがある。
\r
348 * その場合はいったん任務をクリアして、現在のページの任務だけを登録し直す。
\r
354 private void AddQuest(int id, int category, string name, string detail, int[] material, int progress,
\r
357 var count = _countList.GetCount(id);
\r
360 if (count.AdjustCount(progress))
\r
363 _quests[id] = new QuestStatus
\r
366 Category = category,
\r
369 Material = adjustCount ? material?.Concat(count.Spec.Material).ToArray() : material,
\r
371 Progress = progress,
\r
372 Color = category <= _color.Length ? _color[category - 1] : Control.DefaultBackColor
\r
376 public void ClearQuests()
\r
381 private void ResetQuests()
\r
383 var now = _nowFunc();
\r
384 var daily = now.Date.AddHours(5);
\r
386 daily = daily.AddDays(-1);
\r
387 if (!(_lastReset < daily && daily <= now))
\r
389 RemoveQuest(QuestInterval.Daily);
\r
390 _countList.Remove(QuestInterval.Daily);
\r
391 var weekly = now.Date.AddDays(-((6 + (int)now.DayOfWeek) % 7)).AddHours(5);
\r
392 if (_lastReset < weekly && weekly <= now)
\r
394 RemoveQuest(QuestInterval.Weekly);
\r
395 _countList.Remove(QuestInterval.Weekly);
\r
397 var monthly = new DateTime(now.Year, now.Month, 1, 5, 0, 0);
\r
398 if (_lastReset < monthly && monthly <= now)
\r
400 RemoveQuest(QuestInterval.Monthly);
\r
401 _countList.Remove(QuestInterval.Monthly);
\r
403 var season = now.Month / 3;
\r
404 var quarterly = new DateTime(now.Year - (season == 0 ? 1 : 0), (season == 0 ? 12 : season * 3), 1, 5, 0, 0);
\r
405 if (_lastReset < quarterly && quarterly <= now)
\r
407 RemoveQuest(QuestInterval.Quarterly);
\r
408 _countList.Remove(QuestInterval.Quarterly);
\r
414 private void RemoveQuest(QuestInterval interval)
\r
417 (from kv in _quests where kv.Value.Count.Spec.Interval == interval select kv.Key).ToArray())
\r
418 _quests.Remove(id);
\r
423 private bool _boss;
\r
425 public void InspectMapStart(dynamic json)
\r
427 if (_quests.TryGetValue(214, out var ago)) // あ号
\r
428 ago.Count.NowArray[0]++;
\r
429 InspectMapNext(json);
\r
432 public void InspectMapNext(dynamic json)
\r
434 _map = (int)json.api_maparea_id * 10 + (int)json.api_mapinfo_no;
\r
435 _cell = json.api_no() ? (int)json.api_no : 0;
\r
436 _boss = (int)json.api_event_id == 5;
\r
438 if (_quests.TryGetValue(861, out var q861))
\r
440 if (_map == 16 && (int)json.api_event_id == 8)
\r
442 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)
\r
444 if (fleet.Count(s => s == 10 || s == 22) == 2)
\r
445 IncrementCount(q861.Count);
\r
450 public void InspectBattleResult(dynamic json)
\r
452 var rank = json.api_win_rank;
\r
453 foreach (var quest in _quests.Values)
\r
455 var count = quest.Count;
\r
456 switch (count.Spec)
\r
458 case QuestSortie sortie:
\r
459 if (count.Id == 216 && !_boss || sortie.Check(rank, _map, _boss))
\r
460 IncrementCount(count);
\r
462 case QuestEnemyType enemyType:
\r
463 var num = enemyType.CountResult(
\r
464 _battleInfo.Result.Enemy.Main.Concat(_battleInfo.Result.Enemy.Guard));
\r
466 AddCount(count, num);
\r
470 if (_quests.TryGetValue(214, out var ago))
\r
472 var count = ago.Count;
\r
475 IncrementNowArray(count, 2);
\r
476 if (QuestSortie.CompareRank(rank, "B") <= 0)
\r
477 IncrementNowArray(count, 3);
\r
480 IncrementNowArray(count, 1);
\r
482 if (_quests.TryGetValue(249, out var q249))
\r
484 if (_map == 25 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
486 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.Id)
\r
488 if (fleet.Intersect(new[] {62, 63, 64, 265, 266, 268, 319, 192, 194}).Count() == 3)
\r
489 IncrementCount(q249.Count);
\r
492 if (_quests.TryGetValue(257, out var q257))
\r
494 if (_map == 14 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
496 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)
\r
498 if (fleet[0] == 3 && fleet.Count(s => s == 3) <= 3 && fleet.All(s => s == 2 || s == 3))
\r
499 IncrementCount(q257.Count);
\r
502 if (_quests.TryGetValue(259, out var q259))
\r
504 if (_map == 51 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
506 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec).ToArray();
\r
507 // ReSharper disable once IdentifierTypo
\r
515 if (fleet.Select(s => s.ShipClass).Count(c => ctype.Contains(c)) == 3 &&
\r
516 fleet.Count(s => s.ShipType == 3) > 0)
\r
518 IncrementCount(q259.Count);
\r
522 if (_quests.TryGetValue(264, out var q264))
\r
524 if (_map == 42 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
526 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec)
\r
528 if (fleet.Count(spec => spec.ShipType == 2) >= 2 &&
\r
529 fleet.Count(spec => spec.IsAircraftCarrier) >= 2)
\r
530 IncrementCount(q264.Count);
\r
533 if (_quests.TryGetValue(266, out var q266))
\r
535 if (_map == 25 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
537 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)
\r
539 if (fleet[0] == 2 && fleet.OrderBy(x => x).SequenceEqual(new[] {2, 2, 2, 2, 3, 5}))
\r
540 IncrementCount(q266.Count);
\r
543 if (_quests.TryGetValue(854, out var opz) && _boss)
\r
545 var count = opz.Count;
\r
548 case 24 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
549 IncrementNowArray(count, 0);
\r
551 case 61 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
552 IncrementNowArray(count, 1);
\r
554 case 63 when QuestSortie.CompareRank(rank, "A") <= 0:
\r
555 IncrementNowArray(count, 2);
\r
558 case 64 when QuestSortie.CompareRank(rank, "S") <= 0:
\r
559 IncrementNowArray(count, 3);
\r
563 if (_quests.TryGetValue(862, out var q862))
\r
565 if (_map == 63 && _boss && QuestSortie.CompareRank(rank, "A") <= 0)
\r
567 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)
\r
569 if (fleet.Count(s => s == 3) >= 2 && fleet.Count(s => s == 16) >= 1)
\r
570 IncrementCount(q862.Count);
\r
573 if (_quests.TryGetValue(873, out var q873))
\r
575 if (_battleInfo.Result.Friend.Main.Count(s => s.NowHp > 0 && s.Spec.ShipType == 3) >= 1 &&
\r
576 _boss && QuestSortie.CompareRank(rank, "A") <= 0)
\r
578 var count = q873.Count;
\r
582 IncrementNowArray(count, 0);
\r
585 IncrementNowArray(count, 1);
\r
588 IncrementNowArray(count, 2);
\r
593 if (_quests.TryGetValue(875, out var q875))
\r
595 if (_map == 54 && _boss && QuestSortie.CompareRank(rank, "S") == 0)
\r
597 var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.Id).ToArray();
\r
598 if (fleet.Contains(543) && fleet.Intersect(new[] {344, 345, 359}).Any())
\r
599 IncrementCount(q875.Count);
\r
602 if (_quests.TryGetValue(888, out var q888))
\r
604 if (!_boss || QuestSortie.CompareRank(rank, "S") != 0)
\r
606 var fleet = from ship in _battleInfo.Result.Friend.Main where ship.NowHp > 0 select ship.Spec.Id;
\r
609 69, 272, 427, // 鳥海
\r
611 123, 295, 142, // 衣笠
\r
612 59, 262, 416, // 古鷹
\r
613 60, 263, 417, // 加古
\r
614 51, 213, 477, // 天龍
\r
617 if (fleet.Intersect(member).Count() < 4)
\r
619 var count = q888.Count;
\r
623 IncrementNowArray(count, 0);
\r
626 IncrementNowArray(count, 1);
\r
629 IncrementNowArray(count, 2);
\r
633 if (_quests.TryGetValue(893, out var q893))
\r
635 if (QuestSortie.CompareRank(rank, "S") != 0)
\r
637 var count = q893.Count;
\r
641 IncrementNowArray(count, 0);
\r
644 IncrementNowArray(count, 1);
\r
649 IncrementNowArray(count, 2);
\r
652 IncrementNowArray(count, 3);
\r
656 if (_quests.TryGetValue(894, out var q894))
\r
659 QuestSortie.CompareRank(rank, "S") != 0 ||
\r
660 !_battleInfo.Result.Friend.Main.Any(s => s.Spec.IsAircraftCarrier && s.NowHp > 0))
\r
662 var count = q894.Count;
\r
666 IncrementNowArray(count, 0);
\r
669 IncrementNowArray(count, 1);
\r
672 IncrementNowArray(count, 2);
\r
675 IncrementNowArray(count, 3);
\r
678 IncrementNowArray(count, 4);
\r
684 private int _questFleet;
\r
686 public void StartPractice(string request)
\r
688 var values = HttpUtility.ParseQueryString(request);
\r
689 _questFleet = int.Parse(values["api_deck_id"]) - 1;
\r
692 public void InspectPracticeResult(dynamic json)
\r
694 foreach (var quest in _quests.Values)
\r
696 var count = quest.Count;
\r
697 if (!(count.Spec is QuestPractice practice))
\r
699 if (practice.Check(json.api_win_rank))
\r
700 IncrementCount(count);
\r
702 if (_quests.TryGetValue(318, out var q318))
\r
704 if (_questFleet == 0 && QuestSortie.CompareRank(json.api_win_rank, "B") <= 0 &&
\r
705 _battleInfo.Result.Friend.Main.Count(s => s.Spec.ShipType == 3) >= 2)
\r
707 IncrementCount(q318.Count);
\r
712 private readonly int[] _missionId = new int[ShipInfo.FleetCount];
\r
714 public void InspectDeck(dynamic json)
\r
716 foreach (var entry in json)
\r
717 _missionId[(int)entry.api_id - 1] = (int)entry.api_mission[1];
\r
720 public void InspectMissionResult(string request, dynamic json)
\r
722 var values = HttpUtility.ParseQueryString(request);
\r
723 var deck = int.Parse(values["api_deck_id"]);
\r
724 if ((int)json.api_clear_result == 0)
\r
726 var mid = _missionId[deck - 1];
\r
727 foreach (var quest in _quests.Values)
\r
729 var count = quest.Count;
\r
730 if (!(count.Spec is QuestMission mission))
\r
732 if (mission.Check(mid))
\r
733 IncrementCount(count);
\r
735 if (_quests.TryGetValue(426, out var q426))
\r
737 var count = q426.Count;
\r
741 IncrementNowArray(count, 0);
\r
744 IncrementNowArray(count, 1);
\r
747 IncrementNowArray(count, 2);
\r
750 IncrementNowArray(count, 3);
\r
754 if (_quests.TryGetValue(428, out var q428))
\r
756 var count = q428.Count;
\r
760 IncrementNowArray(count, 0);
\r
763 IncrementNowArray(count, 1);
\r
766 IncrementNowArray(count, 2);
\r
772 private void IncrementCount(QuestCount count)
\r
778 private void AddCount(QuestCount count, int value)
\r
780 count.Now += value;
\r
784 private void IncrementCount(int id)
\r
789 private void AddCount(int id, int value)
\r
791 if (_quests.TryGetValue(id, out var quest))
\r
793 quest.Count.Now += value;
\r
798 private void IncrementNowArray(QuestCount count, int n)
\r
800 count.NowArray[n]++;
\r
804 public void CountNyukyo() => IncrementCount(503);
\r
806 public void CountCharge() => IncrementCount(504);
\r
808 public void CountCreateItem()
\r
810 IncrementCount(605);
\r
811 IncrementCount(607);
\r
814 public void CountCreateShip()
\r
816 IncrementCount(606);
\r
817 IncrementCount(608);
\r
820 public void InspectDestroyShip(string request)
\r
822 AddCount(609, HttpUtility.ParseQueryString(request)["api_ship_id"].Split(',').Length);
\r
825 public void CountRemodelSlot() => IncrementCount(619);
\r
827 public void InspectDestroyItem(string request, dynamic json)
\r
829 var values = HttpUtility.ParseQueryString(request);
\r
830 var items = values["api_slotitem_ids"].Split(',')
\r
831 .Select(id => _itemInfo.GetStatus(int.Parse(id)).Spec).ToArray();
\r
832 IncrementCount(613); // 613: 資源の再利用
\r
833 foreach (var quest in _quests.Values)
\r
835 var count = quest.Count;
\r
836 if (!(count.Spec is QuestDestroyItem destroy))
\r
838 if (destroy.Count(count, items))
\r
841 if (_quests.TryGetValue(680, out var q680))
\r
843 q680.Count.NowArray[0] += items.Count(spec => spec.Type == 21);
\r
844 q680.Count.NowArray[1] += items.Count(spec => spec.Type == 12 || spec.Type == 13);
\r
849 public void InspectPowerUp(dynamic json)
\r
851 if ((int)json.api_powerup_flag == 0)
\r
853 foreach (var quest in _quests.Values)
\r
855 var count = quest.Count;
\r
856 if (!(count.Spec is QuestPowerUp))
\r
858 IncrementCount(count);
\r
862 public void InspectStop(string request)
\r
864 var values = HttpUtility.ParseQueryString(request);
\r
865 _quests.Remove(int.Parse(values["api_quest_id"]));
\r
869 public void InspectClearItemGet(string request)
\r
871 var values = HttpUtility.ParseQueryString(request);
\r
872 var id = int.Parse(values["api_quest_id"]);
\r
873 _countList.Remove(id);
\r
874 _quests.Remove(id);
\r
878 public bool NeedSave { get; private set; }
\r
880 public void SaveState(Status status)
\r
883 status.QuestLastReset = _lastReset;
\r
884 if (_quests != null)
\r
885 status.QuestList = _quests.Values.ToArray();
\r
886 if (_countList != null)
\r
887 status.QuestCountList = _countList.CountList.ToArray();
\r
890 public void LoadState(Status status)
\r
892 _lastReset = status.QuestLastReset;
\r
893 if (status.QuestCountList != null)
\r
894 _countList.CountList = status.QuestCountList;
\r
895 if (status.QuestList != null)
\r
898 foreach (var q in status.QuestList)
\r
899 AddQuest(q.Id, q.Category, q.Name, q.Detail, q.Material, q.Progress, false);
\r