diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 29f93e566..ff38eca0b 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -72,12 +72,12 @@ opencs_units_noqt (view/world ) opencs_units (view/widget - scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun + scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton ) opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget - previewwidget + previewwidget editmode ) opencs_units_noqt (view/render diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index f2ed87d61..190ea87d8 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -328,7 +328,7 @@ std::string CSMWorld::UniversalId::getIcon() const for (int i=0; typeData[i].mName; ++i) if (typeData[i].mType==mType) - return typeData[i].mIcon ? typeData[i].mIcon : ""; + return typeData[i].mIcon ? typeData[i].mIcon : ":placeholder"; throw std::logic_error ("failed to retrieve UniversalId type icon"); } diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp new file mode 100644 index 000000000..51a137d3b --- /dev/null +++ b/apps/opencs/view/render/editmode.cpp @@ -0,0 +1,19 @@ + +#include "editmode.hpp" + +#include "worldspacewidget.hpp" + +CSVRender::EditMode::EditMode (WorldspaceWidget *worldspaceWidget, const QIcon& icon, + unsigned int mask, const QString& tooltip, QWidget *parent) +: ModeButton (icon, tooltip, parent), mWorldspaceWidget (worldspaceWidget), mMask (mask) +{} + +unsigned int CSVRender::EditMode::getInteractionMask() const +{ + return mMask; +} + +void CSVRender::EditMode::activate (CSVWidget::SceneToolbar *toolbar) +{ + mWorldspaceWidget->setInteractionMask (mMask); +} \ No newline at end of file diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp new file mode 100644 index 000000000..c3192f8ea --- /dev/null +++ b/apps/opencs/view/render/editmode.hpp @@ -0,0 +1,28 @@ +#ifndef CSV_RENDER_EDITMODE_H +#define CSV_RENDER_EDITMODE_H + +#include "../widget/modebutton.hpp" + +namespace CSVRender +{ + class WorldspaceWidget; + + class EditMode : public CSVWidget::ModeButton + { + Q_OBJECT + + WorldspaceWidget *mWorldspaceWidget; + unsigned int mMask; + + public: + + EditMode (WorldspaceWidget *worldspaceWidget, const QIcon& icon, unsigned int mask, + const QString& tooltip = "", QWidget *parent = 0); + + unsigned int getInteractionMask() const; + + virtual void activate (CSVWidget::SceneToolbar *toolbar); + }; +} + +#endif diff --git a/apps/opencs/view/render/navigation1st.cpp b/apps/opencs/view/render/navigation1st.cpp index 91f88634a..5d9a03468 100644 --- a/apps/opencs/view/render/navigation1st.cpp +++ b/apps/opencs/view/render/navigation1st.cpp @@ -44,10 +44,11 @@ bool CSVRender::Navigation1st::mouseMoved (const QPoint& delta, int mode) float deltaPitch = getFactor (true) * delta.y(); Ogre::Radian newPitch = oldPitch + Ogre::Degree (deltaPitch); - Ogre::Radian limit (Ogre::Math::PI/2-0.5); - - if ((deltaPitch>0 && newPitch-limit)) + if ((deltaPitch>0 && newPitchOgre::Radian(0.5))) + { mCamera->pitch (Ogre::Degree (deltaPitch)); + } } return true; diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index bb856dbff..a7a059ca0 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -21,9 +21,11 @@ #include "../../model/world/idtable.hpp" #include "../widget/scenetooltoggle.hpp" +#include "../widget/scenetoolmode.hpp" #include "../world/physicssystem.hpp" #include "pathgridpoint.hpp" +#include "editmode.hpp" #include "elements.hpp" bool CSVRender::PagedWorldspaceWidget::adjustCells() @@ -212,6 +214,26 @@ void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event WorldspaceWidget::mouseDoubleClickEvent(event); } +void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( + CSVWidget::SceneToolMode *tool) +{ + WorldspaceWidget::addEditModeSelectorButtons (tool); + + /// \todo replace EditMode with suitable subclasses + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Terrain shape editing"), + "terrain-shape"); + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Terrain texture editing"), + "terrain-texture"); + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Terrain vertex paint editing"), + "terrain-vertex"); + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Terrain movement"), + "terrain-move"); +} + void CSVRender::PagedWorldspaceWidget::updateOverlay() { if(getCamera()->getViewport()) @@ -557,21 +579,21 @@ CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::g } } -unsigned int CSVRender::PagedWorldspaceWidget::getElementMask() const +unsigned int CSVRender::PagedWorldspaceWidget::getVisibilityMask() const { - return WorldspaceWidget::getElementMask() | mControlElements->getSelection(); + return WorldspaceWidget::getVisibilityMask() | mControlElements->getSelection(); } CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector ( CSVWidget::SceneToolbar *parent) { mControlElements = new CSVWidget::SceneToolToggle (parent, - "Controls & Guides Visibility", ":door.png"); + "Controls & Guides Visibility", ":placeholder"); - mControlElements->addButton (":activator.png", Element_CellMarker, ":activator.png", + mControlElements->addButton (":placeholder", Element_CellMarker, ":placeholder", "Cell marker"); - mControlElements->addButton (":armor.png", Element_CellArrow, ":armor.png", "Cell arrows"); - mControlElements->addButton (":armor.png", Element_CellBorder, ":armor.png", "Cell border"); + mControlElements->addButton (":placeholder", Element_CellArrow, ":placeholder", "Cell arrows"); + mControlElements->addButton (":placeholder", Element_CellBorder, ":placeholder", "Cell border"); mControlElements->setSelection (0xffffffff); diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 63f6caa60..fb52ee240 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -83,10 +83,12 @@ namespace CSVRender virtual CSVWidget::SceneToolToggle *makeControlVisibilitySelector ( CSVWidget::SceneToolbar *parent); - virtual unsigned int getElementMask() const; + virtual unsigned int getVisibilityMask() const; protected: + virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); + virtual void updateOverlay(); virtual void mousePressEvent (QMouseEvent *event); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 54d0ce8e8..a162bc7c6 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -21,9 +21,11 @@ #include "../world/physicssystem.hpp" #include "elements.hpp" +#include "editmode.hpp" CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) -: SceneWidget (parent), mDocument(document), mSceneElements(0), mRun(0), mPhysics(0), mMouse(0) +: SceneWidget (parent), mDocument(document), mSceneElements(0), mRun(0), mPhysics(0), mMouse(0), + mInteractionMask (0) { setAcceptDrops(true); @@ -139,7 +141,7 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( CSVWidget::SceneToolToggle *CSVRender::WorldspaceWidget::makeSceneVisibilitySelector (CSVWidget::SceneToolbar *parent) { mSceneElements= new CSVWidget::SceneToolToggle (parent, - "Scene Element Visibility", ":door.png"); + "Scene Element Visibility", ":placeholder"); addVisibilitySelectorButtons (mSceneElements); @@ -181,7 +183,7 @@ CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool ( std::sort (profiles.begin(), profiles.end()); mRun = new CSVWidget::SceneToolRun (parent, "Run OpenMW from the current camera position", - ":door.png", ":faction.png", profiles); + ":placeholder", ":placeholder", profiles); connect (mRun, SIGNAL (runRequest (const std::string&)), this, SLOT (runRequest (const std::string&))); @@ -189,6 +191,16 @@ CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool ( return mRun; } +CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeEditModeSelector ( + CSVWidget::SceneToolbar *parent) +{ + CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Edit Mode"); + + addEditModeSelectorButtons (tool); + + return tool; +} + CSVRender::WorldspaceWidget::DropType CSVRender::WorldspaceWidget::getDropType ( const std::vector< CSMWorld::UniversalId >& data) { @@ -243,18 +255,39 @@ bool CSVRender::WorldspaceWidget::handleDrop (const std::vectorgetSelection(); } +void CSVRender::WorldspaceWidget::setInteractionMask (unsigned int mask) +{ + mInteractionMask = mask | Element_CellMarker | Element_CellArrow; +} + +unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const +{ + return mInteractionMask & getVisibilityMask(); +} + void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( CSVWidget::SceneToolToggle *tool) { - tool->addButton (":activator.png", Element_Reference, ":activator.png", "References"); - tool->addButton (":armor.png", Element_Terrain, ":armor.png", "Terrain"); - tool->addButton (":armor.png", Element_Water, ":armor.png", "Water"); - tool->addButton (":armor.png", Element_Pathgrid, ":armor.png", "Pathgrid"); + tool->addButton (":placeholder", Element_Reference, ":placeholder", "References"); + tool->addButton (":placeholder", Element_Terrain, ":placeholder", "Terrain"); + tool->addButton (":placeholder", Element_Water, ":placeholder", "Water"); + tool->addButton (":placeholder", Element_Pathgrid, ":placeholder", "Pathgrid"); +} + +void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool) +{ + /// \todo replace EditMode with suitable subclasses + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Reference editing"), + "object"); + tool->addButton ( + new EditMode (this, QIcon (":placeholder"), Element_Pathgrid, "Pathgrid editing"), + "pathgrid"); } CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument() @@ -338,7 +371,7 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde void CSVRender::WorldspaceWidget::elementSelectionChanged() { - setVisibilityMask (getElementMask()); + setVisibilityMask (getVisibilityMask()); flagAsModified(); updateOverlay(); } diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 75dc0c264..da2d78d6c 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -42,6 +42,7 @@ namespace CSVRender CSMDoc::Document& mDocument; CSVWorld::PhysicsSystem *mPhysics; MouseState *mMouse; + unsigned int mInteractionMask; public: @@ -77,6 +78,10 @@ namespace CSVRender /// that is the responsibility of the calling function. CSVWidget::SceneToolRun *makeRunTool (CSVWidget::SceneToolbar *parent); + /// \attention The created tool is not added to the toolbar (via addTool). Doing + /// that is the responsibility of the calling function. + CSVWidget::SceneToolMode *makeEditModeSelector (CSVWidget::SceneToolbar *parent); + void selectDefaultNavigationMode(); static DropType getDropType(const std::vector& data); @@ -90,12 +95,22 @@ namespace CSVRender virtual bool handleDrop (const std::vector& data, DropType type); - virtual unsigned int getElementMask() const; + virtual unsigned int getVisibilityMask() const; + + /// \note This function will implicitly add elements that are independent of the + /// selected edit mode. + virtual void setInteractionMask (unsigned int mask); + + /// \note This function will only return those elements that are both visible and + /// marked for interaction. + unsigned int getInteractionMask() const; protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle *tool); + virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); + CSMDoc::Document& getDocument(); virtual void updateOverlay(); diff --git a/apps/opencs/view/widget/modebutton.cpp b/apps/opencs/view/widget/modebutton.cpp new file mode 100644 index 000000000..56896b422 --- /dev/null +++ b/apps/opencs/view/widget/modebutton.cpp @@ -0,0 +1,10 @@ + +#include "modebutton.hpp" + +CSVWidget::ModeButton::ModeButton (const QIcon& icon, const QString& tooltip, QWidget *parent) +: PushButton (icon, Type_Mode, tooltip, parent) +{} + +void CSVWidget::ModeButton::activate (SceneToolbar *toolbar) {} + +void CSVWidget::ModeButton::deactivate (SceneToolbar *toolbar) {} diff --git a/apps/opencs/view/widget/modebutton.hpp b/apps/opencs/view/widget/modebutton.hpp new file mode 100644 index 000000000..ac14afc95 --- /dev/null +++ b/apps/opencs/view/widget/modebutton.hpp @@ -0,0 +1,28 @@ +#ifndef CSV_WIDGET_MODEBUTTON_H +#define CSV_WIDGET_MODEBUTTON_H + +#include "pushbutton.hpp" + +namespace CSVWidget +{ + class SceneToolbar; + + /// \brief Specialist PushButton of Type_Mode for use in SceneToolMode + class ModeButton : public PushButton + { + Q_OBJECT + + public: + + ModeButton (const QIcon& icon, const QString& tooltip = "", + QWidget *parent = 0); + + /// Default-Implementation: do nothing + virtual void activate (SceneToolbar *toolbar); + + /// Default-Implementation: do nothing + virtual void deactivate (SceneToolbar *toolbar); + }; +} + +#endif diff --git a/apps/opencs/view/widget/scenetoolbar.cpp b/apps/opencs/view/widget/scenetoolbar.cpp index eac9bcec3..f7023b31f 100644 --- a/apps/opencs/view/widget/scenetoolbar.cpp +++ b/apps/opencs/view/widget/scenetoolbar.cpp @@ -31,9 +31,20 @@ CSVWidget::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent) connect (focusScene, SIGNAL (activated()), this, SIGNAL (focusSceneRequest())); } -void CSVWidget::SceneToolbar::addTool (SceneTool *tool) +void CSVWidget::SceneToolbar::addTool (SceneTool *tool, SceneTool *insertPoint) { - mLayout->addWidget (tool, 0, Qt::AlignTop); + if (!insertPoint) + mLayout->addWidget (tool, 0, Qt::AlignTop); + else + { + int index = mLayout->indexOf (insertPoint); + mLayout->insertWidget (index+1, tool, 0, Qt::AlignTop); + } +} + +void CSVWidget::SceneToolbar::removeTool (SceneTool *tool) +{ + mLayout->removeWidget (tool); } int CSVWidget::SceneToolbar::getButtonSize() const diff --git a/apps/opencs/view/widget/scenetoolbar.hpp b/apps/opencs/view/widget/scenetoolbar.hpp index 1902ba2be..8e2c8ab00 100644 --- a/apps/opencs/view/widget/scenetoolbar.hpp +++ b/apps/opencs/view/widget/scenetoolbar.hpp @@ -25,7 +25,11 @@ namespace CSVWidget SceneToolbar (int buttonSize, QWidget *parent = 0); - void addTool (SceneTool *tool); + /// If insertPoint==0, insert \a tool at the end of the scrollbar. Otherwise + /// insert tool after \a insertPoint. + void addTool (SceneTool *tool, SceneTool *insertPoint = 0); + + void removeTool (SceneTool *tool); int getButtonSize() const; diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index caedfa3ee..8d871cc5f 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -6,9 +6,9 @@ #include #include "scenetoolbar.hpp" -#include "pushbutton.hpp" +#include "modebutton.hpp" -void CSVWidget::SceneToolMode::adjustToolTip (const PushButton *activeMode) +void CSVWidget::SceneToolMode::adjustToolTip (const ModeButton *activeMode) { QString toolTip = mToolTip; @@ -21,7 +21,7 @@ void CSVWidget::SceneToolMode::adjustToolTip (const PushButton *activeMode) CSVWidget::SceneToolMode::SceneToolMode (SceneToolbar *parent, const QString& toolTip) : SceneTool (parent), mButtonSize (parent->getButtonSize()), mIconSize (parent->getIconSize()), - mToolTip (toolTip), mFirst (0) + mToolTip (toolTip), mFirst (0), mCurrent (0), mToolbar (parent) { mPanel = new QFrame (this, Qt::Popup); @@ -44,8 +44,14 @@ void CSVWidget::SceneToolMode::showPanel (const QPoint& position) void CSVWidget::SceneToolMode::addButton (const std::string& icon, const std::string& id, const QString& tooltip) { - PushButton *button = new PushButton (QIcon (QPixmap (icon.c_str())), PushButton::Type_Mode, - tooltip, mPanel); + ModeButton *button = new ModeButton (QIcon (QPixmap (icon.c_str())), tooltip, mPanel); + addButton (button, id); +} + +void CSVWidget::SceneToolMode::addButton (ModeButton *button, const std::string& id) +{ + button->setParent (mPanel); + button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); button->setIconSize (QSize (mIconSize, mIconSize)); button->setFixedSize (mButtonSize, mButtonSize); @@ -58,29 +64,40 @@ void CSVWidget::SceneToolMode::addButton (const std::string& icon, const std::st if (mButtons.size()==1) { - mFirst = button; + mFirst = mCurrent = button; setIcon (button->icon()); button->setChecked (true); adjustToolTip (button); + mCurrent->activate (mToolbar); } } void CSVWidget::SceneToolMode::selected() { - std::map::const_iterator iter = - mButtons.find (dynamic_cast (sender())); + std::map::const_iterator iter = + mButtons.find (dynamic_cast (sender())); if (iter!=mButtons.end()) { if (!iter->first->hasKeepOpen()) mPanel->hide(); - for (std::map::const_iterator iter2 = mButtons.begin(); + for (std::map::const_iterator iter2 = mButtons.begin(); iter2!=mButtons.end(); ++iter2) iter2->first->setChecked (iter2==iter); setIcon (iter->first->icon()); adjustToolTip (iter->first); + + if (mCurrent!=iter->first) + { + if (mCurrent) + mCurrent->deactivate (mToolbar); + + mCurrent = iter->first; + mCurrent->activate (mToolbar); + } + emit modeChanged (iter->second); } } \ No newline at end of file diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 9959f9835..e6f462cf8 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -10,7 +10,7 @@ class QHBoxLayout; namespace CSVWidget { class SceneToolbar; - class PushButton; + class ModeButton; ///< \brief Mode selector tool class SceneToolMode : public SceneTool @@ -19,13 +19,15 @@ namespace CSVWidget QWidget *mPanel; QHBoxLayout *mLayout; - std::map mButtons; // widget, id + std::map mButtons; // widget, id int mButtonSize; int mIconSize; QString mToolTip; PushButton *mFirst; + ModeButton *mCurrent; + SceneToolbar *mToolbar; - void adjustToolTip (const PushButton *activeMode); + void adjustToolTip (const ModeButton *activeMode); public: @@ -36,6 +38,9 @@ namespace CSVWidget void addButton (const std::string& icon, const std::string& id, const QString& tooltip = ""); + /// The ownership of \a button is transferred to *this. + void addButton (ModeButton *button, const std::string& id); + signals: void modeChanged (const std::string& id); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 433bb828f..5ddefcc6b 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -125,6 +125,9 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp CSVWidget::SceneToolRun *runTool = widget->makeRunTool (toolbar); toolbar->addTool (runTool); + CSVWidget::SceneToolMode *editModeTool = widget->makeEditModeSelector (toolbar); + toolbar->addTool (editModeTool); + return toolbar; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 9ef926bd3..0f98598fd 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -89,6 +89,7 @@ namespace MWGui mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased); mTotalBalance->eventValueChanged += MyGUI::newDelegate(this, &TradeWindow::onBalanceValueChanged); + mTotalBalance->setMinValue(INT_MIN+1); // disallow INT_MIN since abs(INT_MIN) is undefined setCoord(400, 0, 400, 300); } @@ -448,6 +449,9 @@ namespace MWGui void TradeWindow::onIncreaseButtonTriggered() { + // prevent overflows, and prevent entering INT_MIN since abs(INT_MIN) is undefined + if (mCurrentBalance == INT_MAX || mCurrentBalance == INT_MIN+1) + return; if(mCurrentBalance<=-1) mCurrentBalance -= 1; if(mCurrentBalance>=1) mCurrentBalance += 1; updateLabels(); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 02594258d..2e835d57e 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -369,7 +369,7 @@ namespace MWMechanics void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration) { updateDrowning(ptr, duration); - calculateNpcStatModifiers(ptr); + calculateNpcStatModifiers(ptr, duration); updateEquippedLight(ptr, duration); } @@ -499,6 +499,9 @@ namespace MWMechanics effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).getMagnitude() - effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude()); + stat.damage(effects.get(EffectKey(ESM::MagicEffect::DamageAttribute, i)).getMagnitude() * duration * 1.5); + stat.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreAttribute, i)).getMagnitude() * duration * 1.5); + creatureStats.setAttribute(i, stat); } @@ -855,7 +858,7 @@ namespace MWMechanics } } - void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr) + void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr, float duration) { NpcStats &npcStats = ptr.getClass().getNpcStats(ptr); const MagicEffects &effects = npcStats.getMagicEffects(); @@ -867,6 +870,9 @@ namespace MWMechanics skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude() - effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).getMagnitude() - effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude()); + + skill.damage(effects.get(EffectKey(ESM::MagicEffect::DamageSkill, i)).getMagnitude() * duration * 1.5); + skill.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreSkill, i)).getMagnitude() * duration * 1.5); } } @@ -1534,6 +1540,6 @@ namespace MWMechanics adjustMagicEffects(ptr); calculateCreatureStatModifiers(ptr, 0.f); if (ptr.getClass().isNpc()) - calculateNpcStatModifiers(ptr); + calculateNpcStatModifiers(ptr, 0.f); } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 55f1719f6..0ccfaad78 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -34,7 +34,7 @@ namespace MWMechanics void calculateDynamicStats (const MWWorld::Ptr& ptr); void calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration); - void calculateNpcStatModifiers (const MWWorld::Ptr& ptr); + void calculateNpcStatModifiers (const MWWorld::Ptr& ptr, float duration); void calculateRestoration (const MWWorld::Ptr& ptr, float duration); diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 681f01f04..a1b73bc47 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -70,11 +70,13 @@ namespace MWMechanics if (mPermanentSpellEffects.find(lower) != mPermanentSpellEffects.end()) { MagicEffects & effects = mPermanentSpellEffects[lower]; - for (MagicEffects::Collection::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + for (MagicEffects::Collection::const_iterator effectIt = effects.begin(); effectIt != effects.end();) { const ESM::MagicEffect * magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->first.mId); if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) - effects.remove(effectIt->first); + effects.remove((effectIt++)->first); + else + ++effectIt; } } mCorprusSpells.erase(corprusIt); diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 0fb4c5732..1c33db0fd 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -236,20 +236,20 @@ namespace MWMechanics { int mBase; int mModifier; - int mDamage; + float mDamage; // needs to be float to allow continuous damage public: AttributeValue() : mBase(0), mModifier(0), mDamage(0) {} - int getModified() const { return std::max(0, mBase - mDamage + mModifier); } + int getModified() const { return std::max(0, mBase - (int) mDamage + mModifier); } int getBase() const { return mBase; } int getModifier() const { return mModifier; } void setBase(int base) { mBase = std::max(0, base); } void setModifier(int mod) { mModifier = mod; } - void damage(int damage) { mDamage += damage; } - void restore(int amount) { mDamage -= std::min(mDamage, amount); } + void damage(float damage) { mDamage += damage; } + void restore(float amount) { mDamage -= std::min(mDamage, amount); } int getDamage() const { return mDamage; } void writeState (ESM::StatState& state) const; diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index a88c5a101..563a9dde3 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -125,6 +125,9 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); + if (!ptr.getRefData().isEnabled()) + return; + MWBase::Environment::get().getDialogueManager()->startDialogue (ptr); } }; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 80cccd063..eecc4a02d 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -472,10 +472,9 @@ namespace MWWorld physicActor->setInertialForce(Ogre::Vector3(0.0f)); else { - float diff = time*-627.2f; + inertia.z += time * -627.2f; if (inertia.z < 0) - diff *= slowFall; - inertia.z += diff; + inertia.z *= slowFall; physicActor->setInertialForce(inertia); } physicActor->setOnGround(isOnGround); @@ -865,8 +864,8 @@ namespace MWWorld continue; physicActor->setCanWaterWalk(waterCollision); - // 100 points of slowfall reduce gravity by 90% (this is just a guess) - float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).getMagnitude() / 100.f) * 0.9f), 0.9f); + // Slow fall reduces fall speed by a factor of (effect magnitude / 200) + float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum, world->isFlying(iter->first), diff --git a/components/esm/loadligh.cpp b/components/esm/loadligh.cpp index c02bb46b6..f88ff09d6 100644 --- a/components/esm/loadligh.cpp +++ b/components/esm/loadligh.cpp @@ -10,7 +10,7 @@ namespace ESM void Light::load(ESMReader &esm) { - mModel = esm.getHNString("MODL"); + mModel = esm.getHNOString("MODL"); mName = esm.getHNOString("FNAM"); mIcon = esm.getHNOString("ITEX"); assert(sizeof(mData) == 24); diff --git a/components/esm/statstate.hpp b/components/esm/statstate.hpp index f1a3b4d79..801d0ce82 100644 --- a/components/esm/statstate.hpp +++ b/components/esm/statstate.hpp @@ -15,7 +15,7 @@ namespace ESM T mMod; // Note: can either be the modifier, or the modified value. // A bit inconsistent, but we can't fix this without breaking compatibility. T mCurrent; - T mDamage; + float mDamage; float mProgress; StatState(); @@ -36,8 +36,14 @@ namespace ESM esm.getHNOT (mMod, "STMO"); mCurrent = 0; esm.getHNOT (mCurrent, "STCU"); - mDamage = 0; - esm.getHNOT (mDamage, "STDA"); + + // mDamage was changed to a float; ensure backwards compatibility + T oldDamage = 0; + esm.getHNOT(oldDamage, "STDA"); + mDamage = oldDamage; + + esm.getHNOT (mDamage, "STDF"); + mProgress = 0; esm.getHNOT (mProgress, "STPR"); } @@ -54,7 +60,7 @@ namespace ESM esm.writeHNT ("STCU", mCurrent); if (mDamage) - esm.writeHNT ("STDA", mDamage); + esm.writeHNT ("STDF", mDamage); if (mProgress) esm.writeHNT ("STPR", mProgress); diff --git a/credits.txt b/credits.txt index 10065b44d..c6a5c7169 100644 --- a/credits.txt +++ b/credits.txt @@ -46,6 +46,7 @@ Jannik Heller (scrawl) Jason Hooks (jhooks) jeaye Jeffrey Haines (Jyby) +Jengerer Joel Graff (graffy) John Blomberg (fstp) Jordan Ayers @@ -139,7 +140,7 @@ Sadler Artwork: Necrod - OpenMW Logo Mickey Lyle (raevol) - Wordpress Theme -Tom Koenderink (Okulo), SirHerrbatka, crysthala - OpenMW Editor Icons +Tom Koenderink (Okulo), SirHerrbatka, crysthala, Shnatsel - OpenMW Editor Icons Inactive Contributors: Ardekantur diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml index 73c266818..18055a7e5 100644 --- a/files/mygui/openmw_button.skin.xml +++ b/files/mygui/openmw_button.skin.xml @@ -3,6 +3,7 @@ + @@ -12,6 +13,7 @@ + @@ -21,6 +23,7 @@ + @@ -30,6 +33,7 @@ + @@ -39,21 +43,25 @@ + + + + diff --git a/files/opencs/placeholder.png b/files/opencs/placeholder.png new file mode 100644 index 000000000..1d3df3c47 Binary files /dev/null and b/files/opencs/placeholder.png differ diff --git a/files/opencs/resources.qrc b/files/opencs/resources.qrc index 4b2f7de0d..751ae6484 100644 --- a/files/opencs/resources.qrc +++ b/files/opencs/resources.qrc @@ -64,6 +64,7 @@ edit-preview.png edit-clone.png add.png + placeholder.png raster/startup/big/create-addon.png