1 #include "magiceffectcheck.hpp"
2 
3 #include <components/misc/resourcehelpers.hpp>
4 
5 #include "../prefs/state.hpp"
6 
checkObject(const std::string & id,const CSMWorld::UniversalId & type,const std::string & column) const7 std::string CSMTools::MagicEffectCheckStage::checkObject(const std::string &id,
8                                                                 const CSMWorld::UniversalId &type,
9                                                                 const std::string &column) const
10 {
11     CSMWorld::RefIdData::LocalIndex index = mObjects.getDataSet().searchId(id);
12     if (index.first == -1)
13         return (column + " '" + id + "' does not exist");
14     else if (index.second != type.getType())
15         return (column + " '" + id + "' does not have " + type.getTypeName() + " type");
16     return std::string();
17 }
18 
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> & effects,const CSMWorld::IdCollection<ESM::Sound> & sounds,const CSMWorld::RefIdCollection & objects,const CSMWorld::Resources & icons,const CSMWorld::Resources & textures)19 CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
20                                                        const CSMWorld::IdCollection<ESM::Sound> &sounds,
21                                                        const CSMWorld::RefIdCollection &objects,
22                                                        const CSMWorld::Resources &icons,
23                                                        const CSMWorld::Resources &textures)
24     : mMagicEffects(effects),
25       mSounds(sounds),
26       mObjects(objects),
27       mIcons(icons),
28       mTextures(textures)
29 {
30     mIgnoreBaseRecords = false;
31 }
32 
setup()33 int CSMTools::MagicEffectCheckStage::setup()
34 {
35     mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
36 
37     return mMagicEffects.getSize();
38 }
39 
perform(int stage,CSMDoc::Messages & messages)40 void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
41 {
42     const CSMWorld::Record<ESM::MagicEffect> &record = mMagicEffects.getRecord(stage);
43 
44     // Skip "Base" records (setting!) and "Deleted" records
45     if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
46         return;
47 
48     ESM::MagicEffect effect = record.get();
49     CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
50 
51     if (effect.mDescription.empty())
52     {
53         messages.add(id, "Description is missing", "", CSMDoc::Message::Severity_Warning);
54     }
55 
56     if (effect.mData.mBaseCost < 0.0f)
57     {
58         messages.add(id, "Base cost is negative", "", CSMDoc::Message::Severity_Error);
59     }
60 
61     if (effect.mIcon.empty())
62     {
63         messages.add(id, "Icon is missing", "", CSMDoc::Message::Severity_Error);
64     }
65     else
66     {
67         if (mIcons.searchId(effect.mIcon) == -1)
68         {
69             std::string ddsIcon = effect.mIcon;
70             if (!(Misc::ResourceHelpers::changeExtensionToDds(ddsIcon) && mIcons.searchId(ddsIcon) != -1))
71                 messages.add(id, "Icon '" + effect.mIcon + "' does not exist", "", CSMDoc::Message::Severity_Error);
72         }
73     }
74 
75     if (!effect.mParticle.empty())
76     {
77         if (mTextures.searchId(effect.mParticle) == -1)
78         {
79             std::string ddsParticle = effect.mParticle;
80             if (!(Misc::ResourceHelpers::changeExtensionToDds(ddsParticle) && mTextures.searchId(ddsParticle) != -1))
81                 messages.add(id, "Particle texture '" + effect.mParticle + "' does not exist", "", CSMDoc::Message::Severity_Error);
82         }
83     }
84 
85     if (!effect.mCasting.empty())
86     {
87         const std::string error = checkObject(effect.mCasting, CSMWorld::UniversalId::Type_Static, "Casting object");
88         if (!error.empty())
89             messages.add(id, error, "", CSMDoc::Message::Severity_Error);
90     }
91 
92     if (!effect.mHit.empty())
93     {
94         const std::string error = checkObject(effect.mHit, CSMWorld::UniversalId::Type_Static, "Hit object");
95         if (!error.empty())
96             messages.add(id, error, "", CSMDoc::Message::Severity_Error);
97     }
98 
99     if (!effect.mArea.empty())
100     {
101         const std::string error = checkObject(effect.mArea, CSMWorld::UniversalId::Type_Static, "Area object");
102         if (!error.empty())
103             messages.add(id, error, "", CSMDoc::Message::Severity_Error);
104     }
105 
106     if (!effect.mBolt.empty())
107     {
108         const std::string error = checkObject(effect.mBolt, CSMWorld::UniversalId::Type_Weapon, "Bolt object");
109         if (!error.empty())
110             messages.add(id, error, "", CSMDoc::Message::Severity_Error);
111     }
112 
113     if (!effect.mCastSound.empty() && mSounds.searchId(effect.mCastSound) == -1)
114         messages.add(id, "Casting sound '" + effect.mCastSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
115     if (!effect.mHitSound.empty() && mSounds.searchId(effect.mHitSound) == -1)
116         messages.add(id, "Hit sound '" + effect.mHitSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
117     if (!effect.mAreaSound.empty() && mSounds.searchId(effect.mAreaSound) == -1)
118         messages.add(id, "Area sound '" + effect.mAreaSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
119     if (!effect.mBoltSound.empty() && mSounds.searchId(effect.mBoltSound) == -1)
120         messages.add(id, "Bolt sound '" + effect.mBoltSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
121 }
122