1 #include "journalcheck.hpp"
2 
3 #include <set>
4 
5 #include "../prefs/state.hpp"
6 
JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> & journals,const CSMWorld::InfoCollection & journalInfos)7 CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
8     const CSMWorld::InfoCollection& journalInfos)
9     : mJournals(journals), mJournalInfos(journalInfos)
10 {
11     mIgnoreBaseRecords = false;
12 }
13 
setup()14 int CSMTools::JournalCheckStage::setup()
15 {
16     mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
17 
18     return mJournals.getSize();
19 }
20 
perform(int stage,CSMDoc::Messages & messages)21 void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
22 {
23     const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage);
24 
25     // Skip "Base" records (setting!) and "Deleted" records
26     if ((mIgnoreBaseRecords && journalRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || journalRecord.isDeleted())
27         return;
28 
29     const ESM::Dialogue &journal = journalRecord.get();
30     int statusNamedCount = 0;
31     int totalInfoCount = 0;
32     std::set<int> questIndices;
33 
34     CSMWorld::InfoCollection::Range range = mJournalInfos.getTopicRange(journal.mId);
35 
36     for (CSMWorld::InfoCollection::RecordConstIterator it = range.first; it != range.second; ++it)
37     {
38         const CSMWorld::Record<CSMWorld::Info> infoRecord = (*it);
39 
40         if (infoRecord.isDeleted())
41             continue;
42 
43         const CSMWorld::Info& journalInfo = infoRecord.get();
44 
45         totalInfoCount += 1;
46 
47         if (journalInfo.mQuestStatus == ESM::DialInfo::QS_Name)
48         {
49             statusNamedCount += 1;
50         }
51 
52         // Skip "Base" records (setting!)
53         if (mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
54             continue;
55 
56         if (journalInfo.mResponse.empty())
57         {
58             CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
59             messages.add(id, "Missing journal entry text", "", CSMDoc::Message::Severity_Warning);
60         }
61 
62         std::pair<std::set<int>::iterator, bool> result = questIndices.insert(journalInfo.mData.mJournalIndex);
63 
64         // Duplicate index
65         if (!result.second)
66         {
67             CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
68             messages.add(id, "Duplicated quest index " + std::to_string(journalInfo.mData.mJournalIndex), "", CSMDoc::Message::Severity_Error);
69         }
70     }
71 
72     if (totalInfoCount == 0)
73     {
74         CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Journal, journal.mId);
75         messages.add(id, "No related journal entry", "", CSMDoc::Message::Severity_Warning);
76     }
77     else if (statusNamedCount > 1)
78     {
79         CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Journal, journal.mId);
80         messages.add(id, "Multiple entries with quest status 'Named'", "", CSMDoc::Message::Severity_Error);
81     }
82 }
83