summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zinnschlag <marc@zpages.de>2016-12-16 12:28:22 +0100
committerMarc Zinnschlag <marc@zpages.de>2016-12-16 12:28:22 +0100
commit34389e15cd8e70be05dea2182d8b5b84cadf1f62 (patch)
tree39e3391cf416e8739eb7b370f90c1416d439ade2
parent827c78a4cd4f11d26eb58dfa06c50f4e6ede525f (diff)
parentf97be48bf40c3fa887792fe82e57d27f496fb11f (diff)
Merge remote-tracking branch 'origin/master'HEADmaster
-rw-r--r--.travis.yml2
-rw-r--r--AUTHORS.md3
-rw-r--r--CMakeLists.txt38
-rw-r--r--apps/essimporter/importscri.hpp2
-rw-r--r--apps/launcher/main.cpp8
-rw-r--r--apps/opencs/CMakeLists.txt33
-rw-r--r--apps/opencs/main.cpp5
-rw-r--r--apps/opencs/model/prefs/shortcut.hpp2
-rw-r--r--apps/opencs/model/tools/referenceablecheck.cpp6
-rw-r--r--apps/opencs/model/world/idtable.hpp2
-rw-r--r--apps/opencs/model/world/idtree.cpp6
-rw-r--r--apps/opencs/model/world/idtree.hpp4
-rw-r--r--apps/opencs/model/world/refidadapter.hpp2
-rw-r--r--apps/opencs/view/render/cellwater.cpp2
-rw-r--r--apps/opencs/view/render/pagedworldspacewidget.cpp2
-rw-r--r--apps/opencs/view/render/scenewidget.cpp2
-rw-r--r--apps/opencs/view/world/regionmap.hpp4
-rw-r--r--apps/openmw/CMakeLists.txt15
-rw-r--r--apps/openmw/doc.hpp2
-rw-r--r--apps/openmw/engine.cpp2
-rw-r--r--apps/openmw/main.cpp5
-rw-r--r--apps/openmw/mwbase/windowmanager.hpp2
-rw-r--r--apps/openmw/mwclass/door.cpp2
-rw-r--r--apps/openmw/mwclass/potion.cpp2
-rw-r--r--apps/openmw/mwdialogue/dialoguemanagerimp.cpp2
-rw-r--r--apps/openmw/mwgui/itemwidget.cpp2
-rw-r--r--apps/openmw/mwmechanics/actors.cpp17
-rw-r--r--apps/openmw/mwmechanics/aicombat.cpp56
-rw-r--r--apps/openmw/mwmechanics/aicombat.hpp2
-rw-r--r--apps/openmw/mwmechanics/aifollow.cpp2
-rw-r--r--apps/openmw/mwmechanics/aipackage.hpp2
-rw-r--r--apps/openmw/mwmechanics/aiwander.cpp12
-rw-r--r--apps/openmw/mwmechanics/aiwander.hpp2
-rw-r--r--apps/openmw/mwmechanics/character.cpp24
-rw-r--r--apps/openmw/mwmechanics/character.hpp2
-rw-r--r--apps/openmw/mwmechanics/mechanicsmanagerimp.cpp2
-rw-r--r--apps/openmw/mwmechanics/obstacle.hpp2
-rw-r--r--apps/openmw/mwmechanics/pathfinding.cpp12
-rw-r--r--apps/openmw/mwmechanics/pathfinding.hpp8
-rw-r--r--apps/openmw/mwmechanics/pathgrid.cpp6
-rw-r--r--apps/openmw/mwmechanics/pathgrid.hpp2
-rw-r--r--apps/openmw/mwmechanics/spellcasting.cpp19
-rw-r--r--apps/openmw/mwmechanics/spellcasting.hpp4
-rw-r--r--apps/openmw/mwphysics/physicssystem.cpp38
-rw-r--r--apps/openmw/mwphysics/physicssystem.hpp2
-rw-r--r--apps/openmw/mwrender/animation.hpp2
-rw-r--r--apps/openmw/mwrender/sky.hpp2
-rw-r--r--apps/openmw/mwscript/compilercontext.hpp2
-rw-r--r--apps/openmw/mwsound/soundmanagerimp.cpp102
-rw-r--r--apps/openmw/mwsound/soundmanagerimp.hpp15
-rw-r--r--apps/openmw/mwworld/cellref.cpp18
-rw-r--r--apps/openmw/mwworld/cellref.hpp1
-rw-r--r--apps/openmw/mwworld/manualref.cpp1
-rw-r--r--apps/openmw/mwworld/projectilemanager.cpp57
-rw-r--r--apps/openmw/mwworld/projectilemanager.hpp3
-rw-r--r--apps/openmw/mwworld/weather.cpp2
-rw-r--r--apps/wizard/inisettings.cpp4
-rw-r--r--apps/wizard/main.cpp6
-rw-r--r--components/esm/cellref.cpp1
-rw-r--r--components/esm/cellref.hpp1
-rw-r--r--components/files/macospath.cpp2
-rw-r--r--components/nif/controlled.cpp9
-rw-r--r--components/nif/controlled.hpp10
-rw-r--r--components/nif/niffile.cpp1
-rw-r--r--components/nif/record.hpp3
-rw-r--r--components/nifosg/nifloader.cpp7
-rw-r--r--components/nifosg/particle.cpp69
-rw-r--r--components/nifosg/particle.hpp18
-rw-r--r--components/sceneutil/riggeometry.cpp18
-rw-r--r--components/sdlutil/sdlinputwrapper.cpp2
-rw-r--r--docs/source/openmw-cs/tour.rst20
-rw-r--r--files/mygui/CMakeLists.txt6
-rw-r--r--files/settings-default.cfg4
-rw-r--r--files/shaders/CMakeLists.txt6
74 files changed, 573 insertions, 190 deletions
diff --git a/.travis.yml b/.travis.yml
index 574fe1b..4f811ee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
os:
- linux
- - osx
+# - osx
osx_image: xcode7.2
language: cpp
sudo: required
diff --git a/AUTHORS.md b/AUTHORS.md
index a876bcb..83777df 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -23,6 +23,7 @@ Programmers
Alexander Olofsson (Ace)
Allofich
AnyOldName3
+ Aussiemon
Austin Salgat (Salgat)
Artem Kotsynyak (greye)
artemutin
@@ -74,6 +75,7 @@ Programmers
Karl-Felix Glatzer (k1ll)
Kevin Poitra (PuppyKevin)
Koncord
+ Kurnevsky Evgeny (kurnevsky)
Lars Söderberg (Lazaroth)
lazydev
Leon Saunders (emoose)
@@ -120,6 +122,7 @@ Programmers
Scott Howard
Sebastian Wick (swick)
Sergey Shambir
+ ShadowRadiance
sir_herrbatka
smbas
Stefan Galowicz (bogglez)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0d74e8c..960259f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,7 +96,7 @@ endif()
# Set up common paths
if (APPLE)
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
- set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
+ set(OPENMW_RESOURCE_FILES "../Resources/resources" CACHE PATH "location of OpenMW resources files")
elseif(UNIX)
# Paths
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
@@ -286,6 +286,11 @@ endif (APPLE)
# Set up DEBUG define
set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1)
+if (NOT APPLE)
+ set(OPENMW_MYGUI_FILES_ROOT ${OpenMW_BINARY_DIR})
+ set(OPENMW_SHADERS_ROOT ${OpenMW_BINARY_DIR})
+endif ()
+
add_subdirectory(files/)
# Specify build paths
@@ -307,11 +312,15 @@ endif (APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}/settings-default.cfg")
-configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
- "${OpenMW_BINARY_DIR}/openmw.cfg")
-
-configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
- "${OpenMW_BINARY_DIR}/openmw.cfg.install")
+if (NOT APPLE)
+ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
+ "${OpenMW_BINARY_DIR}/openmw.cfg")
+ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
+ "${OpenMW_BINARY_DIR}/openmw.cfg.install")
+else ()
+ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
+ "${OpenMW_BINARY_DIR}/openmw.cfg")
+endif ()
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg
"${OpenMW_BINARY_DIR}/openmw-cs.cfg")
@@ -714,14 +723,7 @@ if (APPLE)
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
endif ()
- set(INSTALL_SUBDIR OpenMW)
-
- install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
- install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
- install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
- install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
- install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
- install(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
+ install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
@@ -729,8 +731,8 @@ if (APPLE)
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
- set(INSTALLED_OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
- set(INSTALLED_OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
+ set(INSTALLED_OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}")
+ set(INSTALLED_OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${OPENCS_BUNDLE_NAME}")
install(CODE "
set(BU_CHMOD_BUNDLE_ITEMS ON)
@@ -774,8 +776,8 @@ if (APPLE)
set(${plugins_var} ${PLUGINS} PARENT_SCOPE)
endfunction (install_plugins_for_bundle)
- install_plugins_for_bundle("${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}" PLUGINS)
- install_plugins_for_bundle("${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
+ install_plugins_for_bundle("${APP_BUNDLE_NAME}" PLUGINS)
+ install_plugins_for_bundle("${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
diff --git a/apps/essimporter/importscri.hpp b/apps/essimporter/importscri.hpp
index 5123f84..fe68e50 100644
--- a/apps/essimporter/importscri.hpp
+++ b/apps/essimporter/importscri.hpp
@@ -13,7 +13,7 @@ namespace ESM
namespace ESSImport
{
- /// Local variable assigments for a running script
+ /// Local variable assignments for a running script
struct SCRI
{
std::string mScript;
diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp
index eadec64..96cadc8 100644
--- a/apps/launcher/main.cpp
+++ b/apps/launcher/main.cpp
@@ -35,14 +35,6 @@ int main(int argc, char *argv[])
// Now we make sure the current dir is set to application path
QDir dir(QCoreApplication::applicationDirPath());
- #ifdef Q_OS_MAC
- if (dir.dirName() == "MacOS") {
- dir.cdUp();
- dir.cdUp();
- dir.cdUp();
- }
- #endif
-
QDir::setCurrent(dir.absolutePath());
Launcher::MainDialog mainWin;
diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt
index acf3cf0..e7e19be 100644
--- a/apps/opencs/CMakeLists.txt
+++ b/apps/opencs/CMakeLists.txt
@@ -162,9 +162,15 @@ endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(APPLE)
- set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
+ set (OPENCS_MAC_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns")
+ set (OPENCS_CFG "${OpenMW_BINARY_DIR}/openmw-cs.cfg")
+ set (OPENCS_DEFAULT_FILTERS_FILE "${OpenMW_BINARY_DIR}/resources/defaultfilters")
+ set (OPENCS_OPENMW_CFG "${OpenMW_BINARY_DIR}/openmw.cfg")
else()
set (OPENCS_MAC_ICON "")
+ set (OPENCS_CFG "")
+ set (OPENCS_DEFAULT_FILTERS_FILE "")
+ set (OPENCS_OPENMW_CFG "")
endif(APPLE)
add_executable(openmw-cs
@@ -174,12 +180,23 @@ add_executable(openmw-cs
${OPENCS_MOC_SRC}
${OPENCS_RES_SRC}
${OPENCS_MAC_ICON}
+ ${OPENCS_CFG}
+ ${OPENCS_DEFAULT_FILTERS_FILE}
+ ${OPENCS_OPENMW_CFG}
)
if(APPLE)
+ set(OPENCS_BUNDLE_NAME "OpenMW-CS")
+ set(OPENCS_BUNDLE_RESOURCES_DIR "${OpenMW_BINARY_DIR}/${OPENCS_BUNDLE_NAME}.app/Contents/Resources")
+
+ set(OPENMW_MYGUI_FILES_ROOT ${OPENCS_BUNDLE_RESOURCES_DIR})
+ set(OPENMW_SHADERS_ROOT ${OPENCS_BUNDLE_RESOURCES_DIR})
+
+ add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files)
+
set_target_properties(openmw-cs PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}"
- OUTPUT_NAME "OpenMW-CS"
+ OUTPUT_NAME ${OPENCS_BUNDLE_NAME}
MACOSX_BUNDLE_ICON_FILE "openmw-cs.icns"
MACOSX_BUNDLE_BUNDLE_NAME "OpenCS"
MACOSX_BUNDLE_GUI_IDENTIFIER "org.openmw.opencs"
@@ -190,6 +207,16 @@ if(APPLE)
set_source_files_properties(${OPENCS_MAC_ICON} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
+ set_source_files_properties(${OPENCS_CFG} PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources)
+ set_source_files_properties(${OPENCS_DEFAULT_FILTERS_FILE} PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources/resources)
+ set_source_files_properties(${OPENCS_OPENMW_CFG} PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources)
+
+ add_custom_command(TARGET openmw-cs
+ POST_BUILD
+ COMMAND cp "${OpenMW_BINARY_DIR}/resources/version" "${OPENCS_BUNDLE_RESOURCES_DIR}/resources")
endif(APPLE)
target_link_libraries(openmw-cs
@@ -236,5 +263,5 @@ endif (MSVC)
if(APPLE)
- INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
+ INSTALL(TARGETS openmw-cs BUNDLE DESTINATION "." COMPONENT BUNDLE)
endif()
diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp
index c6fe348..fc5e8fc 100644
--- a/apps/opencs/main.cpp
+++ b/apps/opencs/main.cpp
@@ -62,11 +62,6 @@ int main(int argc, char *argv[])
#ifdef Q_OS_MAC
QDir dir(QCoreApplication::applicationDirPath());
- if (dir.dirName() == "MacOS") {
- dir.cdUp();
- dir.cdUp();
- dir.cdUp();
- }
QDir::setCurrent(dir.absolutePath());
#endif
diff --git a/apps/opencs/model/prefs/shortcut.hpp b/apps/opencs/model/prefs/shortcut.hpp
index 7a90a1d..4fa6f8a 100644
--- a/apps/opencs/model/prefs/shortcut.hpp
+++ b/apps/opencs/model/prefs/shortcut.hpp
@@ -29,7 +29,7 @@ namespace CSMPrefs
enum SecondaryMode
{
SM_Replace, ///< The secondary signal replaces the regular signal when the modifier is active
- SM_Detach, ///< The secondary signal is emitted independant of the regular signal, even if not active
+ SM_Detach, ///< The secondary signal is emitted independent of the regular signal, even if not active
SM_Ignore ///< The secondary signal will not ever be emitted
};
diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp
index ce78e52..4dd3e1e 100644
--- a/apps/opencs/model/tools/referenceablecheck.cpp
+++ b/apps/opencs/model/tools/referenceablecheck.cpp
@@ -425,7 +425,7 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
//stats checks
if (creature.mData.mLevel < 1)
- messages.push_back (std::make_pair (id, creature.mId + " has non-postive level"));
+ messages.push_back (std::make_pair (id, creature.mId + " has non-positive level"));
if (creature.mData.mStrength < 0)
messages.push_back (std::make_pair (id, creature.mId + " has negative strength"));
@@ -659,7 +659,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
{
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
{
- messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
+ messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happen?
return;
}
@@ -915,7 +915,7 @@ void CSMTools::ReferenceableCheckStage::inventoryListCheck(
id + " contains non-existing item (" + itemName + ")"));
else
{
- // Needs to accomodate Containers, Creatures, and NPCs
+ // Needs to accommodate containers, creatures, and NPCs
switch (localIndex.second)
{
case CSMWorld::UniversalId::Type_Potion:
diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp
index 8c2f8a4..9faf64d 100644
--- a/apps/opencs/model/world/idtable.hpp
+++ b/apps/opencs/model/world/idtable.hpp
@@ -65,7 +65,7 @@ namespace CSMWorld
void setRecord (const std::string& id, const RecordBase& record,
UniversalId::Type type = UniversalId::Type_None);
- ///< Add record or overwrite existing recrod.
+ ///< Add record or overwrite existing record.
const RecordBase& getRecord (const std::string& id) const;
diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp
index 7c4551a..7f43a92 100644
--- a/apps/opencs/model/world/idtree.cpp
+++ b/apps/opencs/model/world/idtree.cpp
@@ -198,12 +198,12 @@ QModelIndex CSMWorld::IdTree::parent (const QModelIndex& index) const
return QModelIndex();
unsigned int id = index.internalId();
- const std::pair<int, int>& adress(unfoldIndexAddress(id));
+ const std::pair<int, int>& address(unfoldIndexAddress(id));
- if (adress.first >= this->rowCount() || adress.second >= this->columnCount())
+ if (address.first >= this->rowCount() || address.second >= this->columnCount())
throw "Parent index is not present in the model";
- return createIndex(adress.first, adress.second);
+ return createIndex(address.first, address.second);
}
unsigned int CSMWorld::IdTree::foldIndexAddress (const QModelIndex& index) const
diff --git a/apps/opencs/model/world/idtree.hpp b/apps/opencs/model/world/idtree.hpp
index 79e93fc..1539bd4 100644
--- a/apps/opencs/model/world/idtree.hpp
+++ b/apps/opencs/model/world/idtree.hpp
@@ -8,9 +8,9 @@
/*! \brief
* Class for holding the model. Uses typical qt table abstraction/interface for granting access
* to the individiual fields of the records, Some records are holding nested data (for instance
- * inventory list of the npc). In casses like this, table model offers interface to access
+ * inventory list of the npc). In cases like this, table model offers interface to access
* nested data in the qt way - that is specify parent. Since some of those nested data require
- * multiple columns to represent informations, single int (default way to index model in the
+ * multiple columns to represent information, single int (default way to index model in the
* qmodelindex) is not sufficiant. Therefore tablemodelindex class can hold two ints for the
* sake of indexing two dimensions of the table. This model does not support multiple levels of
* the nested data. Vast majority of methods makes sense only for the top level data.
diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp
index ba9da57..116adb6 100644
--- a/apps/opencs/model/world/refidadapter.hpp
+++ b/apps/opencs/model/world/refidadapter.hpp
@@ -8,7 +8,7 @@
* Adapters acts as indirection layer, abstracting details of the record types (in the wrappers) from the higher levels of model.
* Please notice that nested adaptor uses helper classes for actually performing any actions. Different record types require different helpers (needs to be created in the subclass and then fetched via member function).
*
- * Important point: don't forget to make sure that getData on the nestedColumn returns true (otherwise code will not treat the index pointing to the column as having childs!
+ * Important point: don't forget to make sure that getData on the nestedColumn returns true (otherwise code will not treat the index pointing to the column as having children!
*/
class QVariant;
diff --git a/apps/opencs/view/render/cellwater.cpp b/apps/opencs/view/render/cellwater.cpp
index b8975da..15ea15c 100644
--- a/apps/opencs/view/render/cellwater.cpp
+++ b/apps/opencs/view/render/cellwater.cpp
@@ -50,7 +50,7 @@ namespace CSVRender
updateCellData(mData.getCells().getRecord(cellIndex));
}
- // Keep water existance/height up to date
+ // Keep water existence/height up to date
QAbstractItemModel* cells = mData.getTableModel(CSMWorld::UniversalId::Type_Cells);
connect(cells, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(cellDataChanged(const QModelIndex&, const QModelIndex&)));
diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp
index 261144f..901dadc 100644
--- a/apps/opencs/view/render/pagedworldspacewidget.cpp
+++ b/apps/opencs/view/render/pagedworldspacewidget.cpp
@@ -516,7 +516,7 @@ void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
// Current coordinate
int x, y;
- // Loop throught all the coordinates to add them to selection
+ // Loop through all the coordinates to add them to selection
while (stream >> ignore1 >> ignore2 >> x >> y)
selection.add (CSMWorld::CellCoordinates (x, y));
diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp
index 4655ee9..e5b61f5 100644
--- a/apps/opencs/view/render/scenewidget.cpp
+++ b/apps/opencs/view/render/scenewidget.cpp
@@ -214,7 +214,7 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
SceneWidget::~SceneWidget()
{
- // Since we're holding on to the scene templates past the existance of this graphics context, we'll need to manually release the created objects
+ // Since we're holding on to the scene templates past the existence of this graphics context, we'll need to manually release the created objects
mResourceSystem->getSceneManager()->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState());
}
diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp
index 0097a16..ba77322 100644
--- a/apps/opencs/view/world/regionmap.hpp
+++ b/apps/opencs/view/world/regionmap.hpp
@@ -45,8 +45,8 @@ namespace CSVWorld
///< \note Non-existent cells are not listed.
QModelIndexList getSelectedCells (bool existent = true, bool nonExistent = false) const;
- ///< \param existant Include existant cells.
- /// \param nonExistant Include non-existant cells.
+ ///< \param existent Include existent cells.
+ /// \param nonExistent Include non-existent cells.
QModelIndexList getMissingRegionCells() const;
///< Unselected cells within all regions that have at least one selected cell.
diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt
index 452629f..ce859bc 100644
--- a/apps/openmw/CMakeLists.txt
+++ b/apps/openmw/CMakeLists.txt
@@ -179,6 +179,21 @@ target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
endif()
if(APPLE)
+ set(BUNDLE_RESOURCES_DIR "${APP_BUNDLE_DIR}/Contents/Resources")
+
+ set(OPENMW_MYGUI_FILES_ROOT ${BUNDLE_RESOURCES_DIR})
+ set(OPENMW_SHADERS_ROOT ${BUNDLE_RESOURCES_DIR})
+
+ add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files)
+
+ configure_file("${OpenMW_BINARY_DIR}/settings-default.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
+ configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
+ configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)
+
+ add_custom_command(TARGET openmw
+ POST_BUILD
+ COMMAND cp "${OpenMW_BINARY_DIR}/resources/version" "${BUNDLE_RESOURCES_DIR}/resources")
+
find_library(COCOA_FRAMEWORK Cocoa)
find_library(IOKIT_FRAMEWORK IOKit)
target_link_libraries(openmw ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK})
diff --git a/apps/openmw/doc.hpp b/apps/openmw/doc.hpp
index ffeef94..5f90650 100644
--- a/apps/openmw/doc.hpp
+++ b/apps/openmw/doc.hpp
@@ -41,4 +41,4 @@
/// \namespace MWScript
/// \ingroup openmw
-/// \brief MW-specific script extentions and integration of the script system into OpenMW
+/// \brief MW-specific script extensions and integration of the script system into OpenMW
diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp
index 62457ca..03ec412 100644
--- a/apps/openmw/engine.cpp
+++ b/apps/openmw/engine.cpp
@@ -493,7 +493,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mEnvironment.setWindowManager (window);
// Create sound system
- mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
+ mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mFallbackMap, mUseSound));
if (!mSkipMenu)
{
diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp
index cfe7fe3..43901d5 100644
--- a/apps/openmw/main.cpp
+++ b/apps/openmw/main.cpp
@@ -352,9 +352,8 @@ int main(int argc, char**argv)
#endif
#ifdef __APPLE__
- // FIXME: set current dir to bundle path
- //boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path();
- //boost::filesystem::current_path(bundlePath);
+ boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0]));
+ boost::filesystem::current_path(binary_path.parent_path());
#endif
engine.reset(new OMW::Engine(cfgMgr));
diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp
index 77d740b..3a53c32 100644
--- a/apps/openmw/mwbase/windowmanager.hpp
+++ b/apps/openmw/mwbase/windowmanager.hpp
@@ -233,7 +233,7 @@ namespace MWBase
virtual void removeDialog(MWGui::Layout* dialog) = 0;
///Gracefully attempts to exit the topmost GUI mode
- /** No guarentee of actually closing the window **/
+ /** No guarantee of actually closing the window **/
virtual void exitCurrentGuiMode() = 0;
virtual void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0;
diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp
index 7494d2b..830ba25 100644
--- a/apps/openmw/mwclass/door.cpp
+++ b/apps/openmw/mwclass/door.cpp
@@ -231,7 +231,7 @@ namespace MWClass
if(lockLevel!=0)
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
else
- ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one
+ ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one
}
void Door::unlock (const MWWorld::Ptr& ptr) const
diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp
index c26b925..2251759 100644
--- a/apps/openmw/mwclass/potion.cpp
+++ b/apps/openmw/mwclass/potion.cpp
@@ -122,7 +122,7 @@ namespace MWClass
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
- // hide effects the player doesnt know about
+ // hide effects the player doesn't know about
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
for (unsigned int i=0; i<info.effects.size(); ++i)
info.effects[i].mKnown = MWMechanics::Alchemy::knownEffect(i, player);
diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
index ee6e249..3102354 100644
--- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
+++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp
@@ -174,7 +174,7 @@ namespace MWDialogue
executeScript (info->mResultScript);
mLastTopic = Misc::StringUtils::lowerCase(it->mId);
- // update topics again to accomodate changes resulting from executeScript
+ // update topics again to accommodate changes resulting from executeScript
updateTopics();
return;
diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp
index 87fca94..fe7cb79 100644
--- a/apps/openmw/mwgui/itemwidget.cpp
+++ b/apps/openmw/mwgui/itemwidget.cpp
@@ -101,6 +101,8 @@ namespace MWGui
{
if (mFrame)
mFrame->setImageTexture("");
+ if (mItemShadow)
+ mItemShadow->setImageTexture("");
mItem->setImageTexture("");
mText->setCaption("");
return;
diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp
index 1a6a62f..23a6f49 100644
--- a/apps/openmw/mwmechanics/actors.cpp
+++ b/apps/openmw/mwmechanics/actors.cpp
@@ -512,8 +512,8 @@ namespace MWMechanics
if (magnitude > 0 && remainingTime > 0 && remainingTime < mDuration)
{
CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor);
- effectTick(creatureStats, mActor, key, magnitude * remainingTime);
- creatureStats.getMagicEffects().add(key, -magnitude);
+ if (effectTick(creatureStats, mActor, key, magnitude * remainingTime))
+ creatureStats.getMagicEffects().add(key, -magnitude);
}
}
};
@@ -527,8 +527,10 @@ namespace MWMechanics
if (duration > 0)
{
- // apply correct magnitude for tickable effects that have just expired,
- // in case duration > remaining time of effect
+ // Apply correct magnitude for tickable effects that have just expired,
+ // in case duration > remaining time of effect.
+ // One case where this will happen is when the player uses the rest/wait command
+ // while there is a tickable effect active that should expire before the end of the rest/wait.
ExpiryVisitor visitor(ptr, duration);
creatureStats.getActiveSpells().visitEffectSources(visitor);
@@ -1269,8 +1271,6 @@ namespace MWMechanics
stats.getActiveSpells().clear();
calculateCreatureStatModifiers(iter->first, 0);
- MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
-
if (cls.isEssential(iter->first))
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
}
@@ -1288,6 +1288,11 @@ namespace MWMechanics
//player's death animation is over
MWBase::Environment::get().getStateManager()->askLoadRecent();
}
+ else
+ {
+ // NPC death animation is over, disable actor collision
+ MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
+ }
// Play Death Music if it was the player dying
if(iter->first == getPlayer())
diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp
index 80b343d..d8dae8b 100644
--- a/apps/openmw/mwmechanics/aicombat.cpp
+++ b/apps/openmw/mwmechanics/aicombat.cpp
@@ -60,30 +60,30 @@ namespace MWMechanics
FleeState_RunToDestination
};
FleeState mFleeState;
- bool mFleeLOS;
- float mFleeUpdateLOSTimer;
+ bool mLOS;
+ float mUpdateLOSTimer;
float mFleeBlindRunTimer;
ESM::Pathgrid::Point mFleeDest;
AiCombatStorage():
- mAttackCooldown(0),
+ mAttackCooldown(0.0f),
mTimerReact(AI_REACTION_TIME),
- mTimerCombatMove(0),
+ mTimerCombatMove(0.0f),
mReadyToAttack(false),
mAttack(false),
- mAttackRange(0),
+ mAttackRange(0.0f),
mCombatMove(false),
mLastTargetPos(0,0,0),
mCell(NULL),
mCurrentAction(),
- mActionCooldown(0),
+ mActionCooldown(0.0f),
mStrength(),
mForceNoShortcut(false),
mShortcutFailPos(),
mMovement(),
mFleeState(FleeState_None),
- mFleeLOS(false),
- mFleeUpdateLOSTimer(0.0f),
+ mLOS(false),
+ mUpdateLOSTimer(0.0f),
mFleeBlindRunTimer(0.0f)
{}
@@ -157,7 +157,7 @@ namespace MWMechanics
*
* TODO:
*
- * Use the Observer Pattern to co-ordinate attacks, provide intelligence on
+ * Use the observer pattern to coordinate attacks, provide intelligence on
* whether the target was hit, etc.
*/
@@ -181,10 +181,14 @@ namespace MWMechanics
if (!storage.isFleeing())
{
- if (storage.mCurrentAction.get()) // need to wait to init action with it's attack range
+ if (storage.mCurrentAction.get()) // need to wait to init action with its attack range
{
- //Update every frame
- bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, storage.mAttackRange);
+ //Update every frame. UpdateLOS uses a timer, so the LOS check does not happen every frame.
+ updateLOS(actor, target, duration, storage);
+ float targetReachedTolerance = 0.0f;
+ if (storage.mLOS)
+ targetReachedTolerance = storage.mAttackRange;
+ bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, targetReachedTolerance);
if (is_target_reached) storage.mReadyToAttack = true;
}
@@ -283,7 +287,7 @@ namespace MWMechanics
osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target);
- storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack);
+ storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS);
if (storage.mReadyToAttack)
{
@@ -309,18 +313,23 @@ namespace MWMechanics
}
}
- void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
+ void MWMechanics::AiCombat::updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
{
static const float LOS_UPDATE_DURATION = 0.5f;
- static const float BLIND_RUN_DURATION = 1.0f;
-
- if (storage.mFleeUpdateLOSTimer <= 0.f)
+ if (storage.mUpdateLOSTimer <= 0.f)
{
- storage.mFleeLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target);
- storage.mFleeUpdateLOSTimer = LOS_UPDATE_DURATION;
+ storage.mLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target);
+ storage.mUpdateLOSTimer = LOS_UPDATE_DURATION;
}
else
- storage.mFleeUpdateLOSTimer -= duration;
+ storage.mUpdateLOSTimer -= duration;
+ }
+
+ void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
+ {
+ static const float BLIND_RUN_DURATION = 1.0f;
+
+ updateLOS(actor, target, duration, storage);
AiCombatStorage::FleeState& state = storage.mFleeState;
switch (state)
@@ -332,7 +341,7 @@ namespace MWMechanics
{
float triggerDist = getMaxAttackDistance(target);
- if (storage.mFleeLOS &&
+ if (storage.mLOS &&
(triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist))
{
const ESM::Pathgrid* pathgrid =
@@ -399,7 +408,7 @@ namespace MWMechanics
static const float fFleeDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFleeDistance")->getFloat();
float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length();
- if ((dist > fFleeDistance && !storage.mFleeLOS)
+ if ((dist > fFleeDistance && !storage.mLOS)
|| pathTo(actor, storage.mFleeDest, duration))
{
state = AiCombatStorage::FleeState_Idle;
@@ -602,9 +611,6 @@ namespace MWMechanics
mMovement.mPosition[2] = 0;
mFleeState = FleeState_None;
mFleeDest = ESM::Pathgrid::Point(0, 0, 0);
- mFleeLOS = false;
- mFleeUpdateLOSTimer = 0.0f;
- mFleeUpdateLOSTimer = 0.0f;
}
bool AiCombatStorage::isFleeing()
diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp
index 3f2bde7..a2e995c 100644
--- a/apps/openmw/mwmechanics/aicombat.hpp
+++ b/apps/openmw/mwmechanics/aicombat.hpp
@@ -61,6 +61,8 @@ namespace MWMechanics
void attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController);
+ void updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
+
void updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
/// Transfer desired movement (from AiCombatStorage) to Actor
diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp
index c563ba3..fb080d0 100644
--- a/apps/openmw/mwmechanics/aifollow.cpp
+++ b/apps/openmw/mwmechanics/aifollow.cpp
@@ -152,7 +152,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte
if (dist > 450)
actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run
- else if (dist < 325) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold
+ else if (dist < 325) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshold
actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk
}
diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp
index 4960c14..5e23e08 100644
--- a/apps/openmw/mwmechanics/aipackage.hpp
+++ b/apps/openmw/mwmechanics/aipackage.hpp
@@ -32,7 +32,7 @@ namespace MWMechanics
class AiPackage
{
public:
- ///Enumerates the various AITypes availible.
+ ///Enumerates the various AITypes available
enum TypeId {
TypeIdNone = -1,
TypeIdWander = 0,
diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp
index 2a591d7..e67c733 100644
--- a/apps/openmw/mwmechanics/aiwander.cpp
+++ b/apps/openmw/mwmechanics/aiwander.cpp
@@ -336,7 +336,7 @@ namespace MWMechanics
{
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mReturnPosition));
- // actor position is already in world co-ordinates
+ // actor position is already in world coordinates
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
// don't take shortcuts for wandering
@@ -649,7 +649,7 @@ namespace MWMechanics
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
ToWorldCoordinates(dest, storage.mCell->getCell());
- // actor position is already in world co-ordinates
+ // actor position is already in world coordinates
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actorPos));
// don't take shortcuts for wandering
@@ -693,8 +693,8 @@ namespace MWMechanics
ESM::Pathgrid::Point pt = paths.back();
for(unsigned int j = 0; j < nodes.size(); j++)
{
- // FIXME: doesn't hadle a door with the same X/Y
- // co-ordinates but with a different Z
+ // FIXME: doesn't handle a door with the same X/Y
+ // coordinates but with a different Z
if(nodes[j].mX == pt.mX && nodes[j].mY == pt.mY)
{
nodes.erase(nodes.begin() + j);
@@ -828,7 +828,7 @@ namespace MWMechanics
// ... pathgrids don't usually include water, so swimmers ignore them
if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor))
{
- // get NPC's position in local (i.e. cell) co-ordinates
+ // get NPC's position in local (i.e. cell) coordinates
osg::Vec3f npcPos(mInitialActorPosition);
CoordinateConverter(cell).toLocal(npcPos);
@@ -837,7 +837,7 @@ namespace MWMechanics
// mAllowedNodes for this actor with pathgrid point indexes based on mDistance
// and if the point is connected to the closest current point
- // NOTE: mPoints and mAllowedNodes are in local co-ordinates
+ // NOTE: mPoints and mAllowedNodes are in local coordinates
int pointIndex = 0;
for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
{
diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp
index da7553c..f9b03ca 100644
--- a/apps/openmw/mwmechanics/aiwander.hpp
+++ b/apps/openmw/mwmechanics/aiwander.hpp
@@ -119,7 +119,7 @@ namespace MWMechanics
GroupIndex_MaxIdle = 9
};
- /// convert point from local (i.e. cell) to world co-ordinates
+ /// convert point from local (i.e. cell) to world coordinates
void ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell);
void SetCurrentNodeToClosestAllowedNode(osg::Vec3f npcPos, AiWanderStorage& storage);
diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp
index d9cae3a..c771d9f 100644
--- a/apps/openmw/mwmechanics/character.cpp
+++ b/apps/openmw/mwmechanics/character.cpp
@@ -1049,6 +1049,9 @@ bool CharacterController::updateCreatureState()
mUpperBodyState = UpperCharState_StartToMinAttack;
mAttackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability());
+
+ if (weapType == WeapType_HandToHand)
+ playSwishSound(0.0f);
}
}
@@ -1370,13 +1373,7 @@ bool CharacterController::updateWeaponState()
}
else
{
- std::string sound = "SwishM";
- if(attackStrength < 0.5f)
- sndMgr->playSound3D(mPtr, sound, 1.0f, 0.8f); //Weak attack
- else if(attackStrength < 1.0f)
- sndMgr->playSound3D(mPtr, sound, 1.0f, 1.0f); //Medium attack
- else
- sndMgr->playSound3D(mPtr, sound, 1.0f, 1.2f); //Strong attack
+ playSwishSound(attackStrength);
}
}
mAttackStrength = attackStrength;
@@ -2271,6 +2268,19 @@ void CharacterController::setHeadTrackTarget(const MWWorld::ConstPtr &target)
mHeadTrackTarget = target;
}
+void CharacterController::playSwishSound(float attackStrength)
+{
+ MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
+
+ std::string sound = "Weapon Swish";
+ if(attackStrength < 0.5f)
+ sndMgr->playSound3D(mPtr, sound, 1.0f, 0.8f); //Weak attack
+ else if(attackStrength < 1.0f)
+ sndMgr->playSound3D(mPtr, sound, 1.0f, 1.0f); //Medium attack
+ else
+ sndMgr->playSound3D(mPtr, sound, 1.0f, 1.2f); //Strong attack
+}
+
void CharacterController::updateHeadTracking(float duration)
{
const osg::Node* head = mAnimation->getNode("Bip01 Head");
diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp
index 3a84f0f..f393f06 100644
--- a/apps/openmw/mwmechanics/character.hpp
+++ b/apps/openmw/mwmechanics/character.hpp
@@ -281,6 +281,8 @@ public:
/// Make this character turn its head towards \a target. To turn off head tracking, pass an empty Ptr.
void setHeadTrackTarget(const MWWorld::ConstPtr& target);
+
+ void playSwishSound(float attackStrength);
};
MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::InventoryStore &inv, WeaponType *weaptype);
diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
index 9588699..97fa98b 100644
--- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
+++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
@@ -236,7 +236,7 @@ namespace MWMechanics
: mWatchedTimeToStartDrowning(0), mWatchedStatsEmpty (true), mUpdatePlayer (true), mClassSelected (false),
mRaceSelected (false), mAI(true)
{
- //buildPlayer no longer here, needs to be done explicitely after all subsystems are up and running
+ //buildPlayer no longer here, needs to be done explicitly after all subsystems are up and running
}
void MechanicsManager::add(const MWWorld::Ptr& ptr)
diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp
index d2e1cfc..1d7cf1e 100644
--- a/apps/openmw/mwmechanics/obstacle.hpp
+++ b/apps/openmw/mwmechanics/obstacle.hpp
@@ -19,7 +19,7 @@ namespace MWMechanics
bool proximityToDoor(const MWWorld::Ptr& actor,
float minSqr = MIN_DIST_TO_DOOR_SQUARED);
- /// Returns door pointer within range. No guarentee is given as too which one
+ /// Returns door pointer within range. No guarantee is given as to which one
/** \return Pointer to the door, or NULL if none exists **/
MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor,
float minSqr = MIN_DIST_TO_DOOR_SQUARED);
diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp
index 0c7e9cd..b0bdce8 100644
--- a/apps/openmw/mwmechanics/pathfinding.cpp
+++ b/apps/openmw/mwmechanics/pathfinding.cpp
@@ -139,7 +139,7 @@ namespace MWMechanics
* NOTE: It may be desirable to simply go directly to the endPoint if for
* example there are no pathgrids in this cell.
*
- * NOTE: startPoint & endPoint are in world co-ordinates
+ * NOTE: startPoint & endPoint are in world coordinates
*
* Updates mPath using aStarSearch() or ray test (if shortcut allowed).
* mPath consists of pathgrid points, except the last element which is
@@ -148,7 +148,7 @@ namespace MWMechanics
* pathgrid point (e.g. wander) then it may be worth while to call
* pop_back() to remove the redundant entry.
*
- * NOTE: co-ordinates must be converted prior to calling GetClosestPoint()
+ * NOTE: coordinates must be converted prior to calling GetClosestPoint()
*
* |
* | cell
@@ -164,8 +164,8 @@ namespace MWMechanics
* +-----------------------------
*
* i = x value of cell itself (multiply by ESM::Land::REAL_SIZE to convert)
- * j = @.x in local co-ordinates (i.e. within the cell)
- * k = @.x in world co-ordinates
+ * j = @.x in local coordinates (i.e. within the cell)
+ * k = @.x in world coordinates
*/
void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint,
const ESM::Pathgrid::Point &endPoint,
@@ -188,7 +188,7 @@ namespace MWMechanics
return;
}
- // NOTE: GetClosestPoint expects local co-ordinates
+ // NOTE: GetClosestPoint expects local coordinates
CoordinateConverter converter(mCell->getCell());
// NOTE: It is possible that GetClosestPoint returns a pathgrind point index
@@ -230,7 +230,7 @@ namespace MWMechanics
{
mPath = mCell->aStarSearch(startNode, endNode.first);
- // convert supplied path to world co-ordinates
+ // convert supplied path to world coordinates
for (std::list<ESM::Pathgrid::Point>::iterator iter(mPath.begin()); iter != mPath.end(); ++iter)
{
converter.toWorld(*iter);
diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp
index 83c56ca..945a7f9 100644
--- a/apps/openmw/mwmechanics/pathfinding.hpp
+++ b/apps/openmw/mwmechanics/pathfinding.hpp
@@ -84,7 +84,7 @@ namespace MWMechanics
/** Synchronize new path with old one to avoid visiting 1 waypoint 2 times
@note
BuildPath() takes closest PathGrid point to NPC as first point of path.
- This is undesireable if NPC has just passed a Pathgrid point, as this
+ This is undesirable if NPC has just passed a Pathgrid point, as this
makes the 2nd point of the new path == the 1st point of old path.
Which results in NPC "running in a circle" back to the just passed waypoint.
*/
@@ -122,11 +122,11 @@ namespace MWMechanics
return (MWMechanics::PathFinder::MakeOsgVec3(point) - pos).length2();
}
- // Return the closest pathgrid point index from the specified position co
- // -ordinates. NOTE: Does not check if there is a sensible way to get there
+ // Return the closest pathgrid point index from the specified position
+ // coordinates. NOTE: Does not check if there is a sensible way to get there
// (e.g. a cliff in front).
//
- // NOTE: pos is expected to be in local co-ordinates, as is grid->mPoints
+ // NOTE: pos is expected to be in local coordinates, as is grid->mPoints
//
static int GetClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos)
{
diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp
index 871baec..c557bea 100644
--- a/apps/openmw/mwmechanics/pathgrid.cpp
+++ b/apps/openmw/mwmechanics/pathgrid.cpp
@@ -225,7 +225,7 @@ namespace MWMechanics
* Should be possible to make this MT safe.
*
* Returns path which may be empty. path contains pathgrid points in local
- * cell co-ordinates (indoors) or world co-ordinates (external).
+ * cell coordinates (indoors) or world coordinates (external).
*
* Input params:
* start, goal - pathgrid point indexes (for this cell)
@@ -239,7 +239,7 @@ namespace MWMechanics
* TODO: An intersting exercise might be to cache the paths created for a
* start/goal pair. To cache the results the paths need to be in
* pathgrid points form (currently they are converted to world
- * co-ordinates). Essentially trading speed w/ memory.
+ * coordinates). Essentially trading speed w/ memory.
*/
std::list<ESM::Pathgrid::Point> PathgridGraph::aStarSearch(const int start,
const int goal) const
@@ -312,7 +312,7 @@ namespace MWMechanics
if(current != goal)
return path; // for some reason couldn't build a path
- // reconstruct path to return, using local co-ordinates
+ // reconstruct path to return, using local coordinates
while(graphParent[current] != -1)
{
path.push_front(mPathgrid->mPoints[current]);
diff --git a/apps/openmw/mwmechanics/pathgrid.hpp b/apps/openmw/mwmechanics/pathgrid.hpp
index ab418ae..d90cb47 100644
--- a/apps/openmw/mwmechanics/pathgrid.hpp
+++ b/apps/openmw/mwmechanics/pathgrid.hpp
@@ -30,7 +30,7 @@ namespace MWMechanics
// the input parameters are pathgrid point indexes
// the output list is in local (internal cells) or world (external
- // cells) co-ordinates
+ // cells) coordinates
//
// NOTE: if start equals end an empty path is returned
std::list<ESM::Pathgrid::Point> aStarSearch(const int start,
diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp
index 5c5fc38..43d77b9 100644
--- a/apps/openmw/mwmechanics/spellcasting.cpp
+++ b/apps/openmw/mwmechanics/spellcasting.cpp
@@ -491,7 +491,7 @@ namespace MWMechanics
appliedLastingEffects.push_back(effect);
// For absorb effects, also apply the effect to the caster - but with a negative
- // magnitude, since we're transfering stats from the target to the caster
+ // magnitude, since we're transferring stats from the target to the caster
if (!caster.isEmpty() && caster.getClass().isActor())
{
for (int i=0; i<5; ++i)
@@ -913,7 +913,7 @@ namespace MWMechanics
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
- if (mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx
+ if (animation && mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx even if they are disabled (animation == NULL)
{
const ESM::Static* castStatic;
@@ -927,7 +927,7 @@ namespace MWMechanics
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture);
}
- if (!mCaster.getClass().isActor())
+ if (animation && !mCaster.getClass().isActor())
animation->addSpellCastGlow(effect);
static const std::string schools[] = {
@@ -980,8 +980,10 @@ namespace MWMechanics
if (charge == 0)
return false;
- // FIXME: charge should be a float, not int so that damage < 1 per frame can be applied.
- // This was also a bug in the original engine.
+ // Store remainder of disintegrate amount (automatically subtracted if > 1)
+ item->getCellRef().applyChargeRemainderToBeSubtracted(disintegrate - std::floor(disintegrate));
+
+ charge = item->getClass().getItemHealth(*item);
charge -=
std::min(static_cast<int>(disintegrate),
charge);
@@ -1009,10 +1011,10 @@ namespace MWMechanics
creatureStats.setDynamic(index, stat);
}
- void effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const EffectKey &effectKey, float magnitude)
+ bool effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const EffectKey &effectKey, float magnitude)
{
if (magnitude == 0.f)
- return;
+ return false;
bool receivedMagicDamage = false;
@@ -1144,10 +1146,13 @@ namespace MWMechanics
case ESM::MagicEffect::RemoveCurse:
actor.getClass().getCreatureStats(actor).getSpells().purgeCurses();
break;
+ default:
+ return false;
}
if (receivedMagicDamage && actor == getPlayer())
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
+ return true;
}
}
diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp
index 852ae79..6e25acf 100644
--- a/apps/openmw/mwmechanics/spellcasting.hpp
+++ b/apps/openmw/mwmechanics/spellcasting.hpp
@@ -63,7 +63,9 @@ namespace MWMechanics
int getEffectiveEnchantmentCastCost (float castCost, const MWWorld::Ptr& actor);
- void effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const MWMechanics::EffectKey& effectKey, float magnitude);
+ /// Apply a magic effect that is applied in tick intervals until its remaining time ends or it is removed
+ /// @return Was the effect a tickable effect with a magnitude?
+ bool effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const MWMechanics::EffectKey& effectKey, float magnitude);
class CastSpell
{
diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp
index cc3ba40..1a97fc6 100644
--- a/apps/openmw/mwphysics/physicssystem.cpp
+++ b/apps/openmw/mwphysics/physicssystem.cpp
@@ -69,7 +69,14 @@ namespace MWPhysics
return osg::RadiansToDegrees(std::acos(normal * osg::Vec3f(0.f, 0.f, 1.f)));
}
- static bool stepMove(const btCollisionObject *colobj, osg::Vec3f &position,
+ enum StepMoveResult
+ {
+ Result_Blocked, // unable to move over obstacle
+ Result_MaxSlope, // unable to end movement on this slope
+ Result_Success
+ };
+
+ static StepMoveResult stepMove(const btCollisionObject *colobj, osg::Vec3f &position,
const osg::Vec3f &toMove, float &remainingTime, const btCollisionWorld* collisionWorld)
{
/*
@@ -120,7 +127,7 @@ namespace MWPhysics
stepper.doTrace(colobj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), collisionWorld);
if(stepper.mFraction < std::numeric_limits<float>::epsilon())
- return false; // didn't even move the smallest representable amount
+ return Result_Blocked; // didn't even move the smallest representable amount
// (TODO: shouldn't this be larger? Why bother with such a small amount?)
/*
@@ -138,7 +145,7 @@ namespace MWPhysics
*/
tracer.doTrace(colobj, stepper.mEndPos, stepper.mEndPos + toMove, collisionWorld);
if(tracer.mFraction < std::numeric_limits<float>::epsilon())
- return false; // didn't even move the smallest representable amount
+ return Result_Blocked; // didn't even move the smallest representable amount
/*
* Try moving back down sStepSizeDown using stepper.
@@ -156,22 +163,22 @@ namespace MWPhysics
* ==============================================
*/
stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld);
- if(stepper.mFraction < 1.0f && getSlope(stepper.mPlaneNormal) <= sMaxSlope)
+ if (getSlope(stepper.mPlaneNormal) > sMaxSlope)
+ return Result_MaxSlope;
+ if(stepper.mFraction < 1.0f)
{
// don't allow stepping up other actors
if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor)
- return false;
+ return Result_Blocked;
// only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
// TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing
// NOTE: caller's variables 'position' & 'remainingTime' are modified here
position = stepper.mEndPos;
remainingTime *= (1.0f-tracer.mFraction); // remaining time is proportional to remaining distance
- return true;
+ return Result_Success;
}
- // moved between 0 and just under sStepSize distance but slope was too great,
- // or moved full sStepSize distance (FIXME: is this a bug?)
- return false;
+ return Result_Blocked;
}
@@ -361,14 +368,15 @@ namespace MWPhysics
osg::Vec3f oldPosition = newPosition;
// We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over)
// NOTE: stepMove modifies newPosition if successful
- bool result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld);
- if (!result) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent
+ const float minStep = 10.f;
+ StepMoveResult result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld);
+ if (result == Result_MaxSlope && (velocity*remainingTime).length() < minStep) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent
{
osg::Vec3f normalizedVelocity = velocity;
normalizedVelocity.normalize();
- result = stepMove(colobj, newPosition, normalizedVelocity*10.f, remainingTime, collisionWorld);
+ result = stepMove(colobj, newPosition, normalizedVelocity*minStep, remainingTime, collisionWorld);
}
- if(result)
+ if(result == Result_Success)
{
// don't let pure water creatures move out of water after stepMove
if (ptr.getClass().isPureWaterCreature(ptr)
@@ -450,8 +458,8 @@ namespace MWPhysics
if (inertia.z() < 0)
inertia.z() *= slowFall;
if (slowFall < 1.f) {
- inertia.x() = 0;
- inertia.y() = 0;
+ inertia.x() *= slowFall;
+ inertia.y() *= slowFall;
}
physicActor->setInertialForce(inertia);
}
diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp
index 2153553..d746318 100644
--- a/apps/openmw/mwphysics/physicssystem.hpp
+++ b/apps/openmw/mwphysics/physicssystem.hpp
@@ -200,7 +200,7 @@ namespace MWPhysics
typedef std::map<MWWorld::Ptr, MWWorld::Ptr> CollisionMap;
CollisionMap mStandingCollisions;
- // replaces all occurences of 'old' in the map by 'updated', no matter if its a key or value
+ // replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value
void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated);
PtrVelocityList mMovementQueue;
diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp
index b994640..584eca6 100644
--- a/apps/openmw/mwrender/animation.hpp
+++ b/apps/openmw/mwrender/animation.hpp
@@ -302,7 +302,7 @@ protected:
/** Sets the root model of the object.
*
- * Note that you must make sure all animation sources are cleared before reseting the object
+ * Note that you must make sure all animation sources are cleared before resetting the object
* root. All nodes previously retrieved with getNode will also become invalidated.
* @param forceskeleton Wrap the object root in a Skeleton, even if it contains no skinned parts. Use this if you intend to add skinned parts manually.
* @param baseonly If true, then any meshes or particle systems in the model are ignored
diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp
index 085eeb2..e047a98 100644
--- a/apps/openmw/mwrender/sky.hpp
+++ b/apps/openmw/mwrender/sky.hpp
@@ -211,7 +211,7 @@ namespace MWRender
osg::Vec3f mStormDirection;
- // remember some settings so we don't have to apply them again if they didnt change
+ // remember some settings so we don't have to apply them again if they didn't change
std::string mClouds;
std::string mNextClouds;
float mCloudBlendFactor;
diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp
index 010926f..ca7efd7 100644
--- a/apps/openmw/mwscript/compilercontext.hpp
+++ b/apps/openmw/mwscript/compilercontext.hpp
@@ -11,7 +11,7 @@ namespace MWScript
enum Type
{
- Type_Full, // global, local, targetted
+ Type_Full, // global, local, targeted
Type_Dialogue,
Type_Console
};
diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp
index 663f888..9b5fb1b 100644
--- a/apps/openmw/mwsound/soundmanagerimp.cpp
+++ b/apps/openmw/mwsound/soundmanagerimp.cpp
@@ -34,8 +34,9 @@
namespace MWSound
{
- SoundManager::SoundManager(const VFS::Manager* vfs, bool useSound)
+ SoundManager::SoundManager(const VFS::Manager* vfs, const std::map<std::string,std::string>& fallbackMap, bool useSound)
: mVFS(vfs)
+ , mFallback(fallbackMap)
, mOutput(new DEFAULT_OUTPUT(*this))
, mMasterVolume(1.0f)
, mSFXVolume(1.0f)
@@ -61,6 +62,13 @@ namespace MWSound
mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound");
mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f);
+ mNearWaterRadius = mFallback.getFallbackInt("Water_NearWaterRadius");
+ mNearWaterPoints = mFallback.getFallbackInt("Water_NearWaterPoints");
+ mNearWaterIndoorTolerance = mFallback.getFallbackFloat("Water_NearWaterIndoorTolerance");
+ mNearWaterOutdoorTolerance = mFallback.getFallbackFloat("Water_NearWaterOutdoorTolerance");
+ mNearWaterIndoorID = mFallback.getFallbackString("Water_NearWaterIndoorID");
+ mNearWaterOutdoorID = mFallback.getFallbackString("Water_NearWaterOutdoorID");
+
mBufferCacheMin = std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1);
mBufferCacheMax = std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1);
mBufferCacheMax *= 1024*1024;
@@ -796,6 +804,96 @@ namespace MWSound
}
}
+ void SoundManager::updateWaterSound(float /*duration*/)
+ {
+ MWBase::World* world = MWBase::Environment::get().getWorld();
+ const MWWorld::ConstPtr player = world->getPlayerPtr();
+ osg::Vec3f pos = player.getRefData().getPosition().asVec3();
+
+ float volume = 0.0f;
+ const std::string& soundId = player.getCell()->isExterior() ? mNearWaterOutdoorID : mNearWaterIndoorID;
+
+ if (!mListenerUnderwater)
+ {
+ if (player.getCell()->getCell()->hasWater())
+ {
+ float dist = std::abs(player.getCell()->getWaterLevel() - pos.z());
+
+ if (player.getCell()->isExterior() && dist < mNearWaterOutdoorTolerance)
+ {
+ volume = (mNearWaterOutdoorTolerance - dist) / mNearWaterOutdoorTolerance;
+
+ if (mNearWaterPoints > 1)
+ {
+ int underwaterPoints = 0;
+
+ float step = mNearWaterRadius * 2.0f / (mNearWaterPoints - 1);
+
+ for (int x = 0; x < mNearWaterPoints; x++)
+ {
+ for (int y = 0; y < mNearWaterPoints; y++)
+ {
+ float height = world->getTerrainHeightAt(
+ osg::Vec3f(pos.x() - mNearWaterRadius + x*step, pos.y() - mNearWaterRadius + y*step, 0.0f));
+
+ if (height < 0)
+ underwaterPoints++;
+ }
+ }
+
+ volume *= underwaterPoints * 2.0f / (mNearWaterPoints*mNearWaterPoints);
+ }
+ }
+ else if (!player.getCell()->isExterior() && dist < mNearWaterIndoorTolerance)
+ {
+ volume = (mNearWaterIndoorTolerance - dist) / mNearWaterIndoorTolerance;
+ }
+ }
+ }
+ else
+ volume = 1.0f;
+
+ volume = std::min(volume, 1.0f);
+
+ if (mNearWaterSound)
+ {
+ if (volume == 0.0f)
+ {
+ mOutput->finishSound(mNearWaterSound);
+ mNearWaterSound.reset();
+ }
+ else
+ {
+ bool soundIdChanged = false;
+
+ Sound_Buffer* sfx = lookupSound(Misc::StringUtils::lowerCase(soundId));
+
+ for (SoundMap::const_iterator snditer = mActiveSounds.begin(); snditer != mActiveSounds.end(); ++snditer)
+ {
+ for (SoundBufferRefPairList::const_iterator pairiter = snditer->second.begin(); pairiter != snditer->second.end(); ++pairiter)
+ {
+ if (pairiter->first == mNearWaterSound)
+ {
+ if (pairiter->second != sfx)
+ soundIdChanged = true;
+ break;
+ }
+ }
+ }
+
+ if (soundIdChanged)
+ {
+ mOutput->finishSound(mNearWaterSound);
+ mNearWaterSound = playSound(soundId, volume, 1.0f, Play_TypeSfx, Play_Loop);
+ }
+ else if (sfx)
+ mNearWaterSound->setVolume(volume * sfx->mVolume);
+ }
+ }
+ else if (volume > 0.0f)
+ mNearWaterSound = playSound(soundId, volume, 1.0f, Play_TypeSfx, Play_Loop);
+ }
+
void SoundManager::updateSounds(float duration)
{
static float timePassed = 0.0;
@@ -941,6 +1039,7 @@ namespace MWSound
{
updateSounds(duration);
updateRegionSound(duration);
+ updateWaterSound(duration);
}
}
@@ -1105,6 +1204,7 @@ namespace MWSound
mOutput->finishStream(*trkiter);
mActiveTracks.clear();
mUnderwaterSound.reset();
+ mNearWaterSound.reset();
stopMusic();
}
}
diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp
index d499dce..abf5edb 100644
--- a/apps/openmw/mwsound/soundmanagerimp.hpp
+++ b/apps/openmw/mwsound/soundmanagerimp.hpp
@@ -11,6 +11,8 @@
#include <components/settings/settings.hpp>
+#include <components/fallback/fallback.hpp>
+
#include "../mwbase/soundmanager.hpp"
namespace VFS
@@ -44,6 +46,8 @@ namespace MWSound
{
const VFS::Manager* mVFS;
+ Fallback::Map mFallback;
+
std::auto_ptr<Sound_Output> mOutput;
// Caches available music tracks by <playlist name, (sound files) >
@@ -56,6 +60,13 @@ namespace MWSound
float mVoiceVolume;
float mFootstepsVolume;
+ int mNearWaterRadius;
+ int mNearWaterPoints;
+ float mNearWaterIndoorTolerance;
+ float mNearWaterOutdoorTolerance;
+ std::string mNearWaterIndoorID;
+ std::string mNearWaterOutdoorID;
+
typedef std::auto_ptr<std::deque<Sound_Buffer> > SoundBufferList;
// List of sound buffers, grown as needed. New enties are added to the
// back, allowing existing Sound_Buffer references/pointers to remain
@@ -94,6 +105,7 @@ namespace MWSound
int mPausedSoundTypes;
MWBase::SoundPtr mUnderwaterSound;
+ MWBase::SoundPtr mNearWaterSound;
Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound);
@@ -108,6 +120,7 @@ namespace MWSound
void streamMusicFull(const std::string& filename);
void updateSounds(float duration);
void updateRegionSound(float duration);
+ void updateWaterSound(float duration);
float volumeFromType(PlayType type) const;
@@ -119,7 +132,7 @@ namespace MWSound
friend class OpenAL_Output;
public:
- SoundManager(const VFS::Manager* vfs, bool useSound);
+ SoundManager(const VFS::Manager* vfs, const std::map<std::string, std::string>& fallbackMap, bool useSound);
virtual ~SoundManager();
virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp
index 0d81e06..72ee56e 100644
--- a/apps/openmw/mwworld/cellref.cpp
+++ b/apps/openmw/mwworld/cellref.cpp
@@ -93,6 +93,24 @@ namespace MWWorld
}
}
+ void CellRef::applyChargeRemainderToBeSubtracted(float chargeRemainder)
+ {
+ mCellRef.mChargeIntRemainder += std::abs(chargeRemainder);
+ if (mCellRef.mChargeIntRemainder > 1.0f)
+ {
+ float newChargeRemainder = (mCellRef.mChargeIntRemainder - std::floor(mCellRef.mChargeIntRemainder));
+ if (mCellRef.mChargeInt <= static_cast<int>(mCellRef.mChargeIntRemainder))
+ {
+ mCellRef.mChargeInt = 0;
+ }
+ else
+ {
+ mCellRef.mChargeInt -= static_cast<int>(mCellRef.mChargeIntRemainder);
+ }
+ mCellRef.mChargeIntRemainder = newChargeRemainder;
+ }
+ }
+
float CellRef::getChargeFloat() const
{
return mCellRef.mChargeFloat;
diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp
index b8e85f2..7e27e6e 100644
--- a/apps/openmw/mwworld/cellref.hpp
+++ b/apps/openmw/mwworld/cellref.hpp
@@ -65,6 +65,7 @@ namespace MWWorld
float getChargeFloat() const; // Implemented as union with int charge
void setCharge(int charge);
void setChargeFloat(float charge);
+ void applyChargeRemainderToBeSubtracted(float chargeRemainder); // Stores remainders and applies if > 1
// The NPC that owns this object (and will get angry if you steal it)
std::string getOwner() const;
diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp
index c683f7e..48270d2 100644
--- a/apps/openmw/mwworld/manualref.cpp
+++ b/apps/openmw/mwworld/manualref.cpp
@@ -16,6 +16,7 @@ namespace
cellRef.mScale = 1;
cellRef.mFactionRank = 0;
cellRef.mChargeInt = -1;
+ cellRef.mChargeIntRemainder = 0.0f;
cellRef.mGoldValue = 1;
cellRef.mEnchantmentCharge = -1;
cellRef.mTeleport = false;
diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp
index 35df52a..4d34233 100644
--- a/apps/openmw/mwworld/projectilemanager.cpp
+++ b/apps/openmw/mwworld/projectilemanager.cpp
@@ -93,6 +93,31 @@ namespace
}
return projectileEffects;
}
+
+ osg::Vec4 getMagicBoltLightDiffuseColor(const ESM::EffectList& effects)
+ {
+ // Calculate combined light diffuse color from magical effects
+ osg::Vec4 lightDiffuseColor;
+ float lightDiffuseRed = 0.0f;
+ float lightDiffuseGreen = 0.0f;
+ float lightDiffuseBlue = 0.0f;
+ for (std::vector<ESM::ENAMstruct>::const_iterator iter(effects.mList.begin());
+ iter != effects.mList.end(); ++iter)
+ {
+ const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
+ iter->mEffectID);
+ lightDiffuseRed += (static_cast<float>(magicEffect->mData.mRed) / 255.f);
+ lightDiffuseGreen += (static_cast<float>(magicEffect->mData.mGreen) / 255.f);
+ lightDiffuseBlue += (static_cast<float>(magicEffect->mData.mBlue) / 255.f);
+ }
+ int numberOfEffects = effects.mList.size();
+ lightDiffuseColor = osg::Vec4(lightDiffuseRed / numberOfEffects
+ , lightDiffuseGreen / numberOfEffects
+ , lightDiffuseBlue / numberOfEffects
+ , 1.0f);
+
+ return lightDiffuseColor;
+ }
}
namespace MWWorld
@@ -136,7 +161,8 @@ namespace MWWorld
};
- void ProjectileManager::createModel(State &state, const std::string &model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate, std::string texture)
+ void ProjectileManager::createModel(State &state, const std::string &model, const osg::Vec3f& pos, const osg::Quat& orient,
+ bool rotate, bool createLight, osg::Vec4 lightDiffuseColor, std::string texture)
{
state.mNode = new osg::PositionAttitudeTransform;
state.mNode->setNodeMask(MWRender::Mask_Effect);
@@ -167,6 +193,25 @@ namespace MWWorld
mResourceSystem->getSceneManager()->getInstance("meshes\\" + weapon->mModel, findVisitor.mFoundNode);
}
+ if (createLight)
+ {
+ osg::ref_ptr<osg::Light> projectileLight(new osg::Light);
+ projectileLight->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ projectileLight->setDiffuse(lightDiffuseColor);
+ projectileLight->setSpecular(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ projectileLight->setConstantAttenuation(0.f);
+ projectileLight->setLinearAttenuation(0.1f);
+ projectileLight->setQuadraticAttenuation(0.f);
+ projectileLight->setPosition(osg::Vec4(pos, 1.0));
+
+ SceneUtil::LightSource* projectileLightSource = new SceneUtil::LightSource;
+ projectileLightSource->setNodeMask(MWRender::Mask_Lighting);
+ projectileLightSource->setRadius(66.f);
+
+ state.mNode->addChild(projectileLightSource);
+ projectileLightSource->setLight(projectileLight);
+ }
+
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
state.mNode->accept(disableFreezeOnCullVisitor);
@@ -229,7 +274,8 @@ namespace MWWorld
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), state.mIdMagic.at(0));
MWWorld::Ptr ptr = ref.getPtr();
- createModel(state, ptr.getClass().getModel(ptr), pos, orient, true, texture);
+ osg::Vec4 lightDiffuseColor = getMagicBoltLightDiffuseColor(effects);
+ createModel(state, ptr.getClass().getModel(ptr), pos, orient, true, true, lightDiffuseColor, texture);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
for (size_t it = 0; it != state.mSoundIds.size(); it++)
@@ -253,7 +299,7 @@ namespace MWWorld
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().getRefId());
MWWorld::Ptr ptr = ref.getPtr();
- createModel(state, ptr.getClass().getModel(ptr), pos, orient, false);
+ createModel(state, ptr.getClass().getModel(ptr), pos, orient, false, false, osg::Vec4(0,0,0,0));
mProjectiles.push_back(state);
}
@@ -483,7 +529,7 @@ namespace MWWorld
return true;
}
- createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), false);
+ createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), false, false, osg::Vec4(0,0,0,0));
mProjectiles.push_back(state);
return true;
@@ -518,7 +564,8 @@ namespace MWWorld
return true;
}
- createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, texture);
+ osg::Vec4 lightDiffuseColor = getMagicBoltLightDiffuseColor(esm.mEffects);
+ createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, true, lightDiffuseColor, texture);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp
index a8769fc..2289706 100644
--- a/apps/openmw/mwworld/projectilemanager.hpp
+++ b/apps/openmw/mwworld/projectilemanager.hpp
@@ -122,7 +122,8 @@ namespace MWWorld
void moveProjectiles(float dt);
void moveMagicBolts(float dt);
- void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate, std::string texture = "");
+ void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient,
+ bool rotate, bool createLight, osg::Vec4 lightDiffuseColor, std::string texture = "");
void update (State& state, float duration);
void operator=(const ProjectileManager&);
diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp
index 7111edd..48ab118 100644
--- a/apps/openmw/mwworld/weather.cpp
+++ b/apps/openmw/mwworld/weather.cpp
@@ -1069,7 +1069,7 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
mResult.mSunDiscColor = lerp(osg::Vec4f(1,1,1,1), current.mSunDiscSunsetColor, factor);
// The SunDiscSunsetColor in the INI isn't exactly the resulting color on screen, most likely because
// MW applied the color to the ambient term as well. After the ambient and emissive terms are added together, the fixed pipeline
- // would then clamp the total lighting to (1,1,1). A noticable change in color tone can be observed when only one of the color components gets clamped.
+ // would then clamp the total lighting to (1,1,1). A noticeable change in color tone can be observed when only one of the color components gets clamped.
// Unfortunately that means we can't use the INI color as is, have to replicate the above nonsense.
mResult.mSunDiscColor = mResult.mSunDiscColor + osg::componentMultiply(mResult.mSunDiscColor, mResult.mAmbientColor);
for (int i=0; i<3; ++i)
diff --git a/apps/wizard/inisettings.cpp b/apps/wizard/inisettings.cpp
index 3711ba0..2367f5c 100644
--- a/apps/wizard/inisettings.cpp
+++ b/apps/wizard/inisettings.cpp
@@ -198,8 +198,8 @@ bool Wizard::IniSettings::parseInx(const QString &path)
const QString section(array.left(index));
// Figure how many characters to read for the key
- int lenght = array.indexOf("\x06", section.length() + 3) - (section.length() + 3);
- const QString key(array.mid(section.length() + 3, lenght));
+ int length = array.indexOf("\x06", section.length() + 3) - (section.length() + 3);
+ const QString key(array.mid(section.length() + 3, length));
QString value(array.mid(section.length() + key.length() + 6));
diff --git a/apps/wizard/main.cpp b/apps/wizard/main.cpp
index c861a4a..e362474 100644
--- a/apps/wizard/main.cpp
+++ b/apps/wizard/main.cpp
@@ -20,12 +20,6 @@ int main(int argc, char *argv[])
QDir dir(QCoreApplication::applicationDirPath());
#ifdef Q_OS_MAC
- if (dir.dirName() == "MacOS") {
- dir.cdUp();
- dir.cdUp();
- dir.cdUp();
- }
-
// force Qt to load only LOCAL plugins, don't touch system Qt installation
QDir pluginsPath(QCoreApplication::applicationDirPath());
pluginsPath.cdUp();
diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp
index 74d45bb..e41201d 100644
--- a/components/esm/cellref.cpp
+++ b/components/esm/cellref.cpp
@@ -196,6 +196,7 @@ void ESM::CellRef::blank()
mFaction.clear();
mFactionRank = -2;
mChargeInt = -1;
+ mChargeIntRemainder = 0.0f;
mEnchantmentCharge = -1;
mGoldValue = 0;
mDestCell.clear();
diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp
index 3c646cc..f146175 100644
--- a/components/esm/cellref.hpp
+++ b/components/esm/cellref.hpp
@@ -69,6 +69,7 @@ namespace ESM
int mChargeInt; // Used by everything except lights
float mChargeFloat; // Used only by lights
};
+ float mChargeIntRemainder; // Stores amount of charge not subtracted from mChargeInt
// Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full).
float mEnchantmentCharge;
diff --git a/components/files/macospath.cpp b/components/files/macospath.cpp
index 2371419..b49b72e 100644
--- a/components/files/macospath.cpp
+++ b/components/files/macospath.cpp
@@ -68,7 +68,7 @@ boost::filesystem::path MacOsPath::getCachePath() const
boost::filesystem::path MacOsPath::getLocalPath() const
{
- return boost::filesystem::path("./");
+ return boost::filesystem::path("../Resources/");
}
boost::filesystem::path MacOsPath::getGlobalDataPath() const
diff --git a/components/nif/controlled.cpp b/components/nif/controlled.cpp
index 5c63094..52e7a73 100644
--- a/components/nif/controlled.cpp
+++ b/components/nif/controlled.cpp
@@ -87,6 +87,15 @@ namespace Nif
nif->skip(17);
}
+ void NiSphericalCollider::read(NIFStream* nif)
+ {
+ Controlled::read(nif);
+
+ mBounceFactor = nif->getFloat();
+ mRadius = nif->getFloat();
+ mCenter = nif->getVector3();
+ }
+
diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp
index 4bd7ce1..5601474 100644
--- a/components/nif/controlled.hpp
+++ b/components/nif/controlled.hpp
@@ -111,6 +111,16 @@ public:
float mPlaneDistance;
};
+class NiSphericalCollider : public Controlled
+{
+public:
+ float mBounceFactor;
+ float mRadius;
+ osg::Vec3f mCenter;
+
+ void read(NIFStream *nif);
+};
+
class NiParticleRotation : public Controlled
{
public:
diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp
index f6e4895..b4b1cae 100644
--- a/components/nif/niffile.cpp
+++ b/components/nif/niffile.cpp
@@ -89,6 +89,7 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
newFactory.insert(makeEntry("NiStringExtraData", &construct <NiStringExtraData> , RC_NiStringExtraData ));
newFactory.insert(makeEntry("NiGravity", &construct <NiGravity> , RC_NiGravity ));
newFactory.insert(makeEntry("NiPlanarCollider", &construct <NiPlanarCollider> , RC_NiPlanarCollider ));
+ newFactory.insert(makeEntry("NiSphericalCollider", &construct <NiSphericalCollider> , RC_NiSphericalCollider ));
newFactory.insert(makeEntry("NiParticleGrowFade", &construct <NiParticleGrowFade> , RC_NiParticleGrowFade ));
newFactory.insert(makeEntry("NiParticleColorModifier", &construct <NiParticleColorModifier> , RC_NiParticleColorModifier ));
newFactory.insert(makeEntry("NiParticleRotation", &construct <NiParticleRotation> , RC_NiParticleRotation ));
diff --git a/components/nif/record.hpp b/components/nif/record.hpp
index bcbdba1..605c4d7 100644
--- a/components/nif/record.hpp
+++ b/components/nif/record.hpp
@@ -92,7 +92,8 @@ enum RecordType
RC_NiSequenceStreamHelper,
RC_NiSourceTexture,
RC_NiSkinInstance,
- RC_RootCollisionNode
+ RC_RootCollisionNode,
+ RC_NiSphericalCollider
};
/// Base class for all records
diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp
index 70ca828..d4dabd2 100644
--- a/components/nifosg/nifloader.cpp
+++ b/components/nifosg/nifloader.cpp
@@ -871,6 +871,13 @@ namespace NifOsg
const Nif::NiPlanarCollider* planarcollider = static_cast<const Nif::NiPlanarCollider*>(colliders.getPtr());
program->addOperator(new PlanarCollider(planarcollider));
}
+ else if (colliders->recType == Nif::RC_NiSphericalCollider)
+ {
+ const Nif::NiSphericalCollider* sphericalcollider = static_cast<const Nif::NiSphericalCollider*>(colliders.getPtr());
+ program->addOperator(new SphericalCollider(sphericalcollider));
+ }
+ else
+ std::cerr << "Unhandled particle collider " << colliders->recName << " in " << mFilename << std::endl;
}
}
diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp
index f542cf3..0259b27 100644
--- a/components/nifosg/particle.cpp
+++ b/components/nifosg/particle.cpp
@@ -376,4 +376,73 @@ void PlanarCollider::operate(osgParticle::Particle *particle, double dt)
}
}
+SphericalCollider::SphericalCollider(const Nif::NiSphericalCollider* collider)
+ : mBounceFactor(collider->mBounceFactor),
+ mSphere(collider->mCenter, collider->mRadius)
+{
+}
+
+SphericalCollider::SphericalCollider()
+ : mBounceFactor(1.0f)
+{
+
+}
+
+SphericalCollider::SphericalCollider(const SphericalCollider& copy, const osg::CopyOp& copyop)
+ : osgParticle::Operator(copy, copyop)
+ , mBounceFactor(copy.mBounceFactor)
+ , mSphere(copy.mSphere)
+ , mSphereInParticleSpace(copy.mSphereInParticleSpace)
+{
+
+}
+
+void SphericalCollider::beginOperate(osgParticle::Program* program)
+{
+ mSphereInParticleSpace = mSphere;
+ if (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF)
+ mSphereInParticleSpace.center() = program->transformLocalToWorld(mSphereInParticleSpace.center());
+}
+
+void SphericalCollider::operate(osgParticle::Particle* particle, double dt)
+{
+ osg::Vec3f cent = (particle->getPosition() - mSphereInParticleSpace.center()); // vector from sphere center to particle
+
+ bool insideSphere = cent.length2() <= mSphereInParticleSpace.radius2();
+
+ if (insideSphere
+ || (cent * particle->getVelocity() < 0.0f)) // if outside, make sure the particle is flying towards the sphere
+ {
+ // Collision test (finding point of contact) is performed by solving a quadratic equation:
+ // ||vec(cent) + vec(vel)*k|| = R /^2
+ // k^2 + 2*k*(vec(cent)*vec(vel))/||vec(vel)||^2 + (||vec(cent)||^2 - R^2)/||vec(vel)||^2 = 0
+
+ float b = -(cent * particle->getVelocity()) / particle->getVelocity().length2();
+
+ osg::Vec3f u = cent + particle->getVelocity() * b;
+
+ if (insideSphere
+ || (u.length2() < mSphereInParticleSpace.radius2()))
+ {
+ float d = (mSphereInParticleSpace.radius2() - u.length2()) / particle->getVelocity().length2();
+ float k = insideSphere ? (std::sqrt(d) + b) : (b - std::sqrt(d));
+
+ if (k < dt)
+ {
+ // collision detected; reflect off the tangent plane
+ osg::Vec3f contact = particle->getPosition() + particle->getVelocity() * k;
+
+ osg::Vec3 normal = (contact - mSphereInParticleSpace.center());
+ normal.normalize();
+
+ float dotproduct = particle->getVelocity() * normal;
+
+ osg::Vec3 reflectedVelocity = particle->getVelocity() - normal * (2 * dotproduct);
+ reflectedVelocity *= mBounceFactor;
+ particle->setVelocity(reflectedVelocity);
+ }
+ }
+ }
+}
+
}
diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp
index 6818aa7..f9c4abd 100644
--- a/components/nifosg/particle.hpp
+++ b/components/nifosg/particle.hpp
@@ -16,6 +16,7 @@ namespace Nif
{
class NiGravity;
class NiPlanarCollider;
+ class NiSphericalCollider;
class NiColorData;
}
@@ -110,6 +111,23 @@ namespace NifOsg
osg::Plane mPlaneInParticleSpace;
};
+ class SphericalCollider : public osgParticle::Operator
+ {
+ public:
+ SphericalCollider(const Nif::NiSphericalCollider* collider);
+ SphericalCollider();
+ SphericalCollider(const SphericalCollider& copy, const osg::CopyOp& copyop);
+
+ META_Object(NifOsg, SphericalCollider)
+
+ virtual void beginOperate(osgParticle::Program* program);
+ virtual void operate(osgParticle::Particle* particle, double dt);
+ private:
+ float mBounceFactor;
+ osg::BoundingSphere mSphere;
+ osg::BoundingSphere mSphereInParticleSpace;
+ };
+
class GrowFadeAffector : public osgParticle::Operator
{
public:
diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp
index 3af5176..297dc69 100644
--- a/components/sceneutil/riggeometry.cpp
+++ b/components/sceneutil/riggeometry.cpp
@@ -120,13 +120,17 @@ void RigGeometry::setSourceGeometry(osg::ref_ptr<osg::Geometry> sourceGeometry)
setVertexArray(vertexArray);
}
- osg::ref_ptr<osg::Array> normalArray = osg::clone(from.getNormalArray(), osg::CopyOp::DEEP_COPY_ALL);
- if (normalArray)
+ if (osg::Array* normals = from.getNormalArray())
{
- normalArray->setVertexBufferObject(vbo);
- setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);
+ osg::ref_ptr<osg::Array> normalArray = osg::clone(normals, osg::CopyOp::DEEP_COPY_ALL);
+ if (normalArray)
+ {
+ normalArray->setVertexBufferObject(vbo);
+ setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);
+ }
}
+
if (osg::Vec4Array* tangents = dynamic_cast<osg::Vec4Array*>(from.getTexCoordArray(7)))
{
mSourceTangents = tangents;
@@ -273,7 +277,8 @@ void RigGeometry::update(osg::NodeVisitor* nv)
{
unsigned short vertex = *vertexIt;
(*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]);
- (*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat);
+ if (normalDst)
+ (*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat);
if (tangentDst)
{
osg::Vec4f srcTangent = (*tangentSrc)[vertex];
@@ -284,7 +289,8 @@ void RigGeometry::update(osg::NodeVisitor* nv)
}
positionDst->dirty();
- normalDst->dirty();
+ if (normalDst)
+ normalDst->dirty();
if (tangentDst)
tangentDst->dirty();
}
diff --git a/components/sdlutil/sdlinputwrapper.cpp b/components/sdlutil/sdlinputwrapper.cpp
index 647a650..6482f37 100644
--- a/components/sdlutil/sdlinputwrapper.cpp
+++ b/components/sdlutil/sdlinputwrapper.cpp
@@ -103,6 +103,8 @@ InputWrapper::InputWrapper(SDL_Window* window, osg::ref_ptr<osgViewer::Viewer> v
mViewer->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_F3);
break;
+ case SDL_TEXTEDITING:
+ break;
case SDL_TEXTINPUT:
mKeyboardListener->textInput(evt.text);
break;
diff --git a/docs/source/openmw-cs/tour.rst b/docs/source/openmw-cs/tour.rst
index 3ddeac4..9844948 100644
--- a/docs/source/openmw-cs/tour.rst
+++ b/docs/source/openmw-cs/tour.rst
@@ -3,9 +3,9 @@ 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 don't need prior knowledge about modding
-Morrowind, but you should be familiar with the game itself. There will be no
-scripting necessary, we chan achieve everything using just what the base game
+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
installed and playable.
@@ -13,7 +13,7 @@ installed and playable.
Adding the ring to the game's records
*************************************
-In this first section we will define what our new ring is, what it looks like
+In this first section we will define what our new ring is, what it looks like,
and what it does. Getting it to work is the first step before we go further.
@@ -28,11 +28,11 @@ options: create a new game, create a new addon, edit a content file.
:alt: Opening dialogue with three option and setting button (the wrench)
The first option is for creating an entirely new game, that's not what we want.
-We want to edit an existing game, so choose the second one. When you save your
+We want to edit an existing game, so choose the second option. When you save your
addon you can use the third option to open it again.
-You will be presented with another window where you get to chose the content to
-edit and the name of your project. We have to chose at least a base game, and
+You will be presented with another window where you get to choose the content to
+edit and the name of your project. Then we have to select at least the base game and
optionally a number of other addons we want to depend on. The name of the
project is arbitrary, it will be used to identify the addon later in the OpenMW
launcher.
@@ -41,7 +41,7 @@ launcher.
:alt: Creation dialogue for a new project, pick content modules and name
Choose Morrowind as your content file and enter `Ring of Night Vision` as the
-name. We could also chose further content files as dependencies if we wanted
+name. We could also choose further content files as dependencies if we wanted
to, but for this mod the base game is enough.
Once the addon has been created you will be presented with a table. If you see
@@ -67,7 +67,7 @@ of the table are the attributes of each object.
Morrowind uses something called a *relational database* for game data. If you
are not familiar with the term, it means that every type of thing can be
expressed as a *table*: there is a table for objects, a table for enchantments,
-a table for icons, one for meshes, and so on. Properties of an entry must be
+a table for icons, one for meshes and so on. Properties of an entry must be
simple values, like numbers or text strings. If we want a more complicated
property we need to reference an entry from another table. There are a few
exceptions to this though, some tables do have subtables. The effects of
@@ -95,7 +95,7 @@ holding Shift to edit it (this is a configurable shortcut), but there is a
better way: right-click the row of our new record and chose *Edit Record*, a
new panel will open.
-We can right-click the row of our new record and chose *Edit Record*, a
+We can right-click the row of our new record and select *Edit Record*, a
new panel will open. Alternatively we can also define a configurable shortcut
instead of using the context menu; the default is double-clicking while
holding down the shift key.
diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt
index 7494d3b..6592de5 100644
--- a/files/mygui/CMakeLists.txt
+++ b/files/mygui/CMakeLists.txt
@@ -1,6 +1,10 @@
+if (NOT DEFINED OPENMW_MYGUI_FILES_ROOT)
+ return()
+endif()
+
# Copy resource files into the build directory
set(SDIR ${CMAKE_CURRENT_SOURCE_DIR})
-set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui)
+set(DDIR ${OPENMW_MYGUI_FILES_ROOT}/resources/mygui)
set(MYGUI_FILES
core.skin
diff --git a/files/settings-default.cfg b/files/settings-default.cfg
index 9813cb1..e17f023 100644
--- a/files/settings-default.cfg
+++ b/files/settings-default.cfg
@@ -188,13 +188,13 @@ clamp lighting = true
# If this option is enabled, normal maps are automatically recognized and used if they are named appropriately
# (see 'normal map pattern', e.g. for a base texture foo.dds, the normal map texture would have to be named foo_n.dds).
-# If this option is disabled, normal maps are only used if they are explicitely listed within the mesh file (.nif or .osg file).
+# If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file).
# Affects objects.
auto use object normal maps = false
# If this option is enabled, specular maps are automatically recognized and used if they are named appropriately
# (see 'specular map pattern', e.g. for a base texture foo.dds, the specular map texture would have to be named foo_spec.dds).
-# If this option is disabled, normal maps are only used if they are explicitely listed within the mesh file (.osg file, not supported in .nif files).
+# If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.osg file, not supported in .nif files).
# Affects objects.
auto use object specular maps = false
diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt
index 0738b57..5ca0d1e 100644
--- a/files/shaders/CMakeLists.txt
+++ b/files/shaders/CMakeLists.txt
@@ -1,6 +1,10 @@
+if (NOT DEFINED OPENMW_SHADERS_ROOT)
+ return()
+endif()
+
# Copy resource files into the build directory
set(SDIR ${CMAKE_CURRENT_SOURCE_DIR})
-set(DDIR ${OpenMW_BINARY_DIR}/resources/shaders)
+set(DDIR ${OPENMW_SHADERS_ROOT}/resources/shaders)
set(SHADER_FILES
water_vertex.glsl