1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-28 19:21:04 +00:00

restarting

This commit is contained in:
Jason Hooks 2012-03-19 19:38:44 -04:00
commit ed7cb1dc67
312 changed files with 20051 additions and 562 deletions

6
.gitmodules vendored

@ -1,6 +0,0 @@
[submodule "libs/mangle"]
path = libs/mangle
url = git://github.com/zinnschlag/mangle.git
[submodule "libs/openengine"]
path = libs/openengine
url = git://github.com/zinnschlag/OpenEngine

@ -18,7 +18,7 @@ include (OpenMWMacros)
# Version # Version
set (OPENMW_VERSION_MAJOR 0) set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 12) set (OPENMW_VERSION_MINOR 13)
set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -27,6 +27,8 @@ set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VE
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp") configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
# Sound source selection # Sound source selection
option(USE_AUDIERE "use Audiere for sound" OFF) option(USE_AUDIERE "use Audiere for sound" OFF)
option(USE_FFMPEG "use ffmpeg for sound" OFF) option(USE_FFMPEG "use ffmpeg for sound" OFF)
@ -116,6 +118,10 @@ set(OENGINE_BULLET
${LIBDIR}/openengine/bullet/physic.hpp ${LIBDIR}/openengine/bullet/physic.hpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp ${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.h ${LIBDIR}/openengine/bullet/BulletShapeLoader.h
${LIBDIR}/openengine/bullet/pmove.h
${LIBDIR}/openengine/bullet/pmove.cpp
${LIBDIR}/openengine/bullet/trace.h
${LIBDIR}/openengine/bullet/trace.cpp
) )
# Sound setup # Sound setup
@ -189,8 +195,16 @@ find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
find_package(OIS REQUIRED) find_package(OIS REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet REQUIRED) find_package(Bullet REQUIRED)
IF(OGRE_STATIC)
find_package(Cg REQUIRED)
IF(WIN32)
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
ELSE(WIN32)
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
ENDIF(WIN32)
ENDIF(OGRE_STATIC)
include_directories("." include_directories("."
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS}
${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}
${PLATFORM_INCLUDE_DIR} ${PLATFORM_INCLUDE_DIR}
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include ${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include
@ -255,6 +269,13 @@ if (APPLE)
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
# prepare plugins # prepare plugins
if (${CMAKE_BUILD_TYPE} MATCHES "Release" OR
${CMAKE_BUILD_TYPE} MATCHES "RelWithDebugInfo")
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
else()
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG})
endif()
foreach(plugin ${USED_OGRE_PLUGINS}) foreach(plugin ${USED_OGRE_PLUGINS})
configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib" configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib"
"${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib" "${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib"
@ -265,8 +286,7 @@ endif (APPLE)
# Compiler settings # Compiler settings
if (CMAKE_COMPILER_IS_GNUCC) if (CMAKE_COMPILER_IS_GNUCC)
#add_definitions (-Wall -Werror) add_definitions (-Wall -Wextra -Wno-unused-parameter -Wno-unused-but-set-parameter -Wno-reorder)
add_definitions (-Wall)
endif (CMAKE_COMPILER_IS_GNUCC) endif (CMAKE_COMPILER_IS_GNUCC)
if(DPKG_PROGRAM) if(DPKG_PROGRAM)
@ -405,6 +425,47 @@ if (WIN32)
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE")
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE")
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE")
# Play a bit with the warning levels
set(WARNINGS "/Wall") # Since windows can only disable specific warnings, not enable them
set(WARNINGS_DISABLE
# Warnings that aren't enabled normally and don't need to be enabled
# They're unneeded and sometimes completely retarded warnings that /Wall enables
# Not going to bother commenting them as they tend to warn on every standard library files
4061 4263 4264 4266 4350 4514 4548 4571 4610 4619 4623 4625 4626 4628 4640 4668 4710 4711 4820 4826 4917 4946
# Warnings that are thrown on standard libraries and not OpenMW
4347 # Non-template function with same name and parameter count as template function
4365 # Variable signed/unsigned mismatch
4510 4512 # Unable to generate copy constructor/assignment operator as it's not public in the base
4706 # Assignment in conditional expression
4738 # Storing 32-bit float result in memory, possible loss of performance
4986 # Undocumented warning that occurs in the crtdbg.h file
4996 # Function was declared deprecated
# OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type
4100 # Unreferenced formal parameter (-Wunused-parameter)
4127 # Conditional expression is constant
4242 # Storing value in a variable of a smaller type, possible loss of data
4244 # Storing value of one type in variable of another (size_t in int, for example)
4305 # Truncating value (double to float, for example)
4309 # Variable overflow, trying to store 128 in a signed char for example
4355 # Using 'this' in member initialization list
4701 # Potentially uninitialized local variable used
)
foreach(d ${WARNINGS_DISABLE})
set(WARNINGS "${WARNINGS} /wd${d}")
endforeach(d)
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
if (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif(MSVC) endif(MSVC)
# Same for MinGW # Same for MinGW

@ -1,46 +1,30 @@
NOTE: This README is for ardekantur's Mac branch of OpenMW. A README #Getting OpenMW Working on OS X
for the main branch has yet to be written. If you want to submit one,
please send me a message!
OpenMW ## Initial setup
====== First of all, clone OpenMW repo.
From the [official website][]: $ git clone github.com/zinnschlag/openmw
> OpenMW is an attempt to reimplement the popular role playing game Or use your github url if you forked.
Morrowind. It aims to be a fully playable, open source
implementation of the game. You must own Morrowind to use OpenMW.
About dependencies: I prefer not to install them globally (i. e. in /usr/local/), so I'm installing them in directory in my home directory. If OpenMW sources is in $HOME/path/openmw, I'm using $HOME/path/libs/root as prefix for boost and other libs.
About This Project It's useful to create env var for lib install prefix:
------------------
This specific repository is a branch of OpenMW intended to keep pace $ export OMW_LIB_PREFIX=$HOME/path/libs/root`
with development of the project in order to provide a Mac build for
interested parties to contribute. This is not an official, sanctioned
branch of the OpenMW project. I will only be able to answer specific
questions about getting this project running on Mac OS X, **no other
platform**. I will not even be able to guarantee my changes maintain
backwards compatibility against builds in other operating systems. You
have been warned.
Most of libs can be installed from [Homebrew][homebrew]. Only mpg123 needs to be installed from source (due to lack of universal compilation support). I think that some of libs can be installed from MacPorts or Fink too.
Getting OpenMW Working As OpenMW currently only supports i386 architecture on OS X, denendencies also should support it. Set some env vars in current terminal:
----------------------
1. Clone this repository.
2. Note about libs: I prefer not to install them globally (i. e. in /usr/local/), so I installing them in directory in my home directory. If OpenMW sources is in $HOME/path/openmw, I'm using $HOME/path/libs/root as prefix for boost and other libs.
It's useful to create env var for lib install prefix:
$ export OMW_LIB_PREFIX=$HOME/path/libs/root
3. First of all, set for current terminal some env vars:
$ export CFLAGS="-arch i386" $ export CFLAGS="-arch i386"
$ export CXXFLAGS="-arch i386" $ export CXXFLAGS="-arch i386"
$ export LDFLAGS="-arch i386" $ export LDFLAGS="-arch i386"
All libs will build with correct architecture.
If you close your terminal, you should set env vars again before pcoceeding to next steps!
4. Download [boost][] (tested with 1.45) and install it with the following command: If you close your terminal, you should set env vars again before pcoceeding to next steps!
## Boost
Download [boost][boost] and install it with the following command:
$ cd /path/to/boost/source $ cd /path/to/boost/source
$ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX $ ./bootstrap.sh --prefix=$OMW_LIB_PREFIX
@ -49,32 +33,47 @@ Getting OpenMW Working
--link-shared,static --prefix=$OMW_LIB_PREFIX install --link-shared,static --prefix=$OMW_LIB_PREFIX install
5. Download [Ogre][] SDK (tested with 1.7.2), unpack it and move Alternatively you can install boost with homebrew:
`lib/Release/Ogre.framework` into `Library/Frameworks`.
6. Download [OIS][] and use the XCode project provided in $ brew install boost --universal
`ois/Mac/XCode-2.2`. Be sure to set your build architecture to
`i386` and your SDK platform to either 10.5 or 10.6. Once it I think MacPorts also should support universal build for boost.
builds, move `ois/Mac/XCode-2.2/build/Debug/OIS.framework` to
`/Library/Frameworks`. ## Ogre
Download [Ogre][] SDK (tested with 1.7.3), unpack it somewhere and move
`lib/Release/Ogre.framework` into `/Library/Frameworks`.
## OIS
Download patched [OIS][] and use the XCode project provided. Be sure to set your build architecture to
`i386`. Once it built, locate built OIS.framework with Xcode and move it to `/Library/Frameworks`.
## mpg123
Download [MPG 123][mpg123] and build it:
7. Download [mpg123][] and build it:
$ cd /path/to/mpg123/source $ cd /path/to/mpg123/source
$ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \ $ ./configure --prefix=$OMW_LIB_PREFIX --disable-debug \
--disable-dependency-tracking \ --disable-dependency-tracking \
--with-optimization=4 \ --with-optimization=4 \
--with-audio=coreaudio \ --with-audio=dummy \
--with-default-audio=coreaudio \ --with-default-audio=dummy \
--with-cpu=sse_alone \ --with-cpu=sse_alone \
$ make install $ make install
8. Download [libsndfile][] and build it: ## libsndfile
Download [libsndfile][] and build it:
$ cd /path/to/libsndfile/source $ cd /path/to/libsndfile/source
$ ./configure --prefix=$OMW_LIB_PREFIX \ $ ./configure --prefix=$OMW_LIB_PREFIX \
--disable-dependency-tracking --disable-dependency-tracking
$ make install $ make install
9. Download [Bullet][] and build it: or install with homebrew:
$ brew install libsndfile --universal
## Bullet
Download [Bullet][] and build it:
$ cd /path/to/bullet/source $ cd /path/to/bullet/source
$ mkdir build $ mkdir build
$ cd build $ cd build
@ -87,12 +86,25 @@ Getting OpenMW Working
-G"Unix Makefiles" ../ -G"Unix Makefiles" ../
$ make install $ make install
10. Generate the Makefile for OpenMW as follows and build OpenMW: or install with homebrew:
$ brew install bullet --HEAD --universal
I prefer head because 2.79 has some issue which causes OpenMW to lag. Also you can edit formula and install 2.77, which is stable and haven't mentioned issue.
## Qt
Install [Qt][qt]. Qt SDK distributed by Nokia is not an option because it's 64 bit only, and OpenMW currently doesn't build for 64 bit on OS X. I'm installing it from Homebrew:
$ brew install qt --universal
## Run CMake
Generate the Makefile for OpenMW as follows and build OpenMW:
$ mkdir /path/to/openmw/build/dir $ mkdir /path/to/openmw/build/dir
$ cd /path/to/open/build/dir $ cd /path/to/open/build/dir
$ cmake \ $ cmake \
-D CMAKE_OSX_ARCHITECTURES=i386 \ -D CMAKE_OSX_ARCHITECTURES=i386 \
-D OGRESDK=/path/to/ogre/sdk \ -D OGRE_SDK=/path/to/ogre/sdk \
-D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \ -D BOOST_INCLUDEDIR=$OMW_LIB_PREFIX/include/boost-1_45 \
-D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \ -D BOOST_LIBRARYDIR=$OMW_LIB_PREFIX/lib \
-D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \ -D SNDFILE_INCLUDE_DIR=$OMW_LIB_PREFIX/include \
@ -106,27 +118,43 @@ Getting OpenMW Working
-D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \ -D BULLET_INCLUDE_DIR=$OMW_LIB_PREFIX/include/bullet/ \
-G "Unix Makefiles" /path/to/openmw/source/dir -G "Unix Makefiles" /path/to/openmw/source/dir
$ make $ make
You can use -G"Xcode" if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles"
if you prefer Eclipse. You also can specify -D CMAKE_BUILD_TYPE=Debug for debug
build.
11. Copy your Morrowind `Data Files` directory into the OpenMW build dir You can use `-G"Xcode"` if you prefer Xcode, or -G"Eclipse CDT4 - Unix Makefiles"
with the name `data` or create symlink: if you prefer Eclipse. You also can specify `-D CMAKE_BUILD_TYPE=Debug` for debug
$ ln -s /path/to/morrowind/data/files /path/to/openmw/build/dir/data build. As for CMake 2.8.7 and Xcode 4.3, Xcode generator is broken. Sadly Eclipse CDT also cannot import generated project at least on my machine.
If all libs installed via homebrew (excluding mpg123), then command would be even simplier:
$ cmake \
-D CMAKE_OSX_ARCHITECTURES="i386" \
-D OGRE_SDK=/path/to/ogre/sdk \
-D MPG123_LIBRARY=$OMW_LIB_PREFIX/lib/libmpg123.a \
-D MPG123_INCLUDE_DIR=$OMW_LIB_PREFIX/include \
-G "Unix Makefiles" /path/to/openmw/source/dir
$ make
Note for users with recent Xcode versions: you must explicitly specify what set of compilers do you use! If not, gcc will be used for C and Clang for C++. Just add this two -D's to command: `-D CMAKE_C_COMPILER=/usr/bin/clang` and `-D CMAKE_CXX_COMPILER=/usr/bin/clang`
Note for Xcode 4.3 users: you should specify full path to used SDK, because current CMake (2.8.7) couldn't find SDKs inside Xcode app bundle:
-D CMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
# Run
From your build directory run:
12. From your build directory run:
$ OpenMW.app/Contents/MacOS/openmw $ OpenMW.app/Contents/MacOS/openmw
or: or:
$ open OpenMW.app $ open OpenMW.app
Enjoy! Enjoy!
[homebrew]: https://github.com/mxcl/homebrew
[boost]: http://www.boost.org [boost]: http://www.boost.org
[Ogre]: http://www.ogre3d.org [Ogre]: http://www.ogre3d.org
[Bullet]: http://bulletphysics.org [Bullet]: http://bulletphysics.org
[OIS]: http://wgois.sf.net [OIS]: https://github.com/corristo/ois-fork
[mpg123]: http://www.mpg123.de [mpg123]: http://www.mpg123.de
[libsndfile]: http://www.mega-nerd.com/libsndfile [libsndfile]: http://www.mega-nerd.com/libsndfile
[official website]: http://openmw.com [official website]: http://openmw.com
[Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/ [Will Thimbleby's Ogre Framework]: http://www.thimbleby.net/ogre/
[qt]: http://qt.nokia.com/

@ -41,10 +41,11 @@ source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC
find_package(Qt4 REQUIRED) find_package(Qt4 REQUIRED)
set(QT_USE_QTGUI 1) set(QT_USE_QTGUI 1)
if (NOT APPLE) # this dependency can be completely removed, but now it only tested on OS X # Set some platform specific settings
find_package(PNG REQUIRED) if(WIN32)
include_directories(${PNG_INCLUDE_DIR}) set(GUI_TYPE WIN32)
endif() set(QT_USE_QTMAIN TRUE)
endif(WIN32)
QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc)
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
@ -52,7 +53,17 @@ QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
include(${QT_USE_FILE}) include(${QT_USE_FILE})
# Main executable # Main executable
IF(OGRE_STATIC)
IF(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
ELSE(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_GL_LIBRARIES})
ENDIF(WIN32)
ENDIF(OGRE_STATIC)
add_executable(omwlauncher add_executable(omwlauncher
${GUI_TYPE}
${LAUNCHER} ${LAUNCHER}
${RCC_SRCS} ${RCC_SRCS}
${MOC_SRCS} ${MOC_SRCS}
@ -61,8 +72,8 @@ add_executable(omwlauncher
target_link_libraries(omwlauncher target_link_libraries(omwlauncher
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${QT_LIBRARIES} ${QT_LIBRARIES}
${PNG_LIBRARY}
components components
) )

@ -9,6 +9,23 @@
#include "pluginsmodel.hpp" #include "pluginsmodel.hpp"
#include "pluginsview.hpp" #include "pluginsview.hpp"
#include <boost/version.hpp>
/**
* Workaround for problems with whitespaces in paths in older versions of Boost library
*/
#if (BOOST_VERSION <= 104600)
namespace boost
{
template<>
inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
{
return boost::filesystem::path(arg);
}
} /* namespace boost */
#endif /* (BOOST_VERSION <= 104600) */
using namespace ESM; using namespace ESM;
using namespace std; using namespace std;

@ -186,7 +186,11 @@ void GraphicsPage::setupOgre()
try try
{ {
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9)
mOgre = new Ogre::Root("", file.fileName().toStdString(), "./launcherOgre.log");
#else
mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log"); mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log");
#endif
} }
catch(Ogre::Exception &ex) catch(Ogre::Exception &ex)
{ {
@ -207,6 +211,15 @@ void GraphicsPage::setupOgre()
return; return;
} }
#ifdef ENABLE_PLUGIN_GL
mGLPlugin = new Ogre::GLPlugin();
mOgre->installPlugin(mGLPlugin);
#endif
#ifdef ENABLE_PLUGIN_Direct3D9
mD3D9Plugin = new Ogre::D3D9Plugin();
mOgre->installPlugin(mD3D9Plugin);
#endif
// Get the available renderers and put them in the combobox // Get the available renderers and put them in the combobox
const Ogre::RenderSystemList &renderers = mOgre->getAvailableRenderers(); const Ogre::RenderSystemList &renderers = mOgre->getAvailableRenderers();

@ -8,6 +8,14 @@
#include <OgreConfigFile.h> #include <OgreConfigFile.h>
#include <OgreConfigDialog.h> #include <OgreConfigDialog.h>
// Static plugin headers
#ifdef ENABLE_PLUGIN_GL
# include "OgreGLPlugin.h"
#endif
#ifdef ENABLE_PLUGIN_Direct3D9
# include "OgreD3D9Plugin.h"
#endif
class QComboBox; class QComboBox;
class QCheckBox; class QCheckBox;
class QStackedWidget; class QStackedWidget;
@ -32,6 +40,12 @@ private:
Ogre::RenderSystem *mSelectedRenderSystem; Ogre::RenderSystem *mSelectedRenderSystem;
Ogre::RenderSystem *mOpenGLRenderSystem; Ogre::RenderSystem *mOpenGLRenderSystem;
Ogre::RenderSystem *mDirect3DRenderSystem; Ogre::RenderSystem *mDirect3DRenderSystem;
#ifdef ENABLE_PLUGIN_GL
Ogre::GLPlugin* mGLPlugin;
#endif
#ifdef ENABLE_PLUGIN_Direct3D9
Ogre::D3D9Plugin* mD3D9Plugin;
#endif
QComboBox *mRendererComboBox; QComboBox *mRendererComboBox;

@ -44,7 +44,7 @@ add_openmw_dir (mwsound
add_openmw_dir (mwworld add_openmw_dir (mwworld
refdata world physicssystem scene environment globals class action nullaction actionteleport refdata world physicssystem scene environment globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellfunctors containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts customdata weather cells localscripts customdata weather inventorystore
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass
@ -57,6 +57,15 @@ add_openmw_dir (mwmechanics
) )
# Main executable # Main executable
IF(OGRE_STATIC)
IF(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_CgProgramManager -DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_Plugin_CgProgramManager_LIBRARIES} ${OGRE_Plugin_OctreeSceneManager_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES} ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
ELSE(WIN32)
ADD_DEFINITIONS(-DENABLE_PLUGIN_CgProgramManager -DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
set(OGRE_STATIC_PLUGINS ${OGRE_Plugin_CgProgramManager_LIBRARIES} ${Cg_LIBRARIES} ${OGRE_Plugin_OctreeSceneManager_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
ENDIF(WIN32)
ENDIF(OGRE_STATIC)
add_executable(openmw add_executable(openmw
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER} ${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
${COMPONENT_FILES} ${COMPONENT_FILES}
@ -72,6 +81,7 @@ add_definitions(${SOUND_DEFINE})
target_link_libraries(openmw target_link_libraries(openmw
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${OIS_LIBRARIES} ${OIS_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPENAL_LIBRARY} ${OPENAL_LIBRARY}

@ -60,7 +60,7 @@ void OMW::Engine::executeLocalScripts()
MWScript::InterpreterContext interpreterContext (mEnvironment, MWScript::InterpreterContext interpreterContext (mEnvironment,
&script.second.getRefData().getLocals(), script.second); &script.second.getRefData().getLocals(), script.second);
mScriptManager->run (script.first, interpreterContext); mEnvironment.mScriptManager->run (script.first, interpreterContext);
if (mEnvironment.mWorld->hasCellChanged()) if (mEnvironment.mWorld->hasCellChanged())
break; break;
@ -182,7 +182,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mCompileAll (false) , mCompileAll (false)
, mReportFocus (false) , mReportFocus (false)
, mFocusTDiff (0) , mFocusTDiff (0)
, mScriptManager (0)
, mScriptContext (0) , mScriptContext (0)
, mFSStrict (false) , mFSStrict (false)
, mCfgMgr(configurationManager) , mCfgMgr(configurationManager)
@ -199,7 +198,7 @@ OMW::Engine::~Engine()
delete mEnvironment.mMechanicsManager; delete mEnvironment.mMechanicsManager;
delete mEnvironment.mDialogueManager; delete mEnvironment.mDialogueManager;
delete mEnvironment.mJournal; delete mEnvironment.mJournal;
delete mScriptManager; delete mEnvironment.mScriptManager;
delete mScriptContext; delete mScriptContext;
delete mOgre; delete mOgre;
} }
@ -348,18 +347,18 @@ void OMW::Engine::go()
mEnvironment); mEnvironment);
mScriptContext->setExtensions (&mExtensions); mScriptContext->setExtensions (&mExtensions);
mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts, mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(),
*mScriptContext); mVerboseScripts, *mScriptContext);
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(), mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
*mScriptManager); *mEnvironment.mScriptManager);
// Create game mechanics system // Create game mechanics system
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment); mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
// Create dialog system // Create dialog system
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment); mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment); mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment,mExtensions);
// load cell // load cell
ESM::Position pos; ESM::Position pos;
@ -393,7 +392,7 @@ void OMW::Engine::go()
// scripts // scripts
if (mCompileAll) if (mCompileAll)
{ {
std::pair<int, int> result = mScriptManager->compileAll(); std::pair<int, int> result = mEnvironment.mScriptManager->compileAll();
if (result.first) if (result.first)
std::cout std::cout
@ -411,6 +410,9 @@ void OMW::Engine::go()
void OMW::Engine::activate() void OMW::Engine::activate()
{ {
if (mEnvironment.mWindowManager->getMode()!=MWGui::GM_Game)
return;
std::string handle = mEnvironment.mWorld->getFacedHandle(); std::string handle = mEnvironment.mWorld->getFacedHandle();
if (handle.empty()) if (handle.empty())
@ -435,7 +437,7 @@ void OMW::Engine::activate()
if (!script.empty()) if (!script.empty())
{ {
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr); mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
mScriptManager->run (script, interpreterContext); mEnvironment.mScriptManager->run (script, interpreterContext);
} }
if (!interpreterContext.hasActivationBeenHandled()) if (!interpreterContext.hasActivationBeenHandled())

@ -78,7 +78,6 @@ namespace OMW
std::string mFocusName; std::string mFocusName;
MWWorld::Environment mEnvironment; MWWorld::Environment mEnvironment;
MWScript::ScriptManager *mScriptManager;
Compiler::Extensions mExtensions; Compiler::Extensions mExtensions;
Compiler::Context *mScriptContext; Compiler::Context *mScriptContext;

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +56,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -71,4 +76,14 @@ namespace MWClass
registerClass (typeid (ESM::Apparatus).name(), instance); registerClass (typeid (ESM::Apparatus).name(), instance);
} }
std::string Apparatus::getUpSoundId (const MWWorld::Ptr& ptr) const
{
return std::string("Item Apparatus Up");
}
std::string Apparatus::getDownSoundId (const MWWorld::Ptr& ptr) const
{
return std::string("Item Apparatus Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
}; };
} }

@ -2,14 +2,22 @@
#include "armor.hpp" #include "armor.hpp"
#include <components/esm/loadarmo.hpp> #include <components/esm/loadarmo.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm_store/cell_store.hpp> #include <components/esm_store/cell_store.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -52,6 +60,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -77,10 +87,105 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Armor::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
std::vector<int> slots;
const int size = 11;
static const int sMapping[size][2] =
{
{ ESM::Armor::Helmet, MWWorld::InventoryStore::Slot_Helmet },
{ ESM::Armor::Cuirass, MWWorld::InventoryStore::Slot_Cuirass },
{ ESM::Armor::LPauldron, MWWorld::InventoryStore::Slot_LeftPauldron },
{ ESM::Armor::RPauldron, MWWorld::InventoryStore::Slot_RightPauldron },
{ ESM::Armor::Greaves, MWWorld::InventoryStore::Slot_Greaves },
{ ESM::Armor::Boots, MWWorld::InventoryStore::Slot_Boots },
{ ESM::Armor::LGauntlet, MWWorld::InventoryStore::Slot_LeftGauntlet },
{ ESM::Armor::RGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet },
{ ESM::Armor::Shield, MWWorld::InventoryStore::Slot_CarriedLeft },
{ ESM::Armor::LBracer, MWWorld::InventoryStore::Slot_LeftGauntlet },
{ ESM::Armor::RBracer, MWWorld::InventoryStore::Slot_RightGauntlet }
};
for (int i=0; i<size; ++i)
if (sMapping[i][0]==ref->base->data.type)
{
slots.push_back (int (sMapping[i][1]));
break;
}
return std::make_pair (slots, false);
}
int Armor::getEquipmentSkill (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
std::string typeGmst;
switch (ref->base->data.type)
{
case ESM::Armor::Helmet: typeGmst = "iHelmWeight"; break;
case ESM::Armor::Cuirass: typeGmst = "iCuirassWeight"; break;
case ESM::Armor::LPauldron:
case ESM::Armor::RPauldron: typeGmst = "iPauldronWeight"; break;
case ESM::Armor::Greaves: typeGmst = "iGreavesWeight"; break;
case ESM::Armor::Boots: typeGmst = "iBootsWeight"; break;
case ESM::Armor::LGauntlet:
case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break;
/// \todo how to determine if shield light, medium or heavy?
// case ESM::Armor::Shield:
case ESM::Armor::LBracer:
case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break;
}
if (typeGmst.empty())
return -1;
float iWeight = environment.mWorld->getStore().gameSettings.find (typeGmst)->i;
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fLightMaxMod")->f>=
ref->base->data.weight)
return ESM::Skill::LightArmor;
if (iWeight * environment.mWorld->getStore().gameSettings.find ("fMedMaxMod")->f>=
ref->base->data.weight)
return ESM::Skill::MediumArmor;
return ESM::Skill::HeavyArmor;
}
void Armor::registerSelf() void Armor::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Armor); boost::shared_ptr<Class> instance (new Armor);
registerClass (typeid (ESM::Armor).name(), instance); registerClass (typeid (ESM::Armor).name(), instance);
} }
std::string Armor::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
int es = getEquipmentSkill(ptr, environment);
if (es == ESM::Skill::LightArmor)
return std::string("Item Armor Light Up");
else if (es == ESM::Skill::MediumArmor)
return std::string("Item Armor Medium Up");
else
return std::string("Item Armor Heavy Up");
}
std::string Armor::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
int es = getEquipmentSkill(ptr, environment);
if (es == ESM::Skill::LightArmor)
return std::string("Item Armor Light Down");
else if (es == ESM::Skill::MediumArmor)
return std::string("Item Armor Medium Down");
else
return std::string("Item Armor Heavy Down");
}
} }

@ -31,7 +31,22 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
const MWWorld::Environment& environment) const;
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
/// no such skill.
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -55,6 +58,8 @@ namespace MWClass
{ {
// TODO implement reading // TODO implement reading
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -73,4 +78,14 @@ namespace MWClass
registerClass (typeid (ESM::Book).name(), instance); registerClass (typeid (ESM::Book).name(), instance);
} }
std::string Book::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Book Up");
}
std::string Book::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Book Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,13 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +57,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -65,10 +71,86 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Clothing::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
std::vector<int> slots;
if (ref->base->data.type==ESM::Clothing::Ring)
{
slots.push_back (int (MWWorld::InventoryStore::Slot_LeftRing));
slots.push_back (int (MWWorld::InventoryStore::Slot_RightRing));
}
else
{
const int size = 9;
static const int sMapping[size][2] =
{
{ ESM::Clothing::Shirt, MWWorld::InventoryStore::Slot_Cuirass },
{ ESM::Clothing::Belt, MWWorld::InventoryStore::Slot_Belt },
{ ESM::Clothing::Robe, MWWorld::InventoryStore::Slot_Robe },
{ ESM::Clothing::Pants, MWWorld::InventoryStore::Slot_Pants },
{ ESM::Clothing::Shoes, MWWorld::InventoryStore::Slot_Boots },
{ ESM::Clothing::LGlove, MWWorld::InventoryStore::Slot_LeftGauntlet },
{ ESM::Clothing::RGlove, MWWorld::InventoryStore::Slot_RightGauntlet },
{ ESM::Clothing::Skirt, MWWorld::InventoryStore::Slot_Skirt },
{ ESM::Clothing::Amulet, MWWorld::InventoryStore::Slot_Amulet }
};
for (int i=0; i<size; ++i)
if (sMapping[i][0]==ref->base->data.type)
{
slots.push_back (int (sMapping[i][1]));
break;
}
}
return std::make_pair (slots, false);
}
int Clothing::getEquipmentSkill (const MWWorld::Ptr& ptr,
const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
if (ref->base->data.type==ESM::Clothing::Shoes)
return ESM::Skill::Unarmored;
return -1;
}
void Clothing::registerSelf() void Clothing::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Clothing); boost::shared_ptr<Class> instance (new Clothing);
registerClass (typeid (ESM::Clothing).name(), instance); registerClass (typeid (ESM::Clothing).name(), instance);
} }
std::string Clothing::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
if (ref->base->data.type == 8)
{
return std::string("Item Ring Up");
}
return std::string("Item Clothes Up");
}
std::string Clothing::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
if (ref->base->data.type == 8)
{
return std::string("Item Ring Down");
}
return std::string("Item Clothes Down");
}
} }

@ -25,7 +25,22 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
const MWWorld::Environment& environment) const;
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
/// no such skill.
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -85,7 +85,7 @@ namespace MWClass
{ {
// TODO check for key // TODO check for key
std::cout << "Locked container" << std::endl; std::cout << "Locked container" << std::endl;
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0); environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
else else
@ -100,7 +100,7 @@ namespace MWClass
{ {
// Trap activation goes here // Trap activation goes here
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0); environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0, false);
ptr.getCellRef().trap = ""; ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }

@ -73,7 +73,7 @@ namespace MWClass
// TODO check for key // TODO check for key
// TODO report failure to player (message, sound?). Look up behaviour of original MW. // TODO report failure to player (message, sound?). Look up behaviour of original MW.
std::cout << "Locked!" << std::endl; std::cout << "Locked!" << std::endl;
environment.mSoundManager->playSound(lockedSound, 1.0, 1.0); environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
@ -81,7 +81,7 @@ namespace MWClass
{ {
// Trap activation // Trap activation
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl; std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
environment.mSoundManager->playSound(trapActivationSound, 1.0, 1.0); environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0, false);
ptr.getCellRef().trap = ""; ptr.getCellRef().trap = "";
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
@ -92,6 +92,7 @@ namespace MWClass
if (environment.mWorld->getPlayer().getPlayer()==actor) if (environment.mWorld->getPlayer().getPlayer()==actor)
{ {
// the player is using the door // the player is using the door
// The reason this is not 3D is that it would get interrupted when you teleport
environment.mSoundManager->playSound(openSound, 1.0, 1.0); environment.mSoundManager->playSound(openSound, 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest));
@ -109,7 +110,7 @@ namespace MWClass
// TODO return action for rotating the door // TODO return action for rotating the door
// This is a little pointless, but helps with testing // This is a little pointless, but helps with testing
environment.mSoundManager->playSound(openSound, 1.0, 1.0); environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0, false);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
} }
} }

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -51,6 +54,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -69,4 +74,14 @@ namespace MWClass
registerClass (typeid (ESM::Ingredient).name(), instance); registerClass (typeid (ESM::Ingredient).name(), instance);
} }
std::string Ingredient::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Ingredient Up");
}
std::string Ingredient::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Ingredient Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -9,6 +9,7 @@
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwsound/soundmanager.hpp" #include "../mwsound/soundmanager.hpp"
@ -82,6 +83,8 @@ namespace MWClass
if (!(ref->base->data.flags & ESM::Light::Carry)) if (!(ref->base->data.flags & ESM::Light::Carry))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction); return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -94,10 +97,33 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Light::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
std::vector<int> slots;
if (ref->base->data.flags & ESM::Light::Carry)
slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedLeft));
return std::make_pair (slots, false);
}
void Light::registerSelf() void Light::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Light); boost::shared_ptr<Class> instance (new Light);
registerClass (typeid (ESM::Light).name(), instance); registerClass (typeid (ESM::Light).name(), instance);
} }
std::string Light::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Misc Up");
}
std::string Light::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Misc Down");
}
} }

@ -30,7 +30,17 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,13 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -54,6 +58,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -66,10 +72,29 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Lockpick::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
std::vector<int> slots;
slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedRight));
return std::make_pair (slots, false);
}
void Lockpick::registerSelf() void Lockpick::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Lockpick); boost::shared_ptr<Class> instance (new Lockpick);
registerClass (typeid (ESM::Tool).name(), instance); registerClass (typeid (ESM::Tool).name(), instance);
} }
std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Lockpick Up");
}
std::string Lockpick::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Lockpick Down");
}
} }

@ -25,7 +25,17 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +56,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -71,4 +76,28 @@ namespace MWClass
registerClass (typeid (ESM::Miscellaneous).name(), instance); registerClass (typeid (ESM::Miscellaneous).name(), instance);
} }
std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
ptr.get<ESM::Miscellaneous>();
if (ref->base->name =="Gold")
{
return std::string("Item Gold Up");
}
return std::string("Item Misc Up");
}
std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
ptr.get<ESM::Miscellaneous>();
if (ref->base->name =="Gold")
{
return std::string("Item Gold Down");
}
return std::string("Item Misc Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -16,7 +16,7 @@
#include "../mwworld/actiontalk.hpp" #include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/customdata.hpp" #include "../mwworld/customdata.hpp"
namespace namespace
@ -29,7 +29,7 @@ namespace
MWMechanics::NpcStats mNpcStats; MWMechanics::NpcStats mNpcStats;
MWMechanics::CreatureStats mCreatureStats; MWMechanics::CreatureStats mCreatureStats;
MWMechanics::Movement mMovement; MWMechanics::Movement mMovement;
MWWorld::ContainerStore mContainerStore; MWWorld::InventoryStore mInventoryStore;
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
}; };
@ -161,7 +161,15 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore; return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
}
MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr)
const
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
} }
std::string Npc::getScript (const MWWorld::Ptr& ptr) const std::string Npc::getScript (const MWWorld::Ptr& ptr) const

@ -38,6 +38,9 @@ namespace MWClass
virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
///< Return container store ///< Return container store
virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const;
///< Return inventory store
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation ///< Generate action for activation

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +56,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -71,4 +76,14 @@ namespace MWClass
registerClass (typeid (ESM::Potion).name(), instance); registerClass (typeid (ESM::Potion).name(), instance);
} }
std::string Potion::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Potion Up");
}
std::string Potion::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Potion Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,13 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +57,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -65,10 +71,29 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Probe::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
std::vector<int> slots;
slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedRight));
return std::make_pair (slots, false);
}
void Probe::registerSelf() void Probe::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Probe); boost::shared_ptr<Class> instance (new Probe);
registerClass (typeid (ESM::Probe).name(), instance); registerClass (typeid (ESM::Probe).name(), instance);
} }
std::string Probe::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Probe Up");
}
std::string Probe::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Probe Down");
}
} }

@ -25,7 +25,17 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,12 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +56,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -71,4 +76,14 @@ namespace MWClass
registerClass (typeid (ESM::Repair).name(), instance); registerClass (typeid (ESM::Repair).name(), instance);
} }
std::string Repair::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Repair Up");
}
std::string Repair::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
return std::string("Item Repair Down");
}
} }

@ -26,6 +26,12 @@ namespace MWClass
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -7,9 +7,13 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwsound/soundmanager.hpp"
namespace MWClass namespace MWClass
{ {
void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -53,6 +57,8 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{ {
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
return boost::shared_ptr<MWWorld::Action> ( return boost::shared_ptr<MWWorld::Action> (
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));
} }
@ -78,10 +84,157 @@ namespace MWClass
return ref->base->script; return ref->base->script;
} }
std::pair<std::vector<int>, bool> Weapon::getEquipmentSlots (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
std::vector<int> slots;
bool stack = false;
if (ref->base->data.type==ESM::Weapon::Arrow || ref->base->data.type==ESM::Weapon::Bolt)
{
slots.push_back (int (MWWorld::InventoryStore::Slot_Ammunition));
stack = true;
}
else if (ref->base->data.type==ESM::Weapon::MarksmanThrown)
{
slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedRight));
stack = true;
}
else
slots.push_back (int (MWWorld::InventoryStore::Slot_CarriedRight));
return std::make_pair (slots, stack);
}
int Weapon::getEquipmentSkill (const MWWorld::Ptr& ptr,
const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
const int size = 12;
static const int sMapping[size][2] =
{
{ ESM::Weapon::ShortBladeOneHand, ESM::Skill::ShortBlade },
{ ESM::Weapon::LongBladeOneHand, ESM::Skill::LongBlade },
{ ESM::Weapon::LongBladeTwoHand, ESM::Skill::LongBlade },
{ ESM::Weapon::BluntOneHand, ESM::Skill::BluntWeapon },
{ ESM::Weapon::BluntTwoClose, ESM::Skill::BluntWeapon },
{ ESM::Weapon::BluntTwoWide, ESM::Skill::BluntWeapon },
{ ESM::Weapon::SpearTwoWide, ESM::Skill::Spear },
{ ESM::Weapon::AxeOneHand, ESM::Skill::Axe },
{ ESM::Weapon::AxeTwoHand, ESM::Skill::Axe },
{ ESM::Weapon::MarksmanBow, ESM::Skill::Marksman },
{ ESM::Weapon::MarksmanCrossbow, ESM::Skill::Marksman },
{ ESM::Weapon::MarksmanThrown, ESM::Skill::Marksman }
};
for (int i=0; i<size; ++i)
if (sMapping[i][0]==ref->base->data.type)
return sMapping[i][1];
return -1;
}
void Weapon::registerSelf() void Weapon::registerSelf()
{ {
boost::shared_ptr<Class> instance (new Weapon); boost::shared_ptr<Class> instance (new Weapon);
registerClass (typeid (ESM::Weapon).name(), instance); registerClass (typeid (ESM::Weapon).name(), instance);
} }
std::string Weapon::getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
int type = ref->base->data.type;
// Ammo
if (type == 12 || type == 13)
{
return std::string("Item Ammo Up");
}
// Bow
if (type == 9)
{
return std::string("Item Weapon Bow Up");
}
// Crossbow
if (type == 10)
{
return std::string("Item Weapon Crossbow Up");
}
// Longblades, One hand and Two
if (type == 1 || type == 2)
{
return std::string("Item Weapon Longblade Up");
}
// Shortblade and thrown weapons
// thrown weapons may not be entirely correct
if (type == 0 || type == 11)
{
return std::string("Item Weapon Shortblade Up");
}
// Spear
if (type == 6)
{
return std::string("Item Weapon Spear Up");
}
// Blunts and Axes
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
{
return std::string("Item Weapon Blunt Up");
}
return std::string("Item Misc Up");
}
std::string Weapon::getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
int type = ref->base->data.type;
// Ammo
if (type == 12 || type == 13)
{
return std::string("Item Ammo Down");
}
// Bow
if (type == 9)
{
return std::string("Item Weapon Bow Down");
}
// Crossbow
if (type == 10)
{
return std::string("Item Weapon Crossbow Down");
}
// Longblades, One hand and Two
if (type == 1 || type == 2)
{
return std::string("Item Weapon Longblade Down");
}
// Shortblade and thrown weapons
// thrown weapons may not be entirely correct
if (type == 0 || type == 11)
{
return std::string("Item Weapon Shortblade Down");
}
// Spear
if (type == 6)
{
return std::string("Item Weapon Spear Down");
}
// Blunts and Axes
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
{
return std::string("Item Weapon Blunt Down");
}
return std::string("Item Misc Down");
}
} }

@ -31,7 +31,22 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const MWWorld::Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
virtual int getEquipmentSkill (const MWWorld::Ptr& ptr,
const MWWorld::Environment& environment) const;
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
/// no such skill.
static void registerSelf(); static void registerSelf();
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the pick up sound Id
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the put down sound Id
}; };
} }

@ -9,16 +9,36 @@
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwworld/refdata.hpp" #include "../mwworld/refdata.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwinput/inputmanager.hpp" #include "../mwinput/inputmanager.hpp"
#include "../mwgui/dialogue.hpp"
#include "../mwgui/window_manager.hpp"
#include "journal.hpp"
#include <iostream> #include <iostream>
#include "../mwscript/extensions.hpp"
#include "../mwscript/scriptmanager.hpp"
#include <components/compiler/exception.hpp>
#include <components/compiler/errorhandler.hpp>
#include <components/compiler/scanner.hpp>
#include <components/compiler/locals.hpp>
#include <components/compiler/output.hpp>
#include <components/interpreter/interpreter.hpp>
#include "../mwscript/compilercontext.hpp"
#include "../mwscript/interpretercontext.hpp"
#include <components/compiler/scriptparser.hpp>
namespace namespace
{ {
std::string toLower (const std::string& name) std::string toLower (const std::string& name)
@ -31,17 +51,18 @@ namespace
return lowerCase; return lowerCase;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
bool selectCompare (char comp, T1 value1, T2 value2) bool selectCompare (char comp, T1 value1, T2 value2)
{ {
switch (comp) switch (comp)
{ {
case '0': return value1==value2; case '0': return value1==value2;
case '1': return value1!=value2; case '1': return value1!=value2;
case '2': return value1>value2; case '2': return value1>value2;
case '3': return value1>=value2; case '3': return value1>=value2;
case '4': return value1<value2; case '4': return value1<value2;
case '5': return value1<=value2; case '5': return value1<=value2;
} }
throw std::runtime_error ("unknown compare type in dialogue info select"); throw std::runtime_error ("unknown compare type in dialogue info select");
@ -87,26 +108,26 @@ namespace
{ {
switch (world.getGlobalVariableType (name)) switch (world.getGlobalVariableType (name))
{ {
case 's': case 's':
return selectCompare (comp, value, world.getGlobalVariable (name).mShort); return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
case 'l': case 'l':
return selectCompare (comp, value, world.getGlobalVariable (name).mLong); return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
case 'f': case 'f':
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat); return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
case ' ': case ' ':
world.getGlobalVariable (name); // trigger exception world.getGlobalVariable (name); // trigger exception
break; break;
default: default:
throw std::runtime_error ("unsupported gobal variable type"); throw std::runtime_error ("unsupported gobal variable type");
} }
return false; return false;
@ -115,6 +136,128 @@ namespace
namespace MWDialogue namespace MWDialogue
{ {
//helper function
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
{
return toLower(str).find(toLower(substr),pos);
}
bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice)
{
bool isAChoice = false;//is there any choice in the filters?
bool isFunction = false;
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
iter != info.selects.end(); ++iter)
{
ESM::DialInfo::SelectStruct select = *iter;
char type = select.selectRule[1];
if(type == '1')
{
isFunction = true;
char comp = select.selectRule[4];
std::string name = select.selectRule.substr (5);
std::string function = select.selectRule.substr(2,2);
int ifunction;
std::istringstream iss(function);
iss >> ifunction;
switch(ifunction)
{
case 39://PC Expelled
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 40://PC Common Disease
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 41://PC Blight Disease
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 43://PC Crime level
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 46://Same faction
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 48://Detected
if(!selectCompare<int,int>(comp,1,select.i)) return false;
break;
case 49://Alarmed
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 50://choice
isAChoice = true;
if(choice)
{
if(!selectCompare<int,int>(comp,mChoice,select.i)) return false;
}
break;
case 60://PC Vampire
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 61://Level
if(!selectCompare<int,int>(comp,1,select.i)) return false;
break;
case 62://Attacked
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 63://Talked to PC
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 64://PC Health
if(!selectCompare<int,int>(comp,50,select.i)) return false;
break;
case 65://Creature target
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 66://Friend hit
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 67://Fight
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 68://Hello????
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 69://Alarm
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 70://Flee
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
case 71://Should Attack
if(!selectCompare<int,int>(comp,0,select.i)) return false;
break;
default:
break;
}
}
}
return true;
}
bool DialogueManager::isMatching (const MWWorld::Ptr& actor, bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
const ESM::DialInfo::SelectStruct& select) const const ESM::DialInfo::SelectStruct& select) const
{ {
@ -124,58 +267,173 @@ namespace MWDialogue
{ {
char comp = select.selectRule[4]; char comp = select.selectRule[4];
std::string name = select.selectRule.substr (5); std::string name = select.selectRule.substr (5);
std::string function = select.selectRule.substr(1,2);
// TODO types 4, 5, 6, 7, 8, 9, A, B, C
switch (type) switch (type)
{ {
case '1': // function case '1': // function
return false; // TODO implement functions return true; // TODO implement functions
case '2': // global case '2': // global
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
select.type==ESM::VT_Long) select.type==ESM::VT_Long)
{ {
if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld)) if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
return false; return false;
} }
else if (select.type==ESM::VT_Float) else if (select.type==ESM::VT_Float)
{ {
if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld)) if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
return false; return false;
} }
else else
throw std::runtime_error ( throw std::runtime_error (
"unsupported variable type in dialogue info select"); "unsupported variable type in dialogue info select");
return true; return true;
case '3': // local case '3': // local
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
select.type==ESM::VT_Long) select.type==ESM::VT_Long)
{ {
if (!checkLocal (comp, toLower (name), select.i, actor, if (!checkLocal (comp, toLower (name), select.i, actor,
mEnvironment.mWorld->getStore())) mEnvironment.mWorld->getStore()))
return false; return false;
} }
else if (select.type==ESM::VT_Float) else if (select.type==ESM::VT_Float)
{ {
if (!checkLocal (comp, toLower (name), select.f, actor, if (!checkLocal (comp, toLower (name), select.f, actor,
mEnvironment.mWorld->getStore())) mEnvironment.mWorld->getStore()))
return false; return false;
} }
else else
throw std::runtime_error ( throw std::runtime_error (
"unsupported variable type in dialogue info select"); "unsupported variable type in dialogue info select");
return true; return true;
default: case '4'://journal
if(select.type==ESM::VT_Int)
{
if(!selectCompare<int,int>(comp,mEnvironment.mJournal->getJournalIndex(toLower(name)),select.i)) return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; return true;
case '5'://item
{
MWWorld::Ptr player = mEnvironment.mWorld->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player);
int sum = 0;
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
if (iter->getCellRef().refID==name)
sum += iter->getRefData().getCount();
if(!selectCompare<int,int>(comp,sum,select.i)) return false;
}
return true;
case '6'://dead
if(!selectCompare<int,int>(comp,0,select.i)) return false;
case '7':// not ID
if(select.type==ESM::VT_String ||select.type==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string
{
int isID = int(toLower(name)==toLower(MWWorld::Class::get (actor).getId (actor)));
if (selectCompare<int,int>(comp,!isID,select.i)) return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
case '8':// not faction
if(select.type==ESM::VT_Int)
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
int isFaction = int(toLower(npc->base->faction) == toLower(name));
if(selectCompare<int,int>(comp,!isFaction,select.i))
return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
case '9':// not class
if(select.type==ESM::VT_Int)
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
int isClass = int(toLower(npc->base->cls) == toLower(name));
if(selectCompare<int,int>(comp,!isClass,select.i))
return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
case 'A'://not Race
if(select.type==ESM::VT_Int)
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
int isRace = int(toLower(npc->base->race) == toLower(name));
if(selectCompare<int,int>(comp,!isRace,select.i))
return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
case 'B'://not Cell
if(select.type==ESM::VT_Int)
{
int isCell = int(toLower(actor.getCell()->cell->name) == toLower(name));
if(selectCompare<int,int>(comp,!isCell,select.i))
return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
case 'C'://not local
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
select.type==ESM::VT_Long)
{
if (checkLocal (comp, toLower (name), select.i, actor,
mEnvironment.mWorld->getStore()))
return false;
}
else if (select.type==ESM::VT_Float)
{
if (checkLocal (comp, toLower (name), select.f, actor,
mEnvironment.mWorld->getStore()))
return false;
}
else
throw std::runtime_error (
"unsupported variable type in dialogue info select");
return true;
default:
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
} }
} }
@ -189,6 +447,10 @@ namespace MWDialogue
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor)) if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
return false; return false;
//PC Faction
if(!info.pcFaction.empty()) return false;
//NPC race
if (!info.race.empty()) if (!info.race.empty())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
@ -200,6 +462,7 @@ namespace MWDialogue
return false; return false;
} }
//NPC class
if (!info.clas.empty()) if (!info.clas.empty())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
@ -211,6 +474,7 @@ namespace MWDialogue
return false; return false;
} }
//NPC faction
if (!info.npcFaction.empty()) if (!info.npcFaction.empty())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
@ -220,10 +484,32 @@ namespace MWDialogue
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction)) if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
return false; return false;
//check NPC rank
if(cellRef->base->npdt52.gold != -10)
{
if(cellRef->base->npdt52.rank < info.data.rank) return false;
}
else
{
if(cellRef->base->npdt12.rank < info.data.rank) return false;
}
} }
// TODO check player faction // TODO check player faction
//check gender
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
if(npc->base->flags&npc->base->Female)
{
if(static_cast<int> (info.data.gender)==0) return false;
}
else
{
if(static_cast<int> (info.data.gender)==1) return false;
}
// check cell // check cell
if (!info.cell.empty()) if (!info.cell.empty())
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell) if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
@ -236,50 +522,281 @@ namespace MWDialogue
if (!isMatching (actor, *iter)) if (!isMatching (actor, *iter))
return false; return false;
std::cout
<< "unchecked entries:" << std::endl
<< " player faction: " << info.pcFaction << std::endl
<< " disposition: " << info.data.disposition << std::endl
<< " NPC rank: " << static_cast<int> (info.data.rank) << std::endl
<< " gender: " << static_cast<int> (info.data.gender) << std::endl
<< " PC rank: " << static_cast<int> (info.data.PCrank) << std::endl;
return true; return true;
} }
DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {} DialogueManager::DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions) :
mEnvironment (environment),mCompilerContext (MWScript::CompilerContext::Type_Dialgoue, environment),
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
{
mChoice = -1;
mIsInChoice = false;
mCompilerContext.setExtensions (&extensions);
}
void DialogueManager::addTopic(std::string topic)
{
knownTopics[toLower(topic)] = true;
}
void DialogueManager::parseText(std::string text)
{
std::list<std::string>::iterator it;
for(it = actorKnownTopics.begin();it != actorKnownTopics.end();it++)
{
size_t pos = find_str_ci(text,*it,0);
if(pos !=std::string::npos)
{
if(pos==0)
{
knownTopics[*it] = true;
}
else if(text.substr(pos -1,1) == " ")
{
knownTopics[*it] = true;
}
}
}
updateTopics();
}
void DialogueManager::startDialogue (const MWWorld::Ptr& actor) void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
{ {
std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl; mChoice = -1;
mIsInChoice = false;
const ESM::Dialogue *dialogue = mEnvironment.mWorld->getStore().dialogs.find ("hello"); mActor = actor;
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin()); mDialogueMap.clear();
iter!=dialogue->mInfo.end(); ++iter) actorKnownTopics.clear();
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{ {
if (isMatching (actor, *iter)) mDialogueMap[it->first] = it->second;
}
//initialise the GUI
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
win->startDialogue(MWWorld::Class::get (actor).getName (actor));
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
updateTopics();
//greeting
bool greetingFound = false;
//ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
ESM::Dialogue ndialogue = it->second;
if(ndialogue.type == ESM::Dialogue::Greeting)
{ {
// start dialogue if (greetingFound) break;
std::cout << "found matching info record" << std::endl; for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
iter!=it->second.mInfo.end(); ++iter)
std::cout << "response: " << iter->response << std::endl;
if (!iter->sound.empty())
{ {
// TODO play sound if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true))
} {
if (!iter->sound.empty())
{
// TODO play sound
}
if (!iter->resultScript.empty()) std::string text = iter->response;
{ parseText(text);
std::cout << "script: " << iter->resultScript << std::endl; win->addText(iter->response);
// TODO execute script executeScript(iter->resultScript);
greetingFound = true;
mLastTopic = it->first;
mLastDialogue = *iter;
break;
}
} }
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
break;
} }
} }
} }
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code)
{
try
{
mErrorHandler.reset();
std::istringstream input (cmd + "\n");
Compiler::Scanner scanner (mErrorHandler, input, mCompilerContext.getExtensions());
Compiler::Locals locals;
std::string actorScript = MWWorld::Class::get (mActor).getScript (mActor);
if (!actorScript.empty())
{
// grab local variables from actor's script, if available.
locals = mEnvironment.mScriptManager->getLocals (actorScript);
}
Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false);
scanner.scan (parser);
if(mErrorHandler.isGood())
{
parser.getCode(code);
return true;
}
return false;
}
catch (const Compiler::SourceException& error)
{
// error has already been reported via error handler
}
catch (const std::exception& error)
{
printError (std::string ("An exception has been thrown: ") + error.what());
}
return false;
}
void DialogueManager::executeScript(std::string script)
{
std::vector<Interpreter::Type_Code> code;
if(compile(script,code))
{
try
{
MWScript::InterpreterContext interpreterContext(mEnvironment,&mActor.getRefData().getLocals(),mActor);
Interpreter::Interpreter interpreter;
MWScript::installOpcodes (interpreter);
interpreter.run (&code[0], code.size(), interpreterContext);
}
catch (const std::exception& error)
{
printError (std::string ("An exception has been thrown: ") + error.what());
}
}
}
void DialogueManager::updateTopics()
{
std::list<std::string> keywordList;
actorKnownTopics.clear();
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
ESM::Dialogue ndialogue = it->second;
if(ndialogue.type == ESM::Dialogue::Topic)
{
for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
iter!=it->second.mInfo.end(); ++iter)
{
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,false))
{
actorKnownTopics.push_back(it->first);
//does the player know the topic?
if(knownTopics.find(toLower(it->first)) != knownTopics.end())
{
keywordList.push_back(it->first);
break;
}
}
}
}
}
win->setKeywords(keywordList);
}
void DialogueManager::keywordSelected(std::string keyword)
{
if(!mIsInChoice)
{
if(mDialogueMap.find(keyword) != mDialogueMap.end())
{
ESM::Dialogue ndialogue = mDialogueMap[keyword];
std::vector<ESM::DialInfo>::const_iterator iter;
if(ndialogue.type == ESM::Dialogue::Topic)
{
for (iter = ndialogue.mInfo.begin();
iter!=ndialogue.mInfo.end(); ++iter)
{
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
{
std::string text = iter->response;
std::string script = iter->resultScript;
parseText(text);
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
win->addTitle(keyword);
win->addText(iter->response);
executeScript(script);
mLastTopic = keyword;
mLastDialogue = *iter;
break;
}
}
}
}
}
updateTopics();
}
void DialogueManager::goodbyeSelected()
{
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Game);
}
void DialogueManager::questionAnswered(std::string answere)
{
if(mChoiceMap.find(answere) != mChoiceMap.end())
{
mChoice = mChoiceMap[answere];
std::vector<ESM::DialInfo>::const_iterator iter;
if(mDialogueMap.find(mLastTopic) != mDialogueMap.end())
{
ESM::Dialogue ndialogue = mDialogueMap[mLastTopic];
if(ndialogue.type == ESM::Dialogue::Topic)
{
for (std::vector<ESM::DialInfo>::const_iterator iter = ndialogue.mInfo.begin();
iter!=ndialogue.mInfo.end(); ++iter)
{
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
{
mChoiceMap.clear();
mChoice = -1;
mIsInChoice = false;
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
std::string text = iter->response;
parseText(text);
win->addText(text);
executeScript(iter->resultScript);
mLastTopic = mLastTopic;
mLastDialogue = *iter;
break;
}
}
}
}
updateTopics();
}
}
void DialogueManager::printError(std::string error)
{
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
win->addText(error);
}
void DialogueManager::askQuestion(std::string question, int choice)
{
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
win->askQuestion(question);
mChoiceMap[question] = choice;
mIsInChoice = true;
}
} }

@ -3,7 +3,13 @@
#include <components/esm/loadinfo.hpp> #include <components/esm/loadinfo.hpp>
#include <components/compiler/streamerrorhandler.hpp>
#include "../mwscript/compilercontext.hpp"
#include "../mwscript/interpretercontext.hpp"
#include <components/compiler/output.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <map>
namespace MWWorld namespace MWWorld
{ {
@ -20,12 +26,48 @@ namespace MWDialogue
bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const;
bool functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice);
void parseText(std::string text);
void updateTopics();
std::map<std::string,ESM::Dialogue> mDialogueMap;
std::map<std::string,bool> knownTopics;// Those are the topics the player knows.
std::list<std::string> actorKnownTopics;
MWScript::CompilerContext mCompilerContext;
std::ostream mErrorStream;
Compiler::StreamErrorHandler mErrorHandler;
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
void executeScript(std::string script);
MWWorld::Ptr mActor;
void printError(std::string error);
int mChoice;
std::map<std::string,int> mChoiceMap;
std::string mLastTopic;
ESM::DialInfo mLastDialogue;
bool mIsInChoice;
public: public:
DialogueManager (MWWorld::Environment& environment); DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions);
void startDialogue (const MWWorld::Ptr& actor); void startDialogue (const MWWorld::Ptr& actor);
void addTopic(std::string topic);
void askQuestion(std::string question,int choice);
//calbacks for the GUI
void keywordSelected(std::string keyword);
void goodbyeSelected();
void questionAnswered(std::string answere);
}; };
} }

@ -3,6 +3,9 @@
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwgui/window_manager.hpp"
#include "../mwgui/messagebox.hpp"
namespace MWDialogue namespace MWDialogue
{ {
Quest& Journal::getQuest (const std::string& id) Quest& Journal::getQuest (const std::string& id)
@ -34,6 +37,10 @@ namespace MWDialogue
Quest& quest = getQuest (id); Quest& quest = getQuest (id);
quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here
std::vector<std::string> empty;
std::string notification = "Your Journal has been updated.";
mEnvironment.mWindowManager->messageBox (notification, empty);
} }
void Journal::setJournalIndex (const std::string& id, int index) void Journal::setJournalIndex (const std::string& id, int index)
@ -60,7 +67,12 @@ namespace MWDialogue
int Journal::getJournalIndex (const std::string& id) const int Journal::getJournalIndex (const std::string& id) const
{ {
return 0; TQuestContainer::const_iterator iter = mQuests.find (id);
if (iter==mQuests.end())
return 0;
return iter->second.getIndex();
} }
Journal::TEntryIter Journal::begin() const Journal::TEntryIter Journal::begin() const

@ -50,7 +50,7 @@ namespace MWGui
return isGood(); return isGood();
} }
catch (const Compiler::SourceException& error) catch (const Compiler::SourceException&)
{ {
// error has already been reported via error handler // error has already been reported via error handler
} }

@ -3,6 +3,8 @@
#include "window_manager.hpp" #include "window_manager.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "components/esm_store/store.hpp" #include "components/esm_store/store.hpp"
#include "../mwworld/environment.hpp"
#include "../mwdialogue/dialoguemanager.hpp"
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
@ -14,8 +16,29 @@
using namespace MWGui; using namespace MWGui;
using namespace Widgets; using namespace Widgets;
DialogueWindow::DialogueWindow(WindowManager& parWindowManager) /**
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager) *Copied from the internet.
*/
std::string lower_string(const std::string& str)
{
std::string lowerCase;
std::transform (str.begin(), str.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
{
return lower_string(str).find(lower_string(substr),pos);
}
DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment)
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager),
mEnvironment(environment)
{ {
// Centre dialog // Centre dialog
center(); center();
@ -27,19 +50,20 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
getWidget(history, "History"); getWidget(history, "History");
history->setOverflowToTheLeft(true); history->setOverflowToTheLeft(true);
history->getClient()->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked); history->getClient()->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
history->setMaxTextLength(1000000);
//Topics list //Topics list
getWidget(topicsList, "TopicsList"); getWidget(topicsList, "TopicsList");
topicsList->setScrollVisible(true); topicsList->setScrollVisible(true);
topicsList->eventListSelectAccept = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); //topicsList->eventListSelectAccept = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
topicsList->eventListMouseItemActivate = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); topicsList->eventListMouseItemActivate = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
topicsList->eventListChangePosition = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); //topicsList->eventListChangePosition = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
MyGUI::ButtonPtr byeButton; MyGUI::ButtonPtr byeButton;
getWidget(byeButton, "ByeButton"); getWidget(byeButton, "ByeButton");
byeButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onByeClicked); byeButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
updateOptions(); getWidget(pDispositionBar, "Disposition");
getWidget(pDispositionText,"DispositionText");
} }
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender) void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
@ -51,70 +75,126 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
const IntPoint& lastPressed = InputManager::getInstance().getLastLeftPressed(); const IntPoint& lastPressed = InputManager::getInstance().getLastLeftPressed();
size_t cursorPosition = t->getCursorPosition(lastPressed); size_t cursorPosition = t->getCursorPosition(lastPressed);
if(history->getColorAtPos(cursorPosition) != "#FFFFFF") MyGUI::UString color = history->getColorAtPos(cursorPosition);
if(color != "#B29154")
{ {
UString key = history->getColorTextAt(cursorPosition); UString key = history->getColorTextAt(cursorPosition);
std::cout << "Clicked on key: " << key << std::endl; if(color == "#686EBA") mEnvironment.mDialogueManager->keywordSelected(lower_string(key));
//eventTopicSelected(key);
if(color == "#572D21") mEnvironment.mDialogueManager->questionAnswered(key);
} }
} }
void DialogueWindow::open() void DialogueWindow::open()
{ {
topicsList->removeAllItems();
pTopicsText.clear();
history->eraseText(0,history->getTextLength());
updateOptions(); updateOptions();
setVisible(true); setVisible(true);
} }
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
{ {
eventBye(); mEnvironment.mDialogueManager->goodbyeSelected();
} }
void DialogueWindow::onSelectTopic(MyGUI::List* _sender, size_t _index) void DialogueWindow::onSelectTopic(MyGUI::List* _sender, size_t _index)
{ {
if (_index == MyGUI::ITEM_NONE) if (_index == MyGUI::ITEM_NONE)
return; return;
std::string topic = _sender->getItemNameAt(_index);
//const std::string* theTopic = topicsList->getItemDataAt<std::string>(_index); mEnvironment.mDialogueManager->keywordSelected(lower_string(topic));
//std::cout << "Selected: "<< theTopic << std::endl;
//eventTopicSelected(key);
} }
void DialogueWindow::startDialogue(std::string npcName)
{
setText("NpcName", npcName);
}
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
{
topicsList->removeAllItems();
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); it++)
{
topicsList->addItem(*it);
}
}
void DialogueWindow::removeKeyword(std::string keyWord)
{
if(topicsList->findItemIndexWith(keyWord) != MyGUI::ITEM_NONE)
{
topicsList->removeItemAt(topicsList->findItemIndexWith(keyWord));
pTopicsText.erase(keyWord);
}
}
void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2)
{
size_t pos = 0;
while((pos = find_str_ci(str,keyword, pos)) != std::string::npos)
{
if(pos==0)
{
str.insert(pos,color1);
pos += color1.length();
pos += keyword.length();
str.insert(pos,color2);
pos+= color2.length();
}
else
{
if(str.substr(pos -1,1) == " ")
{
str.insert(pos,color1);
pos += color1.length();
pos += keyword.length();
str.insert(pos,color2);
pos+= color2.length();
}
else
{
pos += keyword.length();
}
}
}
}
std::string DialogueWindow::parseText(std::string text)
{
for(unsigned int i = 0;i<topicsList->getItemCount();i++)
{
std::string keyWord = topicsList->getItemNameAt(i);
addColorInString(text,keyWord,"#686EBA","#B29154");
}
return text;
}
void DialogueWindow::addText(std::string text)
{
history->addDialogText("#B29154"+parseText(text)+"#B29154");
}
void DialogueWindow::addTitle(std::string text)
{
history->addDialogHeading(text);
}
void DialogueWindow::askQuestion(std::string question)
{
history->addDialogText("#572D21"+question+"#B29154"+" ");
}
void DialogueWindow::updateOptions() void DialogueWindow::updateOptions()
{ {
//FIXME Add this properly
history->addDialogText("Through the translucent surface of the orb, you see shifting images of distant locations...");
for(int z = 0; z < 10; z++)
{
history->addDialogHeading("Fort Frostmoth");
history->addDialogText("The image in the orb flickers, and you see.... The cold courtyard of #FF0000Fort Frostmoth#FFFFFF, battered bu werewolf attack, but still standing, still projecting Imperial might even to this distant and cold corner of the world.");
}
//Clear the list of topics //Clear the list of topics
topicsList->removeAllItems(); topicsList->removeAllItems();
int i = 0; pTopicsText.clear();
topicsList->addItem("Ald'ruhn", i++); history->eraseText(0,history->getTextLength());
topicsList->addItem("Balmora", i++);
topicsList->addItem("Sadrith Mora", i++);
topicsList->addItem("Vivec", i++);
topicsList->addItem("Ald Velothi", i++);
topicsList->addItem("Caldera", i++);
topicsList->addItem("Dagon Fel ", i++);
topicsList->addItem("Gnaar Mok", i++);
topicsList->addItem("Gnisis", i++);
topicsList->addItem("Hla Oad", i++);
topicsList->addItem("Khuul", i++);
topicsList->addItem("Maar Gan", i++);
topicsList->addItem("Molag Mar", i++);
topicsList->addItem("Pelagiad", i++);
topicsList->addItem("Seyda Neen", i++);
topicsList->addItem("Suran", i++);
topicsList->addItem("Tel Aruhn", i++);
topicsList->addItem("Tel Branora", i++);
topicsList->addItem("Tel Fyr", i++);
topicsList->addItem("Tel Mora", i++);
topicsList->addItem("Tel Vos", i++);
topicsList->addItem("Vos", i++);
}
pDispositionBar->setProgressRange(100);
pDispositionBar->setProgressPosition(40);
pDispositionText->eraseText(0,pDispositionText->getTextLength());
pDispositionText->addText("#B29154"+std::string("40/100")+"#B29154");
}

@ -9,6 +9,11 @@ namespace MWGui
class WindowManager; class WindowManager;
} }
namespace MWWorld
{
class Environment;
}
/* /*
This file contains the dialouge window This file contains the dialouge window
Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml. Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml.
@ -23,7 +28,7 @@ namespace MWGui
class DialogueWindow: public WindowBase class DialogueWindow: public WindowBase
{ {
public: public:
DialogueWindow(WindowManager& parWindowManager); DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment);
void open(); void open();
@ -35,6 +40,14 @@ namespace MWGui
*/ */
EventHandle_Void eventBye; EventHandle_Void eventBye;
void startDialogue(std::string npcName);
void stopDialogue();
void setKeywords(std::list<std::string> keyWord);
void removeKeyword(std::string keyWord);
void addText(std::string text);
void addTitle(std::string text);
void askQuestion(std::string question);
protected: protected:
void onSelectTopic(MyGUI::List* _sender, size_t _index); void onSelectTopic(MyGUI::List* _sender, size_t _index);
void onByeClicked(MyGUI::Widget* _sender); void onByeClicked(MyGUI::Widget* _sender);
@ -42,9 +55,18 @@ namespace MWGui
private: private:
void updateOptions(); void updateOptions();
/**
*Helper function that add topic keyword in blue in a text.
*/
std::string parseText(std::string text);
DialogeHistory* history; DialogeHistory* history;
MyGUI::ListPtr topicsList; MyGUI::ListPtr topicsList;
MyGUI::ProgressPtr pDispositionBar;
MyGUI::EditPtr pDispositionText;
std::map<std::string,std::string> pTopicsText;// this map links keyword and "real" text.
MWWorld::Environment& mEnvironment;
}; };
} }
#endif #endif

@ -61,9 +61,9 @@ UString DialogeHistory::getColorTextAt(size_t _pos)
void DialogeHistory::addDialogHeading(const UString& parText) void DialogeHistory::addDialogHeading(const UString& parText)
{ {
UString head("\n#00FF00"); UString head("\n#D8C09A");
head.append(parText); head.append(parText);
head.append("#FFFFFF\n"); head.append("#B29154\n");
addText(head); addText(head);
} }

@ -4,6 +4,8 @@
#include "../mwworld/environment.hpp" #include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwsound/soundmanager.hpp"
namespace namespace
{ {
struct book struct book
@ -115,6 +117,8 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager)
void MWGui::JournalWindow::open() void MWGui::JournalWindow::open()
{ {
mPageNumber = 0; mPageNumber = 0;
std::string journalOpenSound = "book open";
mWindowManager.getEnvironment().mSoundManager->playSound (journalOpenSound, 1.0, 1.0);
if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end()) if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end())
{ {
book journal; book journal;
@ -176,6 +180,8 @@ void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender)
{ {
if(mPageNumber < int(leftPages.size())-1) if(mPageNumber < int(leftPages.size())-1)
{ {
std::string nextSound = "book page2";
mWindowManager.getEnvironment().mSoundManager->playSound (nextSound, 1.0, 1.0);
mPageNumber = mPageNumber + 1; mPageNumber = mPageNumber + 1;
displayLeftText(leftPages[mPageNumber]); displayLeftText(leftPages[mPageNumber]);
displayRightText(rightPages[mPageNumber]); displayRightText(rightPages[mPageNumber]);
@ -186,6 +192,8 @@ void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender)
{ {
if(mPageNumber > 0) if(mPageNumber > 0)
{ {
std::string prevSound = "book page";
mWindowManager.getEnvironment().mSoundManager->playSound (prevSound, 1.0, 1.0);
mPageNumber = mPageNumber - 1; mPageNumber = mPageNumber - 1;
displayLeftText(leftPages[mPageNumber]); displayLeftText(leftPages[mPageNumber]);
displayRightText(rightPages[mPageNumber]); displayRightText(rightPages[mPageNumber]);

@ -51,6 +51,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
console = new Console(w,h, environment, extensions); console = new Console(w,h, environment, extensions);
mJournal = new JournalWindow(*this); mJournal = new JournalWindow(*this);
mMessageBoxManager = new MessageBoxManager(this); mMessageBoxManager = new MessageBoxManager(this);
dialogueWindow = new DialogueWindow(*this,environment);
// The HUD is always on // The HUD is always on
hud->setVisible(true); hud->setVisible(true);
@ -149,6 +150,7 @@ void WindowManager::updateVisible()
stats->setVisible(false); stats->setVisible(false);
console->disable(); console->disable();
mJournal->setVisible(false); mJournal->setVisible(false);
dialogueWindow->setVisible(false);
// Mouse is visible whenever we're not in game mode // Mouse is visible whenever we're not in game mode
gui->setVisiblePointer(isGuiMode()); gui->setVisiblePointer(isGuiMode());
@ -195,11 +197,6 @@ void WindowManager::updateVisible()
if (mode == GM_Dialogue) if (mode == GM_Dialogue)
{ {
if (!dialogueWindow)
{
dialogueWindow = new DialogueWindow(*this);
dialogueWindow->eventBye = MyGUI::newDelegate(this, &WindowManager::onDialogueWindowBye);
}
dialogueWindow->open(); dialogueWindow->open();
return; return;
} }
@ -349,6 +346,7 @@ void WindowManager::updateSkillArea()
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
{ {
std::cout << "dialogue a la poubelle";
assert(dialog); assert(dialog);
if (!dialog) if (!dialog)
return; return;
@ -387,7 +385,8 @@ void WindowManager::onDialogueWindowBye()
if (dialogueWindow) if (dialogueWindow)
{ {
//FIXME set some state and stuff? //FIXME set some state and stuff?
removeDialog(dialogueWindow); //removeDialog(dialogueWindow);
dialogueWindow->setVisible(false);
} }
setGuiMode(GM_Game); setGuiMode(GM_Game);
} }

@ -124,6 +124,8 @@ namespace MWGui
updateVisible(); updateVisible();
} }
MWGui::DialogueWindow* getDialogueWindow() {return dialogueWindow;}
MyGUI::Gui* getGui() const { return gui; } MyGUI::Gui* getGui() const { return gui; }
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount) void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)

@ -111,7 +111,6 @@ namespace MWRender{
Nif::NiTriShapeCopy& copy = *allshapesiter; Nif::NiTriShapeCopy& copy = *allshapesiter;
std::vector<Ogre::Vector3>* allvertices = &copy.vertices; std::vector<Ogre::Vector3>* allvertices = &copy.vertices;
std::vector<Ogre::Vector3>* allnormals = &copy.normals;
@ -182,7 +181,6 @@ namespace MWRender{
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second; std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
int verIndex = iter->first; int verIndex = iter->first;
Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
Ogre::Vector3 currentNormal = (*allnormals)[verIndex];
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
Ogre::Bone *bonePtr = 0; Ogre::Bone *bonePtr = 0;

@ -66,7 +66,7 @@ class Animation{
void stopScript(); void stopScript();
~Animation(); virtual ~Animation();
}; };
} }

@ -16,7 +16,7 @@ namespace MWRender{
class CreatureAnimation: public Animation{ class CreatureAnimation: public Animation{
public: public:
~CreatureAnimation(); virtual ~CreatureAnimation();
CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
virtual void runAnimation(float timepassed); virtual void runAnimation(float timepassed);

@ -20,7 +20,7 @@ class NpcAnimation: public Animation{
public: public:
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
~NpcAnimation(); virtual ~NpcAnimation();
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert); void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
virtual void runAnimation(float timepassed); virtual void runAnimation(float timepassed);

@ -51,7 +51,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
cameraPitchNode->attachObject(mRendering.getCamera()); cameraPitchNode->attachObject(mRendering.getCamera());
//mSkyManager = 0; //mSkyManager = 0;
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0; mSun = 0;
@ -210,8 +210,13 @@ void RenderingManager::configureFog(ESMS::CellStore<MWWorld::RefData> &mCell)
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
{ {
/// \todo make the viewing distance and fog start/end configurable /// \todo make the viewing distance and fog start/end configurable
float low = 3000 / density;
float high = 6200 / density; // right now we load 3x3 cells, so the maximum viewing distance we
// can allow (to prevent objects suddenly popping up) equals:
// 8192 * 0.69
// ^ cell size ^ minimum density value used (clear weather)
float low = 5652.48 / density / 2.f;
float high = 5652.48 / density;
mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high); mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high);

@ -10,16 +10,12 @@
#include <components/nifogre/ogre_nif_loader.hpp> #include <components/nifogre/ogre_nif_loader.hpp>
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
using namespace MWRender; using namespace MWRender;
using namespace Ogre; using namespace Ogre;
// the speed at which the clouds are animated
#define CLOUD_SPEED 0.001
// this distance has to be set accordingly so that the
// celestial bodies are behind the clouds, but in front of the atmosphere
#define CELESTIAL_BODY_DISTANCE 1000.f
BillboardObject::BillboardObject( const String& textureName, BillboardObject::BillboardObject( const String& textureName,
const float initialSize, const float initialSize,
const Vector3& position, const Vector3& position,
@ -50,7 +46,7 @@ void BillboardObject::setVisibility(const float visibility)
void BillboardObject::setPosition(const Vector3& pPosition) void BillboardObject::setPosition(const Vector3& pPosition)
{ {
Vector3 normalised = pPosition.normalisedCopy(); Vector3 normalised = pPosition.normalisedCopy();
Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE; Vector3 finalPosition = normalised * 1000.f;
mBBSet->setCommonDirection( -normalised ); mBBSet->setCommonDirection( -normalised );
@ -59,7 +55,8 @@ void BillboardObject::setPosition(const Vector3& pPosition)
Vector3 BillboardObject::getPosition() const Vector3 BillboardObject::getPosition() const
{ {
return mNode->getPosition(); Vector3 p = mNode->_getDerivedPosition() - mNode->getParentSceneNode()->_getDerivedPosition();
return Vector3(p.x, -p.z, p.y);
} }
void BillboardObject::setColour(const ColourValue& pColour) void BillboardObject::setColour(const ColourValue& pColour)
@ -84,7 +81,7 @@ void BillboardObject::init(const String& textureName,
{ {
SceneManager* sceneMgr = rootNode->getCreator(); SceneManager* sceneMgr = rootNode->getCreator();
Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE; Vector3 finalPosition = position.normalisedCopy() * 1000.f;
static unsigned int bodyCount=0; static unsigned int bodyCount=0;
@ -161,14 +158,20 @@ Moon::Moon( const String& textureName,
" in float2 uv : TEXCOORD0, \n" " in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n" " out float4 oColor : COLOR, \n"
" uniform sampler2D texture : TEXUNIT0, \n" " uniform sampler2D texture : TEXUNIT0, \n"
" uniform float4 skyColour, \n"
" uniform float4 diffuse, \n" " uniform float4 diffuse, \n"
" uniform float4 emissive \n" " uniform float4 emissive \n"
") \n" ") \n"
"{ \n" "{ \n"
" float4 tex = tex2D(texture, uv); \n" " float4 tex = tex2D(texture, uv); \n"
" oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,diffuse.a); \n" " oColor = float4(emissive.xyz,1) * tex; \n"
" float bump = pow((1-diffuse.a),4); \n" // use a circle for the alpha (compute UV distance to center)
" oColor.rgb += float3(bump, bump, bump)*0.5; \n" // looks a bit bad because its not filtered on the edges,
// but it's cheaper than a seperate alpha texture.
" float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n"
" oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n"
" oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour
" oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump
"}"; "}";
fshader->setSource(outStream2.str()); fshader->setSource(outStream2.str());
fshader->load(); fshader->load();
@ -186,10 +189,14 @@ void Moon::setType(const Moon::Type& type)
mType = type; mType = type;
} }
void Moon::setSkyColour(const Ogre::ColourValue& colour)
{
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("skyColour", colour);
}
/// \todo the moon phase rendering is not correct - the dark part of the moon does not occlude the stars
void Moon::setPhase(const Moon::Phase& phase) void Moon::setPhase(const Moon::Phase& phase)
{ {
// Colour texture
Ogre::String textureName = "textures\\tx_"; Ogre::String textureName = "textures\\tx_";
if (mType == Moon::Type_Secunda) textureName += "secunda_"; if (mType == Moon::Type_Secunda) textureName += "secunda_";
@ -285,9 +292,10 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock(); ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
} }
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) : SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env) :
mGlareFade(0), mGlareEnabled(false) mGlareFade(0), mGlareEnabled(false)
{ {
mEnvironment = env;
mViewport = pCamera->getViewport(); mViewport = pCamera->getViewport();
mSceneMgr = pMwRoot->getCreator(); mSceneMgr = pMwRoot->getCreator();
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode(); mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
@ -301,7 +309,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
Pass* pass = material->getTechnique(0)->getPass(0); Pass* pass = material->getTechnique(0)->getPass(0);
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mThunderTextureUnit = pass->createTextureUnitState(); mThunderTextureUnit = pass->createTextureUnitState();
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f));
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f); mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
OverlayManager& ovm = OverlayManager::getSingleton(); OverlayManager& ovm = OverlayManager::getSingleton();
mThunderOverlay = ovm.create( "ThunderOverlay" ); mThunderOverlay = ovm.create( "ThunderOverlay" );
@ -338,24 +346,11 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight = mRootNode->createChildSceneNode();
mAtmosphereNight->attachObject(night1_ent); mAtmosphereNight->attachObject(night1_ent);
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
{
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mStarsMaterials[i] = mp;
}
// Stars vertex shader // Stars vertex shader
HighLevelGpuProgramPtr vshader3 = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM); "cg", GPT_VERTEX_PROGRAM);
vshader3->setParameter("profiles", "vs_2_x arbvp1"); stars_vp->setParameter("profiles", "vs_2_x arbvp1");
vshader3->setParameter("entry_point", "main_vp"); stars_vp->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream4; StringUtil::StrStreamType outStream4;
outStream4 << outStream4 <<
"void main_vp( \n" "void main_vp( \n"
@ -371,10 +366,9 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
" oFade = (position.z > 50) ? 1.f : 0.f; \n" " oFade = (position.z > 50) ? 1.f : 0.f; \n"
" oPosition = mul( worldViewProj, position ); \n" " oPosition = mul( worldViewProj, position ); \n"
"}"; "}";
vshader3->setSource(outStream4.str()); stars_vp->setSource(outStream4.str());
vshader3->load(); stars_vp->load();
vshader3->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(vshader3->getName());
// Stars fragment shader // Stars fragment shader
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
@ -399,7 +393,20 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
stars_fp->load(); stars_fp->load();
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
night1_ent->getSubEntity(3)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
{
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName());
mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
mStarsMaterials[i] = mp;
}
// Atmosphere (day) // Atmosphere (day)
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
@ -494,7 +501,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
" uniform float4 emissive \n" " uniform float4 emissive \n"
") \n" ") \n"
"{ \n" "{ \n"
" uv += float2(1,1) * time * speed * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction " uv += float2(1,0) * time * speed * 0.003; \n" // Scroll in x direction
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n" " float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n" " oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
"}"; "}";
@ -548,7 +555,7 @@ void SkyManager::update(float duration)
if (!mEnabled) return; if (!mEnabled) return;
// UV Scroll the clouds // UV Scroll the clouds
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1); mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", mEnvironment->mWorld->getTimeScaleFactor()/30.f);
/// \todo improve this /// \todo improve this
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) ); mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
@ -583,6 +590,9 @@ void SkyManager::update(float duration)
mSun->setVisible(mSunEnabled); mSun->setVisible(mSunEnabled);
mMasser->setVisible(mMasserEnabled); mMasser->setVisible(mMasserEnabled);
mSecunda->setVisible(mSecundaEnabled); mSecunda->setVisible(mSecundaEnabled);
// rotate the stars by 360 degrees every 4 days
mAtmosphereNight->roll(Degree(mEnvironment->mWorld->getTimeScaleFactor()*duration*360 / (3600*96.f)));
} }
void SkyManager::enable() void SkyManager::enable()
@ -647,6 +657,8 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
if (mSkyColour != weather.mSkyColor) if (mSkyColour != weather.mSkyColor)
{ {
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
mMasser->setSkyColour(weather.mSkyColor);
mSecunda->setSkyColour(weather.mSkyColor);
mSkyColour = weather.mSkyColor; mSkyColour = weather.mSkyColor;
} }
@ -677,6 +689,7 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
strength = 1.f; strength = 1.f;
mSunGlare->setVisibility(weather.mGlareView * strength); mSunGlare->setVisibility(weather.mGlareView * strength);
mSun->setVisibility(strength);
mAtmosphereNight->setVisible(weather.mNight && mEnabled); mAtmosphereNight->setVisible(weather.mNight && mEnabled);
} }

@ -35,6 +35,8 @@ namespace MWRender
); );
BillboardObject(); BillboardObject();
virtual ~BillboardObject() {}
void setColour(const Ogre::ColourValue& pColour); void setColour(const Ogre::ColourValue& pColour);
void setPosition(const Ogre::Vector3& pPosition); void setPosition(const Ogre::Vector3& pPosition);
void setVisible(const bool visible); void setVisible(const bool visible);
@ -70,6 +72,8 @@ namespace MWRender
Ogre::SceneNode* rootNode Ogre::SceneNode* rootNode
); );
virtual ~Moon() {}
enum Phase enum Phase
{ {
Phase_New = 0, Phase_New = 0,
@ -90,6 +94,7 @@ namespace MWRender
void setPhase(const Phase& phase); void setPhase(const Phase& phase);
void setType(const Type& type); void setType(const Type& type);
void setSkyColour(const Ogre::ColourValue& colour);
Phase getPhase() const; Phase getPhase() const;
unsigned int getPhaseInt() const; unsigned int getPhaseInt() const;
@ -102,7 +107,7 @@ namespace MWRender
class SkyManager class SkyManager
{ {
public: public:
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera); SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env);
~SkyManager(); ~SkyManager();
void update(float duration); void update(float duration);
@ -159,6 +164,7 @@ namespace MWRender
Ogre::Vector3 getRealSunPos(); Ogre::Vector3 getRealSunPos();
private: private:
MWWorld::Environment* mEnvironment;
float mHour; float mHour;
int mDay; int mDay;
int mMonth; int mMonth;

@ -8,6 +8,7 @@
#include <components/interpreter/opcodes.hpp> #include <components/interpreter/opcodes.hpp>
#include "../mwdialogue/journal.hpp" #include "../mwdialogue/journal.hpp"
#include "../mwdialogue/dialoguemanager.hpp"
#include "interpretercontext.hpp" #include "interpretercontext.hpp"
@ -72,15 +73,62 @@ namespace MWScript
} }
}; };
class OpAddTopic : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string topic = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
context.getEnvironment().mDialogueManager->addTopic(topic);
}
};
class OpChoice : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
MWDialogue::DialogueManager* dialogue = context.getEnvironment().mDialogueManager;
while(arg0>0)
{
std::string question = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
arg0 = arg0 -1;
Interpreter::Type_Integer choice = 1;
if(arg0>0)
{
choice = runtime[0].mInteger;
runtime.pop();
arg0 = arg0 -1;
}
dialogue->askQuestion(question,choice);
}
}
};
const int opcodeJournal = 0x2000133; const int opcodeJournal = 0x2000133;
const int opcodeSetJournalIndex = 0x2000134; const int opcodeSetJournalIndex = 0x2000134;
const int opcodeGetJournalIndex = 0x2000135; const int opcodeGetJournalIndex = 0x2000135;
const int opcodeAddTopic = 0x200013a;
const int opcodeChoice = 0x2000a;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
extensions.registerInstruction ("journal", "cl", opcodeJournal); extensions.registerInstruction ("journal", "cl", opcodeJournal);
extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex); extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex);
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex); extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic);
extensions.registerInstruction ("choice", "/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -88,6 +136,8 @@ namespace MWScript
interpreter.installSegment5 (opcodeJournal, new OpJournal); interpreter.installSegment5 (opcodeJournal, new OpJournal);
interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex); interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex);
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex); interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
interpreter.installSegment5 (opcodeAddTopic, new OpAddTopic);
interpreter.installSegment3 (opcodeChoice,new OpChoice);
} }
} }

@ -23,7 +23,8 @@ op 0x20006: PlayAnim
op 0x20007: PlayAnim, explicit reference op 0x20007: PlayAnim, explicit reference
op 0x20008: LoopAnim op 0x20008: LoopAnim
op 0x20009: LoopAnim, explicit reference op 0x20009: LoopAnim, explicit reference
opcodes 0x2000a-0x3ffff unused op 0x2000a: Choice
opcodes 0x2000b-0x3ffff unused
Segment 4: Segment 4:
(not implemented yet) (not implemented yet)
@ -115,6 +116,7 @@ op 0x2000136: GetPCCell
op 0x2000137: GetButtonPressed op 0x2000137: GetButtonPressed
op 0x2000138: SkipAnim op 0x2000138: SkipAnim
op 0x2000139: SkipAnim, expplicit reference op 0x2000139: SkipAnim, expplicit reference
op 0x200013a: AddTopic
op 0x200013b: twf op 0x200013b: twf
op 0x200013c: FadeIn op 0x200013c: FadeIn
op 0x200013d: FadeOut op 0x200013d: FadeOut

@ -63,7 +63,7 @@ namespace MWScript
{ {
std::vector<Interpreter::Type_Code> code; std::vector<Interpreter::Type_Code> code;
mParser.getCode (code); mParser.getCode (code);
mScripts.insert (std::make_pair (name, code)); mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals())));
// TODO sanity check on generated locals // TODO sanity check on generated locals
@ -77,8 +77,7 @@ namespace MWScript
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext) void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
{ {
// compile script // compile script
std::map<std::string, std::vector<Interpreter::Type_Code> >::iterator iter = ScriptCollection::iterator iter = mScripts.find (name);
mScripts.find (name);
if (iter==mScripts.end()) if (iter==mScripts.end())
{ {
@ -86,7 +85,7 @@ namespace MWScript
{ {
// failed -> ignore script from now on. // failed -> ignore script from now on.
std::vector<Interpreter::Type_Code> empty; std::vector<Interpreter::Type_Code> empty;
mScripts.insert (std::make_pair (name, empty)); mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
return; return;
} }
@ -95,7 +94,7 @@ namespace MWScript
} }
// execute script // execute script
if (!iter->second.empty()) if (!iter->second.first.empty())
try try
{ {
if (!mOpcodesInstalled) if (!mOpcodesInstalled)
@ -104,7 +103,7 @@ namespace MWScript
mOpcodesInstalled = true; mOpcodesInstalled = true;
} }
mInterpreter.run (&iter->second[0], iter->second.size(), interpreterContext); mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -113,7 +112,7 @@ namespace MWScript
if (mVerbose) if (mVerbose)
std::cerr << "(" << e.what() << ")" << std::endl; std::cerr << "(" << e.what() << ")" << std::endl;
iter->second.clear(); // don't execute again. iter->second.first.clear(); // don't execute again.
} }
} }
@ -132,4 +131,24 @@ namespace MWScript
return std::make_pair (count, success); return std::make_pair (count, success);
} }
Compiler::Locals& ScriptManager::getLocals (const std::string& name)
{
ScriptCollection::iterator iter = mScripts.find (name);
if (iter==mScripts.end())
{
if (!compile (name))
{
// failed -> ignore script from now on.
std::vector<Interpreter::Type_Code> empty;
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
throw std::runtime_error ("failed to compile script " + name);
}
iter = mScripts.find (name);
}
return iter->second.second;
}
} }

@ -39,7 +39,11 @@ namespace MWScript
Interpreter::Interpreter mInterpreter; Interpreter::Interpreter mInterpreter;
bool mOpcodesInstalled; bool mOpcodesInstalled;
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts; typedef std::pair<std::vector<Interpreter::Type_Code>, Compiler::Locals> CompiledScript;
typedef std::map<std::string, CompiledScript> ScriptCollection;
ScriptCollection mScripts;
public: public:
@ -56,6 +60,9 @@ namespace MWScript
std::pair<int, int> compileAll(); std::pair<int, int> compileAll();
///< Compile all scripts ///< Compile all scripts
/// \return count, success /// \return count, success
Compiler::Locals& getLocals (const std::string& name);
///< Return locals for script \a name.
}; };
}; };

@ -67,6 +67,7 @@ namespace MWSound
, updater(mgr) , updater(mgr)
, cameraTracker(mgr) , cameraTracker(mgr)
, mCurrentPlaylist(NULL) , mCurrentPlaylist(NULL)
, mUsingSound(useSound)
{ {
if(useSound) if(useSound)
{ {
@ -105,8 +106,11 @@ namespace MWSound
SoundManager::~SoundManager() SoundManager::~SoundManager()
{ {
Ogre::Root::getSingleton().removeFrameListener(&updater); if(mUsingSound)
cameraTracker.unfollowCamera(); {
Ogre::Root::getSingleton().removeFrameListener(&updater);
cameraTracker.unfollowCamera();
}
} }
// Convert a soundId to file name, and modify the volume // Convert a soundId to file name, and modify the volume
@ -136,7 +140,7 @@ namespace MWSound
max = std::max(min, max); max = std::max(min, max);
} }
return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict); return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict, false);
} }
// Add a sound to the list and play it // Add a sound to the list and play it
@ -145,7 +149,7 @@ namespace MWSound
const std::string &id, const std::string &id,
float volume, float pitch, float volume, float pitch,
float min, float max, float min, float max,
bool loop) bool loop, bool untracked)
{ {
try try
{ {
@ -157,7 +161,10 @@ namespace MWSound
setPos(snd, ptr); setPos(snd, ptr);
snd->play(); snd->play();
sounds[ptr][id] = WSoundPtr(snd); if (!untracked)
{
sounds[ptr][id] = WSoundPtr(snd);
}
} }
catch(...) catch(...)
{ {
@ -290,7 +297,7 @@ namespace MWSound
void SoundManager::streamMusic(const std::string& filename) void SoundManager::streamMusic(const std::string& filename)
{ {
std::string filePath = mMusicLibrary.locate(filename, mFSStrict).string(); std::string filePath = mMusicLibrary.locate(filename, mFSStrict, true).string();
if(!filePath.empty()) if(!filePath.empty())
{ {
streamMusicFull(filePath); streamMusicFull(filePath);
@ -351,6 +358,9 @@ namespace MWSound
void SoundManager::playPlaylist(std::string playlist) void SoundManager::playPlaylist(std::string playlist)
{ {
if (!mUsingSound)
return;
if (playlist == "") if (playlist == "")
{ {
if(!isMusicPlaying()) if(!isMusicPlaying())
@ -372,8 +382,11 @@ namespace MWSound
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
{ {
if (!mUsingSound)
return;
// The range values are not tested // The range values are not tested
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict); std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true);
if(!filePath.empty()) if(!filePath.empty())
add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false); add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false);
else else
@ -397,6 +410,7 @@ namespace MWSound
snd->setVolume(volume); snd->setVolume(volume);
snd->setRange(min,max); snd->setRange(min,max);
snd->setPitch(pitch); snd->setPitch(pitch);
snd->setRelative(true);
snd->play(); snd->play();
if (loop) if (loop)
@ -412,13 +426,13 @@ namespace MWSound
} }
void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId,
float volume, float pitch, bool loop) float volume, float pitch, bool loop, bool untracked)
{ {
// Look up the sound in the ESM data // Look up the sound in the ESM data
float min, max; float min, max;
const std::string &file = lookup(soundId, volume, min, max); const std::string &file = lookup(soundId, volume, min, max);
if (file != "") if (file != "")
add(file, ptr, soundId, volume, pitch, min, max, loop); add(file, ptr, soundId, volume, pitch, min, max, loop, untracked);
} }
void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId) void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId)

@ -82,12 +82,14 @@ namespace MWSound
IDMap mLoopedSounds; IDMap mLoopedSounds;
bool mUsingSound;
std::string lookup(const std::string &soundId, std::string lookup(const std::string &soundId,
float &volume, float &min, float &max); float &volume, float &min, float &max);
void add(const std::string &file, void add(const std::string &file,
MWWorld::Ptr ptr, const std::string &id, MWWorld::Ptr ptr, const std::string &id,
float volume, float pitch, float min, float max, float volume, float pitch, float min, float max,
bool loop); bool loop, bool untracked=false);
void clearAll(PtrMap::iterator& it); void clearAll(PtrMap::iterator& it);
void remove(MWWorld::Ptr ptr, const std::string &id = ""); void remove(MWWorld::Ptr ptr, const std::string &id = "");
bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const; bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const;
@ -136,7 +138,7 @@ namespace MWSound
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
void playSound3D (MWWorld::Ptr reference, const std::string& soundId, void playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, bool loop); float volume, float pitch, bool loop, bool untracked=false);
///< Play a sound from an object ///< Play a sound from an object
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = ""); void stopSound3D (MWWorld::Ptr reference, const std::string& soundId = "");

@ -5,6 +5,8 @@
#include <algorithm> #include <algorithm>
#include "world.hpp" #include "world.hpp"
#include "class.hpp"
#include "containerstore.hpp"
MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell)
{ {
@ -35,6 +37,39 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell)
} }
} }
void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
{
for (ESMS::CellRefList<ESM::Container, RefData>::List::iterator iter (
cellStore.containers.list.begin());
iter!=cellStore.containers.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->inventory, mStore);
}
for (ESMS::CellRefList<ESM::Creature, RefData>::List::iterator iter (
cellStore.creatures.list.begin());
iter!=cellStore.creatures.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->inventory, mStore);
}
for (ESMS::CellRefList<ESM::NPC, RefData>::List::iterator iter (
cellStore.npcs.list.begin());
iter!=cellStore.npcs.list.end(); ++iter)
{
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->base->inventory, mStore);
}
}
MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world) MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world)
: mStore (store), mReader (reader), mWorld (world) {} : mStore (store), mReader (reader), mWorld (world) {}
@ -43,6 +78,8 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y)
std::map<std::pair<int, int>, Ptr::CellStore>::iterator result = std::map<std::pair<int, int>, Ptr::CellStore>::iterator result =
mExteriors.find (std::make_pair (x, y)); mExteriors.find (std::make_pair (x, y));
bool fill = false;
if (result==mExteriors.end()) if (result==mExteriors.end())
{ {
const ESM::Cell *cell = mStore.cells.searchExt (x, y); const ESM::Cell *cell = mStore.cells.searchExt (x, y);
@ -63,11 +100,16 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y)
result = mExteriors.insert (std::make_pair ( result = mExteriors.insert (std::make_pair (
std::make_pair (x, y), Ptr::CellStore (cell))).first; std::make_pair (x, y), Ptr::CellStore (cell))).first;
fill = true;
} }
if (result->second.mState!=Ptr::CellStore::State_Loaded) if (result->second.mState!=Ptr::CellStore::State_Loaded)
result->second.load (mStore, mReader); result->second.load (mStore, mReader);
if (fill)
fillContainers (result->second);
return &result->second; return &result->second;
} }
@ -75,16 +117,23 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
{ {
std::map<std::string, Ptr::CellStore>::iterator result = mInteriors.find (name); std::map<std::string, Ptr::CellStore>::iterator result = mInteriors.find (name);
bool fill = false;
if (result==mInteriors.end()) if (result==mInteriors.end())
{ {
const ESM::Cell *cell = mStore.cells.findInt (name); const ESM::Cell *cell = mStore.cells.findInt (name);
result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first;
fill = true;
} }
if (result->second.mState!=Ptr::CellStore::State_Loaded) if (result->second.mState!=Ptr::CellStore::State_Loaded)
result->second.load (mStore, mReader); result->second.load (mStore, mReader);
if (fill)
fillContainers (result->second);
return &result->second; return &result->second;
} }

@ -34,6 +34,8 @@ namespace MWWorld
Ptr::CellStore *getCellStore (const ESM::Cell *cell); Ptr::CellStore *getCellStore (const ESM::Cell *cell);
void fillContainers (Ptr::CellStore& cellStore);
public: public:
Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world); Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world);

@ -77,6 +77,11 @@ namespace MWWorld
throw std::runtime_error ("class does not have a container store"); throw std::runtime_error ("class does not have a container store");
} }
InventoryStore& Class::getInventoryStore (const Ptr& ptr) const
{
throw std::runtime_error ("class does not have an inventory store");
}
void Class::lock (const Ptr& ptr, int lockLevel) const void Class::lock (const Ptr& ptr, int lockLevel) const
{ {
throw std::runtime_error ("class does not support locking"); throw std::runtime_error ("class does not support locking");
@ -122,6 +127,16 @@ namespace MWWorld
return Ogre::Vector3 (0, 0, 0); return Ogre::Vector3 (0, 0, 0);
} }
std::pair<std::vector<int>, bool> Class::getEquipmentSlots (const Ptr& ptr) const
{
return std::make_pair (std::vector<int>(), false);
}
int Class::getEquipmentSkill (const Ptr& ptr, const Environment& environment) const
{
return -1;
}
const Class& Class::get (const std::string& key) const Class& Class::get (const std::string& key)
{ {
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key); std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);
@ -141,4 +156,14 @@ namespace MWWorld
{ {
sClasses.insert (std::make_pair (key, instance)); sClasses.insert (std::make_pair (key, instance));
} }
std::string Class::getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const
{
throw std::runtime_error ("class does not have an up sound");
}
std::string Class::getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const
{
throw std::runtime_error ("class does not have an down sound");
}
} }

@ -3,6 +3,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <vector>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@ -34,6 +35,7 @@ namespace MWWorld
class Ptr; class Ptr;
class Environment; class Environment;
class ContainerStore; class ContainerStore;
class InventoryStore;
/// \brief Base class for referenceable esm records /// \brief Base class for referenceable esm records
class Class class Class
@ -108,6 +110,10 @@ namespace MWWorld
///< Return container store or throw an exception, if class does not have a ///< Return container store or throw an exception, if class does not have a
/// container store (default implementation: throw an exceoption) /// container store (default implementation: throw an exceoption)
virtual InventoryStore& getInventoryStore (const Ptr& ptr) const;
///< Return inventory store or throw an exception, if class does not have a
/// inventory store (default implementation: throw an exceoption)
virtual void lock (const Ptr& ptr, int lockLevel) const; virtual void lock (const Ptr& ptr, int lockLevel) const;
///< Lock object (default implementation: throw an exception) ///< Lock object (default implementation: throw an exception)
@ -137,6 +143,18 @@ namespace MWWorld
///< Return desired movement vector (determined based on movement settings, ///< Return desired movement vector (determined based on movement settings,
/// stance and stats). /// stance and stats).
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const Ptr& ptr) const;
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
/// stay stacked when equipped?
///
/// Default implementation: return (empty vector, false).
virtual int getEquipmentSkill (const Ptr& ptr, const Environment& environment)
const;
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
/// no such skill.
/// (default implementation: return -1)
static const Class& get (const std::string& key); static const Class& get (const std::string& key);
///< If there is no class for this \a key, an exception is thrown. ///< If there is no class for this \a key, an exception is thrown.
@ -144,6 +162,14 @@ namespace MWWorld
///< If there is no class for this pointer, an exception is thrown. ///< If there is no class for this pointer, an exception is thrown.
static void registerClass (const std::string& key, boost::shared_ptr<Class> instance); static void registerClass (const std::string& key, boost::shared_ptr<Class> instance);
virtual std::string getUpSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the up sound ID of \a ptr or throw an exception, if class does not support ID retrieval
/// (default implementation: throw an exception)
virtual std::string getDownSoundId (const Ptr& ptr, const MWWorld::Environment& environment) const;
///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval
/// (default implementation: throw an exception)
}; };
} }

@ -5,6 +5,12 @@
#include <typeinfo> #include <typeinfo>
#include <stdexcept> #include <stdexcept>
#include <components/esm/loadcont.hpp>
#include "manualref.hpp"
MWWorld::ContainerStore::~ContainerStore() {}
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::begin (int mask) MWWorld::ContainerStoreIterator MWWorld::ContainerStore::begin (int mask)
{ {
return ContainerStoreIterator (mask, this); return ContainerStoreIterator (mask, this);
@ -17,7 +23,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
void MWWorld::ContainerStore::add (const Ptr& ptr) void MWWorld::ContainerStore::add (const Ptr& ptr)
{ {
/// \todo implement item stocking /// \todo implement item stacking
switch (getType (ptr)) switch (getType (ptr))
{ {
@ -36,6 +42,40 @@ void MWWorld::ContainerStore::add (const Ptr& ptr)
} }
} }
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const ESMS::ESMStore& store)
{
for (std::vector<ESM::ContItem>::const_iterator iter (items.list.begin()); iter!=items.list.end();
++iter)
{
ManualRef ref (store, iter->item.toString());
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
{
/// \todo implement leveled item lists
continue;
}
ref.getPtr().getRefData().setCount (iter->count);
add (ref.getPtr());
}
}
void MWWorld::ContainerStore::clear()
{
potions.list.clear();
appas.list.clear();
armors.list.clear();
books.list.clear();
clothes.list.clear();
ingreds.list.clear();
lights.list.clear();
lockpicks.list.clear();
miscItems.list.clear();
probes.list.clear();
repairs.list.clear();
weapons.list.clear();
}
int MWWorld::ContainerStore::getType (const Ptr& ptr) int MWWorld::ContainerStore::getType (const Ptr& ptr)
{ {
if (ptr.isEmpty()) if (ptr.isEmpty())
@ -331,6 +371,11 @@ int MWWorld::ContainerStoreIterator::getType() const
return mType; return mType;
} }
const MWWorld::ContainerStore *MWWorld::ContainerStoreIterator::getContainerStore() const
{
return mContainer;
}
bool MWWorld::operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right) bool MWWorld::operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right)
{ {
return left.isEqual (right); return left.isEqual (right);

@ -1,11 +1,18 @@
#ifndef GAME_MWWORLD_CONTAINERSTORE_H #ifndef GAME_MWWORLD_CONTAINERSTORE_H
#define GAME_MWWORLD_CONTAINERSTORE_H #define GAME_MWWORLD_CONTAINERSTORE_H
#include <iterator>
#include <components/esm_store/cell_store.hpp> #include <components/esm_store/cell_store.hpp>
#include "refdata.hpp" #include "refdata.hpp"
#include "ptr.hpp" #include "ptr.hpp"
namespace ESM
{
struct InventoryList;
}
namespace MWWorld namespace MWWorld
{ {
class ContainerStoreIterator; class ContainerStoreIterator;
@ -48,6 +55,8 @@ namespace MWWorld
public: public:
virtual ~ContainerStore();
ContainerStoreIterator begin (int mask = Type_All); ContainerStoreIterator begin (int mask = Type_All);
ContainerStoreIterator end(); ContainerStoreIterator end();
@ -60,6 +69,12 @@ namespace MWWorld
/// \attention Do not add items to an existing stack by increasing the count instead of /// \attention Do not add items to an existing stack by increasing the count instead of
/// calling this function! /// calling this function!
void fill (const ESM::InventoryList& items, const ESMS::ESMStore& store);
///< Insert items into *this.
void clear();
///< Empty container.
static int getType (const Ptr& ptr); static int getType (const Ptr& ptr);
///< This function throws an exception, if ptr does not point to an object, that can be ///< This function throws an exception, if ptr does not point to an object, that can be
/// put into a container. /// put into a container.
@ -71,6 +86,7 @@ namespace MWWorld
/// ///
/// \note The iterator will automatically skip over deleted objects. /// \note The iterator will automatically skip over deleted objects.
class ContainerStoreIterator class ContainerStoreIterator
: public std::iterator<std::forward_iterator_tag, Ptr, std::ptrdiff_t, Ptr *, Ptr&>
{ {
int mType; int mType;
int mMask; int mMask;
@ -126,6 +142,8 @@ namespace MWWorld
int getType() const; int getType() const;
const ContainerStore *getContainerStore() const;
friend class ContainerStore; friend class ContainerStore;
}; };

@ -9,6 +9,7 @@ namespace MWSound
namespace MWScript namespace MWScript
{ {
class GlobalScripts; class GlobalScripts;
class ScriptManager;
} }
namespace MWGui namespace MWGui
@ -41,7 +42,7 @@ namespace MWWorld
{ {
public: public:
Environment() Environment()
: mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), : mWorld (0), mSoundManager (0), mGlobalScripts (0), mScriptManager (0), mWindowManager (0),
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0), mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0),
mInputManager (0) mInputManager (0)
{} {}
@ -49,6 +50,7 @@ namespace MWWorld
World *mWorld; World *mWorld;
MWSound::SoundManager *mSoundManager; MWSound::SoundManager *mSoundManager;
MWScript::GlobalScripts *mGlobalScripts; MWScript::GlobalScripts *mGlobalScripts;
MWScript::ScriptManager *mScriptManager;
MWGui::WindowManager *mWindowManager; MWGui::WindowManager *mWindowManager;
MWMechanics::MechanicsManager *mMechanicsManager; MWMechanics::MechanicsManager *mMechanicsManager;
MWDialogue::DialogueManager *mDialogueManager; MWDialogue::DialogueManager *mDialogueManager;

@ -0,0 +1,86 @@
#include "inventorystore.hpp"
#include <iterator>
#include <algorithm>
#include "class.hpp"
void MWWorld::InventoryStore::copySlots (const InventoryStore& store)
{
// some const-trickery, required because of a flaw in the handling of MW-references and the
// resulting workarounds
for (std::vector<ContainerStoreIterator>::const_iterator iter (
const_cast<InventoryStore&> (store).mSlots.begin());
iter!=const_cast<InventoryStore&> (store).mSlots.end(); ++iter)
{
std::size_t distance = std::distance (const_cast<InventoryStore&> (store).begin(), *iter);
ContainerStoreIterator slot = begin();
std::advance (slot, distance);
mSlots.push_back (slot);
}
}
MWWorld::InventoryStore::InventoryStore()
{
for (int i=0; i<Slots; ++i)
mSlots.push_back (end());
}
MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
: ContainerStore (store)
{
copySlots (store);
}
MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store)
{
ContainerStore::operator= (store);
mSlots.clear();
copySlots (store);
return *this;
}
void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& iterator)
{
if (slot<0 || slot>=static_cast<int> (mSlots.size()))
throw std::runtime_error ("slot number out of range");
if (iterator.getContainerStore()!=this)
throw std::runtime_error ("attempt to equip an item that is not in the inventory");
if (iterator!=end())
{
std::pair<std::vector<int>, bool> slots = Class::get (*iterator).getEquipmentSlots (*iterator);
if (std::find (slots.first.begin(), slots.first.end(), slot)==slots.first.end())
throw std::runtime_error ("invalid slot");
}
/// \todo restack item previously in this slot (if required)
/// \todo unstack item pointed to by iterator if required)
mSlots[slot] = iterator;
}
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot)
{
if (slot<0 || slot>=static_cast<int> (mSlots.size()))
throw std::runtime_error ("slot number out of range");
if (mSlots[slot]==end())
return end();
if (mSlots[slot]->getRefData().getCount()<1)
{
// object has been deleted
mSlots[slot] = end();
return end();
}
return mSlots[slot];
}

@ -0,0 +1,58 @@
#ifndef GAME_MWWORLD_INVENTORYSTORE_H
#define GAME_MWWORLD_INVENTORYSTORE_H
#include "containerstore.hpp"
namespace MWWorld
{
///< \brief Variant of the ContainerStore for NPCs
class InventoryStore : public ContainerStore
{
public:
static const int Slot_Helmet = 0;
static const int Slot_Cuirass = 1;
static const int Slot_Greaves = 2;
static const int Slot_LeftPauldron = 3;
static const int Slot_RightPauldron = 4;
static const int Slot_LeftGauntlet = 5;
static const int Slot_RightGauntlet = 6;
static const int Slot_Boots = 7;
static const int Slot_Shirt = 8;
static const int Slot_Pants = 9;
static const int Slot_Skirt = 10;
static const int Slot_Robe = 11;
static const int Slot_LeftRing = 12;
static const int Slot_RightRing = 13;
static const int Slot_Amulet = 14;
static const int Slot_Belt = 15;
static const int Slot_CarriedRight = 16;
static const int Slot_CarriedLeft = 17;
static const int Slot_Ammunition = 18;
static const int Slots = 19;
static const int Slot_NoSlot = -1;
private:
mutable std::vector<ContainerStoreIterator> mSlots;
void copySlots (const InventoryStore& store);
public:
InventoryStore();
InventoryStore (const InventoryStore& store);
InventoryStore& operator= (const InventoryStore& store);
void equip (int slot, const ContainerStoreIterator& iterator);
///< \note \a iteartor can be an end-iterator
ContainerStoreIterator getSlot (int slot);
};
}
#endif

@ -26,6 +26,7 @@ const float WeatherGlobals::mSunsetTime = 18;
const float WeatherGlobals::mSunriseDuration = 2; const float WeatherGlobals::mSunriseDuration = 2;
const float WeatherGlobals::mSunsetDuration = 2; const float WeatherGlobals::mSunsetDuration = 2;
const float WeatherGlobals::mWeatherUpdateTime = 20.f; const float WeatherGlobals::mWeatherUpdateTime = 20.f;
const float WeatherGlobals::mThunderFrequency = .4; const float WeatherGlobals::mThunderFrequency = .4;
const float WeatherGlobals::mThunderThreshold = 0.6; const float WeatherGlobals::mThunderThreshold = 0.6;
const float WeatherGlobals::mThunderSoundDelay = 0.25; const float WeatherGlobals::mThunderSoundDelay = 0.25;
@ -328,6 +329,9 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environmen
void WeatherManager::setWeather(const String& weather, bool instant) void WeatherManager::setWeather(const String& weather, bool instant)
{ {
if (weather == mCurrentWeather && mNextWeather == "")
return;
if (instant || mFirstUpdate) if (instant || mFirstUpdate)
{ {
mNextWeather = ""; mNextWeather = "";
@ -339,12 +343,12 @@ void WeatherManager::setWeather(const String& weather, bool instant)
if (mNextWeather != "") if (mNextWeather != "")
{ {
// transition more than 50% finished? // transition more than 50% finished?
if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60) <= 0.5) if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600) <= 0.5)
mCurrentWeather = mNextWeather; mCurrentWeather = mNextWeather;
} }
mNextWeather = weather; mNextWeather = weather;
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60; mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600;
} }
} }
@ -362,15 +366,12 @@ WeatherResult WeatherManager::getResult(const String& weather)
result.mAmbientLoopSoundID = current.mAmbientLoopSoundID; result.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
result.mSunColor = current.mSunDiscSunsetColor; result.mSunColor = current.mSunDiscSunsetColor;
const float fade_duration = current.mTransitionDelta * 24.f; result.mNight = (mHour < 6 || mHour > 19);
result.mNight = (mHour < 6.f+fade_duration || mHour > 20.f-fade_duration);
result.mFogDepth = result.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth; result.mFogDepth = result.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
// night // night
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration) if (mHour <= 5.5f || mHour >= 21)
|| mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration))
{ {
result.mFogColor = current.mFogNightColor; result.mFogColor = current.mFogNightColor;
result.mAmbientColor = current.mAmbientNightColor; result.mAmbientColor = current.mAmbientNightColor;
@ -380,40 +381,33 @@ WeatherResult WeatherManager::getResult(const String& weather)
} }
// sunrise // sunrise
else if (mHour >= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration) && mHour <= WeatherGlobals::mSunriseTime) else if (mHour >= 5.5f && mHour <= 9)
{ {
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration)) if (mHour <= 6)
{ {
// fade in // fade in
float advance = (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration)-mHour; float advance = 6-mHour;
float factor = (advance / fade_duration); float factor = advance / 0.5f;
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor); result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor);
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor); result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor);
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor); result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor);
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor); result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor);
result.mNightFade = factor; result.mNightFade = factor;
} }
else if (mHour >= (WeatherGlobals::mSunriseTime-fade_duration)) else //if (mHour >= 6)
{ {
// fade out // fade out
float advance = mHour-(WeatherGlobals::mSunriseTime-fade_duration); float advance = mHour-6;
float factor = advance / fade_duration; float factor = advance / 3.f;
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor); result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor);
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor); result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor);
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor); result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor);
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor); result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor);
} }
else
{
result.mFogColor = current.mFogSunriseColor;
result.mAmbientColor = current.mAmbientSunriseColor;
result.mSunColor = current.mSunSunriseColor;
result.mSkyColor = current.mSkySunriseColor;
}
} }
// day // day
else if (mHour >= (WeatherGlobals::mSunriseTime) && mHour <= (WeatherGlobals::mSunsetTime)) else if (mHour >= 9 && mHour <= 17)
{ {
result.mFogColor = current.mFogDayColor; result.mFogColor = current.mFogDayColor;
result.mAmbientColor = current.mAmbientDayColor; result.mAmbientColor = current.mAmbientDayColor;
@ -422,36 +416,29 @@ WeatherResult WeatherManager::getResult(const String& weather)
} }
// sunset // sunset
else if (mHour >= (WeatherGlobals::mSunsetTime) && mHour <= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration)) else if (mHour >= 17 && mHour <= 21)
{ {
if (mHour <= (WeatherGlobals::mSunsetTime+fade_duration)) if (mHour <= 19)
{ {
// fade in // fade in
float advance = (WeatherGlobals::mSunsetTime+fade_duration)-mHour; float advance = 19-mHour;
float factor = (advance / fade_duration); float factor = (advance / 2);
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor); result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor);
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor); result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor);
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor); result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor);
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor); result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor);
} }
else if (mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration)) else //if (mHour >= 19)
{ {
// fade out // fade out
float advance = mHour-(WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration); float advance = mHour-19;
float factor = advance / fade_duration; float factor = advance / 2.f;
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor); result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor);
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor); result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor);
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor); result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor);
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor); result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor);
result.mNightFade = factor; result.mNightFade = factor;
} }
else
{
result.mFogColor = current.mFogSunsetColor;
result.mAmbientColor = current.mAmbientSunsetColor;
result.mSunColor = current.mSunSunsetColor;
result.mSkyColor = current.mSkySunsetColor;
}
} }
return result; return result;
@ -476,27 +463,23 @@ WeatherResult WeatherManager::transition(float factor)
result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor); result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor);
result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth); result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth);
result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed); result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed);
result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed); //result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed);
result.mCloudSpeed = current.mCloudSpeed;
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity); result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
result.mGlareView = lerp(current.mGlareView, other.mGlareView); result.mGlareView = lerp(current.mGlareView, other.mGlareView);
result.mNight = current.mNight; result.mNight = current.mNight;
// sound change behaviour:
// if 'other' has a new sound, switch to it after 1/2 of the transition length
if (other.mAmbientLoopSoundID != "")
result.mAmbientLoopSoundID = factor>0.5 ? other.mAmbientLoopSoundID : current.mAmbientLoopSoundID;
// if 'current' has a sound and 'other' does not have a sound, turn off the sound immediately
else if (current.mAmbientLoopSoundID != "")
result.mAmbientLoopSoundID = "";
return result; return result;
} }
void WeatherManager::update(float duration) void WeatherManager::update(float duration)
{ {
mWeatherUpdateTime -= duration; mWeatherUpdateTime -= duration * mEnvironment->mWorld->getTimeScaleFactor();
if (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior())
bool exterior = (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior());
if (exterior)
{ {
std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region; std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region;
boost::algorithm::to_lower(regionstr); boost::algorithm::to_lower(regionstr);
@ -504,7 +487,7 @@ void WeatherManager::update(float duration)
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
{ {
mCurrentRegion = regionstr; mCurrentRegion = regionstr;
mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*60.f; mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*3600;
std::string weather; std::string weather;
@ -555,22 +538,13 @@ void WeatherManager::update(float duration)
} }
setWeather(weather, false); setWeather(weather, false);
/*
std::cout << "roll result: " << random << std::endl;
std::cout << regionstr << " weather probabilities: " << clear << " " << cloudy << " " << foggy << " "
<< overcast << " " << rain << " " << thunder << " " << ash << " " << blight << " " << snow << " "
<< blizzard << std::endl;
std::cout << "New weather : " << weather << std::endl;
*/
} }
WeatherResult result; WeatherResult result;
if (mNextWeather != "") if (mNextWeather != "")
{ {
mRemainingTransitionTime -= duration; mRemainingTransitionTime -= duration * mEnvironment->mWorld->getTimeScaleFactor();
if (mRemainingTransitionTime < 0) if (mRemainingTransitionTime < 0)
{ {
mCurrentWeather = mNextWeather; mCurrentWeather = mNextWeather;
@ -579,29 +553,36 @@ void WeatherManager::update(float duration)
} }
if (mNextWeather != "") if (mNextWeather != "")
result = transition(1-(mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60))); result = transition(1-(mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600)));
else else
result = getResult(mCurrentWeather); result = getResult(mCurrentWeather);
mRendering->configureFog(result.mFogDepth, result.mFogColor); mRendering->configureFog(result.mFogDepth, result.mFogColor);
// disable sun during night // disable sun during night
if (mHour >= WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration if (mHour >= 20 || mHour <= 6.f)
|| mHour <= WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration)
mRendering->getSkyManager()->sunDisable(); mRendering->getSkyManager()->sunDisable();
else else
{
// during day, calculate sun angle
float height = 1-std::abs(((mHour-13)/7.f));
int facing = mHour > 13.f ? 1 : -1;
Vector3 final(
(1-height)*facing,
(1-height)*facing,
height);
mRendering->setSunDirection(final);
mRendering->getSkyManager()->sunEnable(); mRendering->getSkyManager()->sunEnable();
}
// sun angle
float height;
// rise at 6, set at 20
if (mHour >= 6 && mHour <= 20)
height = 1-std::abs(((mHour-13)/7.f));
else if (mHour > 20)
height = (mHour-20.f)/4.f;
else //if (mHour > 0 && mHour < 6)
height = 1-(mHour/6.f);
int facing = (mHour > 13.f) ? 1 : -1;
Vector3 final(
(1-height)*facing,
(1-height)*facing,
height);
mRendering->setSunDirection(final);
// moon calculations // moon calculations
float night; float night;
@ -671,7 +652,7 @@ void WeatherManager::update(float duration)
mRendering->getSkyManager()->secundaDisable(); mRendering->getSkyManager()->secundaDisable();
} }
if (mCurrentWeather == "thunderstorm" && mNextWeather == "") if (mCurrentWeather == "thunderstorm" && mNextWeather == "" && exterior)
{ {
if (mThunderFlash > 0) if (mThunderFlash > 0)
{ {
@ -730,19 +711,46 @@ void WeatherManager::update(float duration)
mRendering->skyDisable(); mRendering->skyDisable();
mRendering->getSkyManager()->setThunder(0.f); mRendering->getSkyManager()->setThunder(0.f);
} }
// play sounds
std::string ambientSnd = (mNextWeather == "" ? mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID : "");
if (!exterior) ambientSnd = "";
if (ambientSnd != "")
{
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end())
{
mSoundsPlaying.push_back(ambientSnd);
mEnvironment->mSoundManager->playSound(ambientSnd, 1.0, 1.0, true);
}
}
std::string rainSnd = (mNextWeather == "" ? mWeatherSettings[mCurrentWeather].mRainLoopSoundID : "");
if (!exterior) rainSnd = "";
if (rainSnd != "")
{
if (std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end())
{
mSoundsPlaying.push_back(rainSnd);
mEnvironment->mSoundManager->playSound(rainSnd, 1.0, 1.0, true);
}
}
// stop sounds
std::vector<std::string>::iterator it=mSoundsPlaying.begin();
while (it!=mSoundsPlaying.end())
{
if ( *it != ambientSnd && *it != rainSnd)
{
mEnvironment->mSoundManager->stopSound(*it);
it = mSoundsPlaying.erase(it);
}
else
++it;
}
} }
void WeatherManager::setHour(const float hour) void WeatherManager::setHour(const float hour)
{ {
// accelerate a bit for testing
/*
mHour += 0.005;
if (mHour >= 24.f) mHour = 0.f;
std::cout << "hour " << mHour << std::endl;
*/
mHour = hour; mHour = hour;
} }

@ -246,6 +246,8 @@ namespace MWWorld
std::map<std::string, std::string> mRegionOverrides; std::map<std::string, std::string> mRegionOverrides;
std::vector<std::string> mSoundsPlaying;
Ogre::String mCurrentWeather; Ogre::String mCurrentWeather;
Ogre::String mNextWeather; Ogre::String mNextWeather;

@ -478,7 +478,7 @@ namespace MWWorld
float World::getTimeScaleFactor() const float World::getTimeScaleFactor() const
{ {
return mGlobalVariables->getInt ("timescale"); return mGlobalVariables->getFloat ("timescale");
} }
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)

53
cmake/FindCg.cmake Normal file

@ -0,0 +1,53 @@
#-------------------------------------------------------------------
# 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/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
# - Try to find Cg
# Once done, this will define
#
# Cg_FOUND - system has Cg
# Cg_INCLUDE_DIRS - the Cg include directories
# Cg_LIBRARIES - link these to use Cg
include(FindPkgMacros)
findpkg_begin(Cg)
# Get path, convert backslashes as ${ENV_${var}}
getenv_path(Cg_HOME)
getenv_path(OGRE_SOURCE)
getenv_path(OGRE_HOME)
# construct search paths
set(Cg_PREFIX_PATH ${Cg_HOME} ${ENV_Cg_HOME}
${OGRE_SOURCE}/Dependencies
${ENV_OGRE_SOURCE}/Dependencies
${OGRE_HOME} ${ENV_OGRE_HOME}
/opt/nvidia-cg-toolkit)
create_search_paths(Cg)
# redo search if prefix path changed
clear_if_changed(Cg_PREFIX_PATH
Cg_LIBRARY_FWK
Cg_LIBRARY_REL
Cg_LIBRARY_DBG
Cg_INCLUDE_DIR
)
set(Cg_LIBRARY_NAMES Cg)
get_debug_names(Cg_LIBRARY_NAMES)
use_pkgconfig(Cg_PKGC Cg)
findpkg_framework(Cg)
find_path(Cg_INCLUDE_DIR NAMES cg.h HINTS ${Cg_FRAMEWORK_INCLUDES} ${Cg_INC_SEARCH_PATH} ${Cg_PKGC_INCLUDE_DIRS} PATH_SUFFIXES Cg)
find_library(Cg_LIBRARY_REL NAMES ${Cg_LIBRARY_NAMES} HINTS ${Cg_LIB_SEARCH_PATH} ${Cg_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel)
find_library(Cg_LIBRARY_DBG NAMES ${Cg_LIBRARY_NAMES_DBG} HINTS ${Cg_LIB_SEARCH_PATH} ${Cg_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug)
make_library_set(Cg_LIBRARY)
findpkg_finish(Cg)
add_parent_dir(Cg_INCLUDE_DIRS Cg_INCLUDE_DIR)

47
cmake/FindFreeImage.cmake Normal file

@ -0,0 +1,47 @@
#-------------------------------------------------------------------
# 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/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
# - Try to find FreeImage
# Once done, this will define
#
# FreeImage_FOUND - system has FreeImage
# FreeImage_INCLUDE_DIRS - the FreeImage include directories
# FreeImage_LIBRARIES - link these to use FreeImage
include(FindPkgMacros)
findpkg_begin(FreeImage)
# Get path, convert backslashes as ${ENV_${var}}
getenv_path(FREEIMAGE_HOME)
# construct search paths
set(FreeImage_PREFIX_PATH ${FREEIMAGE_HOME} ${ENV_FREEIMAGE_HOME})
create_search_paths(FreeImage)
# redo search if prefix path changed
clear_if_changed(FreeImage_PREFIX_PATH
FreeImage_LIBRARY_FWK
FreeImage_LIBRARY_REL
FreeImage_LIBRARY_DBG
FreeImage_INCLUDE_DIR
)
set(FreeImage_LIBRARY_NAMES freeimage)
get_debug_names(FreeImage_LIBRARY_NAMES)
use_pkgconfig(FreeImage_PKGC freeimage)
findpkg_framework(FreeImage)
find_path(FreeImage_INCLUDE_DIR NAMES FreeImage.h HINTS ${FreeImage_INC_SEARCH_PATH} ${FreeImage_PKGC_INCLUDE_DIRS})
find_library(FreeImage_LIBRARY_REL NAMES ${FreeImage_LIBRARY_NAMES} HINTS ${FreeImage_LIB_SEARCH_PATH} ${FreeImage_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel)
find_library(FreeImage_LIBRARY_DBG NAMES ${FreeImage_LIBRARY_NAMES_DBG} HINTS ${FreeImage_LIB_SEARCH_PATH} ${FreeImage_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug)
make_library_set(FreeImage_LIBRARY)
findpkg_finish(FreeImage)

@ -28,12 +28,11 @@
# Plugin_BSPSceneManager, Plugin_CgProgramManager, # Plugin_BSPSceneManager, Plugin_CgProgramManager,
# Plugin_OctreeSceneManager, Plugin_OctreeZone, # Plugin_OctreeSceneManager, Plugin_OctreeZone,
# Plugin_ParticleFX, Plugin_PCZSceneManager, # Plugin_ParticleFX, Plugin_PCZSceneManager,
# RenderSystem_GL, RenderSystem_Direct3D9, # RenderSystem_GL, RenderSystem_Direct3D9, RenderSystem_Direct3D10,
# Paging, Terrain # Paging, Terrain
# #
# For each of these components, the following variables are defined: # For each of these components, the following variables are defined:
# #
# OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available # OGRE_${COMPONENT}_FOUND - ${COMPONENT} is available
# OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT} # OGRE_${COMPONENT}_INCLUDE_DIRS - additional include directories for ${COMPONENT}
# OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT} # OGRE_${COMPONENT}_LIBRARIES - link these to use ${COMPONENT}
@ -128,7 +127,7 @@ endif ()
set(OGRE_COMPONENTS Paging Terrain set(OGRE_COMPONENTS Paging Terrain
Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager Plugin_BSPSceneManager Plugin_CgProgramManager Plugin_OctreeSceneManager
Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX Plugin_OctreeZone Plugin_PCZSceneManager Plugin_ParticleFX
RenderSystem_Direct3D11 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES RenderSystem_GLES2) RenderSystem_Direct3D10 RenderSystem_Direct3D9 RenderSystem_GL RenderSystem_GLES)
set(OGRE_RESET_VARS set(OGRE_RESET_VARS
OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR OGRE_CONFIG_INCLUDE_DIR OGRE_INCLUDE_DIR
OGRE_LIBRARY_FWK OGRE_LIBRARY_REL OGRE_LIBRARY_DBG OGRE_LIBRARY_FWK OGRE_LIBRARY_REL OGRE_LIBRARY_DBG
@ -145,7 +144,7 @@ clear_if_changed(OGRE_PREFIX_WATCH ${OGRE_RESET_VARS})
# try to locate Ogre via pkg-config # try to locate Ogre via pkg-config
use_pkgconfig(OGRE_PKGC "OGRE${OGRE_LIB_SUFFIX}") use_pkgconfig(OGRE_PKGC "OGRE${OGRE_LIB_SUFFIX}")
if(NOT OGRE_BUILD_PLATFORM_APPLE_IOS) if(NOT OGRE_BUILD_PLATFORM_IPHONE AND APPLE)
# try to find framework on OSX # try to find framework on OSX
findpkg_framework(OGRE) findpkg_framework(OGRE)
else() else()
@ -236,7 +235,6 @@ if (OGRE_STATIC)
find_package(Freetype QUIET) find_package(Freetype QUIET)
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
find_package(OpenGLES QUIET) find_package(OpenGLES QUIET)
find_package(OpenGLES2 QUIET)
find_package(ZLIB QUIET) find_package(ZLIB QUIET)
find_package(ZZip QUIET) find_package(ZZip QUIET)
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@ -246,26 +244,24 @@ if (OGRE_STATIC)
set(X11_FOUND FALSE) set(X11_FOUND FALSE)
endif () endif ()
endif () endif ()
if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS) if (APPLE AND NOT OGRE_BUILD_PLATFORM_IPHONE)
find_package(Cocoa QUIET) find_package(Cocoa QUIET)
find_package(Carbon QUIET) find_package(Carbon QUIET)
find_package(CoreVideo QUIET) if (NOT Cocoa_FOUND OR NOT Carbon_FOUND)
if (NOT Cocoa_FOUND OR NOT Carbon_FOUND OR NOT CoreVideo_FOUND)
set(OGRE_DEPS_FOUND FALSE) set(OGRE_DEPS_FOUND FALSE)
endif () endif ()
endif () endif ()
if (APPLE AND OGRE_BUILD_PLATFORM_APPLE_IOS) if (APPLE AND OGRE_BUILD_PLATFORM_IPHONE)
find_package(iPhoneSDK QUIET) find_package(iPhoneSDK QUIET)
if (NOT iPhoneSDK_FOUND) if (NOT iPhoneSDK_FOUND)
set(OGRE_DEPS_FOUND FALSE) set(OGRE_DEPS_FOUND FALSE)
endif () endif ()
endif () endif ()
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES} ${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES} ) set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${OGRE_LIBRARY_FWK} ${ZZip_LIBRARIES} ${ZLIB_LIBRARIES}
${FreeImage_LIBRARIES} ${FREETYPE_LIBRARIES}
if (APPLE AND NOT OGRE_BUILD_PLATFORM_APPLE_IOS) ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB}
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${X11_LIBRARIES} ${X11_Xt_LIBRARIES} ${XAW_LIBRARY} ${X11_Xrandr_LIB} ${Carbon_LIBRARIES} ${Cocoa_LIBRARIES}) ${Cocoa_LIBRARIES} ${Carbon_LIBRARIES})
endif()
if (NOT ZLIB_FOUND OR NOT ZZip_FOUND) if (NOT ZLIB_FOUND OR NOT ZZip_FOUND)
set(OGRE_DEPS_FOUND FALSE) set(OGRE_DEPS_FOUND FALSE)
@ -409,10 +405,22 @@ macro(ogre_find_plugin PLUGIN HEADER)
set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}") set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}")
get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES) get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES)
set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK}) set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK})
# Search for release plugins in OGRE dir with version suffix
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES} find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt) HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE-${OGRE_VERSION} opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
if(NOT EXISTS "${OGRE_${PLUGIN}_LIBRARY_REL}")
# Search for release plugins in OGRE dir without version suffix
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
endif()
# Search for debug plugins in OGRE dir with version suffix
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG} find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt) HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE-${OGRE_VERSION} opt debug debug/opt)
if(NOT EXISTS "${OGRE_${PLUGIN}_LIBRARY_DBG}")
# Search for debug plugins in OGRE dir without version suffix
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt)
endif()
make_library_set(OGRE_${PLUGIN}_LIBRARY) make_library_set(OGRE_${PLUGIN}_LIBRARY)
if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR) if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR)
@ -445,9 +453,13 @@ macro(ogre_find_plugin PLUGIN HEADER)
PATH_SUFFIXES "" bin bin/debug debug) PATH_SUFFIXES "" bin bin/debug debug)
elseif (UNIX) elseif (UNIX)
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH) get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH)
set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)" FORCE) # For some reason this fails
#set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)")
set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP})
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH) get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH)
set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)" FORCE) # Same here
#set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)")
set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP})
endif () endif ()
endif () endif ()
@ -475,8 +487,8 @@ ogre_find_plugin(Plugin_OctreeSceneManager OgreOctreeSceneManager.h PlugIns/Octr
ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include) ogre_find_plugin(Plugin_ParticleFX OgreParticleFXPrerequisites.h PlugIns/ParticleFX/include)
ogre_find_plugin(RenderSystem_GL OgreGLRenderSystem.h RenderSystems/GL/include) ogre_find_plugin(RenderSystem_GL OgreGLRenderSystem.h RenderSystems/GL/include)
ogre_find_plugin(RenderSystem_GLES OgreGLESRenderSystem.h RenderSystems/GLES/include) ogre_find_plugin(RenderSystem_GLES OgreGLESRenderSystem.h RenderSystems/GLES/include)
ogre_find_plugin(RenderSystem_GLES2 OgreGLES2RenderSystem.h RenderSystems/GLES2/include)
ogre_find_plugin(RenderSystem_Direct3D9 OgreD3D9RenderSystem.h RenderSystems/Direct3D9/include) ogre_find_plugin(RenderSystem_Direct3D9 OgreD3D9RenderSystem.h RenderSystems/Direct3D9/include)
ogre_find_plugin(RenderSystem_Direct3D10 OgreD3D10RenderSystem.h RenderSystems/Direct3D10/include)
ogre_find_plugin(RenderSystem_Direct3D11 OgreD3D11RenderSystem.h RenderSystems/Direct3D11/include) ogre_find_plugin(RenderSystem_Direct3D11 OgreD3D11RenderSystem.h RenderSystems/Direct3D11/include)
if (OGRE_STATIC) if (OGRE_STATIC)
@ -484,18 +496,18 @@ if (OGRE_STATIC)
if (NOT DirectX_FOUND) if (NOT DirectX_FOUND)
set(OGRE_RenderSystem_Direct3D9_FOUND FALSE) set(OGRE_RenderSystem_Direct3D9_FOUND FALSE)
endif () endif ()
if (NOT DirectX_D3D10_FOUND)
set(OGRE_RenderSystem_Direct3D10_FOUND FALSE)
endif ()
if (NOT DirectX_D3D11_FOUND) if (NOT DirectX_D3D11_FOUND)
set(OGRE_RenderSystem_Direct3D11_FOUND FALSE) set(OGRE_RenderSystem_Direct3D11_FOUND FALSE)
endif () endif ()
if (NOT OPENGL_FOUND) if (NOT OPENGL_FOUND)
set(OGRE_RenderSystem_GL_FOUND FALSE) set(OGRE_RenderSystem_GL_FOUND FALSE)
endif () endif ()
if (NOT OPENGLES_FOUND) if (NOT OPENGLES_FOUND AND NOT OPENGLES2_FOUND)
set(OGRE_RenderSystem_GLES_FOUND FALSE) set(OGRE_RenderSystem_GLES_FOUND FALSE)
endif () endif ()
if (NOT OPENGLES2_FOUND)
set(OGRE_RenderSystem_GLES2_FOUND FALSE)
endif ()
if (NOT Cg_FOUND) if (NOT Cg_FOUND)
set(OGRE_Plugin_CgProgramManager_FOUND FALSE) set(OGRE_Plugin_CgProgramManager_FOUND FALSE)
endif () endif ()
@ -503,7 +515,9 @@ if (OGRE_STATIC)
set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES} set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES}
${DirectX_LIBRARIES} ${DirectX_LIBRARIES}
) )
set(OGRE_RenderSystem_Direct3D10_LIBRARIES ${OGRE_RenderSystem_Direct3D10_LIBRARIES}
${DirectX_D3D10_LIBRARIES}
)
set(OGRE_RenderSystem_Direct3D11_LIBRARIES ${OGRE_RenderSystem_Direct3D11_LIBRARIES} set(OGRE_RenderSystem_Direct3D11_LIBRARIES ${OGRE_RenderSystem_Direct3D11_LIBRARIES}
${DirectX_D3D11_LIBRARIES} ${DirectX_D3D11_LIBRARIES}
) )
@ -513,9 +527,6 @@ if (OGRE_STATIC)
set(OGRE_RenderSystem_GLES_LIBRARIES ${OGRE_RenderSystem_GLES_LIBRARIES} set(OGRE_RenderSystem_GLES_LIBRARIES ${OGRE_RenderSystem_GLES_LIBRARIES}
${OPENGLES_LIBRARIES} ${OPENGLES_LIBRARIES}
) )
set(OGRE_RenderSystem_GLES2_LIBRARIES ${OGRE_RenderSystem_GLES2_LIBRARIES}
${OPENGLES2_LIBRARIES}
)
set(OGRE_Plugin_CgProgramManager_LIBRARIES ${OGRE_Plugin_CgProgramManager_LIBRARIES} set(OGRE_Plugin_CgProgramManager_LIBRARIES ${OGRE_Plugin_CgProgramManager_LIBRARIES}
${Cg_LIBRARIES} ${Cg_LIBRARIES}
) )
@ -540,3 +551,4 @@ set(OGRE_MEDIA_SEARCH_SUFFIX
clear_if_changed(OGRE_PREFIX_WATCH OGRE_MEDIA_DIR) clear_if_changed(OGRE_PREFIX_WATCH OGRE_MEDIA_DIR)
find_path(OGRE_MEDIA_DIR NAMES packs/cubemapsJS.zip HINTS ${OGRE_MEDIA_SEARCH_PATH} find_path(OGRE_MEDIA_DIR NAMES packs/cubemapsJS.zip HINTS ${OGRE_MEDIA_SEARCH_PATH}
PATHS ${OGRE_PREFIX_PATH} PATH_SUFFIXES ${OGRE_MEDIA_SEARCH_SUFFIX}) PATHS ${OGRE_PREFIX_PATH} PATH_SUFFIXES ${OGRE_MEDIA_SEARCH_SUFFIX})

48
cmake/FindZZip.cmake Normal file

@ -0,0 +1,48 @@
#-------------------------------------------------------------------
# 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/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
# - Try to find zziplib
# Once done, this will define
#
# ZZip_FOUND - system has ZZip
# ZZip_INCLUDE_DIRS - the ZZip include directories
# ZZip_LIBRARIES - link these to use ZZip
include(FindPkgMacros)
findpkg_begin(ZZip)
# Get path, convert backslashes as ${ENV_${var}}
getenv_path(ZZIP_HOME)
# construct search paths
set(ZZip_PREFIX_PATH ${ZZIP_HOME} ${ENV_ZZIP_HOME})
create_search_paths(ZZip)
# redo search if prefix path changed
clear_if_changed(ZZip_PREFIX_PATH
ZZip_LIBRARY_FWK
ZZip_LIBRARY_REL
ZZip_LIBRARY_DBG
ZZip_INCLUDE_DIR
)
set(ZZip_LIBRARY_NAMES zzip zziplib)
get_debug_names(ZZip_LIBRARY_NAMES)
use_pkgconfig(ZZip_PKGC zziplib)
findpkg_framework(ZZip)
find_path(ZZip_INCLUDE_DIR NAMES zzip/zzip.h HINTS ${ZZip_INC_SEARCH_PATH} ${ZZip_PKGC_INCLUDE_DIRS})
find_library(ZZip_LIBRARY_REL NAMES ${ZZip_LIBRARY_NAMES} HINTS ${ZZip_LIB_SEARCH_PATH} ${ZZip_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel)
find_library(ZZip_LIBRARY_DBG NAMES ${ZZip_LIBRARY_NAMES_DBG} HINTS ${ZZip_LIB_SEARCH_PATH} ${ZZip_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug)
make_library_set(ZZip_LIBRARY)
findpkg_finish(ZZip)

@ -95,8 +95,6 @@ namespace Compiler
return true; return true;
} }
return false;
} }
bool ControlParser::parseWhileBody (int keyword, const TokenLoc& loc, Scanner& scanner) bool ControlParser::parseWhileBody (int keyword, const TokenLoc& loc, Scanner& scanner)
@ -108,7 +106,7 @@ namespace Compiler
Codes expr; Codes expr;
mExprParser.append (expr); mExprParser.append (expr);
Generator::jump (loop, -mCodeBlock.size()-expr.size()); Generator::jump (loop, -static_cast<int> (mCodeBlock.size()-expr.size()));
std::copy (expr.begin(), expr.end(), std::back_inserter (mCode)); std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
@ -122,7 +120,7 @@ namespace Compiler
Codes loop2; Codes loop2;
Generator::jump (loop2, -mCodeBlock.size()-expr.size()-skip.size()); Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()-expr.size()-skip.size()));
if (loop.size()!=loop2.size()) if (loop.size()!=loop2.size())
throw std::logic_error ( throw std::logic_error (
@ -153,8 +151,6 @@ namespace Compiler
return true; return true;
} }
return false;
} }
ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals, ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals,

@ -639,7 +639,7 @@ namespace Compiler
std::vector<Interpreter::Type_Code>& code, bool invert) std::vector<Interpreter::Type_Code>& code, bool invert)
{ {
bool optional = false; bool optional = false;
bool optionalCount = 0; int optionalCount = 0;
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true); ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
StringParser stringParser (getErrorHandler(), getContext(), mLiterals); StringParser stringParser (getErrorHandler(), getContext(), mLiterals);

@ -77,4 +77,3 @@ namespace Compiler
mOutput.clear(); mOutput.clear();
} }
} }

@ -39,6 +39,11 @@ namespace Compiler
mState = CommaState; mState = CommaState;
return true; return true;
} }
else if (code==Scanner::S_newline && mState==StartState)
{
scanner.putbackSpecial (code, loc);
return false;
}
return Parser::parseSpecial (code, loc, scanner); return Parser::parseSpecial (code, loc, scanner);
} }

@ -3,32 +3,68 @@
namespace ESM namespace ESM
{ {
void PathGrid::load(ESMReader &esm) void Pathgrid::load(ESMReader &esm)
{ {
esm.getHNT(data, "DATA", 12); esm.getHNT(data, "DATA", 12);
cell = esm.getHNString("NAME"); cell = esm.getHNString("NAME");
// Remember this file position // keep track of total connections so we can reserve edge vector size
context = esm.getContext(); int edgeCount = 0;
// Check that the sizes match up. Size = 16 * s2 (path points?)
if (esm.isNextSub("PGRP")) if (esm.isNextSub("PGRP"))
{ {
esm.skipHSub(); esm.getSubHeader();
int size = esm.getSubSize(); int size = esm.getSubSize();
if (size != 16 * data.s2) // Check that the sizes match up. Size = 16 * s2 (path points)
esm.fail("Path grid table size mismatch"); if (size != static_cast<int> (sizeof(Point) * data.s2))
esm.fail("Path point subrecord size mismatch");
else
{
int pointCount = data.s2;
points.reserve(pointCount);
for (int i = 0; i < pointCount; ++i)
{
Point p;
esm.getExact(&p, sizeof(Point));
points.push_back(p);
edgeCount += p.connectionNum;
}
}
} }
// Size varies. Path grid chances? Connections? Multiples of 4
// suggest either int or two shorts, or perhaps a float. Study
// it later.
if (esm.isNextSub("PGRC")) if (esm.isNextSub("PGRC"))
{ {
esm.skipHSub(); esm.getSubHeader();
int size = esm.getSubSize(); int size = esm.getSubSize();
if (size % 4 != 0) if (size % sizeof(int) != 0)
esm.fail("PGRC size not a multiple of 4"); esm.fail("PGRC size not a multiple of 4");
else
{
int rawConnNum = size / sizeof(int);
std::vector<int> rawConnections;
rawConnections.reserve(rawConnNum);
for (int i = 0; i < rawConnNum; ++i)
{
int currentValue;
esm.getT(currentValue);
rawConnections.push_back(currentValue);
}
std::vector<int>::const_iterator rawIt = rawConnections.begin();
int pointIndex = 0;
edges.reserve(edgeCount);
for(PointList::const_iterator it = points.begin(); it != points.end(); it++, pointIndex++)
{
unsigned char connectionNum = (*it).connectionNum;
for (int i = 0; i < connectionNum; ++i) {
Edge edge;
edge.v0 = pointIndex;
edge.v1 = *rawIt;
rawIt++;
edges.push_back(edge);
}
}
}
} }
} }

@ -9,20 +9,37 @@ namespace ESM
/* /*
* Path grid. * Path grid.
*/ */
struct PathGrid struct Pathgrid
{ {
struct DATAstruct struct DATAstruct
{ {
int x, y; // Grid location, matches cell for exterior cells int x, y; // Grid location, matches cell for exterior cells
short s1; // ?? Usually but not always a power of 2. Doesn't seem short s1; // ?? Usually but not always a power of 2. Doesn't seem
// to have any relation to the size of PGRC. // to have any relation to the size of PGRC.
short s2; // Number of path points? Size of PGRP block is always 16 * s2; short s2; // Number of path points.
}; // 12 bytes }; // 12 bytes
struct Point // path grid point
{
int x, y, z; // Location of point
unsigned char autogenerated; // autogenerated vs. user coloring flag?
unsigned char connectionNum; // number of connections for this point
short unknown;
}; // 16 bytes
struct Edge // path grid edge
{
int v0, v1; // index of points connected with this edge
}; // 8 bytes
std::string cell; // Cell name std::string cell; // Cell name
DATAstruct data; DATAstruct data;
ESM_Context context; // Context so we can return here later and
// finish the job typedef std::vector<Point> PointList;
PointList points;
typedef std::vector<Edge> EdgeList;
EdgeList edges;
void load(ESMReader &esm); void load(ESMReader &esm);
}; };

@ -22,6 +22,8 @@ namespace ESMS
struct RecList struct RecList
{ {
virtual ~RecList() {}
virtual void load(ESMReader &esm, const std::string &id) = 0; virtual void load(ESMReader &esm, const std::string &id) = 0;
virtual int getSize() = 0; virtual int getSize() = 0;
virtual void listIdentifier (std::vector<std::string>& identifier) const = 0; virtual void listIdentifier (std::vector<std::string>& identifier) const = 0;
@ -42,6 +44,8 @@ namespace ESMS
template <typename X> template <typename X>
struct RecListT : RecList struct RecListT : RecList
{ {
virtual ~RecListT() {}
typedef std::map<std::string,X> MapType; typedef std::map<std::string,X> MapType;
MapType list; MapType list;
@ -90,6 +94,8 @@ namespace ESMS
template <typename X> template <typename X>
struct RecListWithIDT : RecList struct RecListWithIDT : RecList
{ {
virtual ~RecListWithIDT() {}
typedef std::map<std::string,X> MapType; typedef std::map<std::string,X> MapType;
MapType list; MapType list;
@ -139,6 +145,8 @@ namespace ESMS
template <typename X> template <typename X>
struct RecIDListT : RecList struct RecIDListT : RecList
{ {
virtual ~RecIDListT() {}
typedef std::map<std::string,X> MapType; typedef std::map<std::string,X> MapType;
MapType list; MapType list;
@ -189,6 +197,8 @@ namespace ESMS
*/ */
struct LTexList : RecList struct LTexList : RecList
{ {
virtual ~LTexList() {}
// TODO: For multiple ESM/ESP files we need one list per file. // TODO: For multiple ESM/ESP files we need one list per file.
std::vector<LandTexture> ltex; std::vector<LandTexture> ltex;
int count; int count;
@ -223,6 +233,8 @@ namespace ESMS
*/ */
struct LandList : RecList struct LandList : RecList
{ {
virtual ~LandList() {}
// Map containing all landscapes // Map containing all landscapes
typedef std::map<int, Land*> LandsCol; typedef std::map<int, Land*> LandsCol;
typedef std::map<int, LandsCol> Lands; typedef std::map<int, LandsCol> Lands;
@ -296,7 +308,7 @@ namespace ESMS
identifier.push_back (iter->first); identifier.push_back (iter->first);
} }
~CellList() virtual ~CellList()
{ {
for (IntCells::iterator it = intCells.begin(); it!=intCells.end(); ++it) for (IntCells::iterator it = intCells.begin(); it!=intCells.end(); ++it)
delete it->second; delete it->second;
@ -390,9 +402,100 @@ namespace ESMS
} }
}; };
struct PathgridList : RecList
{
int count;
// List of grids for interior cells. Indexed by cell name.
typedef std::map<std::string,ESM::Pathgrid*, ciLessBoost> IntGrids;
IntGrids intGrids;
// List of grids for exterior cells. Indexed as extCells[gridX][gridY].
typedef std::map<std::pair<int, int>, ESM::Pathgrid*> ExtGrids;
ExtGrids extGrids;
PathgridList() : count(0) {}
virtual ~PathgridList()
{
for (IntGrids::iterator it = intGrids.begin(); it!=intGrids.end(); ++it)
delete it->second;
for (ExtGrids::iterator it = extGrids.begin(); it!=extGrids.end(); ++it)
delete it->second;
}
int getSize() { return count; }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
// do nothing
}
void load(ESMReader &esm, const std::string &id)
{
count++;
ESM::Pathgrid *grid = new ESM::Pathgrid;
grid->load(esm);
if (grid->data.x == 0 && grid->data.y == 0)
{
intGrids[grid->cell] = grid;
}
else
{
extGrids[std::make_pair(grid->data.x, grid->data.y)] = grid;
}
}
Pathgrid *find(int cellX, int cellY, std::string cellName) const
{
Pathgrid *result = search(cellX, cellY, cellName);
if (!result)
{
throw std::runtime_error("no pathgrid found for cell " + cellName);
}
return result;
}
Pathgrid *search(int cellX, int cellY, std::string cellName) const
{
Pathgrid *result = NULL;
if (cellX == 0 && cellY == 0) // possibly interior
{
IntGrids::const_iterator it = intGrids.find(cellName);
if (it != intGrids.end())
result = it->second;
}
else
{
ExtGrids::const_iterator it = extGrids.find(std::make_pair(cellX, cellY));
if (it != extGrids.end())
result = it->second;
}
return result;
}
Pathgrid *search(const ESM::Cell &cell) const
{
int cellX, cellY;
if (cell.data.flags & ESM::Cell::Interior)
{
cellX = cellY = 0;
}
else
{
cellX = cell.data.gridX;
cellY = cell.data.gridY;
}
return search(cellX, cellY, cell.name);
}
};
template <typename X> template <typename X>
struct ScriptListT : RecList struct ScriptListT : RecList
{ {
virtual ~ScriptListT() {}
typedef std::map<std::string,X> MapType; typedef std::map<std::string,X> MapType;
MapType list; MapType list;
@ -444,6 +547,8 @@ namespace ESMS
template <typename X> template <typename X>
struct IndexListT struct IndexListT
{ {
virtual ~IndexListT() {}
typedef std::map<int, X> MapType; typedef std::map<int, X> MapType;
MapType list; MapType list;

@ -74,7 +74,8 @@ namespace ESMS
ScriptListT<Script> scripts; ScriptListT<Script> scripts;
IndexListT<MagicEffect> magicEffects; IndexListT<MagicEffect> magicEffects;
IndexListT<Skill> skills; IndexListT<Skill> skills;
//RecListT<PathGrid> pathgrids; //RecListT<Pathgrid> pathgrids;
PathgridList pathgrids;
// Special entry which is hardcoded and not loaded from an ESM // Special entry which is hardcoded and not loaded from an ESM
IndexListT<Attribute> attributes; IndexListT<Attribute> attributes;
@ -124,7 +125,7 @@ namespace ESMS
recLists[REC_MISC] = &miscItems; recLists[REC_MISC] = &miscItems;
recLists[REC_NPC_] = &npcs; recLists[REC_NPC_] = &npcs;
recLists[REC_NPCC] = &npcChange; recLists[REC_NPCC] = &npcChange;
//recLists[REC_PGRD] = &pathgrids; recLists[REC_PGRD] = &pathgrids;
recLists[REC_PROB] = &probes; recLists[REC_PROB] = &probes;
recLists[REC_RACE] = &races; recLists[REC_RACE] = &races;
recLists[REC_REGN] = &regions; recLists[REC_REGN] = &regions;

@ -89,12 +89,12 @@ namespace Files
} }
// Searches the library for an item and returns a boost path to it // Searches the library for an item and returns a boost path to it
boost::filesystem::path FileLibrary::locate(std::string item, bool strict, std::string sectionName) boost::filesystem::path FileLibrary::locate(std::string item, bool strict, bool ignoreExtensions, std::string sectionName)
{ {
boost::filesystem::path result(""); boost::filesystem::path result("");
if (sectionName == "") if (sectionName == "")
{ {
return FileListLocator(mPriorityList, boost::filesystem::path(item), strict); return FileListLocator(mPriorityList, boost::filesystem::path(item), strict, ignoreExtensions);
} }
else else
{ {
@ -103,7 +103,7 @@ namespace Files
std::cout << "Warning: There is no section named " << sectionName << "\n"; std::cout << "Warning: There is no section named " << sectionName << "\n";
return result; return result;
} }
result = FileListLocator(mMap[sectionName], boost::filesystem::path(item), strict); result = FileListLocator(mMap[sectionName], boost::filesystem::path(item), strict, ignoreExtensions);
} }
return result; return result;
} }

@ -39,7 +39,7 @@ namespace Files
/// Optionally you can provide a specific section /// Optionally you can provide a specific section
/// The result is the first that comes up according to alphabetical /// The result is the first that comes up according to alphabetical
/// section naming /// section naming
boost::filesystem::path locate(std::string item, bool strict, std::string sectionName=""); boost::filesystem::path locate(std::string item, bool strict, bool ignoreExtensions, std::string sectionName="");
/// Prints all the available sections, used for debugging /// Prints all the available sections, used for debugging
void printSections(); void printSections();

@ -13,6 +13,14 @@ bool isFile(const char *name)
return boost::filesystem::exists(boost::filesystem::path(name)); return boost::filesystem::exists(boost::filesystem::path(name));
} }
// Returns true if the last part of the superset matches the subset
bool endingMatches(const std::string& superset, const std::string& subset)
{
if (subset.length() > superset.length())
return false;
return superset.substr(superset.length() - subset.length()) == subset;
}
// Makes a list of files from a directory // Makes a list of files from a directory
void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive) void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive)
{ {
@ -42,13 +50,18 @@ bool isFile(const char *name)
} }
// Locates path in path container // Locates path in path container
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind, bool strict) boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind,
bool strict, bool ignoreExtensions)
{ {
boost::filesystem::path result(""); boost::filesystem::path result("");
if (list.empty()) if (list.empty())
return result; return result;
std::string toFindStr = toFind.string(); std::string toFindStr;
if (ignoreExtensions)
toFindStr = boost::filesystem::basename(toFind);
else
toFindStr = toFind.string();
std::string fullPath; std::string fullPath;
@ -80,11 +93,15 @@ bool isFile(const char *name)
for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it) for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it)
{ {
fullPath = it->string(); fullPath = it->string();
if (ignoreExtensions)
fullPath.erase(fullPath.length() -
boost::filesystem::path (it->extension()).string().length());
if (!strict) if (!strict)
{ {
boost::algorithm::to_lower(fullPath); boost::algorithm::to_lower(fullPath);
} }
if(fullPath.find(toFindStr) != std::string::npos) if(endingMatches(fullPath, toFindStr))
{ {
result = *it; result = *it;
break; break;
@ -94,9 +111,9 @@ bool isFile(const char *name)
} }
// Overloaded form of the locator that takes a string and returns a string // Overloaded form of the locator that takes a string and returns a string
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict) std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict, bool ignoreExtensions)
{ {
return FileListLocator(list, boost::filesystem::path(toFind), strict).string(); return FileListLocator(list, boost::filesystem::path(toFind), strict, ignoreExtensions).string();
} }
} }

@ -27,10 +27,11 @@ bool isFile(const char *name);
/// that contains the searched path. /// that contains the searched path.
/// If it's not found it returns and empty path /// If it's not found it returns and empty path
/// Takes care of slashes, backslashes and it has a strict option. /// Takes care of slashes, backslashes and it has a strict option.
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind, bool strict); boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind,
bool strict, bool ignoreExtensions);
/// Overloaded form of the locator that takes a string and returns a string /// Overloaded form of the locator that takes a string and returns a string
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict); std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict, bool ignoreExtensions);
} }

@ -177,6 +177,8 @@ void NIFFile::parse()
records[i]->post(this); records[i]->post(this);
} }
/// \todo move to the write cpp file
void NiSkinInstance::post(NIFFile *nif) void NiSkinInstance::post(NIFFile *nif)
{ {
int bnum = bones.length(); int bnum = bones.length();

@ -100,6 +100,8 @@ struct Record
/// Does post-processing, after the entire tree is loaded /// Does post-processing, after the entire tree is loaded
virtual void post(NIFFile *nif) {} virtual void post(NIFFile *nif) {}
virtual ~Record() {}
/* /*
Use these later if you want custom allocation of all NIF objects Use these later if you want custom allocation of all NIF objects

@ -54,6 +54,7 @@ configure_file("${SDIR}/openmw_chargen_class_description_layout.xml" "${DDIR}/op
configure_file("${SDIR}/openmw_chargen_birth_layout.xml" "${DDIR}/openmw_chargen_birth_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_chargen_birth_layout.xml" "${DDIR}/openmw_chargen_birth_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_chargen_review_layout.xml" "${DDIR}/openmw_chargen_review_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_chargen_review_layout.xml" "${DDIR}/openmw_chargen_review_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_dialogue_window_layout.xml" "${DDIR}/openmw_dialogue_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_dialogue_window_layout.xml" "${DDIR}/openmw_dialogue_window_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_dialogue_window_skin.xml" "${DDIR}/openmw_dialogue_window_skin.xml" COPYONLY)
configure_file("${SDIR}/openmw_inventory_window_layout.xml" "${DDIR}/openmw_inventory_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_inventory_window_layout.xml" "${DDIR}/openmw_inventory_window_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY) configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY)
configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY)

@ -20,6 +20,7 @@
<List file="openmw_mainmenu_skin.xml" group="General"/> <List file="openmw_mainmenu_skin.xml" group="General"/>
<List file="openmw_console.skin.xml" group="General"/> <List file="openmw_console.skin.xml" group="General"/>
<List file="openmw_journal_skin.xml" group="General"/> <List file="openmw_journal_skin.xml" group="General"/>
<List file="openmw_dialogue_window_skin.xml" group="General"/>
</MyGUI> </MyGUI>
</MyGUI> </MyGUI>

@ -17,8 +17,13 @@
<Property key="Edit_VisibleVScroll" value="1" /> <Property key="Edit_VisibleVScroll" value="1" />
</Widget> </Widget>
<!-- The disposition bar-->
<Widget type="Progress" skin="MW_EnergyBar_Blue" position="432 39 132 18"
align="Right Top" name="Disposition">
<Widget type="Edit" skin="MW_DispositionEdit" position_real = "0.25 0 0.5 1" name = "DispositionText"/>
</Widget>
<!-- The list of topics --> <!-- The list of topics -->
<Widget type="List" skin="MW_List" position="432 39 132 341" name="TopicsList"> <Widget type="List" skin="MW_List" position="432 62 132 318" name="TopicsList">
</Widget> </Widget>
<!-- The Goodbye button --> <!-- The Goodbye button -->

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Skin">
<Skin name = "MW_DispEdit" size = "10 10">
<Property key="FontName" value = "MonoFont" />
<Property key="AlignText" value = "Left Top" />
<Property key="Colour" value = "0000FF" />
<!--Property key="Pointer" value = "beam" /-->
<BasisSkin type="EditText" offset = "0 0 10 10" align = "Stretch"/>
</Skin>
<Skin name="MW_DispositionEdit" size="0 0 50 50">
<Property key="WordWrap" value = "true" />
<Child type="Widget" skin="MW_DispEdit" offset="0 0 35 10" align = "ALIGN_STRETCH" name = "Client"/>
<!--Child type="VScroll" skin="VScroll" offset = "35 0 15 50" align = "Right VStretch" name = "VScroll"/-->
</Skin>
</MyGUI>

@ -1 +0,0 @@
Subproject commit 14b2851e72f610ae81dd296598867e6fb0babd2a

3
libs/mangle/.gitignore vendored Normal file

@ -0,0 +1,3 @@
upload_docs.sh
docs
*~

1510
libs/mangle/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

26
libs/mangle/LICENSE.txt Normal file

@ -0,0 +1,26 @@
Minimal Abstraction Game Layer (Mangle) is licensed under the
'zlib/libpng' license:
----
Copyright (c) 2009 Nicolay Korslund
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 redistribute it
freely, subject to the following restrictions:
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 must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

129
libs/mangle/README.txt Normal file

@ -0,0 +1,129 @@
Welcome to Mangle v0.1
----------------------
Written by: Nicolay Korslund (korslund@gmail.com)
License: zlib/png (see LICENSE.txt)
WWW: http://asm-soft.com/mangle/
Documentation: http://asm-soft.com/mangle/docs
Mangle is the project name for a small set of generic interfaces for
various game middleware libraries, such as sound, input, graphics, and
so on. You can imagine that it stands for "Minimal Abstraction Game
Layer", if you like. It will consist of several more or less
independent modules, one for each of these areas. These may be used
together to build an entire game engine, or they can be used
individually as separate libraries.
However, Mangle does NOT actually implement a game engine, or any new
fundamental functionality. More on that below.
Currently there's modules for sound and streams / archives (virtual
file systems.) More will come in the future (including input, 2D/3D
graphics, GUI, physics, and more.)
Main idea
---------
The idea behind Mangle is to provide a uniform, consistent interface
to other game libraries. The library does not provide ANY
functionality on its own. Instead it connects to a backend
implementation of your choice (or of your making.)
The Sound module, for example, currently has backends for OpenAL
(output only), FFmpeg (input only) and for Audiere. Hopefully we'll
add IrrKlang, FMod, DirectSound, Miles and more in the future. It can
combine libraries to get more complete functionality (like using
OpenAL for output and FFmpeg to decode sound files), and it's also
easy to write your own backend if you're using a different (or
home-brewed) sound system.
Regardless of what backend you use, the front-end interfaces (found
eg. in sound/output.h) is identical, and as a library user you
shouldn't notice much difference at all if you swap one backend for
another at a later point. It should Just Work.
The interfaces themselves are also quite simple. Setting up a sound
stream from FFmpeg or other decoder into OpenAL can be quite hairy -
but with Mangle the hairy parts have already been written for you. You
just plug the parts together.
The goal in the long run is to support a wide variety of game-related
libraries, and as many backend libraries (free and commercial) as
possible, so that you the user will have to write as little code as
possible.
What is it good for
-------------------
The main point of Mangle, as we said above, is that it connects to any
library of your choice "behind the scenes" but provides the same,
super-simple interface front-end for all of them. There can benefit
you in many ways:
- If you want to use a new library that Mangle support. You don't have
to scour the net for tutorials and usage examples, since much of the
common usage code is already included in the implementation classes.
- If you don't want to pollute your code with library-specific code.
The Mangle interfaces can help you keep your code clean, and its
user interface is often simpler than the exteral library one.
- If you want to quickly connect different libraries together, it
really helps if they speak a common language. The Mangle interfaces
are exactly that - a common language between libraries. Do you need
Audiere to load sounds from a weird archive format only implemented
for PhysFS, all channeled through the OGRE resource system? No
problem!
- If you are creating a library that depends on a specific feature
(such as sound), but you don't want to lock your users into any
specific sound library. Mangle works as an abstraction that lets
your users select their own implementation.
- If you want to support multiple backends for your game/app, or want
to make it possible to easily switch backends later. You can select
backends at compile time or even at runtime. For example you might
want to switch to to a commercial sound library at a later stage in
development, or you may want to use a different input library on
console platforms than on PC.
The Mangle implementations are extremely light-weight - often just one
or two cpp/h pairs per module. You can plug them directly into your
program, there's no separate library building step required.
Since the library aims to be very modularly put together, you can
also, in many cases, just copy-and-paste the parts you need and ignore
the rest. Or modify stuff without fearing that the whole 'system' will
come crashing down, because there is no big 'system' to speak of.
Past and future
---------------
Mangle started out as (and still is) a spin-off from OpenMW, another
project I am personally working on ( http://openmw.com/ ). OpenMW is
an attempt to recreate the engine behind the commercial game
Morrowind, using only open source software.
The projects are still tightly interlinked, and they will continue to
be until OpenMW is finished. Most near-future work on Mangle will be
focused chiefly on OpenMW at the moment. However I will gladly include
external contributions and suggestions that are not OpenMW-related if
someone sends them to me.
Conclusion
----------
As you might have guessed, Mangle is more a concept in development
than a finished library right now.
All feedback, ideas, concepts, questions and code are very
welcome. Send them to: korslund@gmail.com
I will put up a forum later as well if there's enough interest.

Some files were not shown because too many files have changed in this diff Show More