From 801c0eb57c4300ffb35556711a84411a1b62b28a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Feb 2015 17:34:08 +0100 Subject: [PATCH 1/8] Detect Creature should detect alive creatures only (Fixes #2353) --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a60eae48a3..0694a3da6b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2886,6 +2886,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; From 03257ecae538feb9fdd1482629a16883c57ca191 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Feb 2015 18:05:02 +0100 Subject: [PATCH 2/8] QString encoding fix --- apps/launcher/graphicspage.cpp | 10 +++++----- apps/launcher/main.cpp | 2 +- components/contentselector/model/contentmodel.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index dccf8bb8ce..cdb51348c8 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 5c3f384581..11ea568692 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/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 56a86f87f6..ec1fcc21e4 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()); From 399c24c64668046f879e788418def56285dd5d8f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 7 Feb 2015 23:27:32 +0100 Subject: [PATCH 3/8] CMake cleanup: remove redundant setting of Permissions to default values --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b80d4c956..ed4136813c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,23 +438,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) From 218f789d88ac1ea46ba9675dc9dcd67009602184 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 8 Feb 2015 01:08:07 +0100 Subject: [PATCH 4/8] Fix player DrawState reset when selecting enchanted item (Fixes #2356) --- apps/openmw/mwgui/spellwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 6d3c79b349..69365c1081 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(); } From ee574e08ef48c2496ad522c9fa8aecd5b218dccc Mon Sep 17 00:00:00 2001 From: jacmoe Date: Tue, 3 Feb 2015 23:12:33 +0100 Subject: [PATCH 5/8] MIT License header added to all terrain component files. --- components/terrain/buffercache.cpp | 21 +++++++++++++++++++++ components/terrain/buffercache.hpp | 21 +++++++++++++++++++++ components/terrain/chunk.cpp | 21 +++++++++++++++++++++ components/terrain/chunk.hpp | 21 +++++++++++++++++++++ components/terrain/defaultworld.cpp | 21 +++++++++++++++++++++ components/terrain/defaultworld.hpp | 21 +++++++++++++++++++++ components/terrain/defs.hpp | 21 +++++++++++++++++++++ components/terrain/material.cpp | 21 +++++++++++++++++++++ components/terrain/material.hpp | 21 +++++++++++++++++++++ components/terrain/quadtreenode.cpp | 21 +++++++++++++++++++++ components/terrain/quadtreenode.hpp | 21 +++++++++++++++++++++ components/terrain/storage.cpp | 21 +++++++++++++++++++++ components/terrain/storage.hpp | 21 +++++++++++++++++++++ components/terrain/terraingrid.cpp | 21 +++++++++++++++++++++ components/terrain/terraingrid.hpp | 21 +++++++++++++++++++++ components/terrain/world.cpp | 21 +++++++++++++++++++++ components/terrain/world.hpp | 21 +++++++++++++++++++++ files/materials/terrain.shader | 22 ++++++++++++++++++++++ 18 files changed, 379 insertions(+) diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp index 3d0b359104..01032bcdae 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 51c0a61af2..887f0822ef 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 9c60ee0173..cce5abd363 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 9b2ed76ac6..22b4f26ef4 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 9436582353..e14c64f3a0 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 62441c4200..90e8cc2b6a 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 6859376532..6d173d1361 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 a40e576ed9..4ff04ab93a 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 b9000cb1b9..f35080e7c6 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 755c45c219..5fce5eae91 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 e8392b8e40..1ecd6fcd56 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 e69de29bb2..14009127d2 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 aa52ffc4bc..7846e91c6e 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 6a66ac3d7c..269152e611 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 7cbf455760..97ef6d14d3 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 93caeb8df9..5cc2647c67 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 beca7903ab..3e63b4c936 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 8384588e4f..a4ca10fcc3 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) From 3ccf4642b4e7f68c73c43ed451732789cf559683 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 10 Feb 2015 20:25:57 +0100 Subject: [PATCH 6/8] Implement ToggleScripts --- apps/openmw/engine.cpp | 11 ++++++---- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwscript/docs/vmformat.txt | 3 ++- apps/openmw/mwscript/miscextensions.cpp | 14 +++++++++++++ apps/openmw/mwworld/worldimp.cpp | 28 ++++++++++++++++++++----- apps/openmw/mwworld/worldimp.hpp | 4 ++++ components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 1 + 9 files changed, 56 insertions(+), 11 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 611f0a3045..669bae60a7 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(); + if (MWBase::Environment::get().getWorld()->getScriptsEnabled()) + { + // local scripts + executeLocalScripts(); - // global scripts - MWBase::Environment::get().getScriptManager()->getGlobalScripts().run(); + // global scripts + MWBase::Environment::get().getScriptManager()->getGlobalScripts().run(); + } MWBase::Environment::get().getWorld()->markCellAsUnchanged(); } diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 154d96f7d4..8180d0b1ab 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 5cb67c048d..4270c4be16 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/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 41cc6b88a9..93720aef62 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 cdc9f58cf8..52094947ce 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 0694a3da6b..188f3cdad3 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) { @@ -3167,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 1d103c6a94..9980f6f906 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 70338669e3..c56ee2ffb5 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 e5cf2e965e..a4aab8aa1b 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; From bf1839b3701df0937e096f8aed2f2b1c9c1b8c32 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 10 Feb 2015 22:01:57 +0100 Subject: [PATCH 7/8] Always print the exception to stderr --- apps/openmw/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 475fe63a2d..82fda060ed 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; } From 9009889d240185fb50e251d175341288957852a8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 10 Feb 2015 23:16:25 +0100 Subject: [PATCH 8/8] Don't rely on subrecord order when reading (Fixes #2361) --- components/esm/aipackage.cpp | 67 +++++++----- components/esm/aipackage.hpp | 12 ++- components/esm/loadarmo.cpp | 103 ++++++++++++------ components/esm/loadarmo.hpp | 4 + components/esm/loadbook.cpp | 68 ++++++++---- components/esm/loadclot.cpp | 47 +++++++-- components/esm/loadcont.cpp | 11 +- components/esm/loadcont.hpp | 4 + components/esm/loaddoor.cpp | 52 +++++++--- components/esm/loadmgef.cpp | 75 ++++++++++---- components/esm/loadmisc.cpp | 55 +++++++--- components/esm/loadnpc.cpp | 196 +++++++++++++++++++++-------------- components/esm/loadrace.cpp | 32 +++++- components/esm/loadspel.cpp | 27 ++++- components/esm/loadweap.cpp | 62 +++++++---- components/esm/spelllist.cpp | 7 +- components/esm/spelllist.hpp | 5 + 17 files changed, 574 insertions(+), 253 deletions(-) diff --git a/components/esm/aipackage.cpp b/components/esm/aipackage.cpp index 209a1fe264..8ad64b7975 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 cbe82f16ed..30bd2ce04c 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 f8c3a4718a..066551d6fe 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 6be9dd9717..356dfc1c5e 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 c8b7e94789..47f52fc31a 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 17ecdf3ae5..5f49b5e709 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 51a385f069..f48f069306 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 2808b67b56..93db94759d 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 c56b063379..f446eed611 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 cbdca3e317..3ec07a2a91 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 2ca09e8aec..81c094f2bc 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 6ca070cf37..3d617241b6 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -8,93 +8,137 @@ 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) + void NPC::load(ESMReader &esm) { - 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"); + mPersistent = esm.getRecordFlags() & 0x0400; - esm.getHNT(mFlags, "FLAG"); + mSpells.mList.clear(); + mInventory.mList.clear(); + mTransport.clear(); + mAiPackage.mList.clear(); - mInventory.load(esm); - mSpells.load(esm); - - 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); + 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); + 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); + esm.writeHNT("FLAG", mFlags); - mInventory.save(esm); - mSpells.save(esm); - if (mHasAI) { - esm.writeHNT("AIDT", mAiData, sizeof(mAiData)); + 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); + } + mAiPackage.save(esm); } - 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); -} - bool NPC::isMale() const { return (mFlags & Female) == 0; } diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index 17f2e02679..211fd5ffb3 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 2c98d796d3..716f47e715 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 1d0b149df1..981a5815a2 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 8ec386db40..98bd53ae6a 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 bcd6ba7984..9493199a80 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; };