diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37f8552cd..0ec1a817b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -444,23 +444,23 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
# Install icon and desktop file
- INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
- INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS)
- INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
- INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
+ INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS)
# Install global configuration files
- INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
- INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
- INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
IF(BUILD_OPENCS)
- INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS)
# Install resources
- INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources")
+ INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" COMPONENT "Resources")
INSTALL(DIRECTORY DESTINATION "${DATADIR}/data" COMPONENT "Resources")
ENDIF(NOT WIN32 AND NOT APPLE)
diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp
index dccf8bb8c..cdb51348c 100644
--- a/apps/launcher/graphicspage.cpp
+++ b/apps/launcher/graphicspage.cpp
@@ -67,7 +67,7 @@ bool Launcher::GraphicsPage::setupOgre()
}
catch(Ogre::Exception &ex)
{
- QString ogreError = QString::fromStdString(ex.getFullDescription().c_str());
+ QString ogreError = QString::fromUtf8(ex.getFullDescription().c_str());
QMessageBox msgBox;
msgBox.setWindowTitle("Error creating Ogre::Root");
msgBox.setIcon(QMessageBox::Critical);
@@ -135,7 +135,7 @@ bool Launcher::GraphicsPage::setupSDL()
msgBox.setWindowTitle(tr("Error receiving number of screens"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.setText(tr("
SDL_GetNumDisplayModes failed:
") + QString::fromStdString(SDL_GetError()) + "
");
+ msgBox.setText(tr("
SDL_GetNumDisplayModes failed:
") + QString::fromUtf8(SDL_GetError()) + "
");
msgBox.exec();
return false;
}
@@ -237,7 +237,7 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre
opt_it != i->second.possibleValues.end(); ++opt_it, ++idx)
{
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
- result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
+ result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromUtf8((*opt_it).c_str()).simplified();
}
}
}
@@ -266,7 +266,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
msgBox.setWindowTitle(tr("Error receiving resolutions"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.setText(tr("
SDL_GetNumDisplayModes failed:
") + QString::fromStdString(SDL_GetError()) + "
");
+ msgBox.setText(tr("
SDL_GetNumDisplayModes failed:
") + QString::fromUtf8(SDL_GetError()) + "
");
msgBox.exec();
return result;
}
@@ -279,7 +279,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
msgBox.setWindowTitle(tr("Error receiving resolutions"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
- msgBox.setText(tr("
SDL_GetDisplayMode failed:
") + QString::fromStdString(SDL_GetError()) + "
");
+ msgBox.setText(tr("
SDL_GetDisplayMode failed:
") + QString::fromUtf8(SDL_GetError()) + "
");
msgBox.exec();
return result;
}
diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp
index 5c3f38458..11ea56869 100644
--- a/apps/launcher/main.cpp
+++ b/apps/launcher/main.cpp
@@ -24,7 +24,7 @@ int main(int argc, char *argv[])
SDL_SetMainReady();
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
- qDebug() << "SDL_Init failed: " << QString::fromStdString(SDL_GetError());
+ qDebug() << "SDL_Init failed: " << QString::fromUtf8(SDL_GetError());
return 0;
}
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp
index 611f0a304..669bae60a 100644
--- a/apps/openmw/engine.cpp
+++ b/apps/openmw/engine.cpp
@@ -109,11 +109,14 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
if (!paused)
{
- // local scripts
- executeLocalScripts();
-
- // global scripts
- MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
+ if (MWBase::Environment::get().getWorld()->getScriptsEnabled())
+ {
+ // local scripts
+ executeLocalScripts();
+
+ // global scripts
+ MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
+ }
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
}
diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp
index 475fe63a2..82fda060e 100644
--- a/apps/openmw/main.cpp
+++ b/apps/openmw/main.cpp
@@ -390,12 +390,12 @@ int main(int argc, char**argv)
catch (std::exception &e)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
- if (isatty(fileno(stdin)))
- std::cerr << "\nERROR: " << e.what() << std::endl;
- else
+ if (!isatty(fileno(stdin)))
#endif
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
+ std::cerr << "\nERROR: " << e.what() << std::endl;
+
ret = 1;
}
diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp
index 154d96f7d..8180d0b1a 100644
--- a/apps/openmw/mwbase/world.hpp
+++ b/apps/openmw/mwbase/world.hpp
@@ -489,6 +489,9 @@ namespace MWBase
virtual bool toggleGodMode() = 0;
+ virtual bool toggleScripts() = 0;
+ virtual bool getScriptsEnabled() const = 0;
+
/**
* @brief startSpellCast attempt to start casting a spell. Might fail immediately if conditions are not met.
* @param actor
diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp
index 5cb67c048..4270c4be1 100644
--- a/apps/openmw/mwgui/inventorywindow.cpp
+++ b/apps/openmw/mwgui/inventorywindow.cpp
@@ -420,7 +420,7 @@ namespace MWGui
// Give the script a chance to run once before we do anything else
// this is important when setting pcskipequip as a reaction to onpcequip being set (bk_treasuryreport does this)
- if (!script.empty())
+ if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
{
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp
index 6d3c79b34..69365c108 100644
--- a/apps/openmw/mwgui/spellwindow.cpp
+++ b/apps/openmw/mwgui/spellwindow.cpp
@@ -95,8 +95,9 @@ namespace MWGui
return;
}
- MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
store.setSelectedEnchantItem(it);
+ // to reset WindowManager::mSelectedSpell immediately
+ MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(*it);
updateSpells();
}
diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt
index 41cc6b88a..93720aef6 100644
--- a/apps/openmw/mwscript/docs/vmformat.txt
+++ b/apps/openmw/mwscript/docs/vmformat.txt
@@ -444,5 +444,6 @@ op 0x20002fd: AddToLevItem
op 0x20002fe: RemoveFromLevItem
op 0x20002ff: SetFactionReaction
op 0x2000300: EnableLevelupMenu
+op 0x2000301: ToggleScripts
-opcodes 0x2000301-0x3ffffff unused
+opcodes 0x2000302-0x3ffffff unused
diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp
index cdc9f58cf..52094947c 100644
--- a/apps/openmw/mwscript/miscextensions.cpp
+++ b/apps/openmw/mwscript/miscextensions.cpp
@@ -915,6 +915,19 @@ namespace MWScript
}
};
+ class OpToggleScripts : public Interpreter::Opcode0
+ {
+ public:
+ virtual void execute (Interpreter::Runtime& runtime)
+ {
+ InterpreterContext& context = static_cast (runtime.getContext());
+
+ bool enabled = MWBase::Environment::get().getWorld()->toggleScripts();
+
+ context.report(enabled ? "Scripts -> On" : "Scripts -> Off");
+ }
+ };
+
class OpToggleGodMode : public Interpreter::Opcode0
{
public:
@@ -1220,6 +1233,7 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars);
interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
+ interpreter.installSegment5 (Compiler::Misc::opcodeToggleScripts, new OpToggleScripts);
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation);
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation);
interpreter.installSegment5 (Compiler::Misc::opcodeCast, new OpCast);
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index a60eae48a..188f3cdad 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -151,7 +151,8 @@ namespace MWWorld
mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true),
mGodMode(false), mContentFiles (contentFiles),
mGoToJail(false), mDaysInPrison(0),
- mStartCell (startCell), mStartupScript(startupScript)
+ mStartCell (startCell), mStartupScript(startupScript),
+ mScriptsEnabled(true)
{
mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine();
@@ -293,6 +294,7 @@ namespace MWWorld
mDoorStates.clear();
mGodMode = false;
+ mScriptsEnabled = true;
mSky = true;
mTeleportEnabled = true;
mLevitationEnabled = true;
@@ -2587,6 +2589,17 @@ namespace MWWorld
return mGodMode;
}
+ bool World::toggleScripts()
+ {
+ mScriptsEnabled = !mScriptsEnabled;
+ return mScriptsEnabled;
+ }
+
+ bool World::getScriptsEnabled() const
+ {
+ return mScriptsEnabled;
+ }
+
void World::loadContentFiles(const Files::Collections& fileCollections,
const std::vector& content, ContentLoader& contentLoader)
{
@@ -2886,6 +2899,9 @@ namespace MWWorld
}
else if (ptr.getClass().getTypeName() != typeid(ESM::Creature).name())
return false;
+
+ if (ptr.getClass().getCreatureStats(ptr).isDead())
+ return false;
}
if (mType == World::Detect_Key && !ptr.getClass().isKey(ptr))
return false;
@@ -3164,12 +3180,17 @@ namespace MWWorld
breakInvisibility(actor);
- if (!script.empty())
+ if (mScriptsEnabled)
{
- getLocalScripts().setIgnore (object);
- MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
+ if (!script.empty())
+ {
+ getLocalScripts().setIgnore (object);
+ MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
+ }
+ if (!interpreterContext.hasActivationBeenHandled())
+ interpreterContext.executeActivation(object, actor);
}
- if (!interpreterContext.hasActivationBeenHandled())
+ else
interpreterContext.executeActivation(object, actor);
}
diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp
index 1d103c6a9..9980f6f90 100644
--- a/apps/openmw/mwworld/worldimp.hpp
+++ b/apps/openmw/mwworld/worldimp.hpp
@@ -82,6 +82,7 @@ namespace MWWorld
boost::shared_ptr mProjectileManager;
bool mGodMode;
+ bool mScriptsEnabled;
std::vector mContentFiles;
// not implemented
@@ -572,6 +573,9 @@ namespace MWWorld
virtual bool toggleGodMode();
+ virtual bool toggleScripts();
+ virtual bool getScriptsEnabled() const;
+
/**
* @brief startSpellCast attempt to start casting a spell. Might fail immediately if conditions are not met.
* @param actor
diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp
index 70338669e..c56ee2ffb 100644
--- a/components/compiler/extensions0.cpp
+++ b/components/compiler/extensions0.cpp
@@ -303,6 +303,7 @@ namespace Compiler
extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit);
extensions.registerInstruction("tgm", "", opcodeToggleGodMode);
extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode);
+ extensions.registerInstruction("togglescripts", "", opcodeToggleScripts);
extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation);
extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation);
extensions.registerFunction ("getpcinjail", 'l', "", opcodeGetPcInJail);
diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp
index e5cf2e965..a4aab8aa1 100644
--- a/components/compiler/opcodes.hpp
+++ b/components/compiler/opcodes.hpp
@@ -278,6 +278,7 @@ namespace Compiler
const int opcodeShowVars = 0x200021d;
const int opcodeShowVarsExplicit = 0x200021e;
const int opcodeToggleGodMode = 0x200021f;
+ const int opcodeToggleScripts = 0x2000301;
const int opcodeDisableLevitation = 0x2000220;
const int opcodeEnableLevitation = 0x2000221;
const int opcodeCast = 0x2000227;
diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp
index 56a86f87f..ec1fcc21e 100644
--- a/components/contentselector/model/contentmodel.cpp
+++ b/components/contentselector/model/contentmodel.cpp
@@ -459,7 +459,7 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
EsmFile *file = new EsmFile(path);
foreach (const ESM::Header::MasterData &item, fileReader.getGameFiles())
- file->addGameFile(QString::fromStdString(item.name));
+ file->addGameFile(QString::fromUtf8(item.name.c_str()));
file->setAuthor (QString::fromUtf8(fileReader.getAuthor().c_str()));
file->setDate (info.lastModified());
diff --git a/components/esm/aipackage.cpp b/components/esm/aipackage.cpp
index 209a1fe26..8ad64b797 100644
--- a/components/esm/aipackage.cpp
+++ b/components/esm/aipackage.cpp
@@ -11,36 +11,55 @@ namespace ESM
mServices = 0;
}
+ void AIPackageList::add(ESMReader &esm)
+ {
+ AIPackage pack;
+ if (esm.retSubName() == AI_CNDT) {
+ mList.back().mCellName = esm.getHString();
+ } else if (esm.retSubName() == AI_Wander) {
+ pack.mType = AI_Wander;
+ esm.getHExact(&pack.mWander, 14);
+ mList.push_back(pack);
+ } else if (esm.retSubName() == AI_Travel) {
+ pack.mType = AI_Travel;
+ esm.getHExact(&pack.mTravel, 16);
+ mList.push_back(pack);
+ } else if (esm.retSubName() == AI_Escort ||
+ esm.retSubName() == AI_Follow)
+ {
+ pack.mType =
+ (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow;
+ esm.getHExact(&pack.mTarget, 48);
+ mList.push_back(pack);
+ } else if (esm.retSubName() == AI_Activate) {
+ pack.mType = AI_Activate;
+ esm.getHExact(&pack.mActivate, 33);
+ mList.push_back(pack);
+ } else { // not AI package related data, so leave
+ return;
+ }
+
+ }
+
void AIPackageList::load(ESMReader &esm)
{
mList.clear();
while (esm.hasMoreSubs()) {
// initialize every iteration
- AIPackage pack;
- esm.getSubName();
- if (esm.retSubName() == 0x54444e43) { // CNDT
- mList.back().mCellName = esm.getHString();
- } else if (esm.retSubName() == AI_Wander) {
- pack.mType = AI_Wander;
- esm.getHExact(&pack.mWander, 14);
- mList.push_back(pack);
- } else if (esm.retSubName() == AI_Travel) {
- pack.mType = AI_Travel;
- esm.getHExact(&pack.mTravel, 16);
- mList.push_back(pack);
- } else if (esm.retSubName() == AI_Escort ||
- esm.retSubName() == AI_Follow)
+ esm.getSubName();
+ switch (esm.retSubName().val)
{
- pack.mType =
- (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow;
- esm.getHExact(&pack.mTarget, 48);
- mList.push_back(pack);
- } else if (esm.retSubName() == AI_Activate) {
- pack.mType = AI_Activate;
- esm.getHExact(&pack.mActivate, 33);
- mList.push_back(pack);
- } else { // not AI package related data, so leave
- return;
+ case AI_Wander:
+ case AI_Activate:
+ case AI_Escort:
+ case AI_Follow:
+ case AI_Travel:
+ case AI_CNDT:
+
+ add(esm);
+ break;
+ default:
+ return;
}
}
}
diff --git a/components/esm/aipackage.hpp b/components/esm/aipackage.hpp
index cbe82f16e..30bd2ce04 100644
--- a/components/esm/aipackage.hpp
+++ b/components/esm/aipackage.hpp
@@ -63,7 +63,8 @@ namespace ESM
AI_Travel = 0x545f4941,
AI_Follow = 0x465f4941,
AI_Escort = 0x455f4941,
- AI_Activate = 0x415f4941
+ AI_Activate = 0x415f4941,
+ AI_CNDT = 0x54444e43
};
/// \note Used for storaging packages in a single container
@@ -90,11 +91,12 @@ namespace ESM
{
std::vector mList;
- /// \note This breaks consistency of subrecords reading:
- /// after calling it subrecord name is already read, so
- /// it needs to use retSubName() if needed. But, hey, there
- /// is only one field left (XSCL) and only two records uses AI
+ /// Add a single AIPackage, assumes subrecord name was already read
+ void add(ESMReader &esm);
+
+ /// TODO: remove this method. The ESM format does not guarantee that all AI packages follow one another
void load(ESMReader &esm);
+
void save(ESMWriter &esm) const;
};
}
diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp
index f8c3a4718..066551d6f 100644
--- a/components/esm/loadarmo.cpp
+++ b/components/esm/loadarmo.cpp
@@ -7,52 +7,87 @@
namespace ESM
{
-void PartReferenceList::load(ESMReader &esm)
-{
- mParts.clear();
- while (esm.isNextSub("INDX"))
+ void PartReferenceList::add(ESMReader &esm)
{
PartReference pr;
esm.getHT(pr.mPart); // The INDX byte
pr.mMale = esm.getHNOString("BNAM");
pr.mFemale = esm.getHNOString("CNAM");
mParts.push_back(pr);
+
}
-}
-void PartReferenceList::save(ESMWriter &esm) const
-{
- for (std::vector::const_iterator it = mParts.begin(); it != mParts.end(); ++it)
+ void PartReferenceList::load(ESMReader &esm)
{
- esm.writeHNT("INDX", it->mPart);
- esm.writeHNOString("BNAM", it->mMale);
- esm.writeHNOString("CNAM", it->mFemale);
+ mParts.clear();
+ while (esm.isNextSub("INDX"))
+ {
+ add(esm);
+ }
}
-}
-unsigned int Armor::sRecordId = REC_ARMO;
+ void PartReferenceList::save(ESMWriter &esm) const
+ {
+ for (std::vector::const_iterator it = mParts.begin(); it != mParts.end(); ++it)
+ {
+ esm.writeHNT("INDX", it->mPart);
+ esm.writeHNOString("BNAM", it->mMale);
+ esm.writeHNOString("CNAM", it->mFemale);
+ }
+ }
-void Armor::load(ESMReader &esm)
-{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- mScript = esm.getHNOString("SCRI");
- esm.getHNT(mData, "AODT", 24);
- mIcon = esm.getHNOString("ITEX");
- mParts.load(esm);
- mEnchant = esm.getHNOString("ENAM");
-}
+ unsigned int Armor::sRecordId = REC_ARMO;
-void Armor::save(ESMWriter &esm) const
-{
- esm.writeHNCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNOCString("SCRI", mScript);
- esm.writeHNT("AODT", mData, 24);
- esm.writeHNOCString("ITEX", mIcon);
- mParts.save(esm);
- esm.writeHNOCString("ENAM", mEnchant);
-}
+ void Armor::load(ESMReader &esm)
+ {
+ mParts.mParts.clear();
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'A','O','D','T'>::value:
+ esm.getHT(mData, 24);
+ hasData = true;
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'I','T','E','X'>::value:
+ mIcon = esm.getHString();
+ break;
+ case ESM::FourCC<'E','N','A','M'>::value:
+ mEnchant = esm.getHString();
+ break;
+ case ESM::FourCC<'I','N','D','X'>::value:
+ mParts.add(esm);
+ break;
+ default:
+ esm.fail("Unknown subrecord");
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing CTDT subrecord");
+ }
+
+ void Armor::save(ESMWriter &esm) const
+ {
+ esm.writeHNCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNOCString("SCRI", mScript);
+ esm.writeHNT("AODT", mData, 24);
+ esm.writeHNOCString("ITEX", mIcon);
+ mParts.save(esm);
+ esm.writeHNOCString("ENAM", mEnchant);
+ }
void Armor::blank()
{
diff --git a/components/esm/loadarmo.hpp b/components/esm/loadarmo.hpp
index 6be9dd971..356dfc1c5 100644
--- a/components/esm/loadarmo.hpp
+++ b/components/esm/loadarmo.hpp
@@ -55,6 +55,10 @@ struct PartReferenceList
{
std::vector mParts;
+ /// Load one part, assumes the subrecord name was already read
+ void add(ESMReader &esm);
+
+ /// TODO: remove this method. The ESM format does not guarantee that all Part subrecords follow one another.
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
};
diff --git a/components/esm/loadbook.cpp b/components/esm/loadbook.cpp
index c8b7e9478..47f52fc31 100644
--- a/components/esm/loadbook.cpp
+++ b/components/esm/loadbook.cpp
@@ -8,26 +8,54 @@ namespace ESM
{
unsigned int Book::sRecordId = REC_BOOK;
-void Book::load(ESMReader &esm)
-{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "BKDT", 20);
- mScript = esm.getHNOString("SCRI");
- mIcon = esm.getHNOString("ITEX");
- mText = esm.getHNOString("TEXT");
- mEnchant = esm.getHNOString("ENAM");
-}
-void Book::save(ESMWriter &esm) const
-{
- esm.writeHNCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNT("BKDT", mData, 20);
- esm.writeHNOCString("SCRI", mScript);
- esm.writeHNOCString("ITEX", mIcon);
- esm.writeHNOString("TEXT", mText);
- esm.writeHNOCString("ENAM", mEnchant);
-}
+ void Book::load(ESMReader &esm)
+ {
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'B','K','D','T'>::value:
+ esm.getHT(mData, 20);
+ hasData = true;
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'I','T','E','X'>::value:
+ mIcon = esm.getHString();
+ break;
+ case ESM::FourCC<'E','N','A','M'>::value:
+ mEnchant = esm.getHString();
+ break;
+ case ESM::FourCC<'T','E','X','T'>::value:
+ mText = esm.getHString();
+ break;
+ default:
+ esm.fail("Unknown subrecord");
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing BKDT subrecord");
+ }
+ void Book::save(ESMWriter &esm) const
+ {
+ esm.writeHNCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNT("BKDT", mData, 20);
+ esm.writeHNOCString("SCRI", mScript);
+ esm.writeHNOCString("ITEX", mIcon);
+ esm.writeHNOString("TEXT", mText);
+ esm.writeHNOCString("ENAM", mEnchant);
+ }
void Book::blank()
{
diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp
index 17ecdf3ae..5f49b5e70 100644
--- a/components/esm/loadclot.cpp
+++ b/components/esm/loadclot.cpp
@@ -10,17 +10,42 @@ namespace ESM
void Clothing::load(ESMReader &esm)
{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "CTDT", 12);
-
- mScript = esm.getHNOString("SCRI");
- mIcon = esm.getHNOString("ITEX");
-
- mParts.load(esm);
-
-
- mEnchant = esm.getHNOString("ENAM");
+ mParts.mParts.clear();
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'C','T','D','T'>::value:
+ esm.getHT(mData, 12);
+ hasData = true;
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'I','T','E','X'>::value:
+ mIcon = esm.getHString();
+ break;
+ case ESM::FourCC<'E','N','A','M'>::value:
+ mEnchant = esm.getHString();
+ break;
+ case ESM::FourCC<'I','N','D','X'>::value:
+ mParts.add(esm);
+ break;
+ default:
+ esm.fail("Unknown subrecord");
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing CTDT subrecord");
}
void Clothing::save(ESMWriter &esm) const
diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp
index 51a385f06..f48f06930 100644
--- a/components/esm/loadcont.cpp
+++ b/components/esm/loadcont.cpp
@@ -7,14 +7,19 @@
namespace ESM
{
+void InventoryList::add(ESMReader &esm)
+{
+ ContItem ci;
+ esm.getHT(ci, 36);
+ mList.push_back(ci);
+}
+
void InventoryList::load(ESMReader &esm)
{
mList.clear();
- ContItem ci;
while (esm.isNextSub("NPCO"))
{
- esm.getHT(ci, 36);
- mList.push_back(ci);
+ add(esm);
}
}
diff --git a/components/esm/loadcont.hpp b/components/esm/loadcont.hpp
index 2808b67b5..93db94759 100644
--- a/components/esm/loadcont.hpp
+++ b/components/esm/loadcont.hpp
@@ -26,6 +26,10 @@ struct InventoryList
{
std::vector mList;
+ /// Load one item, assumes subrecord name is already read
+ void add(ESMReader &esm);
+
+ /// TODO: remove this method, the ESM format doesn't guarantee that all ContItems follow one another
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
};
diff --git a/components/esm/loaddoor.cpp b/components/esm/loaddoor.cpp
index c56b06337..f446eed61 100644
--- a/components/esm/loaddoor.cpp
+++ b/components/esm/loaddoor.cpp
@@ -8,23 +8,43 @@ namespace ESM
{
unsigned int Door::sRecordId = REC_DOOR;
-void Door::load(ESMReader &esm)
-{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- mScript = esm.getHNOString("SCRI");
- mOpenSound = esm.getHNOString("SNAM");
- mCloseSound = esm.getHNOString("ANAM");
-}
+ void Door::load(ESMReader &esm)
+ {
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'S','N','A','M'>::value:
+ mOpenSound = esm.getHString();
+ break;
+ case ESM::FourCC<'A','N','A','M'>::value:
+ mCloseSound = esm.getHString();
+ break;
+ default:
+ esm.fail("Unknown subrecord");
+ }
+ }
+ }
-void Door::save(ESMWriter &esm) const
-{
- esm.writeHNCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNOCString("SCRI", mScript);
- esm.writeHNOCString("SNAM", mOpenSound);
- esm.writeHNOCString("ANAM", mCloseSound);
-}
+ void Door::save(ESMWriter &esm) const
+ {
+ esm.writeHNCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNOCString("SCRI", mScript);
+ esm.writeHNOCString("SNAM", mOpenSound);
+ esm.writeHNOCString("ANAM", mCloseSound);
+ }
void Door::blank()
{
diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp
index cbdca3e31..3ec07a2a9 100644
--- a/components/esm/loadmgef.cpp
+++ b/components/esm/loadmgef.cpp
@@ -191,33 +191,64 @@ namespace ESM
void MagicEffect::load(ESMReader &esm)
{
- esm.getHNT(mIndex, "INDX");
+ esm.getHNT(mIndex, "INDX");
mId = indexToId (mIndex);
- esm.getHNT(mData, "MEDT", 36);
- if (esm.getFormat() == 0)
- {
- // don't allow mods to change fixed flags in the legacy format
- mData.mFlags &= (AllowSpellmaking | AllowEnchanting | NegativeLight);
- if (mIndex>=0 && mIndex=0 && mIndex::value:
+ mIcon = esm.getHString();
+ break;
+ case ESM::FourCC<'P','T','E','X'>::value:
+ mParticle = esm.getHString();
+ break;
+ case ESM::FourCC<'B','S','N','D'>::value:
+ mBoltSound = esm.getHString();
+ break;
+ case ESM::FourCC<'C','S','N','D'>::value:
+ mCastSound = esm.getHString();
+ break;
+ case ESM::FourCC<'H','S','N','D'>::value:
+ mHitSound = esm.getHString();
+ break;
+ case ESM::FourCC<'A','S','N','D'>::value:
+ mAreaSound = esm.getHString();
+ break;
+ case ESM::FourCC<'C','V','F','X'>::value:
+ mCasting = esm.getHString();
+ break;
+ case ESM::FourCC<'B','V','F','X'>::value:
+ mBolt = esm.getHString();
+ break;
+ case ESM::FourCC<'H','V','F','X'>::value:
+ mHit = esm.getHString();
+ break;
+ case ESM::FourCC<'A','V','F','X'>::value:
+ mArea = esm.getHString();
+ break;
+ case ESM::FourCC<'D','E','S','C'>::value:
+ mDescription = esm.getHString();
+ break;
+ default:
+ esm.fail("Unknown subrecord " + esm.retSubName().toString());
+ }
+ }
}
void MagicEffect::save(ESMWriter &esm) const
{
diff --git a/components/esm/loadmisc.cpp b/components/esm/loadmisc.cpp
index 2ca09e8ae..81c094f2b 100644
--- a/components/esm/loadmisc.cpp
+++ b/components/esm/loadmisc.cpp
@@ -8,22 +8,45 @@ namespace ESM
{
unsigned int Miscellaneous::sRecordId = REC_MISC;
-void Miscellaneous::load(ESMReader &esm)
-{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "MCDT", 12);
- mScript = esm.getHNOString("SCRI");
- mIcon = esm.getHNOString("ITEX");
-}
-void Miscellaneous::save(ESMWriter &esm) const
-{
- esm.writeHNCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNT("MCDT", mData, 12);
- esm.writeHNOCString("SCRI", mScript);
- esm.writeHNOCString("ITEX", mIcon);
-}
+ void Miscellaneous::load(ESMReader &esm)
+ {
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'M','C','D','T'>::value:
+ esm.getHT(mData, 12);
+ hasData = true;
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'I','T','E','X'>::value:
+ mIcon = esm.getHString();
+ break;
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing MCDT subrecord");
+ }
+
+ void Miscellaneous::save(ESMWriter &esm) const
+ {
+ esm.writeHNCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNT("MCDT", mData, 12);
+ esm.writeHNOCString("SCRI", mScript);
+ esm.writeHNOCString("ITEX", mIcon);
+ }
void Miscellaneous::blank()
{
diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp
index 6ca070cf3..3d617241b 100644
--- a/components/esm/loadnpc.cpp
+++ b/components/esm/loadnpc.cpp
@@ -8,92 +8,136 @@ namespace ESM
{
unsigned int NPC::sRecordId = REC_NPC_;
-void NPC::load(ESMReader &esm)
-{
- mPersistent = esm.getRecordFlags() & 0x0400;
-
- mModel = esm.getHNOString("MODL");
- mName = esm.getHNOString("FNAM");
-
- mRace = esm.getHNString("RNAM");
- mClass = esm.getHNString("CNAM");
- mFaction = esm.getHNString("ANAM");
- mHead = esm.getHNString("BNAM");
- mHair = esm.getHNString("KNAM");
-
- mScript = esm.getHNOString("SCRI");
-
- esm.getSubNameIs("NPDT");
- esm.getSubHeader();
- if (esm.getSubSize() == 52)
- {
- mNpdtType = NPC_DEFAULT;
- esm.getExact(&mNpdt52, 52);
- }
- else if (esm.getSubSize() == 12)
+ void NPC::load(ESMReader &esm)
{
- mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
- esm.getExact(&mNpdt12, 12);
- }
- else
- esm.fail("NPC_NPDT must be 12 or 52 bytes long");
-
- esm.getHNT(mFlags, "FLAG");
+ mPersistent = esm.getRecordFlags() & 0x0400;
- mInventory.load(esm);
- mSpells.load(esm);
+ mSpells.mList.clear();
+ mInventory.mList.clear();
+ mTransport.clear();
+ mAiPackage.mList.clear();
- if (esm.isNextSub("AIDT"))
- {
- esm.getHExact(&mAiData, sizeof(mAiData));
- mHasAI= true;
- }
- else
+ bool hasNpdt = false;
+ bool hasFlags = false;
mHasAI = false;
-
- mTransport.clear();
- while (esm.isNextSub("DODT") || esm.isNextSub("DNAM")) {
- if (esm.retSubName() == 0x54444f44) { // DODT struct
- Dest dodt;
- esm.getHExact(&dodt.mPos, 24);
- mTransport.push_back(dodt);
- } else if (esm.retSubName() == 0x4d414e44) { // DNAM struct
- mTransport.back().mCellName = esm.getHString();
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'R','N','A','M'>::value:
+ mRace = esm.getHString();
+ break;
+ case ESM::FourCC<'C','N','A','M'>::value:
+ mClass = esm.getHString();
+ break;
+ case ESM::FourCC<'A','N','A','M'>::value:
+ mFaction = esm.getHString();
+ break;
+ case ESM::FourCC<'B','N','A','M'>::value:
+ mHead = esm.getHString();
+ break;
+ case ESM::FourCC<'K','N','A','M'>::value:
+ mHair = esm.getHString();
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'N','P','D','T'>::value:
+ hasNpdt = true;
+ esm.getSubHeader();
+ if (esm.getSubSize() == 52)
+ {
+ mNpdtType = NPC_DEFAULT;
+ esm.getExact(&mNpdt52, 52);
+ }
+ else if (esm.getSubSize() == 12)
+ {
+ mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
+ esm.getExact(&mNpdt12, 12);
+ }
+ else
+ esm.fail("NPC_NPDT must be 12 or 52 bytes long");
+ break;
+ case ESM::FourCC<'F','L','A','G'>::value:
+ hasFlags = true;
+ esm.getHT(mFlags);
+ break;
+ case ESM::FourCC<'N','P','C','S'>::value:
+ mSpells.add(esm);
+ break;
+ case ESM::FourCC<'N','P','C','O'>::value:
+ mInventory.add(esm);
+ break;
+ case ESM::FourCC<'A','I','D','T'>::value:
+ esm.getHExact(&mAiData, sizeof(mAiData));
+ mHasAI= true;
+ break;
+ case ESM::FourCC<'D','O','D','T'>::value:
+ {
+ Dest dodt;
+ esm.getHExact(&dodt.mPos, 24);
+ mTransport.push_back(dodt);
+ break;
+ }
+ case ESM::FourCC<'D','N','A','M'>::value:
+ mTransport.back().mCellName = esm.getHString();
+ break;
+ case AI_Wander:
+ case AI_Activate:
+ case AI_Escort:
+ case AI_Follow:
+ case AI_Travel:
+ case AI_CNDT:
+ mAiPackage.add(esm);
+ break;
+ default:
+ esm.fail("Unknown subrecord " + esm.retSubName().toString());
+ }
}
+ if (!hasNpdt)
+ esm.fail("Missing NPDT subrecord");
+ if (!hasFlags)
+ esm.fail("Missing FLAG subrecord");
}
- mAiPackage.load(esm);
-}
-void NPC::save(ESMWriter &esm) const
-{
- esm.writeHNOCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNCString("RNAM", mRace);
- esm.writeHNCString("CNAM", mClass);
- esm.writeHNCString("ANAM", mFaction);
- esm.writeHNCString("BNAM", mHead);
- esm.writeHNCString("KNAM", mHair);
- esm.writeHNOCString("SCRI", mScript);
-
- if (mNpdtType == NPC_DEFAULT)
- esm.writeHNT("NPDT", mNpdt52, 52);
- else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS)
- esm.writeHNT("NPDT", mNpdt12, 12);
-
- esm.writeHNT("FLAG", mFlags);
-
- mInventory.save(esm);
- mSpells.save(esm);
- if (mHasAI) {
- esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
- }
+ void NPC::save(ESMWriter &esm) const
+ {
+ esm.writeHNOCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNCString("RNAM", mRace);
+ esm.writeHNCString("CNAM", mClass);
+ esm.writeHNCString("ANAM", mFaction);
+ esm.writeHNCString("BNAM", mHead);
+ esm.writeHNCString("KNAM", mHair);
+ esm.writeHNOCString("SCRI", mScript);
+
+ if (mNpdtType == NPC_DEFAULT)
+ esm.writeHNT("NPDT", mNpdt52, 52);
+ else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS)
+ esm.writeHNT("NPDT", mNpdt12, 12);
+
+ esm.writeHNT("FLAG", mFlags);
+
+ mInventory.save(esm);
+ mSpells.save(esm);
+ if (mHasAI) {
+ esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
+ }
- typedef std::vector::const_iterator DestIter;
- for (DestIter it = mTransport.begin(); it != mTransport.end(); ++it) {
- esm.writeHNT("DODT", it->mPos, sizeof(it->mPos));
- esm.writeHNOCString("DNAM", it->mCellName);
+ typedef std::vector::const_iterator DestIter;
+ for (DestIter it = mTransport.begin(); it != mTransport.end(); ++it) {
+ esm.writeHNT("DODT", it->mPos, sizeof(it->mPos));
+ esm.writeHNOCString("DNAM", it->mCellName);
+ }
+ mAiPackage.save(esm);
}
- mAiPackage.save(esm);
-}
bool NPC::isMale() const {
return (mFlags & Female) == 0;
diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp
index 17f2e0267..211fd5ffb 100644
--- a/components/esm/loadrace.cpp
+++ b/components/esm/loadrace.cpp
@@ -20,10 +20,34 @@ namespace ESM
void Race::load(ESMReader &esm)
{
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "RADT", 140);
- mPowers.load(esm);
- mDescription = esm.getHNOString("DESC");
+ mPowers.mList.clear();
+
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'R','A','D','T'>::value:
+ esm.getHT(mData, 140);
+ hasData = true;
+ break;
+ case ESM::FourCC<'D','E','S','C'>::value:
+ mDescription = esm.getHString();
+ break;
+ case ESM::FourCC<'N','P','C','S'>::value:
+ mPowers.add(esm);
+ break;
+ default:
+ esm.fail("Unknown subrecord " + esm.retSubName().toString());
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing RADT subrecord");
}
void Race::save(ESMWriter &esm) const
{
diff --git a/components/esm/loadspel.cpp b/components/esm/loadspel.cpp
index 2c98d796d..716f47e71 100644
--- a/components/esm/loadspel.cpp
+++ b/components/esm/loadspel.cpp
@@ -10,9 +10,30 @@ namespace ESM
void Spell::load(ESMReader &esm)
{
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "SPDT", 12);
- mEffects.load(esm);
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t val = esm.retSubName().val;
+
+ switch (val)
+ {
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'S','P','D','T'>::value:
+ esm.getHT(mData, 12);
+ hasData = true;
+ break;
+ case ESM::FourCC<'E','N','A','M'>::value:
+ ENAMstruct s;
+ esm.getHT(s, 24);
+ mEffects.mList.push_back(s);
+ break;
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing SPDT subrecord");
}
void Spell::save(ESMWriter &esm) const
diff --git a/components/esm/loadweap.cpp b/components/esm/loadweap.cpp
index 1d0b149df..981a5815a 100644
--- a/components/esm/loadweap.cpp
+++ b/components/esm/loadweap.cpp
@@ -8,24 +8,50 @@ namespace ESM
{
unsigned int Weapon::sRecordId = REC_WEAP;
-void Weapon::load(ESMReader &esm)
-{
- mModel = esm.getHNString("MODL");
- mName = esm.getHNOString("FNAM");
- esm.getHNT(mData, "WPDT", 32);
- mScript = esm.getHNOString("SCRI");
- mIcon = esm.getHNOString("ITEX");
- mEnchant = esm.getHNOString("ENAM");
-}
-void Weapon::save(ESMWriter &esm) const
-{
- esm.writeHNCString("MODL", mModel);
- esm.writeHNOCString("FNAM", mName);
- esm.writeHNT("WPDT", mData, 32);
- esm.writeHNOCString("SCRI", mScript);
- esm.writeHNOCString("ITEX", mIcon);
- esm.writeHNOCString("ENAM", mEnchant);
-}
+ void Weapon::load(ESMReader &esm)
+ {
+ bool hasData = false;
+ while (esm.hasMoreSubs())
+ {
+ esm.getSubName();
+ uint32_t name = esm.retSubName().val;
+ switch (name)
+ {
+ case ESM::FourCC<'M','O','D','L'>::value:
+ mModel = esm.getHString();
+ break;
+ case ESM::FourCC<'F','N','A','M'>::value:
+ mName = esm.getHString();
+ break;
+ case ESM::FourCC<'W','P','D','T'>::value:
+ esm.getHT(mData, 32);
+ hasData = true;
+ break;
+ case ESM::FourCC<'S','C','R','I'>::value:
+ mScript = esm.getHString();
+ break;
+ case ESM::FourCC<'I','T','E','X'>::value:
+ mIcon = esm.getHString();
+ break;
+ case ESM::FourCC<'E','N','A','M'>::value:
+ mEnchant = esm.getHString();
+ break;
+ default:
+ esm.fail("Unknown subrecord");
+ }
+ }
+ if (!hasData)
+ esm.fail("Missing WPDT subrecord");
+ }
+ void Weapon::save(ESMWriter &esm) const
+ {
+ esm.writeHNCString("MODL", mModel);
+ esm.writeHNOCString("FNAM", mName);
+ esm.writeHNT("WPDT", mData, 32);
+ esm.writeHNOCString("SCRI", mScript);
+ esm.writeHNOCString("ITEX", mIcon);
+ esm.writeHNOCString("ENAM", mEnchant);
+ }
void Weapon::blank()
{
diff --git a/components/esm/spelllist.cpp b/components/esm/spelllist.cpp
index 8ec386db4..98bd53ae6 100644
--- a/components/esm/spelllist.cpp
+++ b/components/esm/spelllist.cpp
@@ -9,10 +9,15 @@ void SpellList::load(ESMReader &esm)
{
mList.clear();
while (esm.isNextSub("NPCS")) {
- mList.push_back(esm.getHString());
+ add(esm);
}
}
+void SpellList::add(ESMReader &esm)
+{
+ mList.push_back(esm.getHString());
+}
+
void SpellList::save(ESMWriter &esm) const
{
for (std::vector::const_iterator it = mList.begin(); it != mList.end(); ++it) {
diff --git a/components/esm/spelllist.hpp b/components/esm/spelllist.hpp
index bcd6ba798..9493199a8 100644
--- a/components/esm/spelllist.hpp
+++ b/components/esm/spelllist.hpp
@@ -19,6 +19,11 @@ namespace ESM
/// Is this spell ID in mList?
bool exists(const std::string& spell) const;
+ /// Load one spell, assumes the subrecord name was already read
+ void add(ESMReader &esm);
+
+ /// Load all spells
+ /// TODO: remove this method, the ESM format doesn't guarantee that all spell subrecords follow one another
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
};
diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp
index 3d0b35910..01032bcda 100644
--- a/components/terrain/buffercache.cpp
+++ b/components/terrain/buffercache.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "buffercache.hpp"
#include
diff --git a/components/terrain/buffercache.hpp b/components/terrain/buffercache.hpp
index 51c0a61af..887f0822e 100644
--- a/components/terrain/buffercache.hpp
+++ b/components/terrain/buffercache.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_BUFFERCACHE_H
#define COMPONENTS_TERRAIN_BUFFERCACHE_H
diff --git a/components/terrain/chunk.cpp b/components/terrain/chunk.cpp
index 9c60ee017..cce5abd36 100644
--- a/components/terrain/chunk.cpp
+++ b/components/terrain/chunk.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "chunk.hpp"
#include
diff --git a/components/terrain/chunk.hpp b/components/terrain/chunk.hpp
index 9b2ed76ac..22b4f26ef 100644
--- a/components/terrain/chunk.hpp
+++ b/components/terrain/chunk.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_TERRAINBATCH_H
#define COMPONENTS_TERRAIN_TERRAINBATCH_H
diff --git a/components/terrain/defaultworld.cpp b/components/terrain/defaultworld.cpp
index 943658235..e14c64f3a 100644
--- a/components/terrain/defaultworld.cpp
+++ b/components/terrain/defaultworld.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "defaultworld.hpp"
#include
diff --git a/components/terrain/defaultworld.hpp b/components/terrain/defaultworld.hpp
index 62441c420..90e8cc2b6 100644
--- a/components/terrain/defaultworld.hpp
+++ b/components/terrain/defaultworld.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_H
#define COMPONENTS_TERRAIN_H
diff --git a/components/terrain/defs.hpp b/components/terrain/defs.hpp
index 685937653..6d173d136 100644
--- a/components/terrain/defs.hpp
+++ b/components/terrain/defs.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_DEFS_HPP
#define COMPONENTS_TERRAIN_DEFS_HPP
diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp
index a40e576ed..4ff04ab93 100644
--- a/components/terrain/material.cpp
+++ b/components/terrain/material.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "material.hpp"
#include
diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp
index b9000cb1b..f35080e7c 100644
--- a/components/terrain/material.hpp
+++ b/components/terrain/material.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_MATERIAL_H
#define COMPONENTS_TERRAIN_MATERIAL_H
diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp
index 755c45c21..5fce5eae9 100644
--- a/components/terrain/quadtreenode.cpp
+++ b/components/terrain/quadtreenode.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "quadtreenode.hpp"
#include
diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp
index e8392b8e4..1ecd6fcd5 100644
--- a/components/terrain/quadtreenode.hpp
+++ b/components/terrain/quadtreenode.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_QUADTREENODE_H
#define COMPONENTS_TERRAIN_QUADTREENODE_H
diff --git a/components/terrain/storage.cpp b/components/terrain/storage.cpp
index e69de29bb..14009127d 100644
--- a/components/terrain/storage.cpp
+++ b/components/terrain/storage.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
diff --git a/components/terrain/storage.hpp b/components/terrain/storage.hpp
index aa52ffc4b..7846e91c6 100644
--- a/components/terrain/storage.hpp
+++ b/components/terrain/storage.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_STORAGE_H
#define COMPONENTS_TERRAIN_STORAGE_H
diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp
index 6a66ac3d7..269152e61 100644
--- a/components/terrain/terraingrid.cpp
+++ b/components/terrain/terraingrid.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "terraingrid.hpp"
#include
diff --git a/components/terrain/terraingrid.hpp b/components/terrain/terraingrid.hpp
index 7cbf45576..97ef6d14d 100644
--- a/components/terrain/terraingrid.hpp
+++ b/components/terrain/terraingrid.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_TERRAINGRID_H
#define COMPONENTS_TERRAIN_TERRAINGRID_H
diff --git a/components/terrain/world.cpp b/components/terrain/world.cpp
index 93caeb8df..5cc2647c6 100644
--- a/components/terrain/world.cpp
+++ b/components/terrain/world.cpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "world.hpp"
#include
diff --git a/components/terrain/world.hpp b/components/terrain/world.hpp
index beca7903a..3e63b4c93 100644
--- a/components/terrain/world.hpp
+++ b/components/terrain/world.hpp
@@ -1,3 +1,24 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef COMPONENTS_TERRAIN_WORLD_H
#define COMPONENTS_TERRAIN_WORLD_H
diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader
index 8384588e4..a4ca10fcc 100644
--- a/files/materials/terrain.shader
+++ b/files/materials/terrain.shader
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2015 scrawl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "core.h"
#define IS_FIRST_PASS (@shPropertyString(pass_index) == 0)