From 97924d97c785fda67f690ad49d9b624996526fc8 Mon Sep 17 00:00:00 2001 From: Daniel Vukelich Date: Fri, 12 Jan 2018 20:02:43 -0500 Subject: [PATCH 001/103] Add the option for multiple quicksave slots With more than 1 quicksave slot, slots will be created each time you quicksave until the maximum number (configured in settings) of quicksaves has been reached. After that, the oldest quicksave slot will be replaced each time you quicksave. Saves are numbered sequentially, unless the maximum number of slots is 1, in which case it is not numbered. --- apps/openmw/CMakeLists.txt | 3 +- apps/openmw/mwstate/quicksavemanager.cpp | 73 +++++++++++++++++++ apps/openmw/mwstate/quicksavemanager.hpp | 42 +++++++++++ apps/openmw/mwstate/statemanagerimp.cpp | 17 +++-- .../reference/modding/settings/saves.rst | 13 +++- files/settings-default.cfg | 8 +- 6 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 apps/openmw/mwstate/quicksavemanager.cpp create mode 100644 apps/openmw/mwstate/quicksavemanager.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 491394324..6e97df297 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -89,7 +89,7 @@ add_openmw_dir (mwmechanics ) add_openmw_dir (mwstate - statemanagerimp charactermanager character + statemanagerimp charactermanager character quicksavemanager ) add_openmw_dir (mwbase @@ -223,4 +223,3 @@ endif (MSVC) if (WIN32) INSTALL(TARGETS openmw RUNTIME DESTINATION ".") endif (WIN32) - diff --git a/apps/openmw/mwstate/quicksavemanager.cpp b/apps/openmw/mwstate/quicksavemanager.cpp new file mode 100644 index 000000000..3ead7165a --- /dev/null +++ b/apps/openmw/mwstate/quicksavemanager.cpp @@ -0,0 +1,73 @@ +#include "quicksavemanager.hpp" + +#include + +MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves){ + this->saveName = saveName; + this->maxSaves = maxSaves; + this->oldestSlotVisited = NULL; + this->oldestSlotId = 0; + this->slotsVisited = 0; +} + +void MWState::QuickSaveManager::visitSave(const Slot *saveSlot){ + int slotId; + if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)){ + ++slotsVisited; + if(isOldestSave(saveSlot)){ + oldestSlotVisited = saveSlot; + oldestSlotId = slotId; + } + } +} + +bool MWState::QuickSaveManager::isOldestSave(const Slot *compare){ + if(oldestSlotVisited == NULL) + return true; + return (compare->mTimeStamp < oldestSlotVisited->mTimeStamp); +} + +bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, int &extractedId){ + std::istringstream formattedExtractor = std::istringstream(slotName); + + std::string nameToTest; + formattedExtractor >> nameToTest; + if(nameToTest == saveName){ + //Only try to extract the id if maxSaves > 1 + //With maxSaves == 1, we don't append the slotId to the name + if(formattedExtractor >> extractedId) + return (isSlotIdValid(extractedId)); + else if(maxSaves == 1) + return formattedExtractor.eof(); + } + return false; +} + +bool MWState::QuickSaveManager::isSlotIdValid(int slotId){ + return (slotId > 0 && slotId <= maxSaves); +} + +bool MWState::QuickSaveManager::shouldCreateNewSlot(){ + return (slotsVisited < maxSaves); +} + +const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot(){ + if(shouldCreateNewSlot()) + return NULL; + return oldestSlotVisited; +} + +std::string MWState::QuickSaveManager::getNextQuickSaveName(){ + std::ostringstream nameFormatter; + nameFormatter << saveName; + //Only print the number if there will be more than 1 + if(maxSaves > 1) + nameFormatter << " " << calcNextSlotId(); + return nameFormatter.str(); +} + +int MWState::QuickSaveManager::calcNextSlotId(){ + if(shouldCreateNewSlot()) + return (slotsVisited + 1); + return oldestSlotId; +} diff --git a/apps/openmw/mwstate/quicksavemanager.hpp b/apps/openmw/mwstate/quicksavemanager.hpp new file mode 100644 index 000000000..04341897f --- /dev/null +++ b/apps/openmw/mwstate/quicksavemanager.hpp @@ -0,0 +1,42 @@ +#ifndef GAME_STATE_QUICKSAVEMANAGER_H +#define GAME_STATE_QUICKSAVEMANAGER_H + +#include "character.hpp" +#include "../mwbase/statemanager.hpp" + +#include + +namespace MWState{ + class QuickSaveManager{ + std::string saveName; + int maxSaves; + int slotsVisited; + int oldestSlotId; + const Slot *oldestSlotVisited; + private: + bool tryExtractSlotId(const std::string &slotName, int &extractedIdll); + bool isSlotIdValid(int slotId); + bool shouldCreateNewSlot(); + bool isOldestSave(const Slot *compare); + int calcNextSlotId(); + public: + QuickSaveManager(std::string &saveName, int maxSaves); + ///< A utility class to manage multiple quicksave slots + /// + /// \param saveName The name of the save ("QuickSave", "AutoSave", etc) + /// \param maxSaves The maximum number of save slots to use before recycling old ones + + void visitSave(const Slot *saveSlot); + ///< Visits the given \a slot \a + + const Slot *getNextQuickSaveSlot(); + ///< Get the slot that the next quicksave should use. + /// + ///\return Either the oldest quicksave slot visited, or NULL if a new slot can be made + + std::string getNextQuickSaveName(); + ///< Get the name that the next quicksave should use ("QuickSave 1", "AutoSave 10", etc) + }; +} + +#endif diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 14ee5adee..5b126cbb5 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -37,6 +37,8 @@ #include "../mwscript/globalscripts.hpp" +#include "quicksavemanager.hpp" + void MWState::StateManager::cleanup (bool force) { if (mState!=State_NoGame || force) @@ -324,20 +326,25 @@ void MWState::StateManager::quickSave (std::string name) return; } - const Slot* slot = NULL; + int maxSaves = Settings::Manager::getInt("max quicksaves", "Saves"); + if(maxSaves < 1) + maxSaves = 1; + Character* currentCharacter = getCurrentCharacter(); //Get current character + QuickSaveManager saveFinder = QuickSaveManager(name, maxSaves); - //Find quicksave slot if (currentCharacter) { for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it) { - if (it->mProfile.mDescription == name) - slot = &*it; + //Visiting slots allows the quicksave finder to find the oldest quicksave + saveFinder.visitSave(&*it); } } - saveGame(name, slot); + //Once all the saves have been visited, the save finder can tell us which + //one to replace (or create) + saveGame(saveFinder.getNextQuickSaveName(), saveFinder.getNextQuickSaveSlot()); } void MWState::StateManager::loadGame(const std::string& filepath) diff --git a/docs/source/reference/modding/settings/saves.rst b/docs/source/reference/modding/settings/saves.rst index 90bd56ca5..f5fd553a9 100644 --- a/docs/source/reference/modding/settings/saves.rst +++ b/docs/source/reference/modding/settings/saves.rst @@ -5,7 +5,7 @@ character --------- :Type: string -:Range: +:Range: :Default: "" This setting contains the default character name for loading saved games. @@ -35,3 +35,14 @@ This setting determines whether the amount of the time the player has spent play for each saved game in the Load menu. This setting can only be configured by editing the settings configuration file. + +max quicksaves +---------- + +:Type: integer +:Range: >0 +:Default: 5 + +This setting determines how many quicksave and autosave slots you can have at a time. If greater than 1, quicksaves will be sequentially created each time you quicksave. Once the maximum number of quicksaves has been reached, the oldest quicksave will be recycled the next time you perform a quicksave. + +This setting can only be configured by editing the settings configuration file. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c694d4db2..3da88b01a 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -7,7 +7,7 @@ # significance of each setting, interaction with other settings, hard # limits on value ranges and more information in general, please read # the detailed documentation at: -# +# # http://openmw.readthedocs.io/en/master/reference/modding/settings/index.html # @@ -288,6 +288,10 @@ autosave = true # Display the time played on each save file in the load menu. timeplayed = false +# The maximum number of quick (or auto) save slots to have. +# If all slots are used, the oldest save is reused +max quicksaves = 5 + [Sound] # Name of audio device file. Blank means use the default device. @@ -376,7 +380,7 @@ reflect actors = false # Overrides the value in '[Camera] small feature culling pixel size' specifically for water reflection/refraction textures. small feature culling pixel size = 20.0 -# By what factor water downscales objects. Only works with water shader and refractions on. +# By what factor water downscales objects. Only works with water shader and refractions on. refraction scale = 1.0 [Windows] From f09fd6795c4519523e7ea927106a17e573019d17 Mon Sep 17 00:00:00 2001 From: Daniel Vukelich Date: Fri, 12 Jan 2018 20:02:43 -0500 Subject: [PATCH 002/103] Follow openmw style guide --- apps/openmw/mwstate/quicksavemanager.cpp | 74 ++++++++++++++---------- apps/openmw/mwstate/quicksavemanager.hpp | 14 ++--- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwstate/quicksavemanager.cpp b/apps/openmw/mwstate/quicksavemanager.cpp index 3ead7165a..1457f7075 100644 --- a/apps/openmw/mwstate/quicksavemanager.cpp +++ b/apps/openmw/mwstate/quicksavemanager.cpp @@ -2,72 +2,84 @@ #include -MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves){ - this->saveName = saveName; - this->maxSaves = maxSaves; - this->oldestSlotVisited = NULL; - this->oldestSlotId = 0; - this->slotsVisited = 0; +MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves) +{ + this->mSaveName = saveName; + this->mMaxSaves = maxSaves; + this->mOldestSlotVisited = NULL; + this->mOldestSlotId = 0; + this->mSlotsVisited = 0; } -void MWState::QuickSaveManager::visitSave(const Slot *saveSlot){ +void MWState::QuickSaveManager::visitSave(const Slot *saveSlot) +{ int slotId; - if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)){ - ++slotsVisited; - if(isOldestSave(saveSlot)){ - oldestSlotVisited = saveSlot; - oldestSlotId = slotId; + if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)) + { + ++mSlotsVisited; + if(isOldestSave(saveSlot)) + { + mOldestSlotVisited = saveSlot; + mOldestSlotId = slotId; } } } -bool MWState::QuickSaveManager::isOldestSave(const Slot *compare){ - if(oldestSlotVisited == NULL) +bool MWState::QuickSaveManager::isOldestSave(const Slot *compare) +{ + if(mOldestSlotVisited == NULL) return true; - return (compare->mTimeStamp < oldestSlotVisited->mTimeStamp); + return (compare->mTimeStamp <= mOldestSlotVisited->mTimeStamp); } -bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, int &extractedId){ - std::istringstream formattedExtractor = std::istringstream(slotName); +bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, int &extractedId) +{ + std::istringstream formattedExtractor(slotName); std::string nameToTest; formattedExtractor >> nameToTest; - if(nameToTest == saveName){ + if(nameToTest == mSaveName) + { //Only try to extract the id if maxSaves > 1 //With maxSaves == 1, we don't append the slotId to the name if(formattedExtractor >> extractedId) return (isSlotIdValid(extractedId)); - else if(maxSaves == 1) + else if(mMaxSaves == 1) return formattedExtractor.eof(); } return false; } -bool MWState::QuickSaveManager::isSlotIdValid(int slotId){ - return (slotId > 0 && slotId <= maxSaves); +bool MWState::QuickSaveManager::isSlotIdValid(int slotId) +{ + return (slotId > 0 && slotId <= mMaxSaves); } -bool MWState::QuickSaveManager::shouldCreateNewSlot(){ - return (slotsVisited < maxSaves); +bool MWState::QuickSaveManager::shouldCreateNewSlot() +{ + return (mSlotsVisited < mMaxSaves); } -const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot(){ +const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot() +{ if(shouldCreateNewSlot()) return NULL; - return oldestSlotVisited; + return mOldestSlotVisited; } -std::string MWState::QuickSaveManager::getNextQuickSaveName(){ +std::string MWState::QuickSaveManager::getNextQuickSaveName() +{ std::ostringstream nameFormatter; - nameFormatter << saveName; + nameFormatter << mSaveName; //Only print the number if there will be more than 1 - if(maxSaves > 1) + if(mMaxSaves > 1) nameFormatter << " " << calcNextSlotId(); return nameFormatter.str(); } -int MWState::QuickSaveManager::calcNextSlotId(){ +int MWState::QuickSaveManager::calcNextSlotId() +{ if(shouldCreateNewSlot()) - return (slotsVisited + 1); - return oldestSlotId; + return (mSlotsVisited + 1); + return mOldestSlotId; } diff --git a/apps/openmw/mwstate/quicksavemanager.hpp b/apps/openmw/mwstate/quicksavemanager.hpp index 04341897f..6a06171d9 100644 --- a/apps/openmw/mwstate/quicksavemanager.hpp +++ b/apps/openmw/mwstate/quicksavemanager.hpp @@ -1,18 +1,18 @@ #ifndef GAME_STATE_QUICKSAVEMANAGER_H #define GAME_STATE_QUICKSAVEMANAGER_H +#include + #include "character.hpp" #include "../mwbase/statemanager.hpp" -#include - namespace MWState{ class QuickSaveManager{ - std::string saveName; - int maxSaves; - int slotsVisited; - int oldestSlotId; - const Slot *oldestSlotVisited; + std::string mSaveName; + int mMaxSaves; + int mSlotsVisited; + int mOldestSlotId; + const Slot *mOldestSlotVisited; private: bool tryExtractSlotId(const std::string &slotName, int &extractedIdll); bool isSlotIdValid(int slotId); From 3af8f63895c94e1a0268720be0680af83130954b Mon Sep 17 00:00:00 2001 From: Daniel Vukelich Date: Wed, 17 Jan 2018 21:43:30 -0500 Subject: [PATCH 003/103] Use unsigned integer types for QuickSave indices --- apps/openmw/mwstate/quicksavemanager.cpp | 8 ++++---- apps/openmw/mwstate/quicksavemanager.hpp | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwstate/quicksavemanager.cpp b/apps/openmw/mwstate/quicksavemanager.cpp index 1457f7075..e49f376d6 100644 --- a/apps/openmw/mwstate/quicksavemanager.cpp +++ b/apps/openmw/mwstate/quicksavemanager.cpp @@ -2,7 +2,7 @@ #include -MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves) +MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, unsigned int maxSaves) { this->mSaveName = saveName; this->mMaxSaves = maxSaves; @@ -13,7 +13,7 @@ MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves) void MWState::QuickSaveManager::visitSave(const Slot *saveSlot) { - int slotId; + unsigned int slotId; if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)) { ++mSlotsVisited; @@ -32,7 +32,7 @@ bool MWState::QuickSaveManager::isOldestSave(const Slot *compare) return (compare->mTimeStamp <= mOldestSlotVisited->mTimeStamp); } -bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, int &extractedId) +bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, unsigned int &extractedId) { std::istringstream formattedExtractor(slotName); @@ -50,7 +50,7 @@ bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, in return false; } -bool MWState::QuickSaveManager::isSlotIdValid(int slotId) +bool MWState::QuickSaveManager::isSlotIdValid(unsigned int slotId) { return (slotId > 0 && slotId <= mMaxSaves); } diff --git a/apps/openmw/mwstate/quicksavemanager.hpp b/apps/openmw/mwstate/quicksavemanager.hpp index 6a06171d9..abe7ef426 100644 --- a/apps/openmw/mwstate/quicksavemanager.hpp +++ b/apps/openmw/mwstate/quicksavemanager.hpp @@ -9,18 +9,18 @@ namespace MWState{ class QuickSaveManager{ std::string mSaveName; - int mMaxSaves; - int mSlotsVisited; - int mOldestSlotId; + unsigned int mMaxSaves; + unsigned int mSlotsVisited; + unsigned int mOldestSlotId; const Slot *mOldestSlotVisited; private: - bool tryExtractSlotId(const std::string &slotName, int &extractedIdll); - bool isSlotIdValid(int slotId); + bool tryExtractSlotId(const std::string &slotName, unsigned int &extractedIdll); + bool isSlotIdValid(unsigned int slotId); bool shouldCreateNewSlot(); bool isOldestSave(const Slot *compare); int calcNextSlotId(); public: - QuickSaveManager(std::string &saveName, int maxSaves); + QuickSaveManager(std::string &saveName, unsigned int maxSaves); ///< A utility class to manage multiple quicksave slots /// /// \param saveName The name of the save ("QuickSave", "AutoSave", etc) From 3bdd989a509fd5d1b56c86ed7db3604583407ace Mon Sep 17 00:00:00 2001 From: Daniel Vukelich Date: Tue, 13 Feb 2018 21:01:15 -0500 Subject: [PATCH 004/103] Remove numeric quicksave slot IDs When multiple quicksaves occurred in quick succession, the numeric order of the saves could not be guaranteed. To prevent players from getting confused as to why their saves appear out of order, don't number them. --- apps/openmw/mwstate/quicksavemanager.cpp | 49 +----------------------- apps/openmw/mwstate/quicksavemanager.hpp | 9 +---- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- 3 files changed, 3 insertions(+), 57 deletions(-) diff --git a/apps/openmw/mwstate/quicksavemanager.cpp b/apps/openmw/mwstate/quicksavemanager.cpp index e49f376d6..4bae9e674 100644 --- a/apps/openmw/mwstate/quicksavemanager.cpp +++ b/apps/openmw/mwstate/quicksavemanager.cpp @@ -1,27 +1,20 @@ #include "quicksavemanager.hpp" -#include - MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, unsigned int maxSaves) { this->mSaveName = saveName; this->mMaxSaves = maxSaves; this->mOldestSlotVisited = NULL; - this->mOldestSlotId = 0; this->mSlotsVisited = 0; } void MWState::QuickSaveManager::visitSave(const Slot *saveSlot) { - unsigned int slotId; - if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)) + if(mSaveName == saveSlot->mProfile.mDescription) { ++mSlotsVisited; if(isOldestSave(saveSlot)) - { mOldestSlotVisited = saveSlot; - mOldestSlotId = slotId; - } } } @@ -32,29 +25,6 @@ bool MWState::QuickSaveManager::isOldestSave(const Slot *compare) return (compare->mTimeStamp <= mOldestSlotVisited->mTimeStamp); } -bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, unsigned int &extractedId) -{ - std::istringstream formattedExtractor(slotName); - - std::string nameToTest; - formattedExtractor >> nameToTest; - if(nameToTest == mSaveName) - { - //Only try to extract the id if maxSaves > 1 - //With maxSaves == 1, we don't append the slotId to the name - if(formattedExtractor >> extractedId) - return (isSlotIdValid(extractedId)); - else if(mMaxSaves == 1) - return formattedExtractor.eof(); - } - return false; -} - -bool MWState::QuickSaveManager::isSlotIdValid(unsigned int slotId) -{ - return (slotId > 0 && slotId <= mMaxSaves); -} - bool MWState::QuickSaveManager::shouldCreateNewSlot() { return (mSlotsVisited < mMaxSaves); @@ -66,20 +36,3 @@ const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot() return NULL; return mOldestSlotVisited; } - -std::string MWState::QuickSaveManager::getNextQuickSaveName() -{ - std::ostringstream nameFormatter; - nameFormatter << mSaveName; - //Only print the number if there will be more than 1 - if(mMaxSaves > 1) - nameFormatter << " " << calcNextSlotId(); - return nameFormatter.str(); -} - -int MWState::QuickSaveManager::calcNextSlotId() -{ - if(shouldCreateNewSlot()) - return (mSlotsVisited + 1); - return mOldestSlotId; -} diff --git a/apps/openmw/mwstate/quicksavemanager.hpp b/apps/openmw/mwstate/quicksavemanager.hpp index abe7ef426..e52cd609f 100644 --- a/apps/openmw/mwstate/quicksavemanager.hpp +++ b/apps/openmw/mwstate/quicksavemanager.hpp @@ -11,20 +11,16 @@ namespace MWState{ std::string mSaveName; unsigned int mMaxSaves; unsigned int mSlotsVisited; - unsigned int mOldestSlotId; const Slot *mOldestSlotVisited; private: - bool tryExtractSlotId(const std::string &slotName, unsigned int &extractedIdll); - bool isSlotIdValid(unsigned int slotId); bool shouldCreateNewSlot(); bool isOldestSave(const Slot *compare); - int calcNextSlotId(); public: QuickSaveManager(std::string &saveName, unsigned int maxSaves); ///< A utility class to manage multiple quicksave slots /// /// \param saveName The name of the save ("QuickSave", "AutoSave", etc) - /// \param maxSaves The maximum number of save slots to use before recycling old ones + /// \param maxSaves The maximum number of save slots to create before recycling old ones void visitSave(const Slot *saveSlot); ///< Visits the given \a slot \a @@ -33,9 +29,6 @@ namespace MWState{ ///< Get the slot that the next quicksave should use. /// ///\return Either the oldest quicksave slot visited, or NULL if a new slot can be made - - std::string getNextQuickSaveName(); - ///< Get the name that the next quicksave should use ("QuickSave 1", "AutoSave 10", etc) }; } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 5b126cbb5..c1bb589e8 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -344,7 +344,7 @@ void MWState::StateManager::quickSave (std::string name) //Once all the saves have been visited, the save finder can tell us which //one to replace (or create) - saveGame(saveFinder.getNextQuickSaveName(), saveFinder.getNextQuickSaveSlot()); + saveGame(name, saveFinder.getNextQuickSaveSlot()); } void MWState::StateManager::loadGame(const std::string& filepath) From 104495a9a432acfbb34f2eb7c9d38766573564d8 Mon Sep 17 00:00:00 2001 From: Daniel Vukelich Date: Tue, 13 Feb 2018 21:05:24 -0500 Subject: [PATCH 005/103] Set default number of quicksaves to 1 --- docs/source/reference/modding/settings/saves.rst | 2 +- files/settings-default.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/reference/modding/settings/saves.rst b/docs/source/reference/modding/settings/saves.rst index f5fd553a9..a3cf5b4e0 100644 --- a/docs/source/reference/modding/settings/saves.rst +++ b/docs/source/reference/modding/settings/saves.rst @@ -41,7 +41,7 @@ max quicksaves :Type: integer :Range: >0 -:Default: 5 +:Default: 1 This setting determines how many quicksave and autosave slots you can have at a time. If greater than 1, quicksaves will be sequentially created each time you quicksave. Once the maximum number of quicksaves has been reached, the oldest quicksave will be recycled the next time you perform a quicksave. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 3da88b01a..e2a0bdf54 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -290,7 +290,7 @@ timeplayed = false # The maximum number of quick (or auto) save slots to have. # If all slots are used, the oldest save is reused -max quicksaves = 5 +max quicksaves = 1 [Sound] From 929fc68160a031e17d419af74ed6354bef895dd9 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 26 Feb 2018 23:21:51 +0300 Subject: [PATCH 006/103] Consider items with dead owner not stolen (fixes bug #4328) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index bd5fa1b11..cd3cd1f80 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1118,8 +1118,11 @@ namespace MWMechanics Misc::StringUtils::lowerCaseInPlace(owner.first); if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) - mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; - + { + const MWWorld::Ptr victimRef = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true); + if (!victimRef.getClass().getCreatureStats(victimRef).isDead()) + mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; + } if (alarm) commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); } From 3393ad623fde05ce8957d556ae5430b436c6100a Mon Sep 17 00:00:00 2001 From: bret curtis Date: Tue, 27 Feb 2018 16:15:43 +0100 Subject: [PATCH 007/103] fix rtd --- docs/source/conf.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b18b40c50..e3fe58bc7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -60,13 +60,29 @@ copyright = u'2017, OpenMW Team' # The short X.Y version. # The full version, including alpha/beta/rc tags. +def get_openmw_version(haystack): + needle = 'OPENMW_VERSION_MAJOR' + line_counter = 0 + for hay in haystack: + if needle in str(hay): + break + line_counter += 1 + + if line_counter == 0: + raise ImportError('Unable to find OpenMW Version') + + version = '.'.join([haystack[line_counter][1][1].contents, + haystack[line_counter+1][1][1].contents, + haystack[line_counter+2][1][1].contents]) + return version + + try: from parse_cmake import parsing cmake_raw = open(project_root+'/CMakeLists.txt', 'r').read() cmake_data = parsing.parse(cmake_raw) - release = version = '.'.join([cmake_data[24][1][1].contents, - cmake_data[25][1][1].contents, - cmake_data[26][1][1].contents]) + release = version = get_openmw_version(cmake_data) + except ImportError: release = "UNRELEASED" print("WARNING: Unable to import parse_cmake, version will be set to: {0}.".format(release)) From 81d90d7fb725007783a419eeaaf30dcac8a3c6fa Mon Sep 17 00:00:00 2001 From: bret curtis Date: Tue, 27 Feb 2018 18:57:37 +0100 Subject: [PATCH 008/103] break for all errors that would raise when checking for version, make them UNRELEASED --- docs/source/conf.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index e3fe58bc7..0ba8567c0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -60,6 +60,9 @@ copyright = u'2017, OpenMW Team' # The short X.Y version. # The full version, including alpha/beta/rc tags. +release = version = "UNRELEASED" + + def get_openmw_version(haystack): needle = 'OPENMW_VERSION_MAJOR' line_counter = 0 @@ -68,9 +71,6 @@ def get_openmw_version(haystack): break line_counter += 1 - if line_counter == 0: - raise ImportError('Unable to find OpenMW Version') - version = '.'.join([haystack[line_counter][1][1].contents, haystack[line_counter+1][1][1].contents, haystack[line_counter+2][1][1].contents]) @@ -83,9 +83,9 @@ try: cmake_data = parsing.parse(cmake_raw) release = version = get_openmw_version(cmake_data) -except ImportError: - release = "UNRELEASED" - print("WARNING: Unable to import parse_cmake, version will be set to: {0}.".format(release)) +except Exception as ex: + print("WARNING: Version will be set to '{0}' because: '{1}'.".format(release, str(ex))) + import traceback; traceback.print_exc() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 4a2e9f2e3d8c9a5bad6fe795d24fb286549f4540 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Tue, 27 Feb 2018 23:52:12 +0000 Subject: [PATCH 009/103] Update AUTHORS.md --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 155d017f3..f6cc51181 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -41,6 +41,7 @@ Programmers Cory F. Cohen (cfcohen) Cris Mihalache (Mirceam) crussell187 + DanielVukelich darkf devnexen Dieho From 4292351993c2d10ef72a26d4925e27684f4312f4 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Tue, 27 Feb 2018 20:17:21 -0600 Subject: [PATCH 010/103] Adding Max Quicksaves setting to Launcher --- apps/launcher/advancedpage.cpp | 9 +++-- files/ui/advancedpage.ui | 66 +++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 3ba378599..27f3cc39d 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -35,8 +35,11 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); - // Other Settings + // Saves Settings loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves")); + + // Other Settings QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) @@ -69,9 +72,11 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); - // Other Settings + // Saves Settings saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksavesComboBox->value()); + // Other Settings std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) mEngineSettings.setString("screenshot format", "General", screenshotFormatString); diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 8a0795d34..6832b86df 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -6,7 +6,7 @@ 0 0 - 434 + 671 373 @@ -27,9 +27,9 @@ 0 - 0 - 393 - 437 + -187 + 630 + 510 @@ -139,6 +139,9 @@ + + 1 + Off @@ -207,11 +210,11 @@ - + - Other + Saves - + @@ -222,12 +225,59 @@ + + + + <html><head/><body><p>This setting determines how many quicksave and autosave slots you can have at a time. If greater than 1, quicksaves will be sequentially created each time you quicksave. Once the maximum number of quicksaves has been reached, the oldest quicksave will be recycled the next time you perform a quicksave.</p></body></html> + + + + -1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Maximum Quicksaves + + + + + + + 1 + + + + + + + + + + + + + Other + + <html><head/><body><p>Specify the format for screen shots taken by pressing the screen shot key (bound to F12 by default). This setting should be the file extension commonly associated with the desired format. The formats supported will be determined at compilation, but “jpg”, “png”, and “tga” should be allowed.</p></body></html> - + -1 From b6d9b6f544ee1e761be5dc8ffa82b9b665eec59f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Tue, 27 Feb 2018 20:17:43 -0600 Subject: [PATCH 011/103] Formatting improvement for advanced page --- apps/launcher/advancedpage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 27f3cc39d..0abefcc8f 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -40,7 +40,6 @@ bool Launcher::AdvancedPage::loadSettings() maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves")); // Other Settings - QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) screenshotFormatComboBox->addItem(screenshotFormatString); From 839196e4faaa4782c2cc339413e964e4ed698b78 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 3 Mar 2018 00:15:57 +0000 Subject: [PATCH 012/103] Force normal polygon mode for the map camera (Fixes #4235) --- apps/openmw/mwrender/localmap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index b78c4dcd2..0b65a6b13 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -174,6 +175,7 @@ osg::ref_ptr LocalMap::createOrthographicCamera(float x, float y, f camera->setNodeMask(Mask_RenderToTexture); osg::ref_ptr stateset = new osg::StateSet; + stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE); // assign large value to effectively turn off fog // shaders don't respect glDisable(GL_FOG) From cc0c6ddaa6aed5c93f83597a58d12fbacba34d46 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 28 Feb 2018 14:04:56 +0300 Subject: [PATCH 013/103] Account for empty victimRef (Bug #4328) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index cd3cd1f80..be5125a2b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1120,7 +1120,7 @@ namespace MWMechanics if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) { const MWWorld::Ptr victimRef = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true); - if (!victimRef.getClass().getCreatureStats(victimRef).isDead()) + if (victimRef.isEmpty() || !victimRef.getClass().getCreatureStats(victimRef).isDead()) mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; } if (alarm) From d371bebb333c419c0c5589bfca090410eb25a1be Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 2 Mar 2018 21:10:05 +0300 Subject: [PATCH 014/103] Prevent items in a container owned by a dead actor from being counted as stolen (Bug #4328) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index be5125a2b..225427829 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1119,7 +1119,7 @@ namespace MWMechanics if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) { - const MWWorld::Ptr victimRef = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true); + const MWWorld::Ptr victimRef = MWBase::Environment::get().getWorld()->searchPtr(ownerCellRef->getOwner(), true); if (victimRef.isEmpty() || !victimRef.getClass().getCreatureStats(victimRef).isDead()) mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; } From 6d557fec8e08dc65683454fde47d1d01a87faa9b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2017 11:42:15 -0700 Subject: [PATCH 015/103] Increase the far clip plane when distant terrain is enabled --- apps/openmw/mwrender/renderingmanager.cpp | 20 ++++++++++++-------- apps/openmw/mwrender/renderingmanager.hpp | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3281a787b..b880943a4 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -179,8 +179,9 @@ namespace MWRender , mUnderwaterFog(0.f) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) - , mFieldOfViewOverride(0.f) + , mDistantTerrain(false) , mFieldOfViewOverridden(false) + , mFieldOfViewOverride(0.f) { resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); @@ -216,12 +217,12 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); - const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); + mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"), - Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), + Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain specular maps", "Shaders")); - if (distantTerrain) + if (mDistantTerrain) mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); else mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); @@ -288,8 +289,10 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); + mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near"); mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far"); @@ -632,7 +635,7 @@ namespace MWRender rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); - rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); + rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mFarClip); rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix()); rttCamera->setViewport(0, 0, w, h); @@ -897,10 +900,10 @@ namespace MWRender float fov = mFieldOfView; if (mFieldOfViewOverridden) fov = mFieldOfViewOverride; - mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance); + mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mFarClip); mUniformNear->set(mNearClip); - mUniformFar->set(mViewDistance); + mUniformFar->set(mFarClip); } void RenderingManager::updateTextureFiltering() @@ -960,6 +963,7 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); + mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; mStateUpdater->setFogEnd(mViewDistance); updateProjectionMatrix(); } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index f0087e43d..16854aaea 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -252,9 +252,11 @@ namespace MWRender float mNightEyeFactor; float mNearClip; + float mFarClip; float mViewDistance; + bool mDistantTerrain : 1; + bool mFieldOfViewOverridden : 1; float mFieldOfViewOverride; - bool mFieldOfViewOverridden; float mFieldOfView; float mFirstPersonFieldOfView; From 154cc8c6592cfe775f0953078ad1ceeb13afd398 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Sep 2017 03:08:45 -0700 Subject: [PATCH 016/103] Use alternate fog parameters when distant land is enabled This allows the distant land to actually be seen when the user enables it. The values used are replicated from MGE XE's default settings and should probably be exposed somewhere. --- apps/openmw/mwrender/renderingmanager.cpp | 85 +++++++++++++++++------ apps/openmw/mwrender/renderingmanager.hpp | 8 ++- apps/openmw/mwrender/sky.hpp | 3 + apps/openmw/mwworld/weather.cpp | 35 ++++++---- apps/openmw/mwworld/weather.hpp | 9 +++ 5 files changed, 103 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b880943a4..ea0fef197 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -51,6 +51,20 @@ #include "terrainstorage.hpp" #include "util.hpp" +namespace +{ + // These values are what MGE XE uses by default when distant land is enabled, and are specified + // in cells (8192 units each). Should make them settings somewhere? Or wait to expose them + // "properly"? + const float DLRenderDistance = 5.0f; + const float DLLandFogStart = 2.0f; + const float DLLandFogEnd = 5.0f; + const float DLUnderwaterFogStart = -0.5f; + const float DLUnderwaterFogEnd = 0.3f; + const float DLInteriorFogStart = 0.0f; + const float DLInteriorFogEnd = 2.0f; +} + namespace MWRender { @@ -173,10 +187,12 @@ namespace MWRender , mResourceSystem(resourceSystem) , mWorkQueue(workQueue) , mUnrefQueue(new SceneUtil::UnrefQueue) - , mFogDepth(0.f) + , mLandFogStart(0.f) + , mLandFogEnd(std::numeric_limits::max()) + , mUnderwaterFogStart(0.f) + , mUnderwaterFogEnd(std::numeric_limits::max()) , mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor")) , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) - , mUnderwaterFog(0.f) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) , mDistantTerrain(false) @@ -289,7 +305,7 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; + mFarClip = mDistantTerrain ? DLRenderDistance*8192.0f : mViewDistance; mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); @@ -482,14 +498,44 @@ namespace MWRender { osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color); + if(mDistantTerrain) + { + float density = std::max(0.2f, cell->mAmbi.mFogDensity); + mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density) * 8192.0f; + mLandFogEnd = DLInteriorFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mFogColor = color; + } + else + configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color); } - void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color) + void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - mFogDepth = fogDepth; + if(mDistantTerrain) + { + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd) * 8192.0f; + mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + } + else + { + if(fogDepth == 0.0) + { + mLandFogStart = 0.0f; + mLandFogEnd = std::numeric_limits::max(); + } + else + { + mLandFogStart = mViewDistance * (1 - fogDepth); + mLandFogEnd = mViewDistance; + } + mUnderwaterFogStart = mViewDistance * (1 - underwaterFog); + mUnderwaterFogEnd = mViewDistance; + } mFogColor = color; - mUnderwaterFog = underwaterFog; } SkyManager* RenderingManager::getSkyManager() @@ -520,23 +566,15 @@ namespace MWRender float viewDistance = mViewDistance; viewDistance = std::min(viewDistance, 6666.f); setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight)); - mStateUpdater->setFogStart(viewDistance * (1 - mUnderwaterFog)); - mStateUpdater->setFogEnd(viewDistance); + mStateUpdater->setFogStart(mUnderwaterFogStart); + mStateUpdater->setFogEnd(mUnderwaterFogEnd); } else { setFogColor(mFogColor); - if (mFogDepth == 0.f) - { - mStateUpdater->setFogStart(0.f); - mStateUpdater->setFogEnd(std::numeric_limits::max()); - } - else - { - mStateUpdater->setFogStart(mViewDistance * (1 - mFogDepth)); - mStateUpdater->setFogEnd(mViewDistance); - } + mStateUpdater->setFogStart(mLandFogStart); + mStateUpdater->setFogEnd(mLandFogEnd); } } @@ -963,9 +1001,12 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; - mStateUpdater->setFogEnd(mViewDistance); - updateProjectionMatrix(); + if(!mDistantTerrain) + { + mFarClip = mViewDistance; + mStateUpdater->setFogEnd(mViewDistance); + updateProjectionMatrix(); + } } else if (it->first == "General" && (it->second == "texture filter" || it->second == "texture mipmap" || diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 16854aaea..d44266e97 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -106,7 +106,7 @@ namespace MWRender void configureAmbient(const ESM::Cell* cell); void configureFog(const ESM::Cell* cell); - void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour); + void configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour); void addCell(const MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store); @@ -241,10 +241,12 @@ namespace MWRender osg::ref_ptr mStateUpdater; - float mFogDepth; + float mLandFogStart; + float mLandFogEnd; + float mUnderwaterFogStart; + float mUnderwaterFogEnd; osg::Vec4f mUnderwaterColor; float mUnderwaterWeight; - float mUnderwaterFog; float mUnderwaterIndoorFog; osg::Vec4f mFogColor; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 4357d468c..a9345cdb4 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -65,6 +65,9 @@ namespace MWRender float mFogDepth; + float mDLFogFactor; + float mDLFogOffset; + float mWindSpeed; float mCloudSpeed; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 2f0a2f8cf..bde4c4c22 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -103,6 +103,8 @@ Weather::Weather(const std::string& name, const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect) : mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture")) , mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"), @@ -129,6 +131,7 @@ Weather::Weather(const std::string& name, , mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed")) , mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed")) , mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View")) + , mDL{dlFactor, dlOffset} , mIsStorm(mWindSpeed > stormWindSpeed) , mRainSpeed(rainSpeed) , mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed")) @@ -541,16 +544,18 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall mTimeSettings.mSunriseTime = mSunriseTime; mWeatherSettings.reserve(10); - addWeather("Clear", fallback); // 0 - addWeather("Cloudy", fallback); // 1 - addWeather("Foggy", fallback); // 2 - addWeather("Overcast", fallback); // 3 - addWeather("Rain", fallback); // 4 - addWeather("Thunderstorm", fallback); // 5 - addWeather("Ashstorm", fallback, "meshes\\ashcloud.nif"); // 6 - addWeather("Blight", fallback, "meshes\\blightcloud.nif"); // 7 - addWeather("Snow", fallback, "meshes\\snow.nif"); // 8 - addWeather("Blizzard", fallback, "meshes\\blizzard.nif"); // 9 + // These distant land fog factor and offset values are the defaults MGE XE provides. Should be + // provided by settings somewhere? + addWeather("Clear", fallback, 1.0f, 0.0f); // 0 + addWeather("Cloudy", fallback, 0.9f, 0.0f); // 1 + addWeather("Foggy", fallback, 0.2f, 30.0f); // 2 + addWeather("Overcast", fallback, 0.7f, 0.0f); // 3 + addWeather("Rain", fallback, 0.5f, 10.0f); // 4 + addWeather("Thunderstorm", fallback, 0.5f, 20.0f); // 5 + addWeather("Ashstorm", fallback, 0.2f, 50.0f, "meshes\\ashcloud.nif"); // 6 + addWeather("Blight", fallback, 0.2f, 60.0f, "meshes\\blightcloud.nif"); // 7 + addWeather("Snow", fallback, 0.5f, 40.0f, "meshes\\snow.nif"); // 8 + addWeather("Blizzard", fallback, 0.16f, 70.0f, "meshes\\blizzard.nif"); // 9 Store::iterator it = store.get().begin(); for(; it != store.get().end(); ++it) @@ -720,7 +725,8 @@ void WeatherManager::update(float duration, bool paused) mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time)); mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time)); - mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor); + mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mDLFogFactor, + mResult.mDLFogOffset/100.0f, mResult.mFogColor); mRendering.setAmbientColour(mResult.mAmbientColor); mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView); @@ -866,11 +872,12 @@ void WeatherManager::clear() inline void WeatherManager::addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect) { static const float fStromWindSpeed = mStore.get().find("fStromWindSpeed")->getFloat(); - Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, particleEffect); + Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect); mWeatherSettings.push_back(weather); } @@ -1058,6 +1065,8 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1); mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings); + mResult.mDLFogFactor = current.mDL.FogFactor; + mResult.mDLFogOffset = current.mDL.FogOffset; mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings); mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings); mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings); @@ -1113,6 +1122,8 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor); mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor); mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); + mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor); + mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor); mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 84a6c5105..4555a9d2a 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -73,6 +73,8 @@ namespace MWWorld const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect); std::string mCloudTexture; @@ -102,6 +104,12 @@ namespace MWWorld // Also appears to modify how visible the sun, moons, and stars are for various weather effects. float mGlareView; + // Fog factor and offset used with distant land rendering. + struct { + float FogFactor; + float FogOffset; + } mDL; + // Sound effect // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) std::string mAmbientLoopSoundID; @@ -293,6 +301,7 @@ namespace MWWorld void addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect = ""); void importRegions(); From 4caa7c9674339e23d48ab076a425e272d7427c71 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Sep 2017 16:35:36 -0700 Subject: [PATCH 017/103] Workaround older MSVC quirk --- apps/openmw/mwworld/weather.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index bde4c4c22..601379f08 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -131,7 +131,6 @@ Weather::Weather(const std::string& name, , mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed")) , mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed")) , mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View")) - , mDL{dlFactor, dlOffset} , mIsStorm(mWindSpeed > stormWindSpeed) , mRainSpeed(rainSpeed) , mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed")) @@ -145,6 +144,8 @@ Weather::Weather(const std::string& name, , mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement")) , mFlashBrightness(0.0f) { + mDL.FogFactor = dlFactor; + mDL.FogOffset = dlOffset; mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0"); mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1"); mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2"); From 41669467aee26fb0f1e99d10b9120a0831bfcc2d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Sep 2017 17:34:44 -0700 Subject: [PATCH 018/103] Make settings for distant fog parameters --- apps/openmw/mwrender/renderingmanager.cpp | 54 +++++++++++++---------- apps/openmw/mwrender/renderingmanager.hpp | 1 + files/settings-default.cfg | 22 +++++++++ 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ea0fef197..b3fee20b5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -53,16 +53,13 @@ namespace { - // These values are what MGE XE uses by default when distant land is enabled, and are specified - // in cells (8192 units each). Should make them settings somewhere? Or wait to expose them - // "properly"? - const float DLRenderDistance = 5.0f; - const float DLLandFogStart = 2.0f; - const float DLLandFogEnd = 5.0f; - const float DLUnderwaterFogStart = -0.5f; - const float DLUnderwaterFogEnd = 0.3f; - const float DLInteriorFogStart = 0.0f; - const float DLInteriorFogEnd = 2.0f; + float DLRenderDistance; + float DLLandFogStart; + float DLLandFogEnd; + float DLUnderwaterFogStart; + float DLUnderwaterFogEnd; + float DLInteriorFogStart; + float DLInteriorFogEnd; } namespace MWRender @@ -195,6 +192,7 @@ namespace MWRender , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) + , mDistantFog(false) , mDistantTerrain(false) , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) @@ -233,6 +231,15 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); + DLRenderDistance = Settings::Manager::getFloat("distant viewing distance", "Camera"); + DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); + DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); + DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); + DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog"); + DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog"); + DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog"); + + mDistantFog = Settings::Manager::getBool("use distant fog", "Fog"); mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), @@ -305,7 +312,7 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? DLRenderDistance*8192.0f : mViewDistance; + mFarClip = mDistantTerrain ? DLRenderDistance : mViewDistance; mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); @@ -498,13 +505,13 @@ namespace MWRender { osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - if(mDistantTerrain) + if(mDistantFog) { float density = std::max(0.2f, cell->mAmbi.mFogDensity); - mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density) * 8192.0f; - mLandFogEnd = DLInteriorFogEnd * 8192.0f; - mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; - mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density); + mLandFogEnd = DLInteriorFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; mFogColor = color; } else @@ -513,12 +520,12 @@ namespace MWRender void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - if(mDistantTerrain) + if(mDistantFog) { - mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd) * 8192.0f; - mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd * 8192.0f; - mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; - mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd); + mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; } else { @@ -1002,11 +1009,10 @@ namespace MWRender { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); if(!mDistantTerrain) - { mFarClip = mViewDistance; + if(!mDistantFog) mStateUpdater->setFogEnd(mViewDistance); - updateProjectionMatrix(); - } + updateProjectionMatrix(); } else if (it->first == "General" && (it->second == "texture filter" || it->second == "texture mipmap" || diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d44266e97..da79fba98 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -256,6 +256,7 @@ namespace MWRender float mNearClip; float mFarClip; float mViewDistance; + bool mDistantFog : 1; bool mDistantTerrain : 1; bool mFieldOfViewOverridden : 1; float mFieldOfViewOverride; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 63afa4438..c1d269e6f 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -25,6 +25,10 @@ small feature culling pixel size = 2.0 # can dramatically affect performance, see documentation for details. viewing distance = 6666.0 +# Maximum visible distance for distant terrain. Caution: setting this too high +# can increase the chance for Z-fighting (flickering artifacts). +distant viewing distance = 40960 + # Camera field of view in degrees (e.g. 30.0 to 110.0). # Does not affect the player's hands in the first person camera. field of view = 55.0 @@ -90,6 +94,24 @@ pointers cache size = 40 # If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells distant terrain = false +[Fog] + +# If true, use extended fog parameters for distant terrain not controlled by +# viewing distance. If false, use the standard fog calculations. +use distant fog = false + +distant land fog start = 16384 + +distant land fog end = 40960 + +distant underwater fog start = -4096 + +distant underwater fog end = 2457.6 + +distant interior fog start = 0 + +distant interior fog end = 16384 + [Map] # Size of each exterior cell in pixels in the world map. (e.g. 12 to 24). From 01dbac7b1589e0c2458d5160c27bad1b212d1d31 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 4 Mar 2018 11:37:11 -0800 Subject: [PATCH 019/103] Don't use a different setting for distant viewing distance --- apps/openmw/mwrender/renderingmanager.cpp | 14 ++++---------- apps/openmw/mwrender/renderingmanager.hpp | 1 - files/settings-default.cfg | 4 ---- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b3fee20b5..6f0ddba3a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -53,7 +53,6 @@ namespace { - float DLRenderDistance; float DLLandFogStart; float DLLandFogEnd; float DLUnderwaterFogStart; @@ -231,7 +230,6 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); - DLRenderDistance = Settings::Manager::getFloat("distant viewing distance", "Camera"); DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); @@ -312,10 +310,8 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? DLRenderDistance : mViewDistance; - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near"); mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far"); @@ -680,7 +676,7 @@ namespace MWRender rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); - rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mFarClip); + rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix()); rttCamera->setViewport(0, 0, w, h); @@ -945,10 +941,10 @@ namespace MWRender float fov = mFieldOfView; if (mFieldOfViewOverridden) fov = mFieldOfViewOverride; - mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mFarClip); + mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance); mUniformNear->set(mNearClip); - mUniformFar->set(mFarClip); + mUniformFar->set(mViewDistance); } void RenderingManager::updateTextureFiltering() @@ -1008,8 +1004,6 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - if(!mDistantTerrain) - mFarClip = mViewDistance; if(!mDistantFog) mStateUpdater->setFogEnd(mViewDistance); updateProjectionMatrix(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index da79fba98..1c689d29f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -254,7 +254,6 @@ namespace MWRender float mNightEyeFactor; float mNearClip; - float mFarClip; float mViewDistance; bool mDistantFog : 1; bool mDistantTerrain : 1; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c1d269e6f..dc770425f 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -25,10 +25,6 @@ small feature culling pixel size = 2.0 # can dramatically affect performance, see documentation for details. viewing distance = 6666.0 -# Maximum visible distance for distant terrain. Caution: setting this too high -# can increase the chance for Z-fighting (flickering artifacts). -distant viewing distance = 40960 - # Camera field of view in degrees (e.g. 30.0 to 110.0). # Does not affect the player's hands in the first person camera. field of view = 55.0 From 6c3ac834c43600ae3e3829e6d1f3c6080982de7d Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Mon, 5 Mar 2018 19:57:19 -0600 Subject: [PATCH 020/103] Preventing max quicksaves from being saved to settings.cfg if it is unchanged. --- apps/launcher/advancedpage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 0abefcc8f..9b6e5fa8c 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -73,7 +73,10 @@ void Launcher::AdvancedPage::saveSettings() // Saves Settings saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); - mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksavesComboBox->value()); + int maximumQuicksaves = maximumQuicksavesComboBox->value(); + if (maximumQuicksaves != mEngineSettings.getInt("max quicksaves", "Saves")) { + mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves); + } // Other Settings std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); From 60a663ef58dfed6f84d613942266b397d61cb420 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 6 Mar 2018 16:14:29 +0300 Subject: [PATCH 021/103] Account for all possible count values in getCountString (Bug #4346) --- apps/openmw/mwgui/itemwidget.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp index a31eb9c76..e793dbf58 100644 --- a/apps/openmw/mwgui/itemwidget.cpp +++ b/apps/openmw/mwgui/itemwidget.cpp @@ -16,7 +16,12 @@ namespace { if (count == 1) return ""; - if (count > 9999) + + if (count > 999999999) + return MyGUI::utility::toString(int(count/1000000000.f)) + "b"; + else if (count > 999999) + return MyGUI::utility::toString(int(count/1000000.f)) + "m"; + else if (count > 9999) return MyGUI::utility::toString(int(count/1000.f)) + "k"; else return MyGUI::utility::toString(count); From 3b922d810a01401d8a8d9b138375c5dbaed63beb Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 7 Mar 2018 14:10:58 +0300 Subject: [PATCH 022/103] Don't use floating point arithmetics for formatted count (Bug #4346) --- apps/openmw/mwgui/itemwidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp index e793dbf58..6b5be0314 100644 --- a/apps/openmw/mwgui/itemwidget.cpp +++ b/apps/openmw/mwgui/itemwidget.cpp @@ -18,11 +18,11 @@ namespace return ""; if (count > 999999999) - return MyGUI::utility::toString(int(count/1000000000.f)) + "b"; + return MyGUI::utility::toString(count/1000000000) + "b"; else if (count > 999999) - return MyGUI::utility::toString(int(count/1000000.f)) + "m"; + return MyGUI::utility::toString(count/1000000) + "m"; else if (count > 9999) - return MyGUI::utility::toString(int(count/1000.f)) + "k"; + return MyGUI::utility::toString(count/1000) + "k"; else return MyGUI::utility::toString(count); } From dfcd243150243af5f1f0e049309ba1dc6f6acbd1 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Wed, 7 Mar 2018 19:57:54 -0600 Subject: [PATCH 023/103] Remove the word "interior" from cell not found message --- apps/openmw/mwworld/store.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 9279e3fe7..158d3f771 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -592,7 +592,7 @@ namespace MWWorld const ESM::Cell *ptr = search(id); if (ptr == 0) { std::ostringstream msg; - msg << "Interior cell '" << id << "' not found"; + msg << "Cell '" << id << "' not found"; throw std::runtime_error(msg.str()); } return ptr; From d3b623b5d32e8eba6c135ba62acfe049840040a4 Mon Sep 17 00:00:00 2001 From: Harald H Date: Thu, 8 Mar 2018 21:23:24 +0100 Subject: [PATCH 024/103] http to https for supported urls (#1625) * http to https for supported urls * http to https * http to https * http to https * http to https * http to https * http to https * http to https * http tp https * http to https * http to https * http to https * http to https * http to https * http to https * http to https * http to https * some url fixes * http to https --- CI/before_script.msvc.sh | 16 +- CMakeLists.txt | 4 +- CONTRIBUTING.md | 2 +- LICENSE | 8 +- README.md | 6 +- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/pathgrid.cpp | 2 +- apps/openmw/mwsound/alext.h | 2 +- apps/openmw/mwsound/ffmpeg_decoder.hpp | 2 +- cmake/FindFreetype.cmake | 2 +- cmake/FindLIBUNSHIELD.cmake | 2 +- cmake/FindOpenGLES.cmake | 2 +- components/bsa/bsa_file.cpp | 4 +- components/bsa/bsa_file.hpp | 4 +- components/nif/controlled.hpp | 4 +- components/nif/controller.hpp | 4 +- components/nif/data.hpp | 4 +- components/nif/effect.hpp | 4 +- components/nif/extra.hpp | 4 +- components/nif/niftypes.hpp | 4 +- components/nif/property.hpp | 4 +- components/nif/record.hpp | 4 +- components/settings/settings.cpp | 2 +- docs/Doxyfile.cmake | 53 +++--- docs/DoxyfilePages.cmake | 16 +- .../openmw-cs/files-and-directories.rst | 6 +- docs/source/manuals/openmw-cs/tour.rst | 32 ++-- .../modding/convert_bump_mapped_mods.rst | 24 +-- docs/source/reference/modding/font.rst | 4 +- extern/oics/tinyxmlparser.cpp | 153 +++++++++--------- files/mac/openmw-Info.plist.in | 2 +- files/mac/openmw-cs-Info.plist.in | 2 +- files/openmw.appdata.xml | 6 +- files/settings-default.cfg | 2 +- files/shaders/water_fragment.glsl | 20 +-- 36 files changed, 205 insertions(+), 209 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index ee48c1f68..2a052912a 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -303,25 +303,25 @@ if [ -z $SKIP_DOWNLOAD ]; then # Boost if [ -z $APPVEYOR ]; then download "Boost 1.61.0" \ - "http://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ + "https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ "boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" fi # Bullet download "Bullet 2.86" \ - "http://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \ + "https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \ "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" # FFmpeg download "FFmpeg 3.2.4" \ - "http://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \ + "https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \ "ffmpeg-3.2.4-win${BITS}.zip" \ - "http://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \ + "https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \ "ffmpeg-3.2.4-dev-win${BITS}.zip" # MyGUI download "MyGUI 3.2.2" \ - "http://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \ + "https://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \ "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" # OpenAL @@ -331,7 +331,7 @@ if [ -z $SKIP_DOWNLOAD ]; then # OSG download "OpenSceneGraph 3.4.1-scrawl" \ - "http://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \ + "https://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \ "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" # Qt @@ -343,9 +343,9 @@ if [ -z $SKIP_DOWNLOAD ]; then fi download "Qt 5.7.2" \ - "http://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ + "https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ "qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \ - "http://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ + "https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ "qt-5-install.qs" fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 2923612fb..7c1f961f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -505,8 +505,8 @@ if(WIN32) SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md") SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}") - SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") - SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe") SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe") SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c82d1dfd..b5543d11e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ How to contribute to OpenMW Not sure what to do with all your free time? Pick out a task from here: -http://bugs.openmw.org/ +https://bugs.openmw.org/ Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first. diff --git a/LICENSE b/LICENSE index 9cecc1d46..9d742475f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -. +. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. +. diff --git a/README.md b/README.md index 0b5f63f93..368609332 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction * Version: 0.43.0 * License: GPLv3 (see [LICENSE](https://github.com/OpenMW/openmw/blob/master/LICENSE) for more information) -* Website: http://www.openmw.org +* Website: https://www.openmw.org * IRC: #openmw on irc.freenode.net Font Licenses: @@ -30,8 +30,8 @@ Getting Started * [Build from source](https://wiki.openmw.org/index.php?title=Development_Environment_Setup) * [Testing the game](https://wiki.openmw.org/index.php?title=Testing) * [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted) -* [Report a bug](http://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug! -* [Known issues](http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker) +* [Report a bug](https://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug! +* [Known issues](https://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker) The data path ------------- diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 134bbf943..974a08c11 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -406,7 +406,7 @@ namespace MWClass // store ptr.getRefData().setCustomData (data.release()); - getInventoryStore(ptr).autoEquip(ptr); + getInventoryStore(ptr).autoEquip(ptr); } } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 676f01922..f88b20a10 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * version 3 along with this program. If not, see - * http://www.gnu.org/licenses/ . + * https://www.gnu.org/licenses/ . */ #include "character.hpp" diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index c0122a861..ea4c973b7 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -8,7 +8,7 @@ namespace { - // See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html + // See https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html // // One of the smallest cost in Seyda Neen is between points 77 & 78: // pt x y diff --git a/apps/openmw/mwsound/alext.h b/apps/openmw/mwsound/alext.h index 4b9a15537..7162fa955 100644 --- a/apps/openmw/mwsound/alext.h +++ b/apps/openmw/mwsound/alext.h @@ -15,7 +15,7 @@ * License along with this library; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html + * Or go to https://www.gnu.org/copyleft/lgpl.html */ #ifndef AL_ALEXT_H diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index e06a68d64..2b76e0d7d 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -21,7 +21,7 @@ extern "C" // From version 54.56 binkaudio encoding format changed from S16 to FLTP. See: // https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d -// http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872 +// https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872 #include } diff --git a/cmake/FindFreetype.cmake b/cmake/FindFreetype.cmake index 3d28613ae..3b7586835 100644 --- a/cmake/FindFreetype.cmake +++ b/cmake/FindFreetype.cmake @@ -1,7 +1,7 @@ #------------------------------------------------------------------- # This file is part of the CMake build system for OGRE # (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ +# For the latest info, see https://www.ogre3d.org/ # # The contents of this file are placed in the public domain. Feel # free to make use of it in any way you like. diff --git a/cmake/FindLIBUNSHIELD.cmake b/cmake/FindLIBUNSHIELD.cmake index 285740b63..ee6414646 100644 --- a/cmake/FindLIBUNSHIELD.cmake +++ b/cmake/FindLIBUNSHIELD.cmake @@ -4,7 +4,7 @@ # LIBUNSHIELD_FOUND, if false, do not try to link to LibUnshield # LIBUNSHIELD_INCLUDE_DIRS, where to find the headers # -# Created by Tom Mason (wheybags) for OpenMW (http://openmw.org), based on FindMPG123.cmake +# Created by Tom Mason (wheybags) for OpenMW (https://openmw.org), based on FindMPG123.cmake # # Ripped off from other sources. In fact, this file is so generic (I # just did a search and replace on another file) that I wonder why the diff --git a/cmake/FindOpenGLES.cmake b/cmake/FindOpenGLES.cmake index 7ee2c07f1..6a0466409 100644 --- a/cmake/FindOpenGLES.cmake +++ b/cmake/FindOpenGLES.cmake @@ -1,7 +1,7 @@ #------------------------------------------------------------------- # This file is part of the CMake build system for OGRE # (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ +# For the latest info, see https://www.ogre3d.org/ # # The contents of this file are placed in the public domain. Feel # free to make use of it in any way you like. diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index c4be428b3..8905a86a1 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (bsa_file.cpp) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsa_file.hpp index 5ff86ef65..196dc30fb 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsa_file.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (bsa_file.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 5601474ac..be48e912e 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (controlled.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 0861dfa6b..527bb74af 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (controller.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 9b4a3a67c..6b7aa579b 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (data.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index 015809a68..453e4b04c 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (effect.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index 1e5a8616d..d935add55 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (extra.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/niftypes.hpp b/components/nif/niftypes.hpp index 5827448fd..778625717 100644 --- a/components/nif/niftypes.hpp +++ b/components/nif/niftypes.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (nif_types.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 96156c6d8..f46f8ef27 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (property.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 605c4d76e..b8597f7d1 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -2,7 +2,7 @@ OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2008-2010 Nicolay Korslund Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ + WWW: https://openmw.org/ This file (record.h) is part of the OpenMW package. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + https://www.gnu.org/licenses/ . */ diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 2e7b5a8ae..15a222d31 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -292,7 +292,7 @@ public: ostream << "# to its default, simply remove it from this file. For available" << std::endl; ostream << "# settings, see the file 'settings-default.cfg' or the documentation at:" << std::endl; ostream << "#" << std::endl; - ostream << "# http://openmw.readthedocs.io/en/master/reference/modding/settings/index.html" << std::endl; + ostream << "# https://openmw.readthedocs.io/en/master/reference/modding/settings/index.html" << std::endl; } // We still have one more thing to do before we're completely done writing the file. diff --git a/docs/Doxyfile.cmake b/docs/Doxyfile.cmake index 38ad84165..71ce32069 100644 --- a/docs/Doxyfile.cmake +++ b/docs/Doxyfile.cmake @@ -20,7 +20,7 @@ # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# built into libc) for the transcoding. See https://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. @@ -295,7 +295,7 @@ EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -328,7 +328,7 @@ BUILTIN_STL_SUPPORT = YES CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -687,7 +687,7 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See @@ -772,7 +772,7 @@ INPUT = @OpenMW_SOURCE_DIR@/apps \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. @@ -993,7 +993,7 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: @@ -1136,7 +1136,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1194,7 +1194,7 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# environment (see: https://developer.apple.com/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in @@ -1239,7 +1239,7 @@ DOCSET_PUBLISHER_NAME = OpenMW # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output @@ -1315,7 +1315,7 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1323,8 +1323,7 @@ QHP_NAMESPACE = org.openmw # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1332,23 +1331,21 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1453,7 +1450,7 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1465,7 +1462,7 @@ USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# https://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. @@ -1480,11 +1477,11 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example @@ -1495,7 +1492,7 @@ MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: https://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1542,7 +1539,7 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer ( doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1555,7 +1552,7 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer ( doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1726,7 +1723,7 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1882,7 +1879,7 @@ DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen -# Definitions (see http://autogen.sf.net) file that captures the structure of +# Definitions (see http://autogen.sourceforge.net) file that captures the structure of # the code including all documentation. Note that this feature is still # experimental and incomplete at the moment. # The default value is: NO. @@ -2093,7 +2090,7 @@ HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: YES. diff --git a/docs/DoxyfilePages.cmake b/docs/DoxyfilePages.cmake index d50a043d6..f3454c9d0 100644 --- a/docs/DoxyfilePages.cmake +++ b/docs/DoxyfilePages.cmake @@ -18,7 +18,7 @@ # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# https://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 @@ -581,7 +581,7 @@ INPUT = @OpenMW_SOURCE_DIR@/apps \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# into libc) for the transcoding. See https://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 @@ -753,7 +753,7 @@ REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You +# tagging system (see https://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO @@ -928,30 +928,30 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. +# Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. -# Qt Help Project / Filter Attributes. +# Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = diff --git a/docs/source/manuals/openmw-cs/files-and-directories.rst b/docs/source/manuals/openmw-cs/files-and-directories.rst index 77593dece..ae39082d7 100644 --- a/docs/source/manuals/openmw-cs/files-and-directories.rst +++ b/docs/source/manuals/openmw-cs/files-and-directories.rst @@ -145,7 +145,7 @@ and a place where OpenMW CS looks for already existing files. Resource files ============== -.. TODO This paragraph sounds weird +.. TODO This paragraph sounds weird Unless we are talking about a fully text based game, like Zork or Rogue, one would expect that a video game is using some media files: 3D models with @@ -219,6 +219,6 @@ files for textures. .. Hyperlink targets for the entire document -.. _FFmpeg: http://ffmpeg.org +.. _FFmpeg: https://ffmpeg.org .. _Vorbis: http://www.vorbis.com -.. _Theora: http://www.theora.org +.. _Theora: https://www.theora.org diff --git a/docs/source/manuals/openmw-cs/tour.rst b/docs/source/manuals/openmw-cs/tour.rst index 645c18453..83b7aae27 100644 --- a/docs/source/manuals/openmw-cs/tour.rst +++ b/docs/source/manuals/openmw-cs/tour.rst @@ -3,7 +3,7 @@ A Tour through OpenMW CS: making a magic ring In this first chapter we will create a mod that adds a new ring with a simple enchantment to the game. The ring will give its wearer a permanent Night Vision -effect while being worn. You do not need previous Morrowind modding experience, +effect while being worn. You do not need previous Morrowind modding experience, but you should be familiar with the game itself. There will be no scripting necessary, we can achieve everything using just what the base game offers out of the box. Before continuing make sure that OpenMW is properly @@ -133,7 +133,7 @@ the filter directly into the filter field rather than the name of an existing filter. To signify that we are using an instant filter the have to use `!` as the first character. Type the following into the field: -.. code:: +.. code:: !string("id", ".*ring.*") @@ -217,20 +217,20 @@ actually modify the contents of the game. Adding to an NPC ================ -The simplest way is probably to add it to the inventory of a shopkeeper. +The simplest way is probably to add it to the inventory of a shopkeeper. An obvious candidate is Arrille in Seyda Neen - he's quick to find in a new game and he's easy to find in the CS as his name comes early alphabetically. .. figure:: _static/images/chapter-1/Ring_to_Arrille.png :alt: Putting the ring into Arrille's inventory - -Open the CS and open the *Objects* table (*World* → *Objects*). + +Open the CS and open the *Objects* table (*World* → *Objects*). Scroll down to Arrille, or use a filter like !string("ID","arrille"). -Open another pane to edit him - either right click and select edit or use the +Open another pane to edit him - either right click and select edit or use the shortcut (default is shift double-click). Scroll down to the inventory section -and right click to add a new row. Type in the id of the ring (or find it in the -object pane, and drag and drop). Set the number of rings for him to stock - with +and right click to add a new row. Type in the id of the ring (or find it in the +object pane, and drag and drop). Set the number of rings for him to stock - with a negative number indicating that he will restock again to maintain that level. However, it's an attractive item, so he will probably wear it rather than sell it. @@ -241,7 +241,7 @@ Fargoth to give it to the player in exchange for his healing ring. .. figure:: _static/images/chapter-1/Ring_to_Fargoth_1.png :alt: Editing Fargoth to give ring to player - + Open the *Topicinfo* Table (*Characters* → *Topic Infos*). Use a filter !string(Topic,ring) and select the row with a response starting with "You found it!". Edit the record, firstly by adding a bit more to the response, then by adding a line to the script @@ -297,7 +297,7 @@ Placing in plain sight ===================== Let's hide the Ring of Night vision in the cabin of the [Ancient Shipwreck] -(http://en.uesp.net/wiki/Morrowind:Ancient_Shipwreck), a derelict vessel +(https://en.uesp.net/wiki/Morrowind:Ancient_Shipwreck), a derelict vessel southeast of Dagon Fel. Open the list of Cells (*World* → *Cells*) and find "Ancient Shipwreck, Cabin". @@ -333,8 +333,8 @@ This is probably a suitable place to start talking about how navigation differs in vanilla Morrowind. There is advice in Scripting for Dummies, the definitive manual for Morrowind Scripting: -"If you give your scripts a common tag, that will make it easier to jump between the -different scripts of your project, e.g. start every script name with AA_Scriptname +"If you give your scripts a common tag, that will make it easier to jump between the +different scripts of your project, e.g. start every script name with AA_Scriptname this will put them right at the beginning of the list and keep them neatly together." This is valid for the rather poorer navigation facilities there, but it's not sensible for @@ -359,12 +359,12 @@ the base game. "Modified" status will cover items from the base game which have been modified in this addon. -Click on the top of the column to toggle between ascending and descending order - thus between "Added" -and "Modified" at the top. Or put your desired modified status into a filter then sort alpabetically +Click on the top of the column to toggle between ascending and descending order - thus between "Added" +and "Modified" at the top. Or put your desired modified status into a filter then sort alpabetically on a different column. - + Checking your new addon ======================= @@ -372,4 +372,4 @@ Launch OpenMW and in the launcher under *Data Files* check your addon, if it's n already checked. Load a game and make your way to Seyda Neen - or start a new game. Check whether Arrille has one (or more) for sale, and whether Fargoth give you one -when you return his healing ring. \ No newline at end of file +when you return his healing ring. diff --git a/docs/source/reference/modding/convert_bump_mapped_mods.rst b/docs/source/reference/modding/convert_bump_mapped_mods.rst index 71ac29468..1891b5c4d 100644 --- a/docs/source/reference/modding/convert_bump_mapped_mods.rst +++ b/docs/source/reference/modding/convert_bump_mapped_mods.rst @@ -20,7 +20,7 @@ General introduction to normal map conversion :Authors: Joakim (Lysol) Berg :Updated: 2016-11-11 -This page has general information and tutorials on how normal mapping works in OpenMW and how you can make mods using the old fake normal mapping technique (such as `Netch Bump mapped`_ and `Hlaalu Bump mapped`_, and maybe the most (in)famous one to give shiny rocks in OpenMW, the mod `On the Rocks`_!, featured in MGSO and Morrowind Rebirth) work in OpenMW. +This page has general information and tutorials on how normal mapping works in OpenMW and how you can make mods using the old fake normal mapping technique (such as `Netch Bump mapped`_ and `Hlaalu Bump mapped`_, and maybe the most (in)famous one to give shiny rocks in OpenMW, the mod `On the Rocks`_!, featured in MGSO and Morrowind Rebirth) work in OpenMW. *Note:* The conversion made in the `Converting Apel's Various Things - Sacks`_-part of this tutorial require the use of the application NifSkope. There are binaries available for Windows, but not for Mac or Linux. Reports say that NifSkope versions 1.X will compile on Linux as long as you have Qt packages installed, while the later 2.X versions will not compile. @@ -179,24 +179,24 @@ The sacks included in Apel's `Various Things - Sacks`_ come in two versions – #. Remove all these tags by selecting them one at a time and press right click>Block>Remove Branch. (Ctrl-Del) #. Repeat this on all the affected models. #. If you launch OpenMW now, you'll `no longer have shiny models`_. But one thing is missing. Can you see it? It's actually hard to spot on still pictures, but we have no normal maps here. -#. Now, go back to the root of where you installed the mod. Now go to ``./Textures/`` and you'll find the texture files in question. +#. Now, go back to the root of where you installed the mod. Now go to ``./Textures/`` and you'll find the texture files in question. #. OpenMW detects normal maps if they have the same name as the base diffuse texture, but with a *_n.dds* suffix. In this mod, the normal maps has a suffix of *_nm.dds*. Change all the files that ends with *_nm.dds* to instead end with *_n.dds*. #. Finally, `we are done`_! Since these models have one or two textures applied to them, the fix was not that time-consuming. It gets worse when you have to fix a model that uses loads of textures. The principle is the same, it just requires more manual work which is annoying and takes time. -.. _`Netch Bump mapped`: http://www.nexusmods.com/morrowind/mods/42851/? -.. _`Hlaalu Bump mapped`: http://www.nexusmods.com/morrowind/mods/42396/? +.. _`Netch Bump mapped`: https://www.nexusmods.com/morrowind/mods/42851/? +.. _`Hlaalu Bump mapped`: https://www.nexusmods.com/morrowind/mods/42396/? .. _`On the Rocks`: http://mw.modhistory.com/download-44-14107 .. _`texture modding`: https://wiki.openmw.org/index.php?title=TextureModding -.. _`MGE XE`: http://www.nexusmods.com/morrowind/mods/26348/? -.. _PeterBitt: http://www.nexusmods.com/morrowind/users/4381248/? -.. _`PBR Scamp Replacer`: http://www.nexusmods.com/morrowind/mods/44314/? +.. _`MGE XE`: https://www.nexusmods.com/morrowind/mods/26348/? +.. _PeterBitt: https://www.nexusmods.com/morrowind/users/4381248/? +.. _`PBR Scamp Replacer`: https://www.nexusmods.com/morrowind/mods/44314/? .. _settings.cfg: https://wiki.openmw.org/index.php?title=Settings .. _`Multiple data folders`: https://wiki.openmw.org/index.php?title=Mod_installation -.. _`Various Things - Sacks`: http://www.nexusmods.com/morrowind/mods/42558/? -.. _Lead: http://imgur.com/bwpcYlc +.. _`Various Things - Sacks`: https://www.nexusmods.com/morrowind/mods/42558/? +.. _Lead: https://imgur.com/bwpcYlc .. _NifSkope: http://niftools.sourceforge.net/wiki/NifSkope -.. _Blocks: http://imgur.com/VmQC0WG -.. _`no longer have shiny models`: http://imgur.com/vu1k7n1 -.. _`we are done`: http://imgur.com/yyZxlTw +.. _Blocks: https://imgur.com/VmQC0WG +.. _`no longer have shiny models`: https://imgur.com/vu1k7n1 +.. _`we are done`: https://imgur.com/yyZxlTw diff --git a/docs/source/reference/modding/font.rst b/docs/source/reference/modding/font.rst index 5f01b12d9..80d01c27f 100644 --- a/docs/source/reference/modding/font.rst +++ b/docs/source/reference/modding/font.rst @@ -15,7 +15,7 @@ Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts. Th - To replace the primary "Magic Cards" font: - #. Download `Pelagiad `_ by Isak Larborn (aka Isaskar). + #. Download `Pelagiad `_ by Isak Larborn (aka Isaskar). #. Install the ``openmw_font.xml`` file into ``resources/mygui/openmw_font.xml`` in your OpenMW installation. #. Copy ``Pelagiad.ttf`` into ``resources/mygui/`` as well. #. If desired, you can now delete the original ``Magic_Cards.*`` files from your Data Files/Fonts directory. @@ -74,4 +74,4 @@ Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts. Th Bitmap fonts ------------ -Morrowind ``.fnt`` files are essentially a bitmap font, but using them is discouraged because of no Unicode support. MyGUI has its own format for bitmap fonts. An example can be seen by using the --export-fonts command line option (see above), which converts Morrowind ``.fnt`` to a MyGUI bitmap font. This is the recommended format to use if you wish to edit Morrowind's bitmap font or create a new bitmap font. \ No newline at end of file +Morrowind ``.fnt`` files are essentially a bitmap font, but using them is discouraged because of no Unicode support. MyGUI has its own format for bitmap fonts. An example can be seen by using the --export-fonts command line option (see above), which converts Morrowind ``.fnt`` to a MyGUI bitmap font. This is the recommended format to use if you wish to edit Morrowind's bitmap font or create a new bitmap font. diff --git a/extern/oics/tinyxmlparser.cpp b/extern/oics/tinyxmlparser.cpp index 253cd93ff..d5bda8fee 100644 --- a/extern/oics/tinyxmlparser.cpp +++ b/extern/oics/tinyxmlparser.cpp @@ -2,23 +2,23 @@ www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you must +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source +3. This notice may not be removed or altered from any source distribution. */ @@ -39,8 +39,8 @@ distribution. // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = { { "&", 5, '&' }, { "<", 4, '<' }, @@ -50,20 +50,20 @@ TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = }; // Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html +// https://www.unicode.org/faq/utf_bom.html // Including the basic of this table, which determines the #bytes in the // sequence from the lead byte. 1 placed for invalid sequences -- // although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: +// Beware of the non-characters in UTF-8: // ef bb bf (Microsoft "lead bytes") // ef bf be -// ef bf bf +// ef bf bf const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; -const int TiXmlBase::utf8ByteTable[256] = +const int TiXmlBase::utf8ByteTable[256] = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 @@ -75,9 +75,9 @@ const int TiXmlBase::utf8ByteTable[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte @@ -91,7 +91,7 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng const unsigned long BYTE_MARK = 0x80; const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - if (input < 0x80) + if (input < 0x80) *length = 1; else if ( input < 0x800 ) *length = 2; @@ -105,22 +105,22 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng output += *length; // Scary scary fall throughs. - switch (*length) + switch (*length) { case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 1: - --output; + --output; *output = (char)(input | FIRST_BYTE_MARK[*length]); } } @@ -130,7 +130,7 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very + // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) @@ -151,7 +151,7 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very + // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) @@ -224,7 +224,7 @@ void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) case '\r': // bump down to the next line ++row; - col = 0; + col = 0; // Eat the character ++p; @@ -266,11 +266,11 @@ void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) // In these cases, don't advance the column. These are // 0-width spaces. if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; + p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; + p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; + p += 3; else { p +=3; ++col; } // A normal character. } @@ -322,10 +322,10 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) while ( *p ) { const unsigned char* pU = (const unsigned char*)p; - + // Skip the stupid Microsoft UTF-8 Byte order marks if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) { p += 3; @@ -413,12 +413,12 @@ const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncodi // After that, they can be letters, underscores, numbers, // hyphens, or colons. (Colons are valid ony for namespaces, // but tinyxml can't tell namespaces from names.) - if ( p && *p + if ( p && *p && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) { const char* start = p; while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) + && ( IsAlphaNum( (unsigned char ) *p, encoding ) || *p == '_' || *p == '-' || *p == '.' @@ -469,7 +469,7 @@ const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXml ucs += mult * (*q - 'a' + 10); else if ( *q >= 'A' && *q <= 'F' ) ucs += mult * (*q - 'A' + 10 ); - else + else return 0; mult *= 16; --q; @@ -492,7 +492,7 @@ const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXml { if ( *q >= '0' && *q <= '9' ) ucs += mult * (*q - '0'); - else + else return 0; mult *= 10; --q; @@ -571,10 +571,10 @@ bool TiXmlBase::StringEqual( const char* p, return false; } -const char* TiXmlBase::ReadText( const char* p, - TIXML_STRING * text, - bool trimWhiteSpace, - const char* endTag, +const char* TiXmlBase::ReadText( const char* p, + TIXML_STRING * text, + bool trimWhiteSpace, + const char* endTag, bool caseInsensitive, TiXmlEncoding encoding ) { @@ -631,7 +631,7 @@ const char* TiXmlBase::ReadText( const char* p, } } } - if ( p ) + if ( p ) p += strlen( endTag ); return p; } @@ -647,7 +647,7 @@ void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) // This "pre-streaming" will never read the closing ">" so the // sub-tag can orient itself. - if ( !StreamTo( in, '<', tag ) ) + if ( !StreamTo( in, '<', tag ) ) { SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return; @@ -669,7 +669,7 @@ void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) if ( in->good() ) { - // We now have something we presume to be a node of + // We now have something we presume to be a node of // some sort. Identify it, and call the node to // continue streaming. TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); @@ -778,7 +778,7 @@ const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiX encoding = TIXML_ENCODING_UTF8; else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else + else encoding = TIXML_ENCODING_LEGACY; } @@ -796,7 +796,7 @@ const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiX } void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ +{ // The first error in a chain is more accurate - don't set again! if ( error ) return; @@ -833,7 +833,7 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) return 0; } - // What is this thing? + // What is this thing? // - Elements start with a letter or underscore, but xml is reserved. // - Comments: - + org.openmw.desktop CC0-1.0 - GPL-3.0 and MIT + GPL-3.0 and MIT OpenMW Unofficial open source engine re-implementation of the game Morrowind @@ -20,7 +20,6 @@ Copyright 2017 Bret Curtis You will still need the original game data to play OpenMW.

- https://wiki.openmw.org/images/b/b2/Openmw_0.11.1_launcher_1.png @@ -34,7 +33,18 @@ Copyright 2017 Bret Curtis https://wiki.openmw.org/images/5/5b/Screenshot_Vivec_seen_from_Ebonheart_0.35.png Vivec seen from Ebonheart on OpenMW + + http://wiki.openmw.org/images/a/a3/0.40_Screenshot-Balmora_3.png + Balmora at morning on OpenMW + + + Game + RolePlaying + + + + https://openmw.org https://bugs.openmw.org/ https://openmw.org/faq/ From 55a6344fb0dca253c2177a1bacd8e5c51ec989ba Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 22 Apr 2018 15:41:07 +0000 Subject: [PATCH 077/103] Revert log spam --- components/fallback/fallback.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/fallback/fallback.cpp b/components/fallback/fallback.cpp index ce6cba313..edc3f2678 100644 --- a/components/fallback/fallback.cpp +++ b/components/fallback/fallback.cpp @@ -1,7 +1,5 @@ #include "fallback.hpp" -#include - #include @@ -19,7 +17,6 @@ namespace Fallback std::map::const_iterator it; if((it = mFallbackMap.find(fall)) == mFallbackMap.end()) { - std::cerr << "Warning: fallback value " << fall << " not found." << std::endl; return ""; } return it->second; From b69e812a52827d5e6e24af9fcd76335abff505f8 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 22 Apr 2018 22:31:56 +0300 Subject: [PATCH 078/103] Utilize inventory character preview lighting color fallback settings --- apps/openmw/mwrender/characterpreview.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index f7219959a..622728c22 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include "../mwbase/environment.hpp" @@ -161,11 +162,18 @@ namespace MWRender lightmodel->setAmbientIntensity(osg::Vec4(0.25, 0.25, 0.25, 1.0)); stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); - /// \todo Read the fallback values from INIImporter (Inventory:Directional*) ? osg::ref_ptr light = new osg::Light; + const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback(); + float diffuseR = fallback->getFallbackFloat("Inventory_DirectionalDiffuseR"); + float diffuseG = fallback->getFallbackFloat("Inventory_DirectionalDiffuseG"); + float diffuseB = fallback->getFallbackFloat("Inventory_DirectionalDiffuseB"); + float ambientR = fallback->getFallbackFloat("Inventory_DirectionalAmbientR"); + float ambientG = fallback->getFallbackFloat("Inventory_DirectionalAmbientG"); + float ambientB = fallback->getFallbackFloat("Inventory_DirectionalAmbientB"); + /// \todo Read DirectionalRotationX/DirectionalRotationY light->setPosition(osg::Vec4(-0.3,0.3,0.7, 0.0)); - light->setDiffuse(osg::Vec4(1,1,1,1)); - light->setAmbient(osg::Vec4(0,0,0,1)); + light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1)); + light->setAmbient(osg::Vec4(ambientR,ambientG,ambientB,1)); light->setSpecular(osg::Vec4(0,0,0,0)); light->setLightNum(0); light->setConstantAttenuation(1.f); From 9073e4d4baf1cf5116c4ab456a5a42ecc321fb01 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 21 Apr 2018 22:20:07 +0300 Subject: [PATCH 079/103] Initialize playlist file list in playPlaylist (fixes #4134) --- apps/openmw/mwsound/soundmanagerimp.cpp | 53 +++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a798d350c..db02bb482 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -393,32 +393,8 @@ namespace MWSound void SoundManager::startRandomTitle() { - std::vector filelist; + const std::vector &filelist = mMusicFiles[mCurrentPlaylist]; auto &tracklist = mMusicToPlay[mCurrentPlaylist]; - if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end()) - { - const std::map& index = mVFS->getIndex(); - - std::string pattern = "Music/" + mCurrentPlaylist; - mVFS->normalizeFilename(pattern); - - std::map::const_iterator found = index.lower_bound(pattern); - while (found != index.end()) - { - if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern) - filelist.push_back(found->first); - else - break; - ++found; - } - - mMusicFiles[mCurrentPlaylist] = filelist; - } - else - filelist = mMusicFiles[mCurrentPlaylist]; - - if(filelist.empty()) - return; // Do a Fisher-Yates shuffle @@ -454,6 +430,33 @@ namespace MWSound void SoundManager::playPlaylist(const std::string &playlist) { + if (mCurrentPlaylist == playlist) + return; + + if (mMusicFiles.find(playlist) == mMusicFiles.end()) + { + std::vector filelist; + const std::map& index = mVFS->getIndex(); + + std::string pattern = "Music/" + playlist; + mVFS->normalizeFilename(pattern); + + std::map::const_iterator found = index.lower_bound(pattern); + while (found != index.end()) + { + if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern) + filelist.push_back(found->first); + else + break; + ++found; + } + + mMusicFiles[playlist] = filelist; + } + + if (mMusicFiles[playlist].empty()) + return; + mCurrentPlaylist = playlist; startRandomTitle(); } From bfcdf660f2052dc40dacd9f50a61d64ce14e22d0 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 23 Apr 2018 21:17:25 +0300 Subject: [PATCH 080/103] Utilize inventory character preview lighting rotation fallback settings --- apps/openmw/mwrender/characterpreview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 622728c22..b3f672f31 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -1,5 +1,6 @@ #include "characterpreview.hpp" +#include #include #include @@ -170,8 +171,12 @@ namespace MWRender float ambientR = fallback->getFallbackFloat("Inventory_DirectionalAmbientR"); float ambientG = fallback->getFallbackFloat("Inventory_DirectionalAmbientG"); float ambientB = fallback->getFallbackFloat("Inventory_DirectionalAmbientB"); - /// \todo Read DirectionalRotationX/DirectionalRotationY - light->setPosition(osg::Vec4(-0.3,0.3,0.7, 0.0)); + float azimuth = osg::DegreesToRadians(180.f - fallback->getFallbackFloat("Inventory_DirectionalRotationX")); + float altitude = osg::DegreesToRadians(fallback->getFallbackFloat("Inventory_DirectionalRotationY")); + float positionX = std::cos(azimuth) * std::sin(altitude); + float positionY = std::sin(azimuth) * std::sin(altitude); + float positionZ = std::cos(altitude); + light->setPosition(osg::Vec4(positionX,positionY,positionZ, 0.0)); light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1)); light->setAmbient(osg::Vec4(ambientR,ambientG,ambientB,1)); light->setSpecular(osg::Vec4(0,0,0,0)); From 4cc65239ff1c33269a1e56c15038b02503af808e Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Wed, 25 Apr 2018 10:21:58 +0000 Subject: [PATCH 081/103] Add section on dealing with regressions --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b2b4dfdd..4805bff3b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,6 +103,10 @@ To be able to merge PRs, commit priviledges are required. If you do not have the The person to merge the PR may either use github's Merge button or if using the command line, use the ```--no-ff``` flag (so a merge commit is created, just like with Github's merge button) and include the pull request number in the commit description. +Dealing with regressions +======================== + +The master branch should always be in a working state that is not worse than the previous release in any way. If a regression is found, the first and foremost priority should be to get the regression fixed quickly, either by reverting the change that caused it or finding a better solution. Please avoid leaving the project in the 'broken' state for an extensive period of time while proper solutions are found. If the solution takes more than a day or so then it is usually better to revert the offending change first and reapply it later when fixed. Other resources =============== From 6b47f729591d01e9d6bd7d0f1fa1f31fda46863b Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 25 Apr 2018 15:31:49 +0300 Subject: [PATCH 082/103] Set character preview scene ambient to 0, 0, 0 --- apps/openmw/mwrender/characterpreview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b3f672f31..faaa3799e 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -160,7 +160,7 @@ namespace MWRender stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); osg::ref_ptr lightmodel = new osg::LightModel; - lightmodel->setAmbientIntensity(osg::Vec4(0.25, 0.25, 0.25, 1.0)); + lightmodel->setAmbientIntensity(osg::Vec4(0.0, 0.0, 0.0, 1.0)); stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); osg::ref_ptr light = new osg::Light; From 5afcc5686062a7c2cab90186a25cc5e9dbfada29 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 29 Apr 2018 09:24:13 +0400 Subject: [PATCH 083/103] Handle NiLookAtController (feature #4407) --- components/nif/controller.cpp | 12 ++++++++++++ components/nif/controller.hpp | 9 +++++++++ components/nif/niffile.cpp | 1 + components/nif/record.hpp | 3 ++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index f39132543..ddfa02a09 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -101,6 +101,18 @@ namespace Nif data.post(nif); } + void NiLookAtController::read(NIFStream *nif) + { + Controller::read(nif); + data.read(nif); + } + + void NiLookAtController::post(NIFFile *nif) + { + Controller::post(nif); + data.post(nif); + } + void NiPathController::read(NIFStream *nif) { Controller::read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 527bb74af..ce8bff041 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -99,6 +99,15 @@ public: void post(NIFFile *nif); }; +class NiLookAtController : public Controller +{ +public: + NiKeyframeDataPtr data; + + void read(NIFStream *nif); + void post(NIFFile *nif); +}; + class NiUVController : public Controller { public: diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b4b1caefc..4061247b5 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -108,6 +108,7 @@ static std::map makeFactory() newFactory.insert(makeEntry("NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper )); newFactory.insert(makeEntry("NiSourceTexture", &construct , RC_NiSourceTexture )); newFactory.insert(makeEntry("NiSkinInstance", &construct , RC_NiSkinInstance )); + newFactory.insert(makeEntry("NiLookAtController", &construct , RC_NiLookAtController )); return newFactory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index b8597f7d1..ee4d508ab 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -93,7 +93,8 @@ enum RecordType RC_NiSourceTexture, RC_NiSkinInstance, RC_RootCollisionNode, - RC_NiSphericalCollider + RC_NiSphericalCollider, + RC_NiLookAtController }; /// Base class for all records From d967983f5c186818f1030871814dc0f04db0e50e Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 25 Apr 2018 00:20:57 +0300 Subject: [PATCH 084/103] Assume Morrowind.esm dependency for dependency-less content addons (fixes #2829) --- components/contentselector/model/contentmodel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index a7ac29b46..41407ec88 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -512,7 +512,9 @@ void ContentSelectorModel::ContentModel::sortFiles() //dependencies appear. for (int j = i + 1; j < fileCount; j++) { - if (gamefiles.contains(mFiles.at(j)->fileName(), Qt::CaseInsensitive)) + if (gamefiles.contains(mFiles.at(j)->fileName(), Qt::CaseInsensitive) + || (!mFiles.at(i)->isGameFile() && gamefiles.isEmpty() + && mFiles.at(j)->fileName().compare("Morrowind.esm", Qt::CaseInsensitive) == 0)) // Hack: implicit dependency on Morrowind.esm for dependency-less files { mFiles.move(j, i); From e4e225f4e7002d3b98c9f5b4206e7d20bd7bfb93 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 3 May 2018 14:32:15 +0300 Subject: [PATCH 085/103] Add topic, journal and related -info icons. --- apps/opencs/model/world/universalid.cpp | 8 ++++---- files/opencs/dialogue-topic-infos.png | Bin 0 -> 306 bytes files/opencs/dialogue-topics.png | Bin 0 -> 282 bytes files/opencs/journal-topic-infos.png | Bin 0 -> 300 bytes files/opencs/journal-topics.png | Bin 0 -> 273 bytes files/opencs/resources.qrc | 4 ++++ 6 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 files/opencs/dialogue-topic-infos.png create mode 100644 files/opencs/dialogue-topics.png create mode 100644 files/opencs/journal-topic-infos.png create mode 100644 files/opencs/journal-topics.png diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index ebeea0184..8d7a7761e 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -75,10 +75,10 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./region.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 }, - { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, - { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":./dialogue-topics.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", ":./journal-topics.png" }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", ":./dialogue-topic-infos.png" }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", ":./journal-topic-infos.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", 0 }, diff --git a/files/opencs/dialogue-topic-infos.png b/files/opencs/dialogue-topic-infos.png new file mode 100644 index 0000000000000000000000000000000000000000..6242eddf4f0858ab3300580784fc9ef193e42c11 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FST zi(`m|;L;#NzC#8)IZUq(o!NXTf5S(yBPaAH+4OK4DhR&o>A7UK)-ht$8>{E1Ew{Z+ zIBXzN^;~9d=2DJ5&G$JXIM1BoT3~ux%beSpqjgn9@VTFs%nA>qJYDk1=oix!i_xbJlLj`N(U)D7#Qcs-tSlrx}w> zIDfDi6f?2Za_oq-Dwn&UA%9=?q1+PlyLR(5!#Ef|G3*havwUje67@fE56gZ0%O7jc z)UaFp?ZMvn$vumuihcHozUnIwKUOa}r6*7QCU@zL`0JSyyE=jXW$<+Mb6Mw<&;$VZ CHFqQc literal 0 HcmV?d00001 diff --git a/files/opencs/dialogue-topics.png b/files/opencs/dialogue-topics.png new file mode 100644 index 0000000000000000000000000000000000000000..caa6d7e7cb15c81562831671e9c04d5e06a4a284 GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FbW zi(`m|;N4(PzC#8)K3v=9Rfc`y^V`E(=w!3_rxeFZ_Cr2LUEVDd>5JI(#>6<;ys)On z(0a!Ad5N2!+FY13`9Rt-#!0)cM>%a14t2bQh$+S(6oCEG2WVCo7-OPbundXxZ0Wukc_xTgUSQI~(jL$`u^ouiG5)jz7G| zaV9VSL6bLgAKLDD8pU)bb#)4(!#)N3L(w5`cCV8zT(!O7o4-Q*!|zL1uHkApVeT|h d`t!=YjE_44d}XR8wE_Lb;OXk;vd$@?2>>MvZcYFI literal 0 HcmV?d00001 diff --git a/files/opencs/journal-topic-infos.png b/files/opencs/journal-topic-infos.png new file mode 100644 index 0000000000000000000000000000000000000000..4cc4464897026d9042d46c8051d636549f86aeaf GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1G6o zi(`m|U~e!d-(dxw>>D3)7W6&Vn4;wLa9&W>tfPtd zS8aS>ExmC{;Ki6+sTUlIIa7A@Z(Q>Ai-xn8XVJO*C7dN*)-_Y+Dl}VKy9#dj+~BbL z;ln#ux2jp~DTrR4{PK;~`xZ|=12#b$%VS?70$EaSI~zV_I4Qku!3L-AU7Vlv*?X)f zM?uqfcy)1SS8^OY3XRXXoXXn!62%etxQq4ojuyVy<4PH%>7;_I}2_J=z_9{}X#o%~lUn1NxM~)78&qol`;+01)we2mk;8 literal 0 HcmV?d00001 diff --git a/files/opencs/journal-topics.png b/files/opencs/journal-topics.png new file mode 100644 index 0000000000000000000000000000000000000000..d4e58a288503ea273e85169fceede9099d0c32e9 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Gy) zi(`m|;N8iu`3@=Yw1%72T33WWczdPcd4d<44|9F)rYTPP@sSgGAI&*^Mak)FXpvst zSD9~dJlVO`L9xeLe`N(8=1o51*8AR^>C@LK?mdA5KMvfKeSNx2#J0si#A1rV(j#Uq z=X`D*zP$ea;=2L`%^h#v_ncaiKD$nfmvPmb0yBjjYnC~t-xc`47v}o^5O3oj?knC- zF$Y=g1XUw~^-szROsOlZTz~Ue>4Go1Q#w~4JCgmx;blVQdwb#THHTlE6WYsoSGw$B TaB+Gs&^rvCu6{1-oD!Mdialogue-greeting.png dialogue-persuasion.png dialogue-voice.png + dialogue-topics.png + dialogue-topic-infos.png + journal-topic-infos.png + journal-topics.png door.png enchantment.png faction.png From 85b7aa4f09d3ebd7bad3bec4dd6f1540e08d9379 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 3 May 2018 19:47:39 +0300 Subject: [PATCH 086/103] Uncomment is_pod test in fixed string tests --- apps/openmw_test_suite/esm/test_fixed_string.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/openmw_test_suite/esm/test_fixed_string.cpp b/apps/openmw_test_suite/esm/test_fixed_string.cpp index 59dd7fe66..598e8daad 100644 --- a/apps/openmw_test_suite/esm/test_fixed_string.cpp +++ b/apps/openmw_test_suite/esm/test_fixed_string.cpp @@ -66,10 +66,8 @@ TEST(EsmFixedString, struct_size) TEST(EsmFixedString, DISABLED_is_pod) { - /* TODO: enable in C++11 - * ASSERT_TRUE(std::is_pod::value); - * ASSERT_TRUE(std::is_pod::value); - * ASSERT_TRUE(std::is_pod::value); - * ASSERT_TRUE(std::is_pod::value); - */ + ASSERT_TRUE(std::is_pod::value); + ASSERT_TRUE(std::is_pod::value); + ASSERT_TRUE(std::is_pod::value); + ASSERT_TRUE(std::is_pod::value); } From 8be93b4a12f634c7e31d13b4039f2de16077907e Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 3 May 2018 19:56:01 +0300 Subject: [PATCH 087/103] Initialize mandatoryIds vector C++11-way --- apps/opencs/model/tools/tools.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 3b2c80263..445db53af 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -61,12 +61,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)), this, SLOT (verifierMessage (const CSMDoc::Message&, int))); - std::vector mandatoryIds; // I want C++11, damn it! - mandatoryIds.push_back ("Day"); - mandatoryIds.push_back ("DaysPassed"); - mandatoryIds.push_back ("GameHour"); - mandatoryIds.push_back ("Month"); - mandatoryIds.push_back ("PCRace"); + std::vector mandatoryIds {"Day", "DaysPassed", "GameHour", "Month", "PCRace"}; mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(), CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); From 9ac9f9463851fc54de742c3c74db02fdf245b1c7 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 4 May 2018 20:00:58 +0300 Subject: [PATCH 088/103] Rename "Model" column to "Model/Animation" (feature #2694) --- apps/opencs/model/world/columns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index ec010ba36..7c0fbff4b 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -66,7 +66,7 @@ namespace CSMWorld { ColumnId_SleepForbidden, "Sleep Forbidden" }, { ColumnId_InteriorWater, "Interior Water" }, { ColumnId_InteriorSky, "Interior Sky" }, - { ColumnId_Model, "Model" }, + { ColumnId_Model, "Model/Animation" }, { ColumnId_Script, "Script" }, { ColumnId_Icon, "Icon" }, { ColumnId_Weight, "Weight" }, From 1dd36329a34e1cf2d5b7412472d5a83f6907d98d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 3 May 2018 10:37:55 +0400 Subject: [PATCH 089/103] Load default markers definitions (bug #4410) --- apps/openmw/mwworld/esmstore.cpp | 1 + apps/openmw/mwworld/store.cpp | 28 ++++++++++++++++++++++++++++ components/esm/loadstat.hpp | 16 +++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 4a1763d0a..2fe9ebcad 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -141,6 +141,7 @@ void ESMStore::setUp() mMagicEffects.setUp(); mAttributes.setUp(); mDialogs.setUp(); + mStatics.setUp(); } int ESMStore::countSavedGameRecords() const diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 158d3f771..e9968c38f 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1053,6 +1053,34 @@ namespace MWWorld } } + template<> + void Store::setUp() + { + // Load default marker definitions, if game files do not have them for some reason + std::pair markers[] = { + std::make_pair("divinemarker", "marker_divine.nif"), + std::make_pair("doormarker", "marker_arrow.nif"), + std::make_pair("northmarker", "marker_north.nif"), + std::make_pair("templemarker", "marker_temple.nif"), + std::make_pair("travelmarker", "marker_travel.nif") + }; + + for (const std::pair marker : markers) + { + if (search(marker.first) == 0) + { + ESM::Static newMarker = ESM::Static(marker.first, marker.second); + mStatic.insert(std::make_pair(marker.first, newMarker)); + + std::map::iterator found = mStatic.find(marker.first); + if (found != mStatic.end()) + { + mShared.push_back(&found->second); + } + } + } + } + template <> inline RecordId Store::load(ESM::ESMReader &esm) { // The original letter case of a dialogue ID is saved, because it's printed diff --git a/components/esm/loadstat.hpp b/components/esm/loadstat.hpp index 930cdb849..f80875b65 100644 --- a/components/esm/loadstat.hpp +++ b/components/esm/loadstat.hpp @@ -26,13 +26,23 @@ struct Static /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string getRecordType() { return "Static"; } - std::string mId, mModel; + std::string mId, mModel; - void load(ESMReader &esm, bool &isDeleted); - void save(ESMWriter &esm, bool isDeleted = false) const; + void load(ESMReader &esm, bool &isDeleted); + void save(ESMWriter &esm, bool isDeleted = false) const; void blank(); ///< Set record to default state (does not touch the ID). + + Static(const std::string id, const std::string &model) + : mId(id) + , mModel(model) + { + } + + Static() + { + } }; } #endif From 3d3bef94cd0b7c8d0840798eff1a2f43ad9e7f9e Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 5 May 2018 16:29:01 +0300 Subject: [PATCH 090/103] Use range-based for loop --- apps/opencs/view/world/table.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 34ecd57d0..986717cb2 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -764,10 +764,8 @@ std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const QModelIndexList selectedRows = selectionModel()->selectedRows(); std::vector idToDrag; - foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW. - { + for (QModelIndex& it : selectedRows) idToDrag.push_back (getUniversalId (it.row())); - } return idToDrag; } From e22409c266ecb953c64d12faecbdcab243248467 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 6 May 2018 00:13:09 +0300 Subject: [PATCH 091/103] Fix sound range warning message --- apps/opencs/model/tools/soundcheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp index 6a059bee2..3dbd3ef11 100644 --- a/apps/opencs/model/tools/soundcheck.cpp +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -27,7 +27,7 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages) CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId); if (sound.mData.mMinRange>sound.mData.mMaxRange) - messages.push_back (std::make_pair (id, "Maximum range larger than minimum range")); + messages.push_back (std::make_pair (id, "Minimum range larger than maximum range")); /// \todo check, if the sound file exists } From 91b97a27ea0a2c19cf9e6c2adea4fb77b595aa61 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 6 May 2018 00:14:14 +0300 Subject: [PATCH 092/103] Remove empty class description warning --- apps/opencs/model/tools/classcheck.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index e4964d4e3..316fc0ce5 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -32,9 +32,6 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages) if (class_.mName.empty()) messages.push_back (std::make_pair (id, class_.mId + " has an empty name")); - if (class_.mDescription.empty()) - messages.push_back (std::make_pair (id, class_.mId + " has an empty description")); - // test for invalid attributes for (int i=0; i<2; ++i) if (class_.mData.mAttribute[i]==-1) From 2502d538167e503bcfae6e1f1ada1bb2360f3e94 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 6 May 2018 00:23:05 +0300 Subject: [PATCH 093/103] Object record verifier updates Removed light 0 duration warning Spelling fixes --- .../opencs/model/tools/referenceablecheck.cpp | 41 ++----------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 4dd3e1edf..750c3ceb4 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -239,9 +239,7 @@ void CSMTools::ReferenceableCheckStage::bookCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Book& book = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Book, book.mId); @@ -260,9 +258,7 @@ void CSMTools::ReferenceableCheckStage::activatorCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Activator& activator = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Activator, activator.mId); @@ -283,9 +279,7 @@ void CSMTools::ReferenceableCheckStage::potionCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Potion& potion = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Potion, potion.mId); @@ -306,9 +300,7 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Apparatus& apparatus = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Apparatus, apparatus.mId); @@ -329,9 +321,7 @@ void CSMTools::ReferenceableCheckStage::armorCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Armor& armor = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Armor, armor.mId); @@ -358,9 +348,7 @@ void CSMTools::ReferenceableCheckStage::clothingCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Clothing& clothing = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Clothing, clothing.mId); @@ -378,9 +366,7 @@ void CSMTools::ReferenceableCheckStage::containerCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Container& container = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Container, container.mId); @@ -512,9 +498,7 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Ingredient& ingredient = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Ingredient, ingredient.mId); @@ -577,13 +561,8 @@ void CSMTools::ReferenceableCheckStage::lightCheck( messages.push_back (std::make_pair (id, light.mId + " has negative light radius")); if (light.mData.mFlags & ESM::Light::Carry) - { inventoryItemCheck(light, messages, id.toString()); - if (light.mData.mTime == 0) - messages.push_back (std::make_pair (id, light.mId + " has zero duration")); - } - // Check that mentioned scripts exist scriptCheck(light, messages, id.toString()); } @@ -596,9 +575,7 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Lockpick& lockpick = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Lockpick, lockpick.mId); @@ -619,9 +596,7 @@ void CSMTools::ReferenceableCheckStage::miscCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Miscellaneous& miscellaneous = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Miscellaneous, miscellaneous.mId); @@ -706,22 +681,14 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( messages.push_back (std::make_pair (id, npc.mId + " has any empty name")); if (npc.mClass.empty()) - { - messages.push_back (std::make_pair (id, npc.mId + " has any empty class")); - } + messages.push_back (std::make_pair (id, npc.mId + " has an empty class")); else if (mClasses.searchId (npc.mClass) == -1) - { messages.push_back (std::make_pair (id, npc.mId + " has invalid class")); - } if (npc.mRace.empty()) - { - messages.push_back (std::make_pair (id, npc.mId + " has any empty race")); - } + messages.push_back (std::make_pair (id, npc.mId + " has an empty race")); else if (mRaces.searchId (npc.mRace) == -1) - { messages.push_back (std::make_pair (id, npc.mId + " has invalid race")); - } if (disposition < 0) messages.push_back (std::make_pair (id, npc.mId + " has negative disposition")); @@ -823,7 +790,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( { //checking of health if (weapon.mData.mHealth <= 0) - messages.push_back (std::make_pair (id, weapon.mId + " has non-positivie health")); + messages.push_back (std::make_pair (id, weapon.mId + " has non-positive health")); if (weapon.mData.mReach < 0) messages.push_back (std::make_pair (id, weapon.mId + " has negative reach")); @@ -842,9 +809,7 @@ void CSMTools::ReferenceableCheckStage::probeCheck( const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Probe& probe = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Probe, probe.mId); From 17222eb8219b546db7ec948e6a16616d2cb5ac76 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 6 May 2018 16:42:05 +0400 Subject: [PATCH 094/103] Get rid of unnecessary find --- apps/openmw/mwworld/store.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index e9968c38f..6f0a1b49f 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1070,12 +1070,10 @@ namespace MWWorld if (search(marker.first) == 0) { ESM::Static newMarker = ESM::Static(marker.first, marker.second); - mStatic.insert(std::make_pair(marker.first, newMarker)); - - std::map::iterator found = mStatic.find(marker.first); - if (found != mStatic.end()) + std::pair ret = mStatic.insert(std::make_pair(marker.first, newMarker)); + if (ret.first != mStatic.end()) { - mShared.push_back(&found->second); + mShared.push_back(&ret.first->second); } } } From 9b971caddc677eba4c496060c7c112c5eb4990c7 Mon Sep 17 00:00:00 2001 From: Alf Henrik Sauge Date: Sun, 6 May 2018 16:43:49 +0200 Subject: [PATCH 095/103] CSVTools::ReportTable should now have case insensitive sorting --- apps/opencs/view/tools/reporttable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 4d1456cd9..a970af168 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -156,6 +156,7 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, setSelectionMode (QAbstractItemView::ExtendedSelection); mProxyModel = new QSortFilterProxyModel (this); + mProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); mProxyModel->setSourceModel (mModel); mProxyModel->setSortRole(Qt::UserRole); From a2745683e6c56dbf9a02b13abce751f44b92c268 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 6 May 2018 22:30:01 +0300 Subject: [PATCH 096/103] new run icon --- files/opencs/resources.qrc | 2 +- files/opencs/run-game.png | Bin 0 -> 642 bytes files/opencs/scene-play.png | Bin 3601 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 files/opencs/run-game.png delete mode 100644 files/opencs/scene-play.png diff --git a/files/opencs/resources.qrc b/files/opencs/resources.qrc index 7a6624ba3..bfa256faf 100644 --- a/files/opencs/resources.qrc +++ b/files/opencs/resources.qrc @@ -89,7 +89,7 @@ camera-first-person.png camera-free.png camera-orbit.png - scene-play.png + run-game.png scene-view-instance.png scene-view-terrain.png scene-view-water.png diff --git a/files/opencs/run-game.png b/files/opencs/run-game.png new file mode 100644 index 0000000000000000000000000000000000000000..f5038654fa1a3238be2f3124e12c06e75e206773 GIT binary patch literal 642 zcmV-|0)737P)e5SHDZcKoowLq~M@~ICt?c(50iZn{;z2E~1kPPC5%Z zI_RRKh@*dmx=4jiPNIvmIw%Nj?#}PhL{m&lle=6fT;P(+{d(W`<-NNXB6m3joB~b( zr+`zyDKMc5)XzSrs)p`q0buMKBsR3x(45S4=GV`^Bx62F5x!uZ)z{6Lw$6G*=4ull zDI>eg4@mN`gO>(~ghjvG|&9nJxE-j)Fz5R0#@>#ijNlJqYDxT zNxO-sv0Z3vFrH5&_#4JAW4C%3d)|!sbBK>NzJ`jAh0JkdHrgi;1N)5+ zFX({8AxfdNq%s1Dz&OR#w!4p8p|r$)3?#@ip3K8(-cL)`5Fd9LL;f{Y{sjgRMQO<_ z+NKBFhrb2GyDauF=qQE2DZT^cPxDx=m;fUd)JTTiD}YvRlRF8lj6j^d-T?eMfIsC? zJw4Vwf&M|JQtuXkU#7tnsoNvKu;EFhtAcOm_4850tPnsl2gQ500MZ0_l|~r5N+l5Q z>m7hs?(%31b!wq<2=x72;!slC;z`P$@v2z@%FhW!@Ld2uHjXx9L1P5|{9LX8{6~hZ zQkt|0;3q}>2fxG5m&)?>B_84W3Cv zK~!ko)tcFF99MS6f9KY%r8lnPBFWk%YnNqs>~V~VXKas+00}Vj2L#D;{-?YJ0fIav z2oN9(Fdi$4SFMy~E!0L)lteA0*c*GPs(bQK)y-~-@)!t^Xb7~rL>9Zg?|k1`?g8bm z{;BrYz;0j?hyV`|Ue7NDQlJg20E<>M-3=TDW`Po5UvmNp&;*tNtPv)2@VkIA;QtX2 zsOK1;TZ4;o;ALRskAOg&UzdQ$8l0Eg#vgdS&IHKuTEMfS+5;<_Uaa5#2Q=J8IQ=#@ zEWR!zhHzRd?v;0r%1!>_y<42Q{5u|{pAl_4i46;{l_VB*KdRV?V?X2Qn_X_q|BlZu ze$KM{HPO^DY!JO31f*}Pt+i5@u-5sUgNNSa$f2EFpZ`yOfAI^J`Gn%s5j;P5eF zv0jN|Ck}G#=mb}<|0`#%lv$OJDNP^1c=q)nkgB4ZpsFCCD2gL-O&Xo6SX1KE$paie zGQyP~{)MwwMyUoLQ=Zy~@x1>V0%oA%tLjTR;55Oh!>FLR+;B2P#4}~yKE00E1PNRDbYs>un-8VRO%;Vzsf6w`wJL#4_qB6N-D0-U#|EL7!4_N4>YUE|#OEtl% zVseYQ{F4PRxv2z$pa_Df5=)J^dkq^__~8AWoI0*toclX2-+P0!{1KJO?JpDA4BGst z1ZZv->*{L`+5i1rO&@;Q#`@F7BHOt84ehn3_=N(6*~1hjcY>IWRCRG*fgTAF0TIL) zB&Q)Lk^?9I4*8W!tHfy)TPpL*U+(1esSfAQ&vEBQndXBQBN`*4+cAC_eA|EiPpU$# z+h_4e>8jAUcY!obDNODrsBB}sx`1=zIG5)B&q(yAznqMS^da~E&1b|xtEA}~ak55O zF7vBj@8PY}EiRtF!0q`3WN|k}Anvw^ruP#}AEYq8v;VtseTBy38&vPlk+z!@r}t8R z;{1bQdR1 zH~8ki&T@Uu;_Ea?bCvF`?+C}XGqURhFYcZrZmbempGqLuiltp!WcAVl))<5KrFVcw zIq#-xi6PA`w0Y(pnrl@zh~?KqRk^1^o^P68r>;sTUZXTx;m>}1hQ;Y9@6i|1|+K}h(S}y2n_oERSKx~BR^=H9;wZZ zvPVLJPEw^EuTh$)@Y!$nvAkU6!hg@Rd~b|WxPvGv(3_eSvyoqFu&Rp6Mj0H6wUd4l zZ;ra=m97swC(&1-7x^u!oNgkdIgvE3($O_WCdz#Jo82rws&et`A6Qx1MkU%#7>0=U z@-Q23tmb?aLHli~S68&JfH5W`G7xp$1iS}&&^oeJ@f)zx5Q!d3uD0ZJUoFX&lZ^2WBa4TP!4PXTsBAlr}WV+qK_CnDU!yP`T13D ze4TLpQiCWgad7|kelIFSA#3$EHVOj@p^&C2*REZmnInP^1k0PR^Y0BAi7jOzj1grT&vUh_qhE6x;%Jmye9ViSb&`;RS zw%PpNi~cLDq?%2zo{3QPS-ex@_C*id+{f(5HtdYx95{6xIk+EV;PSO=oIG+EGw_*C z!J52mE-c(eQO=&b0Kn0M2XN6toVrYbO(k@z#x>M|H(5ys#!YJ?P@f0)>)gF$F!jC6 zj7;NCTAVu6Wk=VZ#SZP=2f#O%F6XB(%gy;8IB@VNc4e(jnx@2waQgTOD&-Qs^)O<% z-*`ysk_`n0qR-~WH4yzlB?jkY&x8m85AWBw@I{lLb%5PF_7hH8)MfM5!^e-gb@v`l z9s76hX8ZIMin4##ZuaclNn^duT5X+$2TN3|b!@x6jx~nS(Q)P%pQ0|MR4A}##}q1x zQ-&=x2zbErFGar(TkuSTk&xx38s~n$!ph<}u3Mtje85;~l8Lb~RF$R2kGOH`He(aB zc*bM?-U4yA!`S!)_m`fr)>ubGhyu&Di3#F3#?DTTfM$MDRpKXLGu*j%kI_>nP*v_fctB-z ziejORB8*SWaR2cN3(GYsrI4LdqxgR24w3A+ws(rlnux;)jE@wk6hofHOX#2iTP5$N z%45Xfc?GN~^887i+m}{pFVAxQQjMd(_;Y;Ur`c!{*Y9BBE>E7`C5aOhrCO`AbJuLv zI8hqSHsXcMPE-i|{E(&Da;Nu9JKX&?vRjN08V^-7Y@t^UZ-Q@2_+FWnXLZh>xrbjr zz<4x6r4kbQ4*)}Ry@QH}S3X42X`p(CBNe&Omn&j27Y|k;UaJ3wz?KNS3acwku3oIMym**L->>r7pY8x4NwNrc;{+p6 zDHmzCySTCAu=rhH0RWdKG@5N7a{?IDWmt5er1d6e+hg4eztUS^<;vt1+6-L85ZE%2 zKgNrd20zTLvAl4Ea`|n>MhiUm&lAV-P{;MHN2eRJT3gQoCE3~`NxRt^M}&H#MdBRW zMvFP7Z10in3QT`;Mzal-?GI9DKan%+lIMny4p|5ye}vEtnEd?^(~ZVdBy=%L*P{? z2HU9DTU?pD&z%dFZs$1L_I|?5$qr5m)S3kXzDb!I8EXl)q0C+ zqmwB>ra-X}(2Wzi@y2Gh-AQP78Utfd2BuIb(CNm+Ns3pTp*Ve-#?v{<1&i?vA{p?F z-L0r*Lzb$lIz+8HO;t5PiBT83EDr>Qk!TvHj&?Vp9UF=}KEx}|prWcJRkhtXk$NizuSjv~B&NIzAT%fgjlUA)sxeyQqHv3x%k)|Tc zsIFL5UCa~rd77qCt=aVwi6opniC^9Wrnfd14A5-FtUr9w-`)*=RZ1a~<0S+kbxP=a zL*x?YNILGNdy~`=`W{bK>QrmZtcVy7uX2D=aW6?@k>=WUTJ3eMl)_Ye+cvlrkj4K2 XE>yyZSdFAp00000NkvXXu0mjfgA3Z> From f5f8f62e8e6b424e61b76ab573e313c9d94ad8a0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 May 2018 09:34:46 +0200 Subject: [PATCH 097/103] updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index f6cc51181..715bbfb90 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -15,6 +15,7 @@ Programmers Adam Hogan (aurix) Aesylwinn aegis + AHSauge Aleksandar Jovanov Alex Haddad (rainChu) Alex McKibben From 57ee5f9b533cffc1d9f1caa68d488d50a215dc01 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 May 2018 09:51:09 +0200 Subject: [PATCH 098/103] updated credits file --- AUTHORS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 715bbfb90..3b8088c7e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -157,6 +157,7 @@ Programmers terrorfisch thegriglat Thomas Luppi (Digmaster) + unelsson Will Herrmann (Thunderforge) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) @@ -226,7 +227,7 @@ Artwork Necrod - OpenMW Logo Mickey Lyle (raevol) - Wordpress Theme - Tom Koenderink (Okulo), SirHerrbatka, crysthala, Shnatsel - OpenMW Editor Icons + Tom Koenderink (Okulo), SirHerrbatka, crysthala, Shnatsel, Lamoot - OpenMW Editor Icons Inactive Contributors --------------------- From 53b6ef6f8ce122ae558000c5cd3de46cee99062c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 May 2018 09:54:42 +0200 Subject: [PATCH 099/103] minor code cleanup --- apps/openmw/mwstate/quicksavemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwstate/quicksavemanager.cpp b/apps/openmw/mwstate/quicksavemanager.cpp index 9f522d7eb..59658ce6e 100644 --- a/apps/openmw/mwstate/quicksavemanager.cpp +++ b/apps/openmw/mwstate/quicksavemanager.cpp @@ -3,8 +3,8 @@ MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, unsigned int maxSaves) : mSaveName(saveName) , mMaxSaves(maxSaves) - , mOldestSlotVisited(NULL) , mSlotsVisited(0) + , mOldestSlotVisited(nullptr) { } From 2f89080b36e4b2ddbb33c15db7b670608d981a9a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 7 May 2018 22:32:04 +0400 Subject: [PATCH 100/103] Load default markers definitions in editor --- apps/opencs/model/world/data.cpp | 26 ++++++++++++++++++++++++++ apps/opencs/model/world/data.hpp | 2 ++ 2 files changed, 28 insertions(+) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 2216d5ca6..053754943 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -962,6 +962,29 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base return mReader->getRecordCount(); } +void CSMWorld::Data::loadFallbackEntries() +{ + // Load default marker definitions, if game files do not have them for some reason + std::pair markers[] = { + std::make_pair("divinemarker", "marker_divine.nif"), + std::make_pair("doormarker", "marker_arrow.nif"), + std::make_pair("northmarker", "marker_north.nif"), + std::make_pair("templemarker", "marker_temple.nif"), + std::make_pair("travelmarker", "marker_travel.nif") + }; + + for (const std::pair marker : markers) + { + if (mReferenceables.searchId (marker.first)==-1) + { + CSMWorld::Record record; + record.mBase = ESM::Static(marker.first, marker.second); + record.mState = CSMWorld::RecordBase::State_BaseOnly; + mReferenceables.appendRecord (record, CSMWorld::UniversalId::Type_Static); + } + } +} + bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) { if (!mReader) @@ -983,6 +1006,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) mReader = 0; mDialogue = 0; + + loadFallbackEntries(); + return true; } diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 8a3667ea1..1b975f430 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -144,6 +144,8 @@ namespace CSMWorld static int count (RecordBase::State state, const CollectionBase& collection); + void loadFallbackEntries(); + public: Data (ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths, From feeee50a88ca6172c841e480a2851a7ac4fd535d Mon Sep 17 00:00:00 2001 From: Alf Henrik Sauge Date: Wed, 9 May 2018 00:25:07 +0200 Subject: [PATCH 101/103] Dropping a separate NPDTstruct12 object and instead use NPDTstruct52 NPDTstruct12 is now only used when loading and saving. Turning auto calc on and off now no longer switches between to different set of values --- apps/esmtool/record.cpp | 62 ++++++++-------- apps/essimporter/converter.hpp | 2 +- apps/essimporter/importer.cpp | 2 +- .../opencs/model/tools/referenceablecheck.cpp | 36 +++++----- apps/opencs/model/world/refidadapterimp.cpp | 72 +++++++++---------- apps/openmw/mwclass/npc.cpp | 45 ++++++------ .../mwmechanics/mechanicsmanagerimp.cpp | 22 +++--- components/esm/loadnpc.cpp | 70 +++++++++++------- components/esm/loadnpc.hpp | 10 ++- 9 files changed, 171 insertions(+), 150 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index c123ace44..089a25c93 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -1040,45 +1040,47 @@ void Record::print() if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { - std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl; - std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl; - std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl; - std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl; - std::cout << " Unknown1: " - << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl; - std::cout << " Unknown2: " - << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl; - std::cout << " Unknown3: " - << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl; - std::cout << " Gold: " << mData.mNpdt12.mGold << std::endl; + std::cout << " Level: " << mData.mNpdt.mLevel << std::endl; + std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl; + std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl; + std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl; + //Why do we want to print these fields? They are padding in the struct and contain + // nothing of real value. Now we don't deal with NPDTstruct12 in runtime either... + //std::cout << " Unknown1: " + // << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl; + //std::cout << " Unknown2: " + // << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl; + //std::cout << " Unknown3: " + // << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl; + std::cout << " Gold: " << mData.mNpdt.mGold << std::endl; } else { - std::cout << " Level: " << mData.mNpdt52.mLevel << std::endl; - std::cout << " Reputation: " << (int)mData.mNpdt52.mReputation << std::endl; - std::cout << " Disposition: " << (int)mData.mNpdt52.mDisposition << std::endl; - std::cout << " Rank: " << (int)mData.mNpdt52.mRank << std::endl; - std::cout << " FactionID: " << (int)mData.mNpdt52.mFactionID << std::endl; + std::cout << " Level: " << mData.mNpdt.mLevel << std::endl; + std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl; + std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl; + std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl; + std::cout << " FactionID: " << (int)mData.mNpdt.mFactionID << std::endl; std::cout << " Attributes:" << std::endl; - std::cout << " Strength: " << (int)mData.mNpdt52.mStrength << std::endl; - std::cout << " Intelligence: " << (int)mData.mNpdt52.mIntelligence << std::endl; - std::cout << " Willpower: " << (int)mData.mNpdt52.mWillpower << std::endl; - std::cout << " Agility: " << (int)mData.mNpdt52.mAgility << std::endl; - std::cout << " Speed: " << (int)mData.mNpdt52.mSpeed << std::endl; - std::cout << " Endurance: " << (int)mData.mNpdt52.mEndurance << std::endl; - std::cout << " Personality: " << (int)mData.mNpdt52.mPersonality << std::endl; - std::cout << " Luck: " << (int)mData.mNpdt52.mLuck << std::endl; + std::cout << " Strength: " << (int)mData.mNpdt.mStrength << std::endl; + std::cout << " Intelligence: " << (int)mData.mNpdt.mIntelligence << std::endl; + std::cout << " Willpower: " << (int)mData.mNpdt.mWillpower << std::endl; + std::cout << " Agility: " << (int)mData.mNpdt.mAgility << std::endl; + std::cout << " Speed: " << (int)mData.mNpdt.mSpeed << std::endl; + std::cout << " Endurance: " << (int)mData.mNpdt.mEndurance << std::endl; + std::cout << " Personality: " << (int)mData.mNpdt.mPersonality << std::endl; + std::cout << " Luck: " << (int)mData.mNpdt.mLuck << std::endl; std::cout << " Skills:" << std::endl; for (int i = 0; i != ESM::Skill::Length; i++) std::cout << " " << skillLabel(i) << ": " - << (int)(mData.mNpdt52.mSkills[i]) << std::endl; + << (int)(mData.mNpdt.mSkills[i]) << std::endl; - std::cout << " Health: " << mData.mNpdt52.mHealth << std::endl; - std::cout << " Magicka: " << mData.mNpdt52.mMana << std::endl; - std::cout << " Fatigue: " << mData.mNpdt52.mFatigue << std::endl; - std::cout << " Unknown: " << (int)mData.mNpdt52.mUnknown << std::endl; - std::cout << " Gold: " << mData.mNpdt52.mGold << std::endl; + std::cout << " Health: " << mData.mNpdt.mHealth << std::endl; + std::cout << " Magicka: " << mData.mNpdt.mMana << std::endl; + std::cout << " Fatigue: " << mData.mNpdt.mFatigue << std::endl; + std::cout << " Unknown: " << (int)mData.mNpdt.mUnknown << std::endl; + std::cout << " Gold: " << mData.mNpdt.mGold << std::endl; } std::vector::iterator cit; diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index 621b85709..1772e0e2d 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -122,7 +122,7 @@ public: } else { - mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel; + mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt.mLevel; mContext->mPlayerBase = npc; ESM::SpellState::SpellParams empty; // FIXME: player start spells and birthsign spells aren't listed here, diff --git a/apps/essimporter/importer.cpp b/apps/essimporter/importer.cpp index 73b15baae..4538d4e63 100644 --- a/apps/essimporter/importer.cpp +++ b/apps/essimporter/importer.cpp @@ -377,7 +377,7 @@ namespace ESSImport profile.mPlayerClassName = context.mCustomPlayerClassName; else profile.mPlayerClassId = context.mPlayerBase.mClass; - profile.mPlayerLevel = context.mPlayerBase.mNpdt52.mLevel; + profile.mPlayerLevel = context.mPlayerBase.mNpdt.mLevel; profile.mPlayerName = header.mGameData.mPlayerName.toString(); writeScreenshot(header, profile); diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 750c3ceb4..1e86dfe37 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -619,12 +619,12 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( const ESM::NPC& npc = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId); - short level(npc.mNpdt52.mLevel); - char disposition(npc.mNpdt52.mDisposition); - char reputation(npc.mNpdt52.mReputation); - char rank(npc.mNpdt52.mRank); + short level(npc.mNpdt.mLevel); + char disposition(npc.mNpdt.mDisposition); + char reputation(npc.mNpdt.mReputation); + char rank(npc.mNpdt.mRank); //Don't know what unknown is for - int gold(npc.mNpdt52.mGold); + int gold(npc.mNpdt.mGold); //Detect if player is present if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl? @@ -638,36 +638,36 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( return; } - level = npc.mNpdt12.mLevel; - disposition = npc.mNpdt12.mDisposition; - reputation = npc.mNpdt12.mReputation; - rank = npc.mNpdt12.mRank; - gold = npc.mNpdt12.mGold; + level = npc.mNpdt.mLevel; + disposition = npc.mNpdt.mDisposition; + reputation = npc.mNpdt.mReputation; + rank = npc.mNpdt.mRank; + gold = npc.mNpdt.mGold; } else { - if (npc.mNpdt52.mAgility == 0) + if (npc.mNpdt.mAgility == 0) messages.push_back (std::make_pair (id, npc.mId + " agility has zero value")); - if (npc.mNpdt52.mEndurance == 0) + if (npc.mNpdt.mEndurance == 0) messages.push_back (std::make_pair (id, npc.mId + " endurance has zero value")); - if (npc.mNpdt52.mIntelligence == 0) + if (npc.mNpdt.mIntelligence == 0) messages.push_back (std::make_pair (id, npc.mId + " intelligence has zero value")); - if (npc.mNpdt52.mLuck == 0) + if (npc.mNpdt.mLuck == 0) messages.push_back (std::make_pair (id, npc.mId + " luck has zero value")); - if (npc.mNpdt52.mPersonality == 0) + if (npc.mNpdt.mPersonality == 0) messages.push_back (std::make_pair (id, npc.mId + " personality has zero value")); - if (npc.mNpdt52.mStrength == 0) + if (npc.mNpdt.mStrength == 0) messages.push_back (std::make_pair (id, npc.mId + " strength has zero value")); - if (npc.mNpdt52.mSpeed == 0) + if (npc.mNpdt.mSpeed == 0) messages.push_back (std::make_pair (id, npc.mId + " speed has zero value")); - if (npc.mNpdt52.mWillpower == 0) + if (npc.mNpdt.mWillpower == 0) messages.push_back (std::make_pair (id, npc.mId + " willpower has zero value")); } diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index ba67b4e14..352384c73 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -914,7 +914,7 @@ void CSMWorld::NpcAttributesRefIdAdapter::setNestedTable (const RefIdColumn* col ESM::NPC npc = record.get(); // store the whole struct - npc.mNpdt52 = + npc.mNpdt = static_cast > &>(nestedTable).mNestedTable.at(0); record.setModified (npc); @@ -928,7 +928,7 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::NpcAttributesRefIdAdapter::nestedTab // return the whole struct std::vector wrap; - wrap.push_back(record.get().mNpdt52); + wrap.push_back(record.get().mNpdt); // deleted by dtor of NestedTableStoring return new NestedTableWrapper >(wrap); } @@ -939,7 +939,7 @@ QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn * const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); - const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52; + const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt; if (subColIndex == 0) return subRowIndex; @@ -966,7 +966,7 @@ void CSMWorld::NpcAttributesRefIdAdapter::setNestedData (const RefIdColumn *colu Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc))); ESM::NPC npc = record.get(); - ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; + ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt; if (subColIndex == 1) switch(subRowIndex) @@ -1021,7 +1021,7 @@ void CSMWorld::NpcSkillsRefIdAdapter::setNestedTable (const RefIdColumn* column, ESM::NPC npc = record.get(); // store the whole struct - npc.mNpdt52 = + npc.mNpdt = static_cast > &>(nestedTable).mNestedTable.at(0); record.setModified (npc); @@ -1035,7 +1035,7 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::NpcSkillsRefIdAdapter::nestedTable ( // return the whole struct std::vector wrap; - wrap.push_back(record.get().mNpdt52); + wrap.push_back(record.get().mNpdt); // deleted by dtor of NestedTableStoring return new NestedTableWrapper >(wrap); } @@ -1046,7 +1046,7 @@ QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *colu const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); - const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52; + const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt; if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) throw std::runtime_error ("index out of range"); @@ -1065,7 +1065,7 @@ void CSMWorld::NpcSkillsRefIdAdapter::setNestedData (const RefIdColumn *column, Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc))); ESM::NPC npc = record.get(); - ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; + ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt; if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) throw std::runtime_error ("index out of range"); @@ -1130,30 +1130,30 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column if (autoCalc) switch (subColIndex) { - case 0: return static_cast(record.get().mNpdt12.mLevel); + case 0: return static_cast(record.get().mNpdt.mLevel); case 1: return QVariant(QVariant::UserType); case 2: return QVariant(QVariant::UserType); case 3: return QVariant(QVariant::UserType); case 4: return QVariant(QVariant::UserType); - case 5: return static_cast(record.get().mNpdt12.mDisposition); - case 6: return static_cast(record.get().mNpdt12.mReputation); - case 7: return static_cast(record.get().mNpdt12.mRank); - case 8: return record.get().mNpdt12.mGold; + case 5: return static_cast(record.get().mNpdt.mDisposition); + case 6: return static_cast(record.get().mNpdt.mReputation); + case 7: return static_cast(record.get().mNpdt.mRank); + case 8: return record.get().mNpdt.mGold; case 9: return record.get().mPersistent == true; default: return QVariant(); // throw an exception here? } else switch (subColIndex) { - case 0: return static_cast(record.get().mNpdt52.mLevel); - case 1: return static_cast(record.get().mNpdt52.mFactionID); - case 2: return static_cast(record.get().mNpdt52.mHealth); - case 3: return static_cast(record.get().mNpdt52.mMana); - case 4: return static_cast(record.get().mNpdt52.mFatigue); - case 5: return static_cast(record.get().mNpdt52.mDisposition); - case 6: return static_cast(record.get().mNpdt52.mReputation); - case 7: return static_cast(record.get().mNpdt52.mRank); - case 8: return record.get().mNpdt52.mGold; + case 0: return static_cast(record.get().mNpdt.mLevel); + case 1: return static_cast(record.get().mNpdt.mFactionID); + case 2: return static_cast(record.get().mNpdt.mHealth); + case 3: return static_cast(record.get().mNpdt.mMana); + case 4: return static_cast(record.get().mNpdt.mFatigue); + case 5: return static_cast(record.get().mNpdt.mDisposition); + case 6: return static_cast(record.get().mNpdt.mReputation); + case 7: return static_cast(record.get().mNpdt.mRank); + case 8: return record.get().mNpdt.mGold; case 9: return record.get().mPersistent == true; default: return QVariant(); // throw an exception here? } @@ -1171,30 +1171,30 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column, if (autoCalc) switch(subColIndex) { - case 0: npc.mNpdt12.mLevel = static_cast(value.toInt()); break; + case 0: npc.mNpdt.mLevel = static_cast(value.toInt()); break; case 1: return; case 2: return; case 3: return; case 4: return; - case 5: npc.mNpdt12.mDisposition = static_cast(value.toInt()); break; - case 6: npc.mNpdt12.mReputation = static_cast(value.toInt()); break; - case 7: npc.mNpdt12.mRank = static_cast(value.toInt()); break; - case 8: npc.mNpdt12.mGold = value.toInt(); break; + case 5: npc.mNpdt.mDisposition = static_cast(value.toInt()); break; + case 6: npc.mNpdt.mReputation = static_cast(value.toInt()); break; + case 7: npc.mNpdt.mRank = static_cast(value.toInt()); break; + case 8: npc.mNpdt.mGold = value.toInt(); break; case 9: npc.mPersistent = value.toBool(); break; default: return; // throw an exception here? } else switch(subColIndex) { - case 0: npc.mNpdt52.mLevel = static_cast(value.toInt()); break; - case 1: npc.mNpdt52.mFactionID = static_cast(value.toInt()); break; - case 2: npc.mNpdt52.mHealth = static_cast(value.toInt()); break; - case 3: npc.mNpdt52.mMana = static_cast(value.toInt()); break; - case 4: npc.mNpdt52.mFatigue = static_cast(value.toInt()); break; - case 5: npc.mNpdt52.mDisposition = static_cast(value.toInt()); break; - case 6: npc.mNpdt52.mReputation = static_cast(value.toInt()); break; - case 7: npc.mNpdt52.mRank = static_cast(value.toInt()); break; - case 8: npc.mNpdt52.mGold = value.toInt(); break; + case 0: npc.mNpdt.mLevel = static_cast(value.toInt()); break; + case 1: npc.mNpdt.mFactionID = static_cast(value.toInt()); break; + case 2: npc.mNpdt.mHealth = static_cast(value.toInt()); break; + case 3: npc.mNpdt.mMana = static_cast(value.toInt()); break; + case 4: npc.mNpdt.mFatigue = static_cast(value.toInt()); break; + case 5: npc.mNpdt.mDisposition = static_cast(value.toInt()); break; + case 6: npc.mNpdt.mReputation = static_cast(value.toInt()); break; + case 7: npc.mNpdt.mRank = static_cast(value.toInt()); break; + case 8: npc.mNpdt.mGold = value.toInt(); break; case 9: npc.mPersistent = value.toBool(); break; default: return; // throw an exception here? } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 974a08c11..f3f763897 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -312,40 +312,40 @@ namespace MWClass int gold=0; if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { - gold = ref->mBase->mNpdt52.mGold; + gold = ref->mBase->mNpdt.mGold; for (unsigned int i=0; i< ESM::Skill::Length; ++i) - data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]); + data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt.mSkills[i]); - data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt52.mStrength); - data->mNpcStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mNpdt52.mIntelligence); - data->mNpcStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mNpdt52.mWillpower); - data->mNpcStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mNpdt52.mAgility); - data->mNpcStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mNpdt52.mSpeed); - data->mNpcStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mNpdt52.mEndurance); - data->mNpcStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mNpdt52.mPersonality); - data->mNpcStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mNpdt52.mLuck); + data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt.mStrength); + data->mNpcStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mNpdt.mIntelligence); + data->mNpcStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mNpdt.mWillpower); + data->mNpcStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mNpdt.mAgility); + data->mNpcStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mNpdt.mSpeed); + data->mNpcStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mNpdt.mEndurance); + data->mNpcStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mNpdt.mPersonality); + data->mNpcStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mNpdt.mLuck); - data->mNpcStats.setHealth (ref->mBase->mNpdt52.mHealth); - data->mNpcStats.setMagicka (ref->mBase->mNpdt52.mMana); - data->mNpcStats.setFatigue (ref->mBase->mNpdt52.mFatigue); + data->mNpcStats.setHealth (ref->mBase->mNpdt.mHealth); + data->mNpcStats.setMagicka (ref->mBase->mNpdt.mMana); + data->mNpcStats.setFatigue (ref->mBase->mNpdt.mFatigue); - data->mNpcStats.setLevel(ref->mBase->mNpdt52.mLevel); - data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt52.mDisposition); - data->mNpcStats.setReputation(ref->mBase->mNpdt52.mReputation); + data->mNpcStats.setLevel(ref->mBase->mNpdt.mLevel); + data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt.mDisposition); + data->mNpcStats.setReputation(ref->mBase->mNpdt.mReputation); data->mNpcStats.setNeedRecalcDynamicStats(false); } else { - gold = ref->mBase->mNpdt12.mGold; + gold = ref->mBase->mNpdt.mGold; for (int i=0; i<3; ++i) data->mNpcStats.setDynamic (i, 10); - data->mNpcStats.setLevel(ref->mBase->mNpdt12.mLevel); - data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt12.mDisposition); - data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation); + data->mNpcStats.setLevel(ref->mBase->mNpdt.mLevel); + data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt.mDisposition); + data->mNpcStats.setReputation(ref->mBase->mNpdt.mReputation); autoCalculateAttributes(ref->mBase, data->mNpcStats); autoCalculateSkills(ref->mBase, data->mNpcStats, ptr); @@ -1327,10 +1327,7 @@ namespace MWClass int Npc::getBaseGold(const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); - if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) - return ref->mBase->mNpdt52.mGold; - else - return ref->mBase->mNpdt12.mGold; + return ref->mBase->mNpdt.mGold; } bool Npc::isClass(const MWWorld::ConstPtr& ptr, const std::string &className) const diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 1de608a1f..df93d875d 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -79,21 +79,21 @@ namespace MWMechanics const ESM::NPC *player = ptr.get()->mBase; // reset - creatureStats.setLevel(player->mNpdt52.mLevel); + creatureStats.setLevel(player->mNpdt.mLevel); creatureStats.getSpells().clear(); creatureStats.modifyMagicEffects(MagicEffects()); for (int i=0; i<27; ++i) - npcStats.getSkill (i).setBase (player->mNpdt52.mSkills[i]); - - creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt52.mStrength); - creatureStats.setAttribute(ESM::Attribute::Intelligence, player->mNpdt52.mIntelligence); - creatureStats.setAttribute(ESM::Attribute::Willpower, player->mNpdt52.mWillpower); - creatureStats.setAttribute(ESM::Attribute::Agility, player->mNpdt52.mAgility); - creatureStats.setAttribute(ESM::Attribute::Speed, player->mNpdt52.mSpeed); - creatureStats.setAttribute(ESM::Attribute::Endurance, player->mNpdt52.mEndurance); - creatureStats.setAttribute(ESM::Attribute::Personality, player->mNpdt52.mPersonality); - creatureStats.setAttribute(ESM::Attribute::Luck, player->mNpdt52.mLuck); + npcStats.getSkill (i).setBase (player->mNpdt.mSkills[i]); + + creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt.mStrength); + creatureStats.setAttribute(ESM::Attribute::Intelligence, player->mNpdt.mIntelligence); + creatureStats.setAttribute(ESM::Attribute::Willpower, player->mNpdt.mWillpower); + creatureStats.setAttribute(ESM::Attribute::Agility, player->mNpdt.mAgility); + creatureStats.setAttribute(ESM::Attribute::Speed, player->mNpdt.mSpeed); + creatureStats.setAttribute(ESM::Attribute::Endurance, player->mNpdt.mEndurance); + creatureStats.setAttribute(ESM::Attribute::Personality, player->mNpdt.mPersonality); + creatureStats.setAttribute(ESM::Attribute::Luck, player->mNpdt.mLuck); const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index a68c97a6a..8609ab65a 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -62,12 +62,23 @@ namespace ESM if (esm.getSubSize() == 52) { mNpdtType = NPC_DEFAULT; - esm.getExact(&mNpdt52, 52); + esm.getExact(&mNpdt, 52); } else if (esm.getSubSize() == 12) { + //Reading into temporary NPDTstruct12 object + NPDTstruct12 npdt12; mNpdtType = NPC_WITH_AUTOCALCULATED_STATS; - esm.getExact(&mNpdt12, 12); + esm.getExact(&npdt12, 12); + + //Clearing the mNdpt struct to initialize all values + blankNpdt(); + //Swiching to an internal representation + mNpdt.mLevel = npdt12.mLevel; + mNpdt.mDisposition = npdt12.mDisposition; + mNpdt.mReputation = npdt12.mReputation; + mNpdt.mRank = npdt12.mRank; + mNpdt.mGold = npdt12.mGold; } else esm.fail("NPC_NPDT must be 12 or 52 bytes long"); @@ -135,9 +146,19 @@ namespace ESM esm.writeHNOCString("SCRI", mScript); if (mNpdtType == NPC_DEFAULT) - esm.writeHNT("NPDT", mNpdt52, 52); + { + esm.writeHNT("NPDT", mNpdt, 52); + } else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS) - esm.writeHNT("NPDT", mNpdt12, 12); + { + NPDTstruct12 npdt12; + npdt12.mLevel = mNpdt.mLevel; + npdt12.mDisposition = mNpdt.mDisposition; + npdt12.mReputation = mNpdt.mReputation; + npdt12.mRank = mNpdt.mRank; + npdt12.mGold = mNpdt.mGold; + esm.writeHNT("NPDT", npdt12, 12); + } esm.writeHNT("FLAG", mFlags); @@ -171,25 +192,7 @@ namespace ESM void NPC::blank() { mNpdtType = NPC_DEFAULT; - mNpdt52.mLevel = 0; - mNpdt52.mStrength = mNpdt52.mIntelligence = mNpdt52.mWillpower = mNpdt52.mAgility = - mNpdt52.mSpeed = mNpdt52.mEndurance = mNpdt52.mPersonality = mNpdt52.mLuck = 0; - for (int i=0; i< Skill::Length; ++i) mNpdt52.mSkills[i] = 0; - mNpdt52.mReputation = 0; - mNpdt52.mHealth = mNpdt52.mMana = mNpdt52.mFatigue = 0; - mNpdt52.mDisposition = 0; - mNpdt52.mFactionID = 0; - mNpdt52.mRank = 0; - mNpdt52.mUnknown = 0; - mNpdt52.mGold = 0; - mNpdt12.mLevel = 0; - mNpdt12.mDisposition = 0; - mNpdt12.mReputation = 0; - mNpdt12.mRank = 0; - mNpdt12.mUnknown1 = 0; - mNpdt12.mUnknown2 = 0; - mNpdt12.mUnknown3 = 0; - mNpdt12.mGold = 0; + blankNpdt(); mFlags = 0; mInventory.mList.clear(); mSpells.mList.clear(); @@ -207,14 +210,27 @@ namespace ESM mHead.clear(); } + void NPC::blankNpdt() + { + mNpdt.mLevel = 0; + mNpdt.mStrength = mNpdt.mIntelligence = mNpdt.mWillpower = mNpdt.mAgility = + mNpdt.mSpeed = mNpdt.mEndurance = mNpdt.mPersonality = mNpdt.mLuck = 0; + for (int i=0; i< Skill::Length; ++i) mNpdt.mSkills[i] = 0; + mNpdt.mReputation = 0; + mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0; + mNpdt.mDisposition = 0; + mNpdt.mFactionID = 0; + mNpdt.mRank = 0; + mNpdt.mUnknown = 0; + mNpdt.mGold = 0; + } + int NPC::getFactionRank() const { if (mFaction.empty()) return -1; - else if (mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) - return mNpdt12.mRank; - else // NPC_DEFAULT - return mNpdt52.mRank; + else + return mNpdt.mRank; } const std::vector& NPC::getTransport() const diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index d7f30e079..5f567d999 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -95,6 +95,8 @@ struct NPC int mGold; }; // 52 bytes + //Structure for autocalculated characters. + // This is only used for load and save operations. struct NPDTstruct12 { short mLevel; @@ -106,8 +108,9 @@ struct NPC #pragma pack(pop) unsigned char mNpdtType; - NPDTstruct52 mNpdt52; - NPDTstruct12 mNpdt12; //for autocalculated characters + //Worth noting when saving the struct: + // Although we might read a NPDTstruct12 in, we use NPDTstruct52 internally + NPDTstruct52 mNpdt; int getFactionRank() const; /// wrapper for mNpdt*, -1 = no rank @@ -141,6 +144,9 @@ struct NPC void blank(); ///< Set record to default state (does not touch the ID). + + /// Resets the mNpdt object + void blankNpdt(); }; } #endif From d4f278a1136972e7cd2642f51c0ad5f39fb61686 Mon Sep 17 00:00:00 2001 From: Alf Henrik Sauge Date: Wed, 9 May 2018 18:02:02 +0200 Subject: [PATCH 102/103] Replacing tab with spaces --- components/esm/loadnpc.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 8609ab65a..dd34934ad 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -66,8 +66,8 @@ namespace ESM } else if (esm.getSubSize() == 12) { - //Reading into temporary NPDTstruct12 object - NPDTstruct12 npdt12; + //Reading into temporary NPDTstruct12 object + NPDTstruct12 npdt12; mNpdtType = NPC_WITH_AUTOCALCULATED_STATS; esm.getExact(&npdt12, 12); @@ -147,17 +147,17 @@ namespace ESM if (mNpdtType == NPC_DEFAULT) { - esm.writeHNT("NPDT", mNpdt, 52); + esm.writeHNT("NPDT", mNpdt, 52); } else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS) { - NPDTstruct12 npdt12; - npdt12.mLevel = mNpdt.mLevel; - npdt12.mDisposition = mNpdt.mDisposition; - npdt12.mReputation = mNpdt.mReputation; - npdt12.mRank = mNpdt.mRank; + NPDTstruct12 npdt12; + npdt12.mLevel = mNpdt.mLevel; + npdt12.mDisposition = mNpdt.mDisposition; + npdt12.mReputation = mNpdt.mReputation; + npdt12.mRank = mNpdt.mRank; npdt12.mGold = mNpdt.mGold; - esm.writeHNT("NPDT", npdt12, 12); + esm.writeHNT("NPDT", npdt12, 12); } esm.writeHNT("FLAG", mFlags); From 6630a02c3f268b07d07b57c98b1b42c20c355e22 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 11 May 2018 09:56:44 +0200 Subject: [PATCH 103/103] updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 3b8088c7e..9c6a5edbe 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -157,6 +157,7 @@ Programmers terrorfisch thegriglat Thomas Luppi (Digmaster) + tri4ng1e unelsson Will Herrmann (Thunderforge) Tom Mason (wheybags)