From c010c28337d73a502cb17ee8f2602e4225212073 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Sep 2014 15:53:27 +0200 Subject: [PATCH 01/19] Implement ToggleWorld instruction --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 10 ++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 3 +++ apps/openmw/mwscript/docs/vmformat.txt | 3 ++- apps/openmw/mwscript/miscextensions.cpp | 12 ++++++++++++ apps/openmw/mwworld/worldimp.cpp | 5 +++++ apps/openmw/mwworld/worldimp.hpp | 1 + components/compiler/extensions0.cpp | 2 ++ components/compiler/opcodes.hpp | 1 + 9 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 2055aeeae5..3f6260c058 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -119,6 +119,7 @@ namespace MWBase virtual void setWaterHeight(const float height) = 0; virtual bool toggleWater() = 0; + virtual bool toggleWorld() = 0; virtual void adjustSky() = 0; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 4512bbbeb7..68d5f515df 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -63,6 +63,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b , mPhysicsEngine(engine) , mTerrain(NULL) , mEffectManager(NULL) + , mRenderWorld(true) { mActors = new MWRender::Actors(mRendering, this); mObjects = new MWRender::Objects(mRendering); @@ -232,6 +233,15 @@ bool RenderingManager::toggleWater() return mWater->toggle(); } +bool RenderingManager::toggleWorld() +{ + mRenderWorld = !mRenderWorld; + + int visibilityMask = mRenderWorld ? ~int(0) : 0; + mRendering.getViewport()->setVisibilityMask(visibilityMask); + return mRenderWorld; +} + void RenderingManager::cellAdded (MWWorld::CellStore *store) { if (store->isExterior()) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 43d22d5ca9..1c735f0567 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -123,6 +123,7 @@ public: void setWaterHeight(const float height); bool toggleWater(); + bool toggleWorld(); /// Updates object rendering after cell change /// \param old Object reference in previous cell @@ -266,6 +267,8 @@ private: MWRender::LocalMap* mLocalMap; MWRender::Shadows* mShadows; + + bool mRenderWorld; }; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 6263325648..b80c84d674 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -432,5 +432,6 @@ op 0x20002ac-0x20002c3: SetMagicEffect, explicit op 0x20002c4-0x20002db: ModMagicEffect op 0x20002dc-0x20002f3: ModMagicEffect, explicit op 0x20002f4: ResetActors +op 0x20002f5: ToggleWorld -opcodes 0x20002f5-0x3ffffff unused +opcodes 0x20002f6-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index be8c85bbf9..ef879a95a0 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -290,6 +290,17 @@ namespace MWScript } }; + class OpToggleWorld : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + runtime.getContext().report(MWBase::Environment::get().getWorld()->toggleWorld() ? "World -> On" + : "World -> Off"); + } + }; + class OpDontSaveObject : public Interpreter::Opcode0 { public: @@ -979,6 +990,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Misc::opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (Compiler::Misc::opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (Compiler::Misc::opcodeToggleWater, new OpToggleWater); + interpreter.installSegment5 (Compiler::Misc::opcodeToggleWorld, new OpToggleWorld); interpreter.installSegment5 (Compiler::Misc::opcodeDontSaveObject, new OpDontSaveObject); interpreter.installSegment5 (Compiler::Misc::opcodeToggleVanityMode, new OpToggleVanityMode); interpreter.installSegment5 (Compiler::Misc::opcodeGetPcSleep, new OpGetPcSleep); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index dd766eed13..91fcf2b95a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1663,6 +1663,11 @@ namespace MWWorld return mRendering->toggleWater(); } + bool World::toggleWorld() + { + return mRendering->toggleWorld(); + } + void World::PCDropped (const Ptr& item) { std::string script = item.getClass().getScript(item); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index d4f11f5b67..8fd27dec9b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -180,6 +180,7 @@ namespace MWWorld virtual void setWaterHeight(const float height); virtual bool toggleWater(); + virtual bool toggleWorld(); virtual void adjustSky(); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index e12ab65eb5..25ee6fdb66 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -256,6 +256,8 @@ namespace Compiler extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo); extensions.registerInstruction ("togglewater", "", opcodeToggleWater); extensions.registerInstruction ("twa", "", opcodeToggleWater); + extensions.registerInstruction ("toggleworld", "", opcodeToggleWorld); + extensions.registerInstruction ("tw", "", opcodeToggleWorld); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 440475773d..5063397e11 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -212,6 +212,7 @@ namespace Compiler const int opcodeFadeOut = 0x200013d; const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; + const int opcodeToggleWorld = 0x20002f5; const int opcodeTogglePathgrid = 0x2000146; const int opcodeDontSaveObject = 0x2000153; const int opcodeToggleVanityMode = 0x2000174; From 795dfdb5576da3cb1d46b1838c2f8d3ab0fb5d58 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Sep 2014 18:14:25 +0200 Subject: [PATCH 02/19] Fix size_t underflow for journals with 1 page (Fixes #1958) --- apps/openmw/mwgui/journalwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 4139a7d24f..0bcd5062d2 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -490,7 +490,7 @@ namespace unsigned int & page = mStates.top ().mPage; Book book = mStates.top ().mBook; - if (page < book->pageCount () - 2) + if (page+2 < book->pageCount()) { page += 2; updateShowingPages (); From c826de49a515fbf9cdb623308b284e945b933061 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Sep 2014 22:57:00 +0200 Subject: [PATCH 03/19] Potential shader compatibility fix --- files/materials/water.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/materials/water.shader b/files/materials/water.shader index 701154ffa3..418b137158 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -40,7 +40,7 @@ SH_START_PROGRAM { - shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(1.0, 1.0, 1.0); + shOutputColour(0).xyz = shSample(animatedTexture, UV * float2(15.0, 15.0)).xyz * float3(1.0, 1.0, 1.0); shOutputColour(0).w = 0.7; #if FOG From ee8b85aa2ca4da655adf19ab4401ac3c539557e7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Sep 2014 22:57:38 +0200 Subject: [PATCH 04/19] Fix priority bug in AiSequence::stack (Fixes #1959) --- apps/openmw/mwmechanics/aisequence.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 0341c9745d..f28809d4fd 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -260,15 +260,14 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { - if(mPackages.front()->getPriority() <= package.getPriority()) + if((*it)->getPriority() <= package.getPriority()) { mPackages.insert(it,package.clone()); return; } } - if(mPackages.empty()) - mPackages.push_front (package.clone()); + mPackages.push_front (package.clone()); } AiPackage* MWMechanics::AiSequence::getActivePackage() From 46adf6344a60f57c66a6a03876e344d630f00f86 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 17:45:20 +0200 Subject: [PATCH 05/19] Adjust third person camera height and default distance to match vanilla MW --- apps/openmw/mwrender/camera.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index bb196f2827..51fcb46863 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -26,8 +26,8 @@ namespace MWRender mNearest(30.f), mFurthest(800.f), mIsNearest(false), - mHeight(128.f), - mCameraDistance(300.f), + mHeight(124.f), + mCameraDistance(192.f), mDistanceAdjusted(false), mVanityToggleQueued(false), mViewModeToggleQueued(false) From f9b6cc468db9d826f260fdc1d893b4c323ffd9ab Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 17:54:18 +0200 Subject: [PATCH 06/19] Don't reset an unbound input action to its default binding if the key/mouse button for that default binding is already used by another action (Fixes #1960) --- apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++++-- extern/oics/ICSInputControlSystem.h | 4 +++- extern/oics/ICSInputControlSystem_keyboard.cpp | 5 +++++ extern/oics/ICSInputControlSystem_mouse.cpp | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 3cd30819c2..10cd347490 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -936,9 +936,11 @@ namespace MWInput { clearAllBindings (control); - if (defaultKeyBindings.find(i) != defaultKeyBindings.end()) + if (defaultKeyBindings.find(i) != defaultKeyBindings.end() + && !mInputBinder->isKeyBound(defaultKeyBindings[i])) mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE); - else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()) + else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end() + && !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i])) mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); } } diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index f874abaf8d..6a6a6bf09c 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -119,9 +119,11 @@ namespace ICS //bool sliderMoved(const OIS::JoyStickEvent &evt, int index); void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction); + bool isKeyBound(SDL_Scancode key) const; void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction); void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction); - void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction); + bool isMouseButtonBound(unsigned int button) const; + void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction); void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction); void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction); void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction); diff --git a/extern/oics/ICSInputControlSystem_keyboard.cpp b/extern/oics/ICSInputControlSystem_keyboard.cpp index af0eec82ad..ed35d9870d 100644 --- a/extern/oics/ICSInputControlSystem_keyboard.cpp +++ b/extern/oics/ICSInputControlSystem_keyboard.cpp @@ -61,6 +61,11 @@ namespace ICS mControlsKeyBinderMap[ key ] = controlKeyBinderItem; } + bool InputControlSystem::isKeyBound(SDL_Scancode key) const + { + return mControlsKeyBinderMap.find(key) != mControlsKeyBinderMap.end(); + } + void InputControlSystem::removeKeyBinding(SDL_Scancode key) { ControlsKeyBinderMapType::iterator it = mControlsKeyBinderMap.find(key); diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp index d1ef721b21..9742d389c1 100644 --- a/extern/oics/ICSInputControlSystem_mouse.cpp +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -139,6 +139,11 @@ namespace ICS mControlsMouseButtonBinderMap[ button ] = controlMouseButtonBinderItem; } + bool InputControlSystem::isMouseButtonBound(unsigned int button) const + { + return mControlsMouseButtonBinderMap.find(button) != mControlsMouseButtonBinderMap.end(); + } + // get bindings InputControlSystem::NamedAxis InputControlSystem::getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction) { From 85f5754bb67fe61bc3c92617860782d4c67007d0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 18:55:35 +0200 Subject: [PATCH 07/19] Apply third person camera distance to the camera node instead of only the camera itself (Fixes #1705) --- apps/openmw/mwrender/camera.cpp | 72 +++++++++++++++-------- apps/openmw/mwrender/camera.hpp | 6 +- apps/openmw/mwrender/renderingmanager.cpp | 12 +++- apps/openmw/mwrender/renderingmanager.hpp | 2 + apps/openmw/mwrender/sky.cpp | 32 ++++++---- apps/openmw/mwrender/sky.hpp | 3 + 6 files changed, 86 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 51fcb46863..5a4b515040 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -19,6 +19,7 @@ namespace MWRender Camera::Camera (Ogre::Camera *camera) : mCamera(camera), mCameraNode(NULL), + mCameraPosNode(NULL), mAnimation(NULL), mFirstPersonView(true), mPreviewMode(false), @@ -66,12 +67,16 @@ namespace MWRender } Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X); - if (!mVanity.enabled && !mPreviewMode) { - mCamera->getParentNode()->setOrientation(xr); - } else { + Ogre::Quaternion orient = xr; + if (mVanity.enabled || mPreviewMode) { Ogre::Quaternion zr(Ogre::Radian(getYaw()), Ogre::Vector3::UNIT_Z); - mCamera->getParentNode()->setOrientation(zr * xr); + orient = zr * xr; } + + if (isFirstPerson()) + mCamera->getParentNode()->setOrientation(orient); + else + mCameraNode->setOrientation(orient); } const std::string &Camera::getHandle() const @@ -79,20 +84,40 @@ namespace MWRender return mTrackingPtr.getRefData().getHandle(); } - void Camera::attachTo(const MWWorld::Ptr &ptr) + Ogre::SceneNode* Camera::attachTo(const MWWorld::Ptr &ptr) { mTrackingPtr = ptr; Ogre::SceneNode *node = mTrackingPtr.getRefData().getBaseNode()->createChildSceneNode(Ogre::Vector3(0.0f, 0.0f, mHeight)); + node->setInheritScale(false); + Ogre::SceneNode *posNode = node->createChildSceneNode(); + posNode->setInheritScale(false); if(mCameraNode) { node->setOrientation(mCameraNode->getOrientation()); - node->setPosition(mCameraNode->getPosition()); - node->setScale(mCameraNode->getScale()); + posNode->setPosition(mCameraPosNode->getPosition()); mCameraNode->getCreator()->destroySceneNode(mCameraNode); + mCameraNode->getCreator()->destroySceneNode(mCameraPosNode); } mCameraNode = node; - if(!mCamera->isAttached()) - mCameraNode->attachObject(mCamera); + mCameraPosNode = posNode; + + if (!isFirstPerson()) + { + mCamera->detachFromParent(); + mCameraPosNode->attachObject(mCamera); + } + + return mCameraPosNode; + } + + void Camera::setPosition(const Ogre::Vector3& position) + { + mCameraPosNode->setPosition(position); + } + + void Camera::setPosition(float x, float y, float z) + { + setPosition(Ogre::Vector3(x,y,z)); } void Camera::updateListener() @@ -155,9 +180,9 @@ namespace MWRender processViewChange(); if (mFirstPersonView) { - mCamera->setPosition(0.f, 0.f, 0.f); + setPosition(0.f, 0.f, 0.f); } else { - mCamera->setPosition(0.f, 0.f, mCameraDistance); + setPosition(0.f, 0.f, mCameraDistance); } } @@ -191,14 +216,14 @@ namespace MWRender Ogre::Vector3 rot(0.f, 0.f, 0.f); if (mVanity.enabled) { rot.x = Ogre::Degree(-30.f).valueRadians(); - mMainCam.offset = mCamera->getPosition().z; + mMainCam.offset = mCameraPosNode->getPosition().z; } else { rot.x = getPitch(); offset = mMainCam.offset; } rot.z = getYaw(); - mCamera->setPosition(0.f, 0.f, offset); + setPosition(0.f, 0.f, offset); rotateCamera(rot, false); return true; @@ -215,7 +240,7 @@ namespace MWRender mPreviewMode = enable; processViewChange(); - float offset = mCamera->getPosition().z; + float offset = mCameraPosNode->getPosition().z; if (mPreviewMode) { mMainCam.offset = offset; offset = mPreviewCam.offset; @@ -224,7 +249,7 @@ namespace MWRender offset = mMainCam.offset; } - mCamera->setPosition(0.f, 0.f, offset); + setPosition(0.f, 0.f, offset); } void Camera::setSneakOffset(float offset) @@ -283,7 +308,7 @@ namespace MWRender float Camera::getCameraDistance() const { - return mCamera->getPosition().z; + return mCameraPosNode->getPosition().z; } void Camera::setCameraDistance(float dist, bool adjust, bool override) @@ -295,7 +320,7 @@ namespace MWRender Ogre::Vector3 v(0.f, 0.f, dist); if (adjust) { - v += mCamera->getPosition(); + v += mCameraPosNode->getPosition(); } if (v.z >= mFurthest) { v.z = mFurthest; @@ -305,7 +330,7 @@ namespace MWRender v.z = mNearest; mIsNearest = true; } - mCamera->setPosition(v); + setPosition(v); if (override) { if (mVanity.enabled || mPreviewMode) { @@ -322,9 +347,9 @@ namespace MWRender { if (mDistanceAdjusted) { if (mVanity.enabled || mPreviewMode) { - mCamera->setPosition(0, 0, mPreviewCam.offset); + setPosition(0, 0, mPreviewCam.offset); } else if (!mFirstPersonView) { - mCamera->setPosition(0, 0, mCameraDistance); + setPosition(0, 0, mCameraDistance); } } mDistanceAdjusted = false; @@ -355,10 +380,10 @@ namespace MWRender Ogre::TagPoint *tag = mAnimation->attachObjectToBone("Head", mCamera); tag->setInheritOrientation(false); } - else + else { mAnimation->setViewMode(NpcAnimation::VM_Normal); - mCameraNode->attachObject(mCamera); + mCameraPosNode->attachObject(mCamera); } rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); } @@ -368,8 +393,7 @@ namespace MWRender mCamera->getParentSceneNode()->needUpdate(true); camera = mCamera->getRealPosition(); - focal = Ogre::Vector3((mCamera->getParentNode()->_getFullTransform() * - Ogre::Vector4(0.0f, 0.0f, 0.0f, 1.0f)).ptr()); + focal = mCameraNode->_getDerivedPosition(); } void Camera::togglePlayerLooking(bool enable) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index f7b0ae6e82..c542dc96ce 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -27,6 +27,7 @@ namespace MWRender Ogre::Camera *mCamera; Ogre::SceneNode *mCameraNode; + Ogre::SceneNode *mCameraPosNode; NpcAnimation *mAnimation; @@ -52,6 +53,9 @@ namespace MWRender /// Updates sound manager listener data void updateListener(); + void setPosition(const Ogre::Vector3& position); + void setPosition(float x, float y, float z); + public: Camera(Ogre::Camera *camera); ~Camera(); @@ -72,7 +76,7 @@ namespace MWRender const std::string &getHandle() const; /// Attach camera to object - void attachTo(const MWWorld::Ptr &); + Ogre::SceneNode* attachTo(const MWWorld::Ptr &); /// @param Force view mode switch, even if currently not allowed by the animation. void toggleViewMode(bool force=false); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 68d5f515df..f476a78073 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -312,7 +312,7 @@ void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr) if(mPlayerAnimation) mPlayerAnimation->updatePtr(ptr); if(mCamera->getHandle() == ptr.getRefData().getHandle()) - mCamera->attachTo(ptr); + attachCameraTo(ptr); } void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) @@ -327,7 +327,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) anim->rebuild(); if(mCamera->getHandle() == ptr.getRefData().getHandle()) { - mCamera->attachTo(ptr); + attachCameraTo(ptr); mCamera->setAnimation(anim); } } @@ -869,7 +869,13 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr) { ptr.getRefData().setBaseNode(mRendering.getScene()->getSceneNode("player")); - mCamera->attachTo(ptr); + attachCameraTo(ptr); +} + +void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr) +{ + Ogre::SceneNode* cameraNode = mCamera->attachTo(ptr); + mSkyManager->attachToNode(cameraNode); } void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 1c735f0567..fa48deafa6 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -221,6 +221,8 @@ private: void setAmbientMode(); void applyFog(bool underwater); + void attachCameraTo(const MWWorld::Ptr& ptr); + void setMenuTransparency(float val); bool mSunEnabled; diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 4620173b51..8e7bd3d895 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -382,9 +382,7 @@ void SkyManager::clearRain() for (std::map::iterator it = mRainModels.begin(); it != mRainModels.end();) { it->second.setNull(); - Ogre::SceneNode* parent = it->first->getParentSceneNode(); mSceneMgr->destroySceneNode(it->first); - mSceneMgr->destroySceneNode(parent); mRainModels.erase(it++); } } @@ -402,9 +400,7 @@ void SkyManager::updateRain(float dt) if (pos.z < -minHeight) { it->second.setNull(); - Ogre::SceneNode* parent = it->first->getParentSceneNode(); mSceneMgr->destroySceneNode(it->first); - mSceneMgr->destroySceneNode(parent); mRainModels.erase(it++); } else @@ -420,17 +416,20 @@ void SkyManager::updateRain(float dt) { mRainTimer = 0; + // TODO: handle rain settings from Morrowind.ini const float rangeRandom = 100; float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2); float yOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2); - Ogre::SceneNode* sceneNode = mCamera->getParentSceneNode()->createChildSceneNode(); - sceneNode->setInheritOrientation(false); // Create a separate node to control the offset, since a node with setInheritOrientation(false) will still // consider the orientation of the parent node for its position, just not for its orientation float startHeight = 700; - Ogre::SceneNode* offsetNode = sceneNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight)); + Ogre::SceneNode* offsetNode = mParticleNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight)); + // Spawn a new rain object for each instance. + // TODO: this is inefficient. We could try to use an Ogre::ParticleSystem instead, but then we would need to make assumptions + // about the rain meshes being Quads and their dimensions. + // Or we could clone meshes into one vertex buffer manually. NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(offsetNode, mRainEffect); for (unsigned int i=0; imEntities.size(); ++i) { @@ -562,12 +561,6 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) } else { - if (!mParticleNode) - { - mParticleNode = mCamera->getParentSceneNode()->createChildSceneNode(); - mParticleNode->setInheritOrientation(false); - } - mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect); for(size_t i = 0; i < mParticle->mParticles.size(); ++i) { @@ -783,3 +776,16 @@ void SkyManager::setGlareEnabled (bool enabled) return; mSunGlare->setVisible (mSunEnabled && enabled); } + +void SkyManager::attachToNode(SceneNode *sceneNode) +{ + if (!mParticleNode) + { + mParticleNode = sceneNode->createChildSceneNode(); + mParticleNode->setInheritOrientation(false); + } + else + { + sceneNode->addChild(mParticleNode); + } +} diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index e40eb1dcec..0544f17eff 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -116,6 +116,9 @@ namespace MWRender SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera); ~SkyManager(); + /// Attach weather particle effects to this scene node (should be the Camera's parent node) + void attachToNode(Ogre::SceneNode* sceneNode); + void update(float duration); void enable(); From 88da7f5157777f8b5e4159cbb3a845cb41e6b272 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 19:53:50 +0200 Subject: [PATCH 08/19] Adjust border skin for loading bar and message boxes to match vanilla MW --- apps/openmw/mwgui/messagebox.cpp | 8 +++----- files/mygui/openmw_loading_screen.layout | 2 +- files/mygui/openmw_messagebox.layout | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 80f38ba40a..d4520aad7e 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -157,12 +157,11 @@ namespace MWGui , mMaxTime(0) { // defines - mBottomPadding = 20; - mNextBoxPadding = 20; + mBottomPadding = 48; + mNextBoxPadding = 4; getWidget(mMessageWidget, "message"); - mMessageWidget->setOverflowToTheLeft(true); mMessageWidget->setCaptionWithReplacing(mMessage); } @@ -178,7 +177,7 @@ namespace MWGui int MessageBox::getHeight () { - return mMainWidget->getHeight()+mNextBoxPadding; // 20 is the padding between this and the next MessageBox + return mMainWidget->getHeight()+mNextBoxPadding; } @@ -204,7 +203,6 @@ namespace MWGui getWidget(mMessageWidget, "message"); getWidget(mButtonsWidget, "buttons"); - mMessageWidget->setOverflowToTheLeft(true); mMessageWidget->setSize(400, mMessageWidget->getHeight()); mMessageWidget->setCaptionWithReplacing(message); diff --git a/files/mygui/openmw_loading_screen.layout b/files/mygui/openmw_loading_screen.layout index eda0020407..49ee0a1de5 100644 --- a/files/mygui/openmw_loading_screen.layout +++ b/files/mygui/openmw_loading_screen.layout @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_messagebox.layout b/files/mygui/openmw_messagebox.layout index 8264d64b99..a70e145032 100644 --- a/files/mygui/openmw_messagebox.layout +++ b/files/mygui/openmw_messagebox.layout @@ -1,7 +1,7 @@ - + From cd52002740b410c4af9e48d1d32d053ac25425a8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 21:41:45 +0200 Subject: [PATCH 09/19] Remove some unneeded bits from collision mask --- libs/openengine/bullet/physic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index d3aa714f14..97418fae02 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -387,7 +387,7 @@ namespace Physic mHeightFieldMap [name] = hf; mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap, - CollisionType_World|CollisionType_Actor|CollisionType_Raycasting); + CollisionType_Actor|CollisionType_Raycasting); } void PhysicEngine::removeHeightField(int x, int y) @@ -494,7 +494,7 @@ namespace Physic { assert (mCollisionObjectMap.find(name) == mCollisionObjectMap.end()); mCollisionObjectMap[name] = body; - mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap); + mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_Actor|CollisionType_HeightMap); } else { From 1c51694aa98963f02c0493b0817f4f0d7b176c41 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 21:54:59 +0200 Subject: [PATCH 10/19] Don't update physics and animation for actors outside the AI processing distance --- apps/openmw/mwmechanics/actors.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a5063594aa..82f60221b7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1122,20 +1122,21 @@ namespace MWMechanics int hostilesCount = 0; // need to know this to play Battle music + // AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this + // (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not) + // This distance could be made configurable later, but the setting must be marked with a big warning: + // using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876) + const float sqrProcessingDistance = 7168*7168; + // AI and magic effects update for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); - - // AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this - // (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not) - // This distance could be made configurable later, but the setting must be marked with a big warning: - // using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876) if (MWBase::Environment::get().getMechanicsManager()->isAIActive() && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos)) - <= 7168*7168) + <= sqrProcessingDistance) { if (timerUpdateAITargets == 0) { @@ -1182,6 +1183,11 @@ namespace MWMechanics CharacterController* playerCharacter = NULL; for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { + if (iter->first != player && + Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos)) + > sqrProcessingDistance) + continue; + if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).getMagnitude() > 0) iter->second->skipAnim(); From a33514fa1db5d18cfa931bfc7fb57db362df53f6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 23:19:23 +0200 Subject: [PATCH 11/19] More shader compatibility fixes --- files/materials/atmosphere.shader | 12 ++++++------ files/materials/clouds.shader | 12 ++++++------ files/materials/moon.shader | 12 ++++++------ files/materials/sun.shader | 12 ++++++------ 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/files/materials/atmosphere.shader b/files/materials/atmosphere.shader index c8a8e02203..5040052fc0 100644 --- a/files/materials/atmosphere.shader +++ b/files/materials/atmosphere.shader @@ -12,13 +12,13 @@ { float4x4 viewFixed = view; #if !SH_GLSL - viewFixed[0][3] = 0; - viewFixed[1][3] = 0; - viewFixed[2][3] = 0; + viewFixed[0][3] = 0.0; + viewFixed[1][3] = 0.0; + viewFixed[2][3] = 0.0; #else - viewFixed[3][0] = 0; - viewFixed[3][1] = 0; - viewFixed[3][2] = 0; + viewFixed[3][0] = 0.0; + viewFixed[3][1] = 0.0; + viewFixed[3][2] = 0.0; #endif shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shInputPosition)); alphaFade = shInputPosition.z < 150.0 ? 0.0 : 1.0; diff --git a/files/materials/clouds.shader b/files/materials/clouds.shader index 9e9b102564..90c4d0f847 100644 --- a/files/materials/clouds.shader +++ b/files/materials/clouds.shader @@ -14,13 +14,13 @@ float4x4 worldviewFixed = worldview; #if !SH_GLSL - worldviewFixed[0][3] = 0; - worldviewFixed[1][3] = 0; - worldviewFixed[2][3] = 0; + worldviewFixed[0][3] = 0.0; + worldviewFixed[1][3] = 0.0; + worldviewFixed[2][3] = 0.0; #else - worldviewFixed[3][0] = 0; - worldviewFixed[3][1] = 0; - worldviewFixed[3][2] = 0; + worldviewFixed[3][0] = 0.0; + worldviewFixed[3][1] = 0.0; + worldviewFixed[3][2] = 0.0; #endif shOutputPosition = shMatrixMult(proj, shMatrixMult(worldviewFixed, shInputPosition)); diff --git a/files/materials/moon.shader b/files/materials/moon.shader index a7d183d108..d369a1c684 100644 --- a/files/materials/moon.shader +++ b/files/materials/moon.shader @@ -13,13 +13,13 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix) { float4x4 viewFixed = view; #if !SH_GLSL - viewFixed[0][3] = 0; - viewFixed[1][3] = 0; - viewFixed[2][3] = 0; + viewFixed[0][3] = 0.0; + viewFixed[1][3] = 0.0; + viewFixed[2][3] = 0.0; #else - viewFixed[3][0] = 0; - viewFixed[3][1] = 0; - viewFixed[3][2] = 0; + viewFixed[3][0] = 0.0; + viewFixed[3][1] = 0.0; + viewFixed[3][2] = 0.0; #endif shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shMatrixMult(world, shInputPosition))); UV = uv0; diff --git a/files/materials/sun.shader b/files/materials/sun.shader index abe4c97f15..fc747b522f 100644 --- a/files/materials/sun.shader +++ b/files/materials/sun.shader @@ -13,13 +13,13 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix) { float4x4 viewFixed = view; #if !SH_GLSL - viewFixed[0][3] = 0; - viewFixed[1][3] = 0; - viewFixed[2][3] = 0; + viewFixed[0][3] = 0.0; + viewFixed[1][3] = 0.0; + viewFixed[2][3] = 0.0; #else - viewFixed[3][0] = 0; - viewFixed[3][1] = 0; - viewFixed[3][2] = 0; + viewFixed[3][0] = 0.0; + viewFixed[3][1] = 0.0; + viewFixed[3][2] = 0.0; #endif shOutputPosition = shMatrixMult(projection, shMatrixMult(viewFixed, shMatrixMult(world, shInputPosition))); UV = uv0; From 0bd9f30c6732a83102b5cb31ad51d7b550ead8b9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 23:24:03 +0200 Subject: [PATCH 12/19] Remove comment for old MyGUI version --- apps/openmw/mwgui/race.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index e3bec37899..2bfc4f1416 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -41,12 +41,11 @@ namespace MWGui getWidget(mHeadRotate, "HeadRotate"); - // Mouse wheel step is hardcoded to 50 in MyGUI 3.2 ("FIXME"). - // Give other steps the same value to accomodate. mHeadRotate->setScrollRange(1000); mHeadRotate->setScrollPosition(500); mHeadRotate->setScrollViewPage(50); mHeadRotate->setScrollPage(50); + mHeadRotate->setScrollWheelPage(50); mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate); // Set up next/previous buttons From d99e416208e22fde052ff683ce28b30da24abb75 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 1 Oct 2014 23:39:17 +0200 Subject: [PATCH 13/19] Remove some unused methods from OEngine::Gui::Layout --- libs/openengine/gui/layout.hpp | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index 26a3fdab84..cd530a1d93 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -42,6 +42,7 @@ namespace GUI MYGUI_ASSERT( ! _throw, "widget name '" << _name << "' in layout '" << mLayoutName << "' not found."); } + private: void initialise(const std::string & _layout, MyGUI::Widget* _parent = nullptr) { @@ -74,6 +75,7 @@ namespace GUI mListWindowRoot.clear(); } + public: void setCoord(int x, int y, int w, int h) { mMainWidget->setCoord(x,y,w,h); @@ -121,29 +123,6 @@ namespace GUI adjustWindowCaption(); } - void setState(const std::string& widget, const std::string& state) - { - MyGUI::Widget* pt; - getWidget(pt, widget); - pt->_setWidgetState(state); - } - - void setTextColor(const std::string& name, float r, float g, float b) - { - MyGUI::Widget* pt; - getWidget(pt, name); - MyGUI::TextBox *st = dynamic_cast(pt); - if(st != NULL) - st->setTextColour(MyGUI::Colour(b,g,r)); - } - - void setImage(const std::string& name, const std::string& imgName) - { - MyGUI::ImageBox* pt; - getWidget(pt, name); - pt->setImageTexture(imgName); - } - void adjustButtonSize(MyGUI::Button* button) { // adjust size of button to fit its text From 7e10818bdfa5c5f7e0bce710ca771538b42869c3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 00:32:22 +0200 Subject: [PATCH 14/19] Fix uninitialized flags for custom-made spells --- apps/openmw/mwgui/spellcreationdialog.cpp | 4 ++-- apps/openmw/mwmechanics/enchanting.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 1116d65438..e2fac9d6d9 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -422,12 +422,12 @@ namespace MWGui y *= 1.5; } - mSpell.mData.mCost = int(y); - ESM::EffectList effectList; effectList.mList = mEffects; mSpell.mEffects = effectList; + mSpell.mData.mCost = int(y); mSpell.mData.mType = ESM::Spell::ST_Spell; + mSpell.mData.mFlags = 0; mMagickaCost->setCaption(boost::lexical_cast(int(y))); diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 63ffbc7e8c..c134942b88 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -53,6 +53,9 @@ namespace MWMechanics MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); ESM::Enchantment enchantment; enchantment.mData.mCharge = getGemCharge(); + enchantment.mData.mAutocalc = 0; + enchantment.mData.mType = mCastStyle; + enchantment.mData.mCost = getEnchantPoints(); store.remove(mSoulGemPtr, 1, player); @@ -72,8 +75,6 @@ namespace MWMechanics { enchantment.mData.mCharge=0; } - enchantment.mData.mType = mCastStyle; - enchantment.mData.mCost = getEnchantPoints(); enchantment.mEffects = mEffectList; // Apply the enchantment From afbd2de51154d1ced815b2fed299b7ce683af33a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 13:54:56 +0200 Subject: [PATCH 15/19] Fix broken alchemy magnitude/duration --- apps/openmw/mwmechanics/alchemy.cpp | 20 ++++++++++++-------- apps/openmw/mwmechanics/alchemy.hpp | 3 +-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 24e7b5aa11..90c1808173 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -133,7 +133,7 @@ void MWMechanics::Alchemy::updateEffects() std::set effects (listEffects()); // general alchemy factor - float x = getChance(); + float x = getAlchemyFactor(); x *= mTools[ESM::Apparatus::MortarPestle].get()->mBase->mData.mQuality; x *= MWBase::Environment::get().getWorld()->getStore().get().find ("fPotionStrengthMult")->getFloat(); @@ -306,18 +306,15 @@ void MWMechanics::Alchemy::increaseSkill() mAlchemist.getClass().skillUsageSucceeded (mAlchemist, ESM::Skill::Alchemy, 0); } -float MWMechanics::Alchemy::getChance() const +float MWMechanics::Alchemy::getAlchemyFactor() const { const CreatureStats& creatureStats = mAlchemist.getClass().getCreatureStats (mAlchemist); const NpcStats& npcStats = mAlchemist.getClass().getNpcStats (mAlchemist); - if (beginEffects() == endEffects()) - return 0.f; - return (npcStats.getSkill (ESM::Skill::Alchemy).getModified() + - 0.1 * creatureStats.getAttribute (1).getModified() - + 0.1 * creatureStats.getAttribute (7).getModified()); + 0.1 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified() + + 0.1 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()); } int MWMechanics::Alchemy::countIngredients() const @@ -461,7 +458,14 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na if (listEffects().empty()) return Result_NoEffects; - if (getChance() (RAND_MAX)*100) + if (beginEffects() == endEffects()) + { + // all effects were nullified due to insufficient skill + removeIngredients(); + return Result_RandomFailure; + } + + if (getAlchemyFactor() (RAND_MAX)*100) { removeIngredients(); return Result_RandomFailure; diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index a2429ca8ef..e6b8c66509 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -69,8 +69,7 @@ namespace MWMechanics void increaseSkill(); ///< Increase alchemist's skill. - float getChance() const; - ///< Return chance of success. + float getAlchemyFactor() const; int countIngredients() const; From cc63f7f05127e94d8913b2ff38051fd4440e9428 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 14:23:13 +0200 Subject: [PATCH 16/19] Fix broken idle camera --- apps/openmw/mwrender/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 5a4b515040..1850df904b 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -197,7 +197,7 @@ namespace MWRender { // Changing the view will stop all playing animations, so if we are playing // anything important, queue the view change for later - if (!mPreviewMode) + if (isFirstPerson() && !mAnimation->upperBodyReady()) { mVanityToggleQueued = true; return false; From 861cc26aa6f5fe8b393d271caf092ff74119a678 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 14:45:57 +0200 Subject: [PATCH 17/19] Don't sell racial spells (Fixes #1961) --- apps/openmw/mwgui/spellbuyingwindow.cpp | 9 +++++++++ apps/openmw/mwmechanics/autocalcspell.cpp | 2 +- components/esm/spelllist.cpp | 8 ++++++++ components/esm/spelllist.hpp | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index cd378aadf8..dd6339b4c7 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -100,6 +100,15 @@ namespace MWGui if (spell->mData.mType!=ESM::Spell::ST_Spell) continue; // don't try to sell diseases, curses or powers + if (actor.getClass().isNpc()) + { + const ESM::Race* race = + MWBase::Environment::get().getWorld()->getStore().get().find( + actor.get()->mBase->mRace); + if (race->mPowers.exists(spell->mId)) + continue; + } + if (playerHasSpell(iter->first)) continue; diff --git a/apps/openmw/mwmechanics/autocalcspell.cpp b/apps/openmw/mwmechanics/autocalcspell.cpp index 01447c6e4d..7b8c43a064 100644 --- a/apps/openmw/mwmechanics/autocalcspell.cpp +++ b/apps/openmw/mwmechanics/autocalcspell.cpp @@ -72,7 +72,7 @@ namespace MWMechanics if (baseMagicka < iAutoSpellTimesCanCast * spell->mData.mCost) continue; - if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell->mId) != race->mPowers.mList.end()) + if (race && race->mPowers.exists(spell->mId)) continue; if (!attrSkillCheck(spell, actorSkills, actorAttributes)) diff --git a/components/esm/spelllist.cpp b/components/esm/spelllist.cpp index aeface6173..8ec386db40 100644 --- a/components/esm/spelllist.cpp +++ b/components/esm/spelllist.cpp @@ -20,4 +20,12 @@ void SpellList::save(ESMWriter &esm) const } } +bool SpellList::exists(const std::string &spell) const +{ + for (std::vector::const_iterator it = mList.begin(); it != mList.end(); ++it) + if (Misc::StringUtils::ciEqual(*it, spell)) + return true; + return false; +} + } diff --git a/components/esm/spelllist.hpp b/components/esm/spelllist.hpp index 934bdda7ad..bcd6ba7984 100644 --- a/components/esm/spelllist.hpp +++ b/components/esm/spelllist.hpp @@ -16,6 +16,9 @@ namespace ESM { std::vector mList; + /// Is this spell ID in mList? + bool exists(const std::string& spell) const; + void load(ESMReader &esm); void save(ESMWriter &esm) const; }; From eda296f1e391e3be38e75ad3edbefe879fe1dd6c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 16:15:56 +0200 Subject: [PATCH 18/19] Remove workaround for Ogre 1.8 (no longer supported) --- components/terrain/quadtreenode.cpp | 34 +---------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 44974eeb1d..57379a334d 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -73,38 +73,6 @@ namespace return NULL; } - - // Ogre::AxisAlignedBox::distance is broken in 1.8. - Ogre::Real distance(const Ogre::AxisAlignedBox& box, const Ogre::Vector3& v) - { - - if (box.contains(v)) - return 0; - else - { - Ogre::Vector3 maxDist(0,0,0); - const Ogre::Vector3& minimum = box.getMinimum(); - const Ogre::Vector3& maximum = box.getMaximum(); - - if (v.x < minimum.x) - maxDist.x = minimum.x - v.x; - else if (v.x > maximum.x) - maxDist.x = v.x - maximum.x; - - if (v.y < minimum.y) - maxDist.y = minimum.y - v.y; - else if (v.y > maximum.y) - maxDist.y = v.y - maximum.y; - - if (v.z < minimum.z) - maxDist.z = minimum.z - v.z; - else if (v.z > maximum.z) - maxDist.z = v.z - maximum.z; - - return maxDist.length(); - } - } - // Create a 2D quad void makeQuad(Ogre::SceneManager* sceneMgr, float left, float top, float right, float bottom, Ogre::MaterialPtr material) { @@ -270,7 +238,7 @@ bool QuadTreeNode::update(const Ogre::Vector3 &cameraPos) if (mBounds.isNull()) return true; - float dist = distance(mWorldBounds, cameraPos); + float dist = mWorldBounds.distance(cameraPos); // Make sure our scene node is attached if (!mSceneNode->isInSceneGraph()) From 7d36a202a8919e85bc9eaf497e6ed29f1b480c91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 2 Oct 2014 16:30:23 +0200 Subject: [PATCH 19/19] Implement cell loading threshold (Fixes #1874) The cell loading threshold (default: 1024 units) prevents exterior cell loading until the player has travelled part-way into the next cell. This gets rid of excessive cell loadings when walking along an exterior cell border. Lower the maximum allowed view distance in options menu to accomodate. Change setting name so that old settings files are upgraded. --- apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 26 ++-- apps/openmw/mwgui/mapwindow.hpp | 4 +- apps/openmw/mwgui/windowmanagerimp.cpp | 15 +- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 9 +- apps/openmw/mwrender/localmap.hpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 6 +- apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwworld/scene.cpp | 173 +++++++++++++--------- apps/openmw/mwworld/scene.hpp | 18 ++- apps/openmw/mwworld/worldimp.cpp | 19 ++- apps/openmw/mwworld/worldimp.hpp | 2 +- files/mygui/openmw_console.layout | 3 +- files/mygui/openmw_settings_window.layout | 4 +- files/settings-default.cfg | 8 +- 17 files changed, 172 insertions(+), 124 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index bce3f516e8..58fa221e66 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -177,7 +177,7 @@ namespace MWBase virtual void changeCell(MWWorld::CellStore* cell) = 0; ///< change the active cell - virtual void setPlayerPos(const float x, const float y) = 0; + virtual void setPlayerPos(int cellX, int cellY, const float x, const float y) = 0; ///< set player position in map space virtual void setPlayerDir(const float x, const float y) = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 3f6260c058..73fa92529b 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -137,7 +137,7 @@ namespace MWBase virtual MWWorld::LocalScripts& getLocalScripts() = 0; virtual bool hasCellChanged() const = 0; - ///< Has the player moved to a different cell, since the last frame? + ///< Has the set of active cells changed, since the last frame? virtual bool isCellExterior() const = 0; diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 37bc4d1e39..80a3c5ae44 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -159,8 +159,6 @@ namespace MWGui , mLocalMap(NULL) , mPrefix() , mChanged(true) - , mLastPositionX(0.0f) - , mLastPositionY(0.0f) , mLastDirectionX(0.0f) , mLastDirectionY(0.0f) , mCompass(NULL) @@ -425,24 +423,24 @@ namespace MWGui mLocalMap->getParent()->_updateChilds(); } - void LocalMapBase::setPlayerPos(const float x, const float y) + void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny) { updateMagicMarkers(); - if (x == mLastPositionX && y == mLastPositionY) - return; - notifyPlayerUpdate (); - MyGUI::IntSize size = mLocalMap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - mLocalMap->setViewOffset(pos); + MyGUI::IntPoint pos(widgetSize+nx*widgetSize-16, widgetSize+ny*widgetSize-16); + pos.left += (cellX - mCurX) * widgetSize; + pos.top -= (cellY - mCurY) * widgetSize; - mCompass->setPosition(MyGUI::IntPoint(widgetSize+x*widgetSize-16, widgetSize+y*widgetSize-16)); - mLastPositionX = x; - mLastPositionY = y; + if (pos != mCompass->getPosition()) + { + mCompass->setPosition(pos); + MyGUI::IntPoint middle (pos.left+16, pos.top+16); + MyGUI::IntCoord viewsize = mLocalMap->getCoord(); + MyGUI::IntPoint viewOffset(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); + mLocalMap->setViewOffset(viewOffset); + } } void LocalMapBase::setPlayerDir(const float x, const float y) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index e9c0c1a69f..a8aaa8e45f 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -75,7 +75,7 @@ namespace MWGui void setCellPrefix(const std::string& prefix); void setActiveCell(const int x, const int y, bool interior=false); void setPlayerDir(const float x, const float y); - void setPlayerPos(const float x, const float y); + void setPlayerPos(int cellX, int cellY, const float nx, const float ny); void onFrame(float dt); @@ -129,8 +129,6 @@ namespace MWGui float mMarkerUpdateTimer; - float mLastPositionX; - float mLastPositionY; float mLastDirectionX; float mLastDirectionY; }; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 70f4b5a2fe..16295d3a5e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -880,9 +880,6 @@ namespace MWGui mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->getCell()->getGridX (), cell->getCell()->getGridY ()); mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY()); - - mMap->setCellPrefix("Cell"); - mHud->setCellPrefix("Cell"); } else { @@ -900,14 +897,20 @@ namespace MWGui void WindowManager::setActiveMap(int x, int y, bool interior) { + if (!interior) + { + mMap->setCellPrefix("Cell"); + mHud->setCellPrefix("Cell"); + } + mMap->setActiveCell(x,y, interior); mHud->setActiveCell(x,y, interior); } - void WindowManager::setPlayerPos(const float x, const float y) + void WindowManager::setPlayerPos(int cellX, int cellY, const float x, const float y) { - mMap->setPlayerPos(x,y); - mHud->setPlayerPos(x,y); + mMap->setPlayerPos(cellX, cellY, x, y); + mHud->setPlayerPos(cellX, cellY, x, y); } void WindowManager::setPlayerDir(const float x, const float y) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 29d40c2e79..1dae776414 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -183,7 +183,7 @@ namespace MWGui virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell - virtual void setPlayerPos(const float x, const float y); ///< set player position in map space + virtual void setPlayerPos(int cellX, int cellY, const float x, const float y); ///< set player position in map space virtual void setPlayerDir(const float x, const float y); ///< set player view direction in map space virtual void setFocusObject(const MWWorld::Ptr& focus); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 85f73ab7ef..f4388eec54 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -25,7 +25,7 @@ using namespace MWRender; using namespace Ogre; LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering) : - mInterior(false), mCellX(0), mCellY(0) + mInterior(false) { mRendering = rend; mRenderingManager = rendering; @@ -522,10 +522,9 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni { x = std::ceil(pos.x / sSize)-1; y = std::ceil(pos.y / sSize)-1; - mCellX = x; - mCellY = y; } - MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior); + else + MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior); // convert from world coordinates to texture UV coordinates std::string texBaseName; @@ -540,7 +539,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni texBaseName = mInteriorName + "_"; } - MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v); + MWBase::Environment::get().getWindowManager()->setPlayerPos(x, y, u, v); MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y); // explore radius (squared) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index b531c3e294..4c60cbb11a 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -134,7 +134,6 @@ namespace MWRender Ogre::RenderTarget* mRenderTarget; bool mInterior; - int mCellX, mCellY; Ogre::AxisAlignedBox mBounds; std::string mInteriorName; }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index f476a78073..6ed11b71f3 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -499,7 +499,7 @@ bool RenderingManager::toggleRenderMode(int mode) } } -void RenderingManager::configureFog(MWWorld::CellStore &mCell) +void RenderingManager::configureFog(const MWWorld::CellStore &mCell) { Ogre::ColourValue color; color.setAsABGR (mCell.getCell()->mAmbi.mFog); @@ -510,7 +510,7 @@ void RenderingManager::configureFog(MWWorld::CellStore &mCell) void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) { mFogColour = colour; - float max = Settings::Manager::getFloat("max viewing distance", "Viewing distance"); + float max = Settings::Manager::getFloat("viewing distance", "Viewing distance"); if (density == 0) { @@ -742,7 +742,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec { setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } - else if (it->second == "max viewing distance" && it->first == "Viewing distance") + else if (it->second == "viewing distance" && it->first == "Viewing distance") { if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior() && MWBase::Environment::get().getWorld()->getPlayerPtr().mCell) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index fa48deafa6..2da0840749 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -183,7 +183,7 @@ public: ///< request the local map for a cell /// configure fog according to cell - void configureFog(MWWorld::CellStore &mCell); + void configureFog(const MWWorld::CellStore &mCell); /// configure fog manually void configureFog(const float density, const Ogre::ColourValue& colour); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index a316f0bb23..c98485dc9a 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -5,7 +5,7 @@ #include #include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" /// FIXME +#include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" @@ -117,6 +117,28 @@ namespace MWWorld } } + void Scene::getGridCenter(int &cellX, int &cellY) + { + int maxX = std::numeric_limits().min(); + int maxY = std::numeric_limits().min(); + int minX = std::numeric_limits().max(); + int minY = std::numeric_limits().max(); + CellStoreCollection::iterator iter = mActiveCells.begin(); + while (iter!=mActiveCells.end()) + { + assert ((*iter)->getCell()->isExterior()); + int x = (*iter)->getCell()->getGridX(); + int y = (*iter)->getCell()->getGridY(); + maxX = std::max(x, maxX); + maxY = std::max(y, maxY); + minX = std::min(x, minX); + minY = std::min(y, minY); + ++iter; + } + cellX = (minX + maxX) / 2; + cellY = (minY + maxY) / 2; + } + void Scene::update (float duration, bool paused) { if (mNeedMapUpdate) @@ -126,6 +148,13 @@ namespace MWWorld for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) mRendering.requestMap(*active); mNeedMapUpdate = false; + + if (mCurrentCell->isExterior()) + { + int cellX, cellY; + getGridCenter(cellX, cellY); + MWBase::Environment::get().getWindowManager()->setActiveMap(cellX,cellY,false); + } } mRendering.update (duration, paused); @@ -213,41 +242,6 @@ namespace MWWorld MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell); } - void Scene::playerCellChange(CellStore *cell, const ESM::Position& pos, bool adjustPlayerPos) - { - MWBase::World *world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr old = world->getPlayerPtr(); - world->getPlayer().setCell(cell); - - MWWorld::Ptr player = world->getPlayerPtr(); - mRendering.updatePlayerPtr(player); - - if (adjustPlayerPos) { - world->moveObject(player, pos.pos[0], pos.pos[1], pos.pos[2]); - - float x = Ogre::Radian(pos.rot[0]).valueDegrees(); - float y = Ogre::Radian(pos.rot[1]).valueDegrees(); - float z = Ogre::Radian(pos.rot[2]).valueDegrees(); - world->rotateObject(player, x, y, z); - - player.getClass().adjustPosition(player, true); - } - - MWBase::MechanicsManager *mechMgr = - MWBase::Environment::get().getMechanicsManager(); - - mechMgr->updateCell(old, player); - mechMgr->watchActor(player); - - mRendering.updateTerrain(); - - // Delay the map update until scripts have been given a chance to run. - // If we don't do this, objects that should be disabled will still appear on the map. - mNeedMapUpdate = true; - - MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - } - void Scene::changeToVoid() { CellStoreCollection::iterator active = mActiveCells.begin(); @@ -257,7 +251,28 @@ namespace MWWorld mCurrentCell = NULL; } - void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) + void Scene::playerMoved(const Ogre::Vector3 &pos) + { + if (!mCurrentCell || !mCurrentCell->isExterior()) + return; + + // figure out the center of the current cell grid (*not* necessarily mCurrentCell, which is the cell the player is in) + int cellX, cellY; + getGridCenter(cellX, cellY); + float centerX, centerY; + MWBase::Environment::get().getWorld()->indexToPosition(cellX, cellY, centerX, centerY, true); + const float maxDistance = 8192/2 + 1024; // 1/2 cell size + threshold + float distance = std::max(std::abs(centerX-pos.x), std::abs(centerY-pos.y)); + if (distance > maxDistance) + { + int newX, newY; + MWBase::Environment::get().getWorld()->positionToIndex(pos.x, pos.y, newX, newY); + changeCellGrid(newX, newY); + mRendering.updateTerrain(); + } + } + + void Scene::changeCellGrid (int X, int Y) { Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::ScopedLoad load(loadingListener); @@ -286,6 +301,7 @@ namespace MWWorld int refsToLoad = 0; // get the number of refs to load for (int x=X-1; x<=X+1; ++x) + { for (int y=Y-1; y<=Y+1; ++y) { CellStoreCollection::iterator iter = mActiveCells.begin(); @@ -304,11 +320,13 @@ namespace MWWorld if (iter==mActiveCells.end()) refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count(); } + } loadingListener->setProgressRange(refsToLoad); // Load cells for (int x=X-1; x<=X+1; ++x) + { for (int y=Y-1; y<=Y+1; ++y) { CellStoreCollection::iterator iter = mActiveCells.begin(); @@ -331,32 +349,47 @@ namespace MWWorld loadCell (cell, loadingListener); } } - - // find current cell - CellStoreCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) - { - assert ((*iter)->getCell()->isExterior()); - - if (X==(*iter)->getCell()->getGridX() && - Y==(*iter)->getCell()->getGridY()) - break; - - ++iter; } - assert (iter!=mActiveCells.end()); - - mCurrentCell = *iter; - - // adjust player - playerCellChange (mCurrentCell, position, adjustPlayerPos); - - // Sky system - MWBase::Environment::get().getWorld()->adjustSky(); + CellStore* current = MWBase::Environment::get().getWorld()->getExterior(X,Y); + MWBase::Environment::get().getWindowManager()->changeCell(current); mCellChanged = true; + + // Delay the map update until scripts have been given a chance to run. + // If we don't do this, objects that should be disabled will still appear on the map. + mNeedMapUpdate = true; + } + + void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos) + { + mCurrentCell = cell; + + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr old = world->getPlayerPtr(); + world->getPlayer().setCell(cell); + + MWWorld::Ptr player = world->getPlayerPtr(); + mRendering.updatePlayerPtr(player); + + if (adjustPlayerPos) { + world->moveObject(player, pos.pos[0], pos.pos[1], pos.pos[2]); + + float x = Ogre::Radian(pos.rot[0]).valueDegrees(); + float y = Ogre::Radian(pos.rot[1]).valueDegrees(); + float z = Ogre::Radian(pos.rot[2]).valueDegrees(); + world->rotateObject(player, x, y, z); + + player.getClass().adjustPosition(player, true); + } + + MWBase::MechanicsManager *mechMgr = + MWBase::Environment::get().getMechanicsManager(); + + mechMgr->updateCell(old, player); + mechMgr->watchActor(player); + + MWBase::Environment::get().getWorld()->adjustSky(); } //We need the ogre renderer and a scene node. @@ -427,33 +460,39 @@ namespace MWWorld // Load cell. std::cout << "cellName: " << cell->getCell()->mName << std::endl; - //Loading Interior loading text - loadCell (cell, loadingListener); - mCurrentCell = cell; + changePlayerCell(cell, position, true); // adjust fog mRendering.configureFog(*mCurrentCell); - // adjust player - playerCellChange (mCurrentCell, position); - // Sky system MWBase::Environment::get().getWorld()->adjustSky(); mCellChanged = true; MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5); + + MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); + + // Delay the map update until scripts have been given a chance to run. + // If we don't do this, objects that should be disabled will still appear on the map. + mNeedMapUpdate = true; } - void Scene::changeToExteriorCell (const ESM::Position& position) + void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos) { int x = 0; int y = 0; MWBase::Environment::get().getWorld()->positionToIndex (position.pos[0], position.pos[1], x, y); - changeCell (x, y, position, true); + changeCellGrid(x, y); + + CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y); + changePlayerCell(current, position, adjustPlayerPos); + + mRendering.updateTerrain(); } CellStore* Scene::getCurrentCell () diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index e0eeee1871..a9d80bf178 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -60,11 +60,13 @@ namespace MWWorld bool mNeedMapUpdate; - void playerCellChange (CellStore *cell, const ESM::Position& position, - bool adjustPlayerPos = true); - void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); + // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center + void changeCellGrid (int X, int Y); + + void getGridCenter(int& cellX, int& cellY); + public: Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics); @@ -75,19 +77,21 @@ namespace MWWorld void loadCell (CellStore *cell, Loading::Listener* loadingListener); - void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); + void playerMoved (const Ogre::Vector3& pos); - CellStore* getCurrentCell (); + void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos); + + CellStore *getCurrentCell(); const CellStoreCollection& getActiveCells () const; bool hasCellChanged() const; - ///< Has the player moved to a different cell, since the last frame? + ///< Has the set of active cells changed, since the last frame? void changeToInteriorCell (const std::string& cellName, const ESM::Position& position); ///< Move to interior cell. - void changeToExteriorCell (const ESM::Position& position); + void changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos); ///< Move to exterior cell. void changeToVoid(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 91fcf2b95a..cf8c11574f 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -241,7 +241,7 @@ namespace MWWorld pos.rot[0] = 0; pos.rot[1] = 0; pos.rot[2] = 0; - mWorldScene->changeToExteriorCell(pos); + mWorldScene->changeToExteriorCell(pos, true); } } @@ -920,7 +920,7 @@ namespace MWWorld mRendering->notifyWorldSpaceChanged(); } removeContainerScripts(getPlayerPtr()); - mWorldScene->changeToExteriorCell(position); + mWorldScene->changeToExteriorCell(position, true); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); } @@ -1057,9 +1057,10 @@ namespace MWWorld changeToInteriorCell(Misc::StringUtils::lowerCase(newCell->getCell()->mName), pos); else { - int cellX = newCell->getCell()->getGridX(); - int cellY = newCell->getCell()->getGridY(); - mWorldScene->changeCell(cellX, cellY, pos, false); + if (mWorldScene->isCellActive(*newCell)) + mWorldScene->changePlayerCell(newCell, pos, false); + else + mWorldScene->changeToExteriorCell(pos, false); } addContainerScripts (getPlayerPtr(), newCell); } @@ -1120,6 +1121,10 @@ namespace MWWorld mRendering->moveObject(ptr, vec); mPhysics->moveObject (ptr); } + if (isPlayer) + { + mWorldScene->playerMoved (vec); + } } bool World::moveObjectImp(const Ptr& ptr, float x, float y, float z) @@ -1565,7 +1570,7 @@ namespace MWWorld bool World::isCellExterior() const { - CellStore *currentCell = mWorldScene->getCurrentCell(); + const CellStore *currentCell = mWorldScene->getCurrentCell(); if (currentCell) { return currentCell->getCell()->isExterior(); @@ -1575,7 +1580,7 @@ namespace MWWorld bool World::isCellQuasiExterior() const { - CellStore *currentCell = mWorldScene->getCurrentCell(); + const CellStore *currentCell = mWorldScene->getCurrentCell(); if (currentCell) { if (!(currentCell->getCell()->mData.mFlags & ESM::Cell::QuasiEx)) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 8fd27dec9b..1a25edbe5b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -198,7 +198,7 @@ namespace MWWorld virtual LocalScripts& getLocalScripts(); virtual bool hasCellChanged() const; - ///< Has the player moved to a different cell, since the last frame? + ///< Has the set of active cells changed, since the last frame? virtual bool isCellExterior() const; diff --git a/files/mygui/openmw_console.layout b/files/mygui/openmw_console.layout index c88c1955d8..854568f9bd 100644 --- a/files/mygui/openmw_console.layout +++ b/files/mygui/openmw_console.layout @@ -2,8 +2,7 @@ - - + diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 5945c68d77..fa64856883 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -346,10 +346,10 @@ - + - + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 67fd5ee8ca..06d999189e 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -122,8 +122,12 @@ small object size = 250 # Rendering distance for small objects small object distance = 3500 -# Max viewing distance at clear weather conditions -max viewing distance = 5600 +# Viewing distance at normal weather conditions +# The maximum distance with no pop-in will be: (see RenderingManager::configureFog) +# viewing distance / minimum weather fog depth (.69) * view frustum factor <= cell size (8192) - loading threshold (1024) +# view frustum factor takes into account that the view frustum end is a plane, so at the edges of the screen you can see further than you should be able to. +# exact factor would depend on FOV +viewing distance = 4600 # Distance at which fog starts (proportional to viewing distance) fog start factor = 0.5