diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 976d7d84c..1832bf542 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -201,6 +201,8 @@ namespace MWBase ///< Hides dialog and schedules dialog to be deleted. virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector()) = 0; + virtual void staticMessageBox(const std::string& message) = 0; + virtual void removeStaticMessageBox() = 0; virtual void enterPressed () = 0; virtual int readPressedButton() = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index a3b9d2cf2..6c9fa6703 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -331,6 +331,10 @@ namespace MWBase virtual void activateDoor(const MWWorld::Ptr& door) = 0; ///< activate (open or close) an non-teleport door + virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object + virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object + virtual float getWindSpeed() = 0; + virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; virtual int canRest() = 0; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index ea49ae4a4..d0f1bcfeb 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -137,8 +137,7 @@ namespace MWClass fJumpAcrobaticsBase = gmst.find("fJumpAcrobaticsBase"); fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier"); fJumpRunMultiplier = gmst.find("fJumpRunMultiplier"); - // Added in Tribunal/Bloodmoon, may not exist - fWereWolfRunMult = gmst.search("fWereWolfRunMult"); + fWereWolfRunMult = gmst.find("fWereWolfRunMult"); inited = true; } diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 6d44e9d2c..12e5b466b 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -76,7 +76,7 @@ namespace MWGui parent = mRightPage; MyGUI::Widget* pageWidget = parent->createWidgetReal("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast(i)); - parser.parse(*it, pageWidget, mLeftPage->getSize().width); + parser.parsePage(*it, pageWidget, mLeftPage->getSize().width); mPages.push_back(pageWidget); ++i; } @@ -157,6 +157,21 @@ namespace MWGui } ++i; } + + //If it is the last page, hide the button "Next Page" + if ( (mCurrentPage+1)*2 == mPages.size() + || (mCurrentPage+1)*2 == mPages.size() + 1) + { + mNextPageButton->setVisible(false); + } else { + mNextPageButton->setVisible(true); + } + //If it is the fist page, hide the button "Prev Page" + if (mCurrentPage == 0) { + mPrevPageButton->setVisible(false); + } else { + mPrevPageButton->setVisible(true); + } } } diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 2d72f2174..6f1e16ff1 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -6,7 +6,10 @@ #include #include +#include #include +#include +#include #include namespace @@ -74,6 +77,12 @@ namespace Ogre::UTFString string(s); return string.getChar(0); } + + bool is_not_empty(const std::string s) { + std::string temp = s; + boost::algorithm::trim(temp); + return !temp.empty(); + } } namespace MWGui @@ -88,6 +97,7 @@ namespace MWGui utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext); boost::algorithm::replace_all(utf8Text, "\n", ""); + boost::algorithm::replace_all(utf8Text, "\r", ""); boost::algorithm::replace_all(utf8Text, "
", "\n"); boost::algorithm::replace_all(utf8Text, "

", "\n\n"); @@ -106,6 +116,14 @@ namespace MWGui size_t currentWordStart = 0; size_t index = 0; + + { + std::string texToTrim = text.asUTF8(); + boost::algorithm::trim( texToTrim ); + text = UTFString(texToTrim); + } + + while (currentHeight <= height - spacing && index < text.size()) { const UTFString::unicode_char ch = text.getChar(index); @@ -176,8 +194,10 @@ namespace MWGui result.push_back(text.substr(0, pageEnd).asUTF8()); text.erase(0, pageEnd); } - - return result; + + std::vector nonEmptyPages; + boost::copy(result | boost::adaptors::filtered(is_not_empty), std::back_inserter(nonEmptyPages)); + return nonEmptyPages; } float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const @@ -193,7 +213,30 @@ namespace MWGui return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight(); } - MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) + MyGUI::IntSize BookTextParser::parsePage(std::string text, MyGUI::Widget* parent, const int width) + { + MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor + text = Interpreter::fixDefinesBook(text, interpreterContext); + + mParent = parent; + mWidth = width; + mHeight = 0; + + assert(mParent); + while (mParent->getChildCount()) + { + MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0)); + } + + // remove trailing " + if (text[text.size()-1] == '\"') + text.erase(text.size()-1); + + parseSubText(text); + return MyGUI::IntSize(mWidth, mHeight); + } + + MyGUI::IntSize BookTextParser::parseScroll(std::string text, MyGUI::Widget* parent, const int width) { MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor text = Interpreter::fixDefinesBook(text, interpreterContext); @@ -209,12 +252,10 @@ namespace MWGui } boost::algorithm::replace_all(text, "\n", ""); + boost::algorithm::replace_all(text, "\r", ""); boost::algorithm::replace_all(text, "
", "\n"); boost::algorithm::replace_all(text, "

", "\n\n"); - - // remove leading newlines - // while (text[0] == '\n') - // text.erase(0); + boost::algorithm::trim_left(text); // remove trailing " if (text[text.size()-1] == '\"') @@ -223,6 +264,7 @@ namespace MWGui parseSubText(text); return MyGUI::IntSize(mWidth, mHeight); } + void BookTextParser::parseImage(std::string tag, bool createWidget) { @@ -309,7 +351,7 @@ namespace MWGui parseImage(tag); if (boost::algorithm::starts_with(tag, "FONT")) parseFont(tag); - if (boost::algorithm::starts_with(tag, "DOV")) + if (boost::algorithm::starts_with(tag, "DIV")) parseDiv(tag); text.erase(0, tagEnd + 1); diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index ab1ee3af4..a32d98fe5 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -32,7 +32,16 @@ namespace MWGui * @param maximum width * @return size of the created widgets */ - MyGUI::IntSize parse(std::string text, MyGUI::Widget* parent, const int width); + MyGUI::IntSize parsePage(std::string text, MyGUI::Widget* parent, const int width); + + /** + * Parse markup as MyGUI widgets + * @param markup to parse + * @param parent for the created widgets + * @param maximum width + * @return size of the created widgets + */ + MyGUI::IntSize parseScroll(std::string text, MyGUI::Widget* parent, const int width); /** * Split the specified text into pieces that fit in the area specified by width and height parameters diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 3b341574d..018f51feb 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -22,6 +22,7 @@ namespace MWGui , mLastRenderTime(0.f) , mLastWallpaperChangeTime(0.f) , mFirstLoad(true) + , mTotalRefsLoading(0) { getWidget(mLoadingText, "LoadingText"); getWidget(mProgressBar, "ProgressBar"); diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 876fb3522..2fc50f257 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -13,6 +13,7 @@ namespace MWGui // defines mMessageBoxSpeed = 0.1; mInterMessageBoxe = NULL; + mStaticMessageBox = NULL; } void MessageBoxManager::onFrame (float frameDuration) @@ -68,11 +69,14 @@ namespace MWGui } } - void MessageBoxManager::createMessageBox (const std::string& message) + void MessageBoxManager::createMessageBox (const std::string& message, bool stat) { MessageBox *box = new MessageBox(*this, message); - removeMessageBox(message.length()*mMessageBoxSpeed, box); + if(stat) + mStaticMessageBox = box; + else + removeMessageBox(message.length()*mMessageBoxSpeed, box); mMessageBoxes.push_back(box); std::vector::iterator it; @@ -90,6 +94,12 @@ namespace MWGui } } + void MessageBoxManager::removeStaticMessageBox () + { + removeMessageBox(mStaticMessageBox); + mStaticMessageBox = NULL; + } + bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector& buttons) { if(mInterMessageBoxe != NULL) { diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 0df6f3544..0e47b0323 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -31,7 +31,8 @@ namespace MWGui public: MessageBoxManager (); void onFrame (float frameDuration); - void createMessageBox (const std::string& message); + void createMessageBox (const std::string& message, bool stat = false); + void removeStaticMessageBox (); bool createInteractiveMessageBox (const std::string& message, const std::vector& buttons); bool isInteractiveMessageBox (); @@ -52,6 +53,7 @@ namespace MWGui private: std::vector mMessageBoxes; InteractiveMessageBox* mInterMessageBoxe; + MessageBox* mStaticMessageBox; std::vector mTimers; float mMessageBoxSpeed; }; diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 95bf17635..b44c21c6e 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -39,7 +39,7 @@ namespace MWGui MWWorld::LiveCellRef *ref = mScroll.get(); BookTextParser parser; - MyGUI::IntSize size = parser.parse(ref->mBase->mText, mTextView, 390); + MyGUI::IntSize size = parser.parseScroll(ref->mBase->mText, mTextView, 390); if (size.height > mTextView->getSize().height) mTextView->setCanvasSize(MyGUI::IntSize(410, size.height)); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 39ee4e01d..413171dd4 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -551,6 +551,8 @@ namespace MWGui while (mControlsBox->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(mControlsBox->getChildAt(0)); + MWBase::Environment::get().getWindowManager ()->removeStaticMessageBox(); + std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); const int h = 18; @@ -585,7 +587,7 @@ namespace MWGui static_cast(_sender)->setCaptionWithReplacing("#{sNone}"); - MWBase::Environment::get().getWindowManager ()->messageBox ("#{sControlsMenu3}"); + MWBase::Environment::get().getWindowManager ()->staticMessageBox ("#{sControlsMenu3}"); MWBase::Environment::get().getWindowManager ()->disallowMouse(); MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 024c0d4c6..46c57bb5f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -603,6 +603,16 @@ namespace MWGui } } + void WindowManager::staticMessageBox(const std::string& message) + { + mMessageBoxManager->createMessageBox(message, true); + } + + void WindowManager::removeStaticMessageBox() + { + mMessageBoxManager->removeStaticMessageBox(); + } + void WindowManager::enterPressed () { mMessageBoxManager->enterPressed(); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index acac77bf3..f3413ca2f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -192,6 +192,8 @@ namespace MWGui virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector()); + virtual void staticMessageBox(const std::string& message); + virtual void removeStaticMessageBox(); virtual void enterPressed (); virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1cd716413..a7ec4d4d2 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -917,6 +917,10 @@ namespace MWInput void InputManager::keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , OIS::KeyCode key, ICS::Control::ControlChangingDirection direction) { + //Disallow binding escape key, and unassigned keys + if(key==OIS::KC_ESCAPE || key==OIS::KC_UNASSIGNED) + return + clearAllBindings(control); ICS::DetectingBindingListener::keyBindingDetected (ICS, control, key, direction); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b82fc4dc5..24a8e53ee 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -104,7 +104,14 @@ static void getStateInfo(CharacterState state, std::string *group) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) - : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), mSecondsOfRunning(0), mSecondsOfSwimming(0) + : mPtr(ptr) + , mAnimation(anim) + , mCharState(state) + , mSkipAnim(false) + , mMovingAnim(false) + , mSecondsOfRunning(0) + , mSecondsOfSwimming(0) + , mLooping(false) { if(!mAnimation) return; diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index b9c055acd..892dab7cf 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -49,6 +49,7 @@ namespace MWRender TerrainMaterial::Profile::Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc) : Ogre::TerrainMaterialGenerator::Profile(parent, name, desc) , mGlobalColourMap(false) + , mMaterial(0) { } diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 6c0323637..a21d03ad6 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -41,7 +41,9 @@ namespace MWRender { { public: Reflection(Ogre::SceneManager* sceneManager) - : mSceneMgr(sceneManager) {} + : mSceneMgr(sceneManager) + , mIsUnderwater(false) + {} virtual ~Reflection() {} virtual void setHeight (float height) {} diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index d02fc9289..85d8deaec 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -331,5 +331,12 @@ op 0x2000208: MoveWorld op 0x2000209: MoveWorld, explicit op 0x200020a: Fall op 0x200020b: Fall, explicit +op 0x200020c: GetStandingPC +op 0x200020d: GetStandingPC, explicit +op 0x200020e: GetStandingActor +op 0x200020f: GetStandingActor, explicit +op 0x2000210: GetStartingAngle +op 0x2000211: GetStartingAngle, explicit +op 0x2000212: GetWindSpeed -opcodes 0x200020c-0x3ffffff unused +opcodes 0x2000213-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index a08563877..5ed26119c 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -565,6 +565,40 @@ namespace MWScript } }; + template + class OpGetStandingPc : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push (MWBase::Environment::get().getWorld()->getPlayerStandingOn(ptr)); + } + }; + + template + class OpGetStandingActor : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push (MWBase::Environment::get().getWorld()->getActorStandingOn(ptr)); + } + }; + + class OpGetWindSpeed : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + runtime.push(MWBase::Environment::get().getWorld()->getWindSpeed()); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -608,6 +642,11 @@ namespace MWScript const int opcodeGetSquareRoot = 0x20001e7; const int opcodeFall = 0x200020a; const int opcodeFallExplicit = 0x200020b; + const int opcodeGetStandingPc = 0x200020c; + const int opcodeGetStandingPcExplicit = 0x200020d; + const int opcodeGetStandingActor = 0x200020e; + const int opcodeGetStandingActorExplicit = 0x200020f; + const int opcodeGetWindSpeed = 0x2000212; const int opcodePlayBink = 0x20001f7; @@ -650,6 +689,9 @@ namespace MWScript extensions.registerInstruction ("setdelete", "l", opcodeSetDelete, opcodeSetDeleteExplicit); extensions.registerFunction ("getsquareroot", 'f', "f", opcodeGetSquareRoot); extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit); + extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit); + extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit); + extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -698,7 +740,11 @@ namespace MWScript interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot); interpreter.installSegment5 (opcodeFall, new OpFall); interpreter.installSegment5 (opcodeFallExplicit, new OpFall); - + interpreter.installSegment5 (opcodeGetStandingPc, new OpGetStandingPc); + interpreter.installSegment5 (opcodeGetStandingPcExplicit, new OpGetStandingPc); + interpreter.installSegment5 (opcodeGetStandingActor, new OpGetStandingActor); + interpreter.installSegment5 (opcodeGetStandingActorExplicit, new OpGetStandingActor); + interpreter.installSegment5 (opcodeGetWindSpeed, new OpGetWindSpeed); } } } diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 327047cdc..9b7b51a5a 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -247,15 +247,15 @@ namespace MWScript if(axis == "x") { - runtime.push(ptr.getRefData().getPosition().pos[0]); + runtime.push(ptr.getCellRef().mPos.pos[0]); } else if(axis == "y") { - runtime.push(ptr.getRefData().getPosition().pos[1]); + runtime.push(ptr.getCellRef().mPos.pos[1]); } else if(axis == "z") { - runtime.push(ptr.getRefData().getPosition().pos[2]); + runtime.push(ptr.getCellRef().mPos.pos[2]); } else throw std::runtime_error ("invalid axis: " + axis); @@ -721,6 +721,8 @@ namespace MWScript const int opcodeSetPosExplicit = 0x2000193; const int opcodeGetStartingPos = 0x2000194; const int opcodeGetStartingPosExplicit = 0x2000195; + const int opcodeGetStartingAngle = 0x2000210; + const int opcodeGetStartingAngleExplicit = 0x2000211; const int opcodePosition = 0x2000196; const int opcodePositionExplicit = 0x2000197; const int opcodePositionCell = 0x2000198; @@ -765,6 +767,7 @@ namespace MWScript extensions.registerInstruction("setatstart","",opcodeSetAtStart,opcodeSetAtStartExplicit); extensions.registerInstruction("move","cf",opcodeMove,opcodeMoveExplicit); extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit); + extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -804,6 +807,8 @@ namespace MWScript interpreter.installSegment5(opcodeMoveExplicit,new OpMove); interpreter.installSegment5(opcodeMoveWorld,new OpMoveWorld); interpreter.installSegment5(opcodeMoveWorldExplicit,new OpMoveWorld); + interpreter.installSegment5(opcodeGetStartingAngle, new OpGetStartingAngle); + interpreter.installSegment5(opcodeGetStartingAngleExplicit, new OpGetStartingAngle); } } } diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 87ac1c6d7..efabe2f63 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -11,11 +11,11 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) { if (cell->mData.mFlags & ESM::Cell::Interior) { - std::map::iterator result = mInteriors.find (cell->mName); + std::map::iterator result = mInteriors.find (Misc::StringUtils::lowerCase(cell->mName)); if (result==mInteriors.end()) { - result = mInteriors.insert (std::make_pair (cell->mName, Ptr::CellStore (cell))).first; + result = mInteriors.insert (std::make_pair (Misc::StringUtils::lowerCase(cell->mName), Ptr::CellStore (cell))).first; } return &result->second; diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 61a106e16..cde9e2425 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -171,6 +171,25 @@ namespace MWWorld return ptr; } + template + const T *insertStatic(const T &x) { + Store &store = const_cast &>(get()); + if (store.search(x.mId) != 0) { + std::ostringstream msg; + msg << "Try to override existing record '" << x.mId << "'"; + throw std::runtime_error(msg.str()); + } + T record = x; + + T *ptr = store.insertStatic(record); + for (iterator it = mStores.begin(); it != mStores.end(); ++it) { + if (it->second == &store) { + mIds[ptr->mId] = it->first; + } + } + return ptr; + } + // This method must be called once, after loading all master/plugin files. This can only be done // from the outside, so it must be public. void setUp(); diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 72bebc049..a905f8aae 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -74,15 +74,6 @@ namespace MWWorld mVariables.insert (std::make_pair (iter->mId, std::make_pair (type, value))); } - - if (mVariables.find ("dayspassed")==mVariables.end()) - { - // vanilla Morrowind does not define dayspassed. - Data value; - value.mLong = 1; // but the addons start counting at 1 :( - - mVariables.insert (std::make_pair ("dayspassed", std::make_pair ('l', value))); - } } const Globals::Data& Globals::operator[] (const std::string& name) const diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 086950574..7abe94aa6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -501,7 +501,7 @@ namespace MWWorld bool PhysicsSystem::toggleCollisionMode() { - for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + for(std::map::iterator it = mEngine->mActorMap.begin(); it != mEngine->mActorMap.end();it++) { if (it->first=="player") { diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 7949cbe00..65041e662 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -92,6 +92,7 @@ namespace MWWorld std::map mDynamic; typedef std::map Dynamic; + typedef std::map Static; friend class ESMStore; @@ -183,6 +184,20 @@ namespace MWWorld return ptr; } + T *insertStatic(const T &item) { + std::string id = Misc::StringUtils::lowerCase(item.mId); + std::pair result = + mStatic.insert(std::pair(id, item)); + T *ptr = &result.first->second; + if (result.second) { + mShared.push_back(ptr); + } else { + *ptr = item; + } + return ptr; + } + + bool eraseStatic(const std::string &id) { T item; item.mId = Misc::StringUtils::lowerCase(id); diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index c940398fa..b6a649bcb 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -65,7 +65,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), mThunderSoundDelay(0), mRemainingTransitionTime(0), mMonth(0), mDay(0), - mTimePassed(0), mFallback(fallback) + mTimePassed(0), mFallback(fallback), mWindSpeed(0.f) { mRendering = rendering; //Globals @@ -367,6 +367,8 @@ void WeatherManager::update(float duration) else result = getResult(mCurrentWeather); + mWindSpeed = result.mWindSpeed; + mRendering->configureFog(result.mFogDepth, result.mFogColor); // disable sun during night @@ -653,3 +655,8 @@ void WeatherManager::changeWeather(const std::string& region, const unsigned int if (Misc::StringUtils::ciEqual(region, playerRegion)) setWeather(weather); } + +float WeatherManager::getWindSpeed() const +{ + return mWindSpeed; +} diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index f8c85b1fe..a1dc45420 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -131,6 +131,8 @@ namespace MWWorld void setHour(const float hour); + float getWindSpeed() const; + void setDate(const int day, const int month); void advanceTime(double hours) @@ -143,6 +145,7 @@ namespace MWWorld private: float mHour; int mDay, mMonth; + float mWindSpeed; MWWorld::Fallback* mFallback; void setFallbackWeather(Weather& weather,const std::string& name); MWRender::RenderingManager* mRendering; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 9a08a1635..d2a6d9af6 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -211,6 +211,10 @@ namespace MWWorld mStore.load (mEsm[idx]); } + // insert records that may not be present in all versions of MW + if (mEsm[0].getFormat() == 0) + ensureNeededRecords(); + mStore.setUp(); // global variables @@ -230,6 +234,41 @@ namespace MWWorld } + void World::ensureNeededRecords() + { + if (!mStore.get().search("sCompanionShare")) + { + ESM::GameSetting sCompanionShare; + sCompanionShare.mId = "sCompanionShare"; + ESM::Variant value; + value.setType(ESM::VT_String); + value.setString("Companion Share"); + sCompanionShare.mValue = value; + mStore.insertStatic(sCompanionShare); + } + if (!mStore.get().search("dayspassed")) + { + // vanilla Morrowind does not define dayspassed. + ESM::Global dayspassed; + dayspassed.mId = "dayspassed"; + ESM::Variant value; + value.setType(ESM::VT_Long); + value.setInteger(1); // but the addons start counting at 1 :( + dayspassed.mValue = value; + mStore.insertStatic(dayspassed); + } + if (!mStore.get().search("fWereWolfRunMult")) + { + ESM::GameSetting fWereWolfRunMult; + fWereWolfRunMult.mId = "fWereWolfRunMult"; + ESM::Variant value; + value.setType(ESM::VT_Float); + value.setFloat(1.f); + fWereWolfRunMult.mValue = value; + mStore.insertStatic(fWereWolfRunMult); + } + } + World::~World() { delete mWeatherManager; @@ -1583,4 +1622,28 @@ namespace MWWorld return !mDoorStates[door]; // if currently opening or closing, then do the opposite return door.getRefData().getLocalRotation().rot[2] == 0; } + + bool World::getPlayerStandingOn (const MWWorld::Ptr& object) + { + MWWorld::Ptr player = mPlayer->getPlayer(); + if (!mPhysEngine->getCharacter("player")->getOnGround()) + return false; + btVector3 from (player.getRefData().getPosition().pos[0], player.getRefData().getPosition().pos[1], player.getRefData().getPosition().pos[2]); + btVector3 to = from - btVector3(0,0,5); + std::pair result = mPhysEngine->rayTest(from, to); + return result.first == object.getRefData().getBaseNode()->getName(); + } + + bool World::getActorStandingOn (const MWWorld::Ptr& object) + { + return mPhysEngine->isAnyActorStandingOn(object.getRefData().getBaseNode()->getName()); + } + + float World::getWindSpeed() + { + if (isCellExterior() || isCellQuasiExterior()) + return mWeatherManager->getWindSpeed(); + else + return 0.f; + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f61f67062..dadb701f5 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -115,9 +115,11 @@ namespace MWWorld void addContainerScripts(const Ptr& reference, Ptr::CellStore* cell); void PCDropped (const Ptr& item); - virtual void processDoors(float duration); + void processDoors(float duration); ///< Run physics simulation and modify \a world accordingly. + void ensureNeededRecords(); + public: World (OEngine::Render::OgreRenderer& renderer, @@ -381,6 +383,10 @@ namespace MWWorld virtual void activateDoor(const MWWorld::Ptr& door); ///< activate (open or close) an non-teleport door + virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object + virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object + virtual float getWindSpeed(); + virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); virtual int canRest(); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 210d18dc9..5a22309f9 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -98,10 +98,12 @@ namespace Compiler if (type!=' ') { - getErrorHandler().error ("catoLowern't re-declare local variable", loc); + /// \todo add option to make re-declared local variables an error + getErrorHandler().warning ("can't re-declare local variable", loc); SkipParser skip (getErrorHandler(), getContext()); scanner.scan (skip); - return false; + mState = EndState; + return true; } mLocals.declare (mState==ShortState ? 's' : (mState==LongState ? 'l' : 'f'), diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 38a9265a1..a547e6ec5 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -428,7 +428,12 @@ namespace Compiler if (get (c)) { if (c=='=') + { special = S_cmpLE; + + if (get (c) && c!='=') // <== is a allowed as an alternative to <= :( + putback (c); + } else { putback (c); @@ -443,7 +448,12 @@ namespace Compiler if (get (c)) { if (c=='=') + { special = S_cmpGE; + + if (get (c) && c!='=') // >== is a allowed as an alternative to >= :( + putback (c); + } else { putback (c); diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 693c5a9cb..77d14d0f6 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -16,7 +16,7 @@ - + @@ -31,7 +31,7 @@ - + @@ -65,35 +65,35 @@ - + - + - + - + - + @@ -118,7 +118,7 @@ - + @@ -134,7 +134,7 @@ - + @@ -199,7 +199,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -232,7 +232,7 @@ - + diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index def69a2e8..2b59e0aad 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -267,8 +267,8 @@ namespace Physic } } - PhysicActorContainer::iterator pa_it = PhysicActorMap.begin(); - for (; pa_it != PhysicActorMap.end(); ++pa_it) + PhysicActorContainer::iterator pa_it = mActorMap.begin(); + for (; pa_it != mActorMap.end(); ++pa_it) { if (pa_it->second != NULL) { @@ -567,13 +567,13 @@ namespace Physic //dynamicsWorld->addAction( newActor->mCharacter ); - PhysicActorMap[name] = newActor; + mActorMap[name] = newActor; } void PhysicEngine::removeCharacter(const std::string &name) { - PhysicActorContainer::iterator it = PhysicActorMap.find(name); - if (it != PhysicActorMap.end() ) + PhysicActorContainer::iterator it = mActorMap.find(name); + if (it != mActorMap.end() ) { PhysicActor* act = it->second; if(act != NULL) @@ -581,16 +581,16 @@ namespace Physic delete act; } - PhysicActorMap.erase(it); + mActorMap.erase(it); } } PhysicActor* PhysicEngine::getCharacter(const std::string &name) { - PhysicActorContainer::iterator it = PhysicActorMap.find(name); - if (it != PhysicActorMap.end() ) + PhysicActorContainer::iterator it = mActorMap.find(name); + if (it != mActorMap.end() ) { - PhysicActor* act = PhysicActorMap[name]; + PhysicActor* act = mActorMap[name]; return act; } else @@ -700,4 +700,22 @@ namespace Physic max = btVector3(0,0,0); } } -}} + + bool PhysicEngine::isAnyActorStandingOn (const std::string& objectName) + { + for (PhysicActorContainer::iterator it = mActorMap.begin(); it != mActorMap.end(); ++it) + { + if (!it->second->getOnGround()) + continue; + Ogre::Vector3 pos = it->second->getPosition(); + btVector3 from (pos.x, pos.y, pos.z); + btVector3 to = from - btVector3(0,0,5); + std::pair result = rayTest(from, to); + if (result.first == objectName) + return true; + } + return false; + } + +} +} diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8b246408a..67e94c8f8 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -288,6 +288,8 @@ namespace Physic void setSceneManager(Ogre::SceneManager* sceneMgr); + bool isAnyActorStandingOn (const std::string& objectName); + /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). */ @@ -329,7 +331,7 @@ namespace Physic RigidBodyContainer mRaycastingObjectMap; typedef std::map PhysicActorContainer; - PhysicActorContainer PhysicActorMap; + PhysicActorContainer mActorMap; Ogre::SceneManager* mSceneMgr;