From f2875e234c194705ac969c088727f6e799e97a67 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 22 Sep 2013 10:43:09 +0200 Subject: [PATCH 01/81] added missing position columns to reference table --- apps/opencs/model/world/columnimp.hpp | 68 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 12 +++++ apps/opencs/model/world/columns.hpp | 12 +++++ apps/opencs/model/world/data.cpp | 13 +++++ 4 files changed, 105 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 1a2bf9df1..a13ac9a8a 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1216,6 +1216,74 @@ namespace CSMWorld return true; } }; + + template + struct PosColumn : public Column + { + ESM::Position ESXRecordT::* mPosition; + int mIndex; + + PosColumn (ESM::Position ESXRecordT::* position, int index, bool door) + : Column ( + (door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos)+index, + ColumnBase::Display_Float), mPosition (position), mIndex (index) {} + + virtual QVariant get (const Record& record) const + { + const ESM::Position& position = record.get().*mPosition; + return position.pos[mIndex]; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + ESM::Position& position = record.get().*mPosition; + + position.pos[mIndex] = data.toFloat(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct RotColumn : public Column + { + ESM::Position ESXRecordT::* mPosition; + int mIndex; + + RotColumn (ESM::Position ESXRecordT::* position, int index, bool door) + : Column ( + (door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index, + ColumnBase::Display_Float), mPosition (position), mIndex (index) {} + + virtual QVariant get (const Record& record) const + { + const ESM::Position& position = record.get().*mPosition; + return position.rot[mIndex]; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + ESM::Position& position = record.get().*mPosition; + + position.rot[mIndex] = data.toFloat(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 5616a4a48..25047807a 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -147,6 +147,18 @@ namespace CSMWorld { ColumnId_Magical, "Magical" }, { ColumnId_Silver, "Silver" }, { ColumnId_Filter, "Filter" }, + { ColumnId_PositionXPos, "Pos X" }, + { ColumnId_PositionYPos, "Pos Y" }, + { ColumnId_PositionZPos, "Pos Z" }, + { ColumnId_PositionXRot, "Rot X" }, + { ColumnId_PositionYRot, "Rot Y" }, + { ColumnId_PositionZRot, "Rot Z" }, + { ColumnId_DoorPositionXPos, "Teleport Pos X" }, + { ColumnId_DoorPositionYPos, "Teleport Pos Y" }, + { ColumnId_DoorPositionZPos, "Teleport Pos Z" }, + { ColumnId_DoorPositionXRot, "Teleport Rot X" }, + { ColumnId_DoorPositionYRot, "Teleport Rot Y" }, + { ColumnId_DoorPositionZRot, "Teleport Rot Z" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 69b20583a..582f5102b 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -140,6 +140,18 @@ namespace CSMWorld ColumnId_Magical = 107, ColumnId_Silver = 108, ColumnId_Filter = 109, + ColumnId_PositionXPos = 110, + ColumnId_PositionYPos = 111, + ColumnId_PositionZPos = 112, + ColumnId_PositionXRot = 113, + ColumnId_PositionYRot = 114, + ColumnId_PositionZRot = 115, + ColumnId_DoorPositionXPos = 116, + ColumnId_DoorPositionYPos = 117, + ColumnId_DoorPositionZPos = 118, + ColumnId_DoorPositionXRot = 119, + ColumnId_DoorPositionYRot = 120, + ColumnId_DoorPositionZRot = 121, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 7eb96a5c3..1e290d45f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "idtable.hpp" #include "columnimp.hpp" @@ -153,6 +154,12 @@ CSMWorld::Data::Data() : mRefs (mCells) mRefs.addColumn (new RecordStateColumn); mRefs.addColumn (new CellColumn); mRefs.addColumn (new IdColumn); + mRefs.addColumn (new PosColumn (&CellRef::mPos, 0, false)); + mRefs.addColumn (new PosColumn (&CellRef::mPos, 1, false)); + mRefs.addColumn (new PosColumn (&CellRef::mPos, 2, false)); + mRefs.addColumn (new RotColumn (&CellRef::mPos, 0, false)); + mRefs.addColumn (new RotColumn (&CellRef::mPos, 1, false)); + mRefs.addColumn (new RotColumn (&CellRef::mPos, 2, false)); mRefs.addColumn (new ScaleColumn); mRefs.addColumn (new OwnerColumn); mRefs.addColumn (new SoulColumn); @@ -163,6 +170,12 @@ CSMWorld::Data::Data() : mRefs (mCells) mRefs.addColumn (new GoldValueColumn); mRefs.addColumn (new TeleportColumn); mRefs.addColumn (new TeleportCellColumn); + mRefs.addColumn (new PosColumn (&CellRef::mDoorDest, 0, true)); + mRefs.addColumn (new PosColumn (&CellRef::mDoorDest, 1, true)); + mRefs.addColumn (new PosColumn (&CellRef::mDoorDest, 2, true)); + mRefs.addColumn (new RotColumn (&CellRef::mDoorDest, 0, true)); + mRefs.addColumn (new RotColumn (&CellRef::mDoorDest, 1, true)); + mRefs.addColumn (new RotColumn (&CellRef::mDoorDest, 2, true)); mRefs.addColumn (new LockLevelColumn); mRefs.addColumn (new KeyColumn); mRefs.addColumn (new TrapColumn); From 9f533dbbe485a107c4e045c215dc01541a29728d Mon Sep 17 00:00:00 2001 From: Xethik Date: Sun, 22 Sep 2013 04:57:01 -0400 Subject: [PATCH 02/81] Fixed "most vexing parse" issue. --- components/nif/niffile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index cb7c2feb0..402eadefb 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -425,7 +425,7 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop, Ogre::Matrix4 Node::getLocalTransform() const { - Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY); + Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY); mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation)); return mat4; } From 1c4a4b4f268a151c9ec5640892f2adb28ab1cd2b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 22 Sep 2013 13:39:44 +0200 Subject: [PATCH 03/81] generalised RefIdTypeDelegate into IdTypeDelegate --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/doc/viewmanager.cpp | 4 +- apps/opencs/view/world/idtypedelegate.cpp | 45 ++++++++++++++ ...fidtypedelegate.hpp => idtypedelegate.hpp} | 20 +++--- apps/opencs/view/world/refidtypedelegate.cpp | 62 ------------------- apps/opencs/view/world/table.cpp | 2 +- 6 files changed, 56 insertions(+), 79 deletions(-) create mode 100755 apps/opencs/view/world/idtypedelegate.cpp rename apps/opencs/view/world/{refidtypedelegate.hpp => idtypedelegate.hpp} (51%) delete mode 100755 apps/opencs/view/world/refidtypedelegate.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index a719750c6..00547a2ba 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -64,7 +64,7 @@ opencs_units (view/world opencs_units_noqt (view/world dialoguesubview subviews - enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate + enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator ) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index a5fe6d356..83cd93e5d 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -14,7 +14,7 @@ #include "../world/enumdelegate.hpp" #include "../world/vartypedelegate.hpp" #include "../world/recordstatusdelegate.hpp" -#include "../world/refidtypedelegate.hpp" +#include "../world/idtypedelegate.hpp" #include "../settings/usersettingsdialog.hpp" #include "view.hpp" @@ -56,7 +56,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) new CSVWorld::RecordStatusDelegateFactory()); mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, - new CSVWorld::RefIdTypeDelegateFactory()); + new CSVWorld::IdTypeDelegateFactory()); struct Mapping { diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp new file mode 100755 index 000000000..b0ddcbc42 --- /dev/null +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -0,0 +1,45 @@ +#include "idtypedelegate.hpp" + +#include "../../model/world/universalid.hpp" + +CSVWorld::IdTypeDelegate::IdTypeDelegate + (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) + : DataDisplayDelegate (values, icons, undoStack, parent) +{} + +bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) +{ + if (settingName == "Referenceable ID Type Display") + { + if (settingValue == "Icon and Text") + mDisplayMode = Mode_IconAndText; + + else if (settingValue == "Icon Only") + mDisplayMode = Mode_IconOnly; + + else if (settingValue == "Text Only") + mDisplayMode = Mode_TextOnly; + + return true; + } + + return false; +} + + +CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory() +{ + for (int i=0; i (i)); + + DataDisplayDelegateFactory::add (id.getType(), QString::fromUtf8 (id.getTypeName().c_str()), + QString::fromUtf8 (id.getIcon().c_str())); + } +} + +CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack, + QObject *parent) const +{ + return new IdTypeDelegate (mValues, mIcons, undoStack, parent); +} diff --git a/apps/opencs/view/world/refidtypedelegate.hpp b/apps/opencs/view/world/idtypedelegate.hpp similarity index 51% rename from apps/opencs/view/world/refidtypedelegate.hpp rename to apps/opencs/view/world/idtypedelegate.hpp index 384aebb98..ea80fd0d9 100755 --- a/apps/opencs/view/world/refidtypedelegate.hpp +++ b/apps/opencs/view/world/idtypedelegate.hpp @@ -1,5 +1,5 @@ -#ifndef REFIDTYPEDELEGATE_HPP -#define REFIDTYPEDELEGATE_HPP +#ifndef IDTYPEDELEGATE_HPP +#define IDTYPEDELEGATE_HPP #include "enumdelegate.hpp" #include "util.hpp" @@ -8,29 +8,23 @@ namespace CSVWorld { - class RefIdTypeDelegate : public DataDisplayDelegate + class IdTypeDelegate : public DataDisplayDelegate { public: - RefIdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent); + IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent); virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue); }; - class RefIdTypeDelegateFactory : public DataDisplayDelegateFactory + class IdTypeDelegateFactory : public DataDisplayDelegateFactory { - - typedef std::vector < std::pair > UidTypeList; - public: - RefIdTypeDelegateFactory(); + + IdTypeDelegateFactory(); virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. - - private: - UidTypeList buildUidTypeList () const; - }; } diff --git a/apps/opencs/view/world/refidtypedelegate.cpp b/apps/opencs/view/world/refidtypedelegate.cpp deleted file mode 100755 index 7cffbf3dd..000000000 --- a/apps/opencs/view/world/refidtypedelegate.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "refidtypedelegate.hpp" - -#include "../../model/world/universalid.hpp" - -CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate - (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) - : DataDisplayDelegate (values, icons, undoStack, parent) -{} - -bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) -{ - if (settingName == "Referenceable ID Type Display") - { - if (settingValue == "Icon and Text") - mDisplayMode = Mode_IconAndText; - - else if (settingValue == "Icon Only") - mDisplayMode = Mode_IconOnly; - - else if (settingValue == "Text Only") - mDisplayMode = Mode_TextOnly; - - return true; - } - - return false; -} - - -CSVWorld::RefIdTypeDelegateFactory::RefIdTypeDelegateFactory() -{ - UidTypeList uIdList = buildUidTypeList(); - - for (UidTypeList::const_iterator it = uIdList.begin(); it != uIdList.end(); it++) - { - int i = it->first; - DataDisplayDelegateFactory::add (i, QString::fromStdString(CSMWorld::UniversalId(it->first, "").getTypeName()), it->second); - } -} - -CSVWorld::CommandDelegate *CSVWorld::RefIdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack, - QObject *parent) const -{ - return new RefIdTypeDelegate (mValues, mIcons, undoStack, parent); -} - -CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFactory::buildUidTypeList() const -{ - UidTypeList list; - - std::vector types = CSMWorld::UniversalId::listReferenceableTypes(); - - for (std::vector::const_iterator iter (types.begin()); - iter!=types.end(); ++iter) - { - CSMWorld::UniversalId id (*iter, ""); - - list.push_back (std::make_pair (id.getType(), id.getIcon().c_str())); - } - - return list; -} diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 72e78c738..6167c084a 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -12,8 +12,8 @@ #include "../../model/world/idtableproxymodel.hpp" #include "../../model/world/idtable.hpp" #include "../../model/world/record.hpp" + #include "recordstatusdelegate.hpp" -#include "refidtypedelegate.hpp" #include "util.hpp" void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) From a6ea670255add9306f4d27b9f52b4739a2b5d0ce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 22 Sep 2013 13:54:01 +0200 Subject: [PATCH 04/81] use IdTypeDelegate in report table --- apps/opencs/view/tools/reportsubview.cpp | 12 ++++++++++++ apps/opencs/view/tools/reportsubview.hpp | 8 ++++++++ apps/opencs/view/world/idtypedelegate.cpp | 1 + 3 files changed, 21 insertions(+) diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index fe1be85d7..182d1cdd6 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -6,6 +6,8 @@ #include "../../model/tools/reportmodel.hpp" +#include "../../view/world/idtypedelegate.hpp" + CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : CSVDoc::SubView (id), mModel (document.getReport (id)) { @@ -18,6 +20,11 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc: mTable->setSelectionBehavior (QAbstractItemView::SelectRows); mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); + mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate ( + document.getUndoStack(), this); + + mTable->setItemDelegateForColumn (0, mIdTypeDelegate); + connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (show (const QModelIndex&))); } @@ -26,6 +33,11 @@ void CSVTools::ReportSubView::setEditLock (bool locked) // ignored. We don't change document state anyway. } +void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QString& value) +{ + mIdTypeDelegate->updateEditorSetting (key, value); +} + void CSVTools::ReportSubView::show (const QModelIndex& index) { focusId (mModel->getUniversalId (index.row())); diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index 626ceb663..6503ebd27 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -16,6 +16,11 @@ namespace CSMTools class ReportModel; } +namespace CSVWorld +{ + class CommandDelegate; +} + namespace CSVTools { class Table; @@ -26,6 +31,7 @@ namespace CSVTools CSMTools::ReportModel *mModel; QTableView *mTable; + CSVWorld::CommandDelegate *mIdTypeDelegate; public: @@ -33,6 +39,8 @@ namespace CSVTools virtual void setEditLock (bool locked); + virtual void updateEditorSetting (const QString&, const QString&); + private slots: void show (const QModelIndex& index); diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index b0ddcbc42..ce4e8f014 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -9,6 +9,7 @@ CSVWorld::IdTypeDelegate::IdTypeDelegate bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) { + /// \todo make the setting key a member variable, that is initialised from a constructor argument if (settingName == "Referenceable ID Type Display") { if (settingValue == "Icon and Text") From c423479f20ae71dbb24e2b8f5e14f1ddc0eef5e5 Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 23 Sep 2013 07:31:14 -0400 Subject: [PATCH 05/81] Fixed bug #887 --- apps/openmw/mwgui/mainmenu.cpp | 3 +++ apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 88227c751..1e967ea93 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -70,7 +70,10 @@ namespace MWGui { MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f); if (sender == mButtons["return"]) + { + MWBase::Environment::get().getSoundManager()->resumeSounds(8); MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); + } else if (sender == mButtons["options"]) MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); else if (sender == mButtons["exitgame"]) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 430a5d843..27977d99c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -617,9 +617,15 @@ namespace MWInput if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) MWBase::Environment::get().getWorld ()->stopVideo (); else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) + { MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getSoundManager()->resumeSounds(8); + } else + { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); + MWBase::Environment::get().getSoundManager()->pauseSounds(8); + } } void InputManager::toggleSpell() From 0c518fb047a966234a23370fb6439cb8ea2e911c Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 23 Sep 2013 07:36:50 -0400 Subject: [PATCH 06/81] Replaced tabs with spaces. --- apps/openmw/mwgui/mainmenu.cpp | 4 ++-- apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 1e967ea93..400dcab96 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -70,10 +70,10 @@ namespace MWGui { MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f); if (sender == mButtons["return"]) - { + { MWBase::Environment::get().getSoundManager()->resumeSounds(8); MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); - } + } else if (sender == mButtons["options"]) MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); else if (sender == mButtons["exitgame"]) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 27977d99c..014045099 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -617,15 +617,15 @@ namespace MWInput if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) MWBase::Environment::get().getWorld ()->stopVideo (); else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) - { + { MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getSoundManager()->resumeSounds(8); - } + } else - { + { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getSoundManager()->pauseSounds(8); - } + } } void InputManager::toggleSpell() From 91d7291c0c79e6c4283b729aa938e4a5de4e672b Mon Sep 17 00:00:00 2001 From: Berulacks Date: Mon, 23 Sep 2013 08:31:36 -0400 Subject: [PATCH 07/81] Switched to using proper enums as opposed to ints. --- apps/openmw/mwgui/mainmenu.cpp | 2 +- apps/openmw/mwinput/inputmanagerimp.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 400dcab96..70cd4b592 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -71,7 +71,7 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f); if (sender == mButtons["return"]) { - MWBase::Environment::get().getSoundManager()->resumeSounds(8); + MWBase::Environment::get().getSoundManager ()->resumeSounds(MWBase::Environment::get().getSoundManager ()-> Play_TypeSfx); MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); } else if (sender == mButtons["options"]) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 014045099..958703df3 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -619,12 +619,12 @@ namespace MWInput else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) { MWBase::Environment::get().getWindowManager()->popGuiMode(); - MWBase::Environment::get().getSoundManager()->resumeSounds(8); + MWBase::Environment::get().getSoundManager()->resumeSounds(MWBase::Environment::get().getSoundManager()->Play_TypeSfx); } else { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); - MWBase::Environment::get().getSoundManager()->pauseSounds(8); + MWBase::Environment::get().getSoundManager()->pauseSounds(MWBase::Environment::get().getSoundManager()->Play_TypeSfx); } } From 0f1c4cb00e6adfd5a8a20555fa8e57cbba8319cd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 23 Sep 2013 15:34:52 +0200 Subject: [PATCH 08/81] cleanup --- apps/openmw/mwgui/mainmenu.cpp | 2 +- apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 70cd4b592..1db6e9ecd 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -71,7 +71,7 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f); if (sender == mButtons["return"]) { - MWBase::Environment::get().getSoundManager ()->resumeSounds(MWBase::Environment::get().getSoundManager ()-> Play_TypeSfx); + MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); } else if (sender == mButtons["options"]) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 958703df3..43f2bcc15 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -577,8 +577,8 @@ namespace MWInput rot[0] = -y; rot[1] = 0.0f; rot[2] = x; - - // Only actually turn player when we're not in vanity mode + + // Only actually turn player when we're not in vanity mode if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot)) { mPlayer->yaw(x/scale); @@ -619,12 +619,12 @@ namespace MWInput else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) { MWBase::Environment::get().getWindowManager()->popGuiMode(); - MWBase::Environment::get().getSoundManager()->resumeSounds(MWBase::Environment::get().getSoundManager()->Play_TypeSfx); + MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); } else { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); - MWBase::Environment::get().getSoundManager()->pauseSounds(MWBase::Environment::get().getSoundManager()->Play_TypeSfx); + MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); } } From ea637a24b99d875804c3d324d48efb7e7696364a Mon Sep 17 00:00:00 2001 From: sirherrbatka Date: Mon, 23 Sep 2013 19:48:18 +0200 Subject: [PATCH 09/81] Issue 912, making branch --- issue912 | 1 + 1 file changed, 1 insertion(+) create mode 100644 issue912 diff --git a/issue912 b/issue912 new file mode 100644 index 000000000..604cc392c --- /dev/null +++ b/issue912 @@ -0,0 +1 @@ +branch for issue912 From ae5e8b95ffba3bd45d277acee9eec4c78447138f Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 23 Sep 2013 20:12:04 +0200 Subject: [PATCH 10/81] Solving Issue912 --- apps/opencs/model/world/universalid.cpp | 26 ++++---- files/opencs/GMST.png | Bin 0 -> 820 bytes files/opencs/Info.png | Bin 0 -> 1234 bytes files/opencs/LandTexture.png | Bin 0 -> 2662 bytes files/opencs/PathGrid.png | Bin 0 -> 1297 bytes files/opencs/activator.png | Bin 2297 -> 1913 bytes files/opencs/added.png | Bin 862 -> 615 bytes files/opencs/apparatus.png | Bin files/opencs/armor.png | Bin files/opencs/attribute.png | Bin 0 -> 1788 bytes files/opencs/birthsign.png | Bin 0 -> 2454 bytes files/opencs/body-part.png | Bin 0 -> 1248 bytes files/opencs/book.png | Bin 1336 -> 1599 bytes files/opencs/cell.png | Bin 0 -> 1403 bytes files/opencs/class.png | Bin 0 -> 2283 bytes files/opencs/clothing.png | Bin files/opencs/container.png | Bin files/opencs/creature.png | Bin files/opencs/dialogoue-info.png | Bin 0 -> 1851 bytes files/opencs/dialogoue-journal.png | Bin 0 -> 1991 bytes files/opencs/dialogoue-regular.png | Bin 0 -> 1486 bytes files/opencs/dialogue-greeting.png | Bin 0 -> 1948 bytes files/opencs/dialogue-persuasion.png | Bin 0 -> 1987 bytes files/opencs/dialogue-speech.png | Bin 0 -> 1987 bytes files/opencs/door.png | Bin files/opencs/enchantment.png | Bin 0 -> 1812 bytes files/opencs/faction.png | Bin 0 -> 1858 bytes files/opencs/filter.png | Bin 0 -> 1375 bytes files/opencs/globvar.png | Bin 0 -> 2394 bytes files/opencs/ingredient.png | Bin 1444 -> 1384 bytes files/opencs/land.png | Bin 0 -> 1220 bytes files/opencs/landpaint.png | Bin 0 -> 1361 bytes files/opencs/leveled-creature.png | Bin files/opencs/light.png | Bin 747 -> 1199 bytes files/opencs/lockpick.png | Bin files/opencs/magic-effect.png | Bin 0 -> 1702 bytes files/opencs/magicrabbit.png | Bin 0 -> 1820 bytes files/opencs/map.png | Bin 0 -> 1477 bytes files/opencs/miscellaneous.png | Bin files/opencs/modified.png | Bin 2149 -> 1320 bytes files/opencs/npc.png | Bin files/opencs/potion.png | Bin files/opencs/probe.png | Bin files/opencs/race.png | Bin 0 -> 1834 bytes files/opencs/random-item.png | Bin 0 -> 1698 bytes files/opencs/random.png | Bin 0 -> 1892 bytes files/opencs/removed.png | Bin 1772 -> 1251 bytes files/opencs/repair.png | Bin files/opencs/resources.qrc | 77 +++++++++++++++++------- files/opencs/script.png | Bin 0 -> 952 bytes files/opencs/skill.png | Bin 0 -> 1676 bytes files/opencs/sound.png | Bin 0 -> 1144 bytes files/opencs/soundgen.png | Bin 0 -> 2149 bytes files/opencs/spell.png | Bin 0 -> 2071 bytes files/opencs/static.png | Bin 1518 -> 1297 bytes files/opencs/weapon.png | Bin 56 files changed, 67 insertions(+), 36 deletions(-) create mode 100644 files/opencs/GMST.png create mode 100644 files/opencs/Info.png create mode 100644 files/opencs/LandTexture.png create mode 100644 files/opencs/PathGrid.png mode change 100755 => 100644 files/opencs/activator.png mode change 100755 => 100644 files/opencs/apparatus.png mode change 100755 => 100644 files/opencs/armor.png create mode 100644 files/opencs/attribute.png create mode 100644 files/opencs/birthsign.png create mode 100644 files/opencs/body-part.png mode change 100755 => 100644 files/opencs/book.png create mode 100644 files/opencs/cell.png create mode 100644 files/opencs/class.png mode change 100755 => 100644 files/opencs/clothing.png mode change 100755 => 100644 files/opencs/container.png mode change 100755 => 100644 files/opencs/creature.png create mode 100644 files/opencs/dialogoue-info.png create mode 100644 files/opencs/dialogoue-journal.png create mode 100644 files/opencs/dialogoue-regular.png create mode 100644 files/opencs/dialogue-greeting.png create mode 100644 files/opencs/dialogue-persuasion.png create mode 100644 files/opencs/dialogue-speech.png mode change 100755 => 100644 files/opencs/door.png create mode 100644 files/opencs/enchantment.png create mode 100644 files/opencs/faction.png create mode 100644 files/opencs/filter.png create mode 100644 files/opencs/globvar.png mode change 100755 => 100644 files/opencs/ingredient.png create mode 100644 files/opencs/land.png create mode 100644 files/opencs/landpaint.png mode change 100755 => 100644 files/opencs/leveled-creature.png mode change 100755 => 100644 files/opencs/light.png mode change 100755 => 100644 files/opencs/lockpick.png create mode 100644 files/opencs/magic-effect.png create mode 100644 files/opencs/magicrabbit.png create mode 100644 files/opencs/map.png mode change 100755 => 100644 files/opencs/miscellaneous.png mode change 100755 => 100644 files/opencs/npc.png mode change 100755 => 100644 files/opencs/potion.png mode change 100755 => 100644 files/opencs/probe.png create mode 100644 files/opencs/race.png create mode 100644 files/opencs/random-item.png create mode 100644 files/opencs/random.png mode change 100755 => 100644 files/opencs/repair.png create mode 100644 files/opencs/script.png create mode 100644 files/opencs/skill.png create mode 100644 files/opencs/sound.png create mode 100644 files/opencs/soundgen.png create mode 100644 files/opencs/spell.png mode change 100755 => 100644 files/opencs/static.png mode change 100755 => 100644 files/opencs/weapon.png diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index d360fde8f..60a8485f8 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -43,18 +43,18 @@ namespace static const TypeData sIdArg[] = { - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", ":./globvar.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./GMST.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, @@ -80,7 +80,7 @@ namespace { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 }, - { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", 0 }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/files/opencs/GMST.png b/files/opencs/GMST.png new file mode 100644 index 0000000000000000000000000000000000000000..f246202882eae9203e9a718ee5117031b8e76aa0 GIT binary patch literal 820 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 U5S+aqrvLx|07*qoM6N<$f?VGlaR2}S literal 0 HcmV?d00001 diff --git a/files/opencs/PathGrid.png b/files/opencs/PathGrid.png new file mode 100644 index 0000000000000000000000000000000000000000..23b6b84d74867d65d7eb4542c5bc2864c94ea0ef GIT binary patch literal 1297 zcmV+s1@8KZP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000DlNkl&1h@qpg`~OoL(;U&%JFjqc8IC%f0>1{m%J)=R3diePsZcO~ic( zJjC(Gh?oS(wt-le0Qr`hOXD2F2L^nKfvLq|#8cZZOV1^rOl*(9UIq$g;Pd09KiG~P z{aLDztS^?&5~S=GUMc&-QeJ+kKoLt9;b2+W*WVsG1a3sFLUAY8Nh6Mt{W_vX#Qx5a zBXjrm?}sxoSyCrSf>*&B0_Bno_62$TE;_hfQUZ<79wnV;ebZ7UPfVlz8$>O>XWE0o z10$vid2$}--b8ylWMH*3I0(=+zS3BVzfx;OejrUi|etDWcK!r(4 zA-NVSLON2n_j>n9!Aa*NwN9msj_a&%1UvNsL%JF5+Nn63P#x3bsB&mST z{5%4*azW=LwcKwgfRtSz;6nnJk$^^;z~h3gm{u;O^J0B~>>AvH*9&jKKf4bU>jQlE zle*0OA1@@dE!}qe%ez_m53giai)HlP-rj^>uTL~KG^ltIMF_l)MM%{ycG!>uvJ=Gi z`3pS2Y7goh4NYOm;uwbWWe3`F(hb{=RP?^x5r@OeWL8mzS3z91g>Gw{AgK zXFWD3Cc${U&o3EU*(cFx6xP<(!0-3NmEmDHYqxEDh)@muNY0E#<0ux(lQRxS3JIld<5tk5%-|l62TVre zZy7QYC4lqiXr8d=UauF>cS>DX$6?@gtwuAty@2~W1ZW`5ytz4Gx7jw0t*vRM!pbSQ z%jF{GF(adEevEUipeG*I7Wu5+M1eh&B>F{a7xDw zUAze69*0kGo_#A}wOT(Ya34r#Aj;Q)C_>aHE`9vcUs_Fd zDjF?$fWPT(ARzDWdn{HGx4c=;UA_7m{cWc!f9ChO@0))EwEBWcff-P}00000NkvXX Hu0mjfN03_( literal 0 HcmV?d00001 diff --git a/files/opencs/activator.png b/files/opencs/activator.png old mode 100755 new mode 100644 index 0446af22cf7d4238e06d7682ab5ec86127b103c8..32cc6f8a3c428c2d6b6bd726c182dc246f6151d9 GIT binary patch delta 1898 zcmV-w2bK8w5%~^~B!3BTNLh0L01FcU01FcV0GgZ_0000PbVXQnQ*UN;cVTj606}DL zVr3vnZDD6+Qe|Oed2z{QJOBU(21!IgRCwB)S6fU|cNqVG(n6tJv_PS-0*N?9K#*$y z5g!B*HNym*VJ3Ui7mW{7W2O&2sEL`Hxn#~I`e3~6!HF}1BYzp=rrbdUMV&xnpaseu zilqqqekVQTP-zvKob+7&=l|V)-}n0+m-+d5TFEabC+B5IaIg~Z_x1Ie|1K+Azmk1i zKewQupddCkC+DvHeHj1Y*fHJVBS&-^KDU3Ky=BYY?YX(JD|R3O$B!Qg=PAj_`J&_QGTEWcSy^yIo|2NXIW#Qn zup>Jz&M?4rHe9%HL1Q!;X<%T0e!F_r6doR~$jHo8g@1;IQb0fe_4M=*9C`o#JvBBo zOz^+u*zx0PA0Hoj_wF6tym`}DSy>tE$cD^WecavMkCvC0-$_hNB!7Q@`sw0DwU?I{ zSu7Tsnwk=vf^oTAPO-7E#OqXit@8HvrZ;ciP<>q;$=uwIIsHUv(NP*69u_vOZ)l+5p&?RucnDaSo}MN@Utih~6GK|9mfYOj$ZR%K zS67#randU_n4X?~+R)ecb60ow=%Nw;aHx6l!-qyh4&zFtvgGW!b6!|eU0qEjj~|ng zGr(manM_6^2Jnxp=(!xz49tv-3Cq(|^sZ*YKe(TmPYHe+$O`A3e(ZQh9_##KxfzHlOidwst z;^N|jdk-EwFefD?DKj%O$;HKmZd|`^;cO=VTT#&_v!(iEU|^tpaBz@DMn+IeLfY{% zjDG`!X=!Oo8kC;n-<2KwdfhtWG*b)Ti{Y{yIB-B25)vZp)7#ri-YS*CU@)9y)B6@m zfIdg7eY=0ZFH(me5MEqd{KdxY@4bHgnliZ@fm{w;k1&R+s;b6ZU0ttMR#lz&qzwT? z2GLuf9f14g$`y)Xbbl`Gj+_H7cuWId!hiLj_wSo{-!&otKWRfe_^zl(fmQ?B0l1}% zqfDKzUiGu{tq6ca*ccHJ5yYTfw3Z_!H$M9N`)T#+)uavxP&76*jXInIm~dPI6+B0) z0qsi}Z*FR;X?^}YL;7xPOiVQcFC9)uv*5pKl~4*sKb%l)jEl?XcONY{AZ0a8Cf&w*WJI3o$Xb0dN+UIA^Is={c z-`lq)2B%O09(rb(RLOu+na%zJv0%0XjIOryiJJiJ032#AHNGJ_x>~2x1=$-%cE#=h zfK5X~-?z23J#t9LdkYK44<0(CdiwM!)joShI_?DfXfUpM?)RhSWNX7eIBY`l1U^NhnvuWq7<|gJAP&BTYVX3gNP#vPx>bcbC7nJ}45*iLN z3g81_fX}f>V`C%rGl_8jE`Q7T#KZ(K!BJ#nKknT#gOot20lX2W89@0t<4F4ek6zI@-eD}6yLev&hm7`gcUxFb zoLvM$s8f!3QES))3apfu3duoG#U)_thQE|?LOQg5G3|!M}O3)InwTH>moKj z$rkc>y_VNs;$fs=Dz0p9Zq8cd0KftD$^vphk}(ZuDin%R@HxWEE&vWrA@UikHMgaurApkB753?|(a{A-CX+HD|DBO`1!NSI48(-VWD+(7tASXg z(Mt~za7edWtyXerwSUq**_kt6tcs!GAfupUASTMn%1oeCuo@!8YzJ0U0W5+B2 z9BRJo4-=cQtSwntu@I2l0VnLg4W+Cm{ngdipGb(04@avp+S{C!*=41l=RD0`s#Gea k$Z8FZjVt;*|6hOs0QX!jM!rPcX8-^I07*qoM6N<$g1YF3VE_OC delta 2285 zcmV004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv00000008+zyMF)x z010qNS#tmY4f_B94f_ELcQu;;00+rQL_t(o!|hdRaFx{=et*9G`|iHq3rT<*66ykh zu#8&cuqvgt(spF1;}{D{ROqOs4(QbJ2V)&OPU|0L>;`pMgpiaVkOn~ziy_d0M8L2o zKrq|A3HN^6-Ol;G{=m!7$|w`;Kc8P`&b;q=p7WmPeGl**zQg|sYu^29^{vFQ-xlFZ zD_@#WJg;T<&VTLW?x;Li6fuAPe9!Xb&sW|okH1~wWy_Yya~_(#tzulo+)33{PaZhX zx`Sbu>53%Fp-`Zv_Nm(Q^XC5G(^xDrcJ$ct880k*@#7ownQ!Cvo9Z|2nOHq>j-eaS z4PAA)oF3b@K}Z3brYD?EN7%A~bEnVT`_!Um4&Ru|-G2`8_Lld*9}0x8UbxuFPo7-; zBZdVmN+nfQkxr*TEec7IoeaZ5*L16?vFX)$^B!{7F0QTGxxKmjwkoi(e#6!Y6DIsv zO{Y(bqHs4a3QTwRWvF@@xm*^65ZJa2p5x&0_z{gnF*rCxB}uecmczjV2WP#$>Wxo^ z?SWiAJAY(R%K82N@dc8{g{}+GbQOlKBa_L36bi5zK;U^~^Eu>lIh2)^aV*1fnyOJ> zFyOtdCwRYU`}XRoRh1>BrB!|Xy-206LQ^%UstPr&B9%(ng?yeNgu=FMSQbIR7X&5L zYHK@G^P82geso&`c76Ddnt(sJN|HpWKhY0O*MFdC8WQ~p>tAh0U)!`{%j{?@GTq@+ z;tb0`5O{DL50}f$h_ZZs)~uOEOLI%#usrbLN4s}~!{Hy=u-RNLi>^x-Ff=%X!NDP% z>NtJyy><2X7h@Ma^F$#MjqpC72cb|HW8)P7!yuQ<<*ha%!l9~AC_GueWjemrFrkR0Z7?#uJU`tEOAPk5Y;#f#>4ulY}EC)#v zF{&&Mp679*{p4r

{MD4u9)E4{ZXz{EYtir*{^N7&)RulH?~X%YtF*=pX2VVd%)1 zCbIcFC?x;@!!$57B%`#nM52_!@At9CkDuth6z zC=QP0c5G|f-qqIHW)v%by?+fAhulRe%^QY+Y&HwiG@8Qa|4+z9}` zTJik;Xf!h2>2$#Dabr~3XfR-H!!VP*Jw0oeEPnQ709d#2Z>yXx*Q_^Iy*cCP(WB(+ z<_sT;MSLS;BO{_D34|0tCbwfigmjk618wmL) z-8tdTlhuIm~A%rY(I-Eh4Wx;VAL`gt(^~6V1O`pectiTH#B!5waAP7(-2Uw0pPfyQ| z4I4Hbx)rjUq4*gwM~?lw)93S!A(UWXpdX3B0qD90)5u(_hDE_~ECf-2Ad0AnSAyqx z5K3{j<80ltbxZ#;905E4ELgBWRurWyl}f3)q4x)afl5LN2qj<`27<(Y+1G%;i6|*4 z1H&*#CX(G=pMS5^<#9!ZTLBILIyySYnE2?!3x2ln=}A>pe-A~%KlixZ9$9uk5JX6# z2$$0hzb}YrGzOMs(f;YNm5XbaJnC_JH^02%m8RhexIPC~{CedF#kC|!A%KCVY5fkx zK_ZbDLZL7$N{0;7)OcP%AQ-9ufYqy4pBXOse+ek!@PCmbg?zq1x-WHanK$R*m|>c; zDWSHS);@lC?)>1MJ$vrSWK3OgD7WPDVPWZuOC7~^eZzY-yZ5z_OppnF*7YNGc7YQR536*Fg7|hF)J`K zIxsM}cUt8D000?uMObuGZ)S9NVRB^vcXxL#X>MzCV_|S*E^l&Yo9;Xs00000NkvXX Hu0mjf&!0hG diff --git a/files/opencs/added.png b/files/opencs/added.png index aff7e25d460be771eb1c93bf556bedce44a06f0f..ddd9c2108e92610ec92b88676e5e4c172e19944d 100644 GIT binary patch delta 566 zcmV-60?GZ}2ImAJiBL{Q4GJ0x0000DNk~Le0000W0000W2nGNE0CReJ^pPPN3kf;^ z00}w)@MMxokwzzf0pv+UK~z|U?U%7?+fWpSzvEtNr#OTNLNFAP&7A^yflL{@BtxKm zjTVw6Q>I82O3-A=;PCxvkaM)NN;B0yDDL{i{HRhQDq?M5KvE7oMDp$-6$s*mSC0l~hlfQYmb+yDRo07*qoM6N<$ Ef`*;_F#rGn delta 815 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 KMNUMnLSTYa`Bd8g literal 0 HcmV?d00001 diff --git a/files/opencs/book.png b/files/opencs/book.png old mode 100755 new mode 100644 index 3afa9e8aae15c8d494e6e6e338890baffde4cec7..9d7669bd7ece44b51116176d9f15151a02fc234f GIT binary patch delta 1567 zcmV+)2H^R)3cn1HBnkm@Qb$4nuFf3kks%X*32;bRa{vGf5&!@T5&_cPe*6Fc02*{f zSaefwW^{L9a%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000H9NklNEpH#62TzIBtw{opb-H^PlCjLdhmK88JGc${hl=nv| zR%!CiBz7+Y@+y_v$X*zPN=q&lm9O>2#5%+J7L8DIlBny@x6TO=&m_r{OSE^Jh?jw>f3p~ z8e(tvWk#X&VQ0pBOol(WIf{aR{4`8m>RRo&v2g0!cD54Ue*0KPP6SMkb{k!Gs-6b8 zcjF?Ct5Y#K(y^&s8_T{n^A+FL=5k1U-B~6q!ke8k5M*WAR|byud@cOWwIOJ7RTv*` zUpFhpz^QLbQyCG!Cj!DH?8YF*z;DhD;%H7X#)eu~kEpTmTXTar-&hKNv5y_JmaAw*&-K<>p3 z^)>6)>sA9tdrr$vGpF!>nb8j9q{U;fr+IbB7z>{r??io70TJNBGQn~YJJ@r^Wcc(* z8?sVkaiP0Ozu`=QU%u3iy2|4adQkx~5j)V;sNd~|j+&v&DSTq61(~WC^mjIx44=B# ziqqxCAP^A&fifZ6-%)Qed~EO>(vuIPucK~ty{;@7Lp`TurKn%C@;#ve$W2}(3@!^yhxKl z?`#~2iNL9XEHsj1L#=^KZ)I^VlHv}+&Xxzhs}oX>MB&tlEL4}|qw1uZyw8IsCj~K) z3cX-WUJBO2zwNF^Dfzu#fHcU1r8g5T`}9aV)MUMe5wM1T?D;cfSu|CjSO>2snb(zT zP+N8kiLpvjg+r(*&0hzvD9S@cQ7+00b5M372kA*M2=o(^nTbYMOC<(6YEe>mMu{d1naQyT_Lu0}DfHmO+0|~D*~90)_YgS2 zN6Lp#>`Xoq+#v9Fgu9m=L;())le<6|Vh1j5hKKJSxC(4x?`jPfzAfDM+r!1p4*Y$8d*S4?8(f~*dxpEyLbunQtKIF) z(e2@LwA6SGmh(J&%Xw?N?Ta?#xzl$0DA(Ge(~4)&w9Cmdof`SD+`rar>@Cu%advKN z+F@nh$+g}#YQ@_&&#^XN=Q RU;qFL002ovPDHLkV1f;u@GAfS delta 1317 zcmV+=1={+*47duAB!2{FK}|sb0I`n?{9y$E0004VQb$4nuFf3k0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv00000008+zyMF)x z010qNS#tmY4f_B94f_ELcQu;;00an0L_t(o!|hgWOj}hLet&N7rKLcjv_M+j_^44n zG6xKXGjUK*V$fI%V=arr#F)&nOfvtNX(E}Lz>>u*j;Oe}O|y`U#F#82^UwY*Qxk)Y zVpJFmjmQ97TxqGLrRVj>y=`wl2QFz$-23OA^PH3Syzlco=iUq4kN-mS8d1n6C()a1KDad+<&cN{PQbV zS#aUtt1sfh>2rVru)bi0a^9$GrZs6um)7ahq7?zfn;JE%B3JVIVPP{Yl z*1z_^@i$%{I`-PJ+4V|mGG{45ex+U zpM3mj-GAuC(Wxyl&}Hi?u-R-cGa?WOL|8pKF@Pw-2+44Y!$E|-t$RBx7R$~}7jU%y=+jTO zw;doz4hJHghM$bYYZsk|*AsC~exAzO{oF{hvw!$_z-%_F_uKY;QC3=39PTXIQEbO@ z95RMj!ajmduiLII)Xsi=4j-!Tc($WoPFt!ZEHY;?v@=TX3AuNQiu8JOyZLN_1UqVK z-pk3&QOaqHUO~u`rN%|3l6!*5x}kV~I%6ZSQ`n@5n1}3RzhS@yf9z^u{KM z^++s3iQbVLR>TAa*XZ-EU*H=W8iXT#hktLFOeRfKd&rCwy;?|uQyd=uvWhSeCx^CB zTR3-XZc!*HG469ZS2PpfPC&8|q)$2ksTgS%=|nPHWX!@>4dQ;1#!@0NhnO8im|yr~ z)#Gu076=Bl!m20GQe9OIgTa7IMV7b^rhXC3HntbYx+4WjbwdWNBu305UK! zGc7PREiyJ#F*iCgH##yfD=;!TFfcirw8{Vg02y>eSaefwW^{L9a%BK_cOG{xX>MzC bV_|S*E^l&Yo9;Xs00000NkvXXu0mjf%~V>i diff --git a/files/opencs/cell.png b/files/opencs/cell.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f00c1f073664f0663ec388f129eec4454b629e GIT binary patch literal 1403 zcmV->1%&#EP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000E)Nkl7ip7{|GL!GmU5b~|71 zeC^K8$L{QOXFp3zmqMYiu=Go@g;L`@FOuHDjH)v=)sFe z4hB6m#xy35AsiGnXkz}(3@&!t?Z=h_G2t+mndfqGJ|?%3PQ$c7~+MY{LSG$>qfDB1nq+aBecO$Ys8j zhcqNXPVhMQWj`iA?ZWYEotXGw3--K{fnMNmc-He7azz`{pdHr0#o5p2i&%6E{!N}u zy_N#sO75^aoAZ*r_f}E-UM4MfMIV4h?^7bvI&0=rj2Y((*eg?5AxECxZ66uQsHQLWsAZ<|uF zX;OjMN|3pf0Xx8gHmET2Dr#y4{ zt9^*INxpJ^nD>+EWD|Cs*8Ohpsl?H2hLMgvj(mxreAZY1SBeCY(Fn{b^DewIh(LP) z0Xu-O7@DbyxF;ZAlGSXNJnO^LqQA$=VdcN%VgPJ{!md-g-*ARbA*qJYF)S{CZ#t#G z=;k5h8E_T_AszzJ*Mru=po}n@pmR$B#V)^Qs{U#2GyjIQ38kx>yaOnuwznd2%b4A!7jVUG`b!}BnZtF zpgipsw~qzsWWW&mSAVi43c_@AQM@^LE{XAvGB|WKjf3yoXfHAt&>lgCf2{5~pWATr zEBD~3aS_Qw0^$dGzj6;QmKd-)eUnk>Y2SglN5bxuD)v^%={u9~$7|=Hh;51D!mH`jKxkASxr_cE#vUXg%mkkQIlj5gkBA6NVdw-j7|fI4xd~a z+>n53usez?Y7234qjJqr^D2+;;UT(U!CD!3RRXF>(JWVq<~XN$NQ5~kK(bj!Y-a23 z@pAu+%l;ECwSa816)Ckk@O?S3Tvd&Hzb^+G0WB8$P{0Fs;2$t|&*3H>@<{*y002ov JPDHLkV1m1kiJ|}i literal 0 HcmV?d00001 diff --git a/files/opencs/class.png b/files/opencs/class.png new file mode 100644 index 0000000000000000000000000000000000000000..316380363ae0a1039bbd8810b2a100099503446c GIT binary patch literal 2283 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000PDNklh8OL{=Oonk%Cu3ta z&NQ7g9>@*LF1yQKz}^=N?807LdvL3}$gw~WSP)zg1QZkm!sS6~L@-H}ai|c}z{Do8 zwpeY^G#;&!F;#0@J8_(Uzx@(+LX=8OX1X)q%sb!l{Ql4JKF_-p0F?jd^~~^Jy!P6Q zB9Yo7j8l2M>t}W1dkK(96GH`j$%s@Ee_?blQvuot^KXyL$p19q*#G^*DCzI*Nvd!*II?QCivokx=u1&yy>bD`Hs! zydhS|b$9#vCYOX)R`$Z>+K-~5y@+Ou?k+bi%Mu_K#rHMT_oJ!lFbw)^7!BEQIz2wm zv$D1$US)zzmIAxI270{%^hjRca-y&-0YuLKk}2?hn69JFU!Qr7$a@YlOqsa*z6V9y zoP=Wl@f>f~=cBhShg^GqMTHK0+Np;$MglfVhVh=~pq5bQ|Cfj*1sD@vxj1+FdCb1| zQ^;jnBxq7`d$JClwFRgww8LT3W87oHvHBEjvFK1%kdFOTHvG0d2`r`vv4Q{^Up_%@L`t?%ZBn)h}8X<~e1X~Y7q-5hnF9mAx%eR&# zz@n!Xo*Z0>3zMtCu z_BE_RjdLYrvDCuvig+vnMB&XoxI}@;E(CY)?XTe-cM;uw8!U|zfdL_4(-}BctMhq& zuv7wiSQs{L2tY8;?1Kl{#}JS@1d)t}BYP+i3#hYC72veLbmRUU1(LM1MR0b@-@t0R z4yJ1wQR>YI5063=lZ!|i6CojVgbOnfYCW_F9+-I)0cl6Th!tYEl>&|Qr5jHdkoEH~ zt4rvRYLX!#@-9wufmby8HN4>}qUtV#UOk7%%JZO=okK*)48jZFN7&Y1KM}skIE1j6 z1oZEsz!1Osu{v0k0<}`{Sw(p{jvqgcv9U3XjErDlU;qUL1z_`pU~K<*S#Y+l0@2Z2 zu%jZupoM`E5sbL#KnPd?knw3-z8wXh0JT#7kHNt~OiWBHf_HUwp{=bAwQe_Pw8*D= z&gO~8#Eu~iNUkB0PkF8O@p`q!c4M{vAsio>E-81yL*>~t02PEgD4@ z7EJLW5cAf9&s_JJMa5K56miT;UgLZA>_KyLGcn^Eh|`T5?d|Qv{BMH8;Xqzq9_%(7 z(utixkE9WmPk*f7qM}$ttxz#N?T3kzemF7ehcfZU^{Q3ambeOyZa>tP`Jvq5 z2R?f(VxxjCQSwveQ$vk8sCVda=Aaunwlug)^H5S!Lc)u4%}6uoaI~!mJF~?o)N`Oo z(2`BYyU!Q4n$etrI%f*HsxxqMa0k*&DHzyYhU}0HC>KVczqJzCnI??261Giz?8+6w zETK(N@=VgHe}B}Do2TnhQ|ZFo+#K==j~6`8&B?*Nd-sS*=fq@_4rg1m&}sDu(0BUa z81HF&wI&kP%tRDdMs~Ob_=cozL<(U%yxuA!Zk#B^Uyc>x%18mS6Qg0*urSlE z$0r>rB)rcN114XEP09Nf!Pjd#uuf7-G%E$(YqR6}IAP~)C(ie0!z5$ijr17&uFFJv z{!wcJ8m$}%8Jl?IHe6^3N#dxBe>k|AgkK)c#>F=+xX^9(!DpJ3NQ(8xuF6$V#fL&5 zqJu4r0V75TjvxYZWe`eoe*(RnM#ATh5O#*LFxQv42tHXSgMuC4JD~Ukn3e2MIWPSF z$3503!m||Nj}nBh-YLm>0X?1-WN+{BP|#IRL5G`yM%N114KF|y_xc@&LGWlPIN|yI zBwnEJ-_xR5V3aXJwL;qb4tp$yT{5!Zyx|f@ZMr6;`;#FP^Qi_Ak2)sgQD^0GYo??z zYo=nNsk3}Gb&SWN8ockwxM4gwC-hotfe6E;UOOUGnORVC1LwaDUzCDx4+sf6h?lQn zICIrBr|6qpE$4{+-FGCcAYR@#b{2B})N%YQpda$he*taD)yj+Zn<@YR002ovPDHLk FV1mysJKq2R literal 0 HcmV?d00001 diff --git a/files/opencs/clothing.png b/files/opencs/clothing.png old mode 100755 new mode 100644 diff --git a/files/opencs/container.png b/files/opencs/container.png old mode 100755 new mode 100644 diff --git a/files/opencs/creature.png b/files/opencs/creature.png old mode 100755 new mode 100644 diff --git a/files/opencs/dialogoue-info.png b/files/opencs/dialogoue-info.png new file mode 100644 index 0000000000000000000000000000000000000000..f6743d43c9766f95655d64d297f66cab4b054eb3 GIT binary patch literal 1851 zcmV-B2gLY^P)N2bPDNB8 zb~7$DE-^4L^m3s900y^7L_t(oN3B-}P*hhGT|^ym&=?g^x-m-EC{lF5N)W|{B4UA{ zpaw(5#L@7ZqC-1$<-&qJti8AvB z{__4i_nmw0xp#TIVf;u*NomW-Om#9gT6kf%gKe_6w?}nAz^V3-kkbeZ^y~5Q@oI5* zcM(`xu8-AFpY1bo;zWzlqeo8}#?j)pNJ>gd$;ryP+1gk?4G;eXRaFIOZmvXITOHoK zX+(Q_6Ispd@3yvjw6s*CzP=2Vm3iRv@8aaiW4#9Y3;vLnmR>UAK*o z5?;NkMrUU$dV2msS63T(uEWch&+y_!32JJJ@celmS@|r$nwnw~L^=C^U0o>zg2(vj z#{kTkqkWk$GGWL-MvWRJp`@tbeLmz&Z)g159h9~8W>fDiROM$m9wioCoevEYS;d=wNsVgcmkCF1bm{WJ)} zK0!>GJlQ@vIvgDx%>?`{5nIKe;FNYp{{v9wTR|m!E!=~SGTQs!oCD9#PeN|)L*(Q< zKvq@)EH|yIA)5Gz1wqs<{gsPjOIuql-o5K(N*70aRaL$)=ks3mnp4H-E zfoEsmX92{=-@+#|RD)Om)8yp#2}(1V%4vxWmUB*UfnjH$>Yxv;W%Hm&SWy0U39jD> z6XtxNn{(h98GqvO<2ZPFx^|BnH%^7OdGm%?3f$e@F)VN@xWx`;P~X1fzy0*v{UfR%y@9%>FM_f3pXJvBjdp%u2$30(ZWhioZ3Z8jhf7-2aK`N zWecO-(9Q(%Nt>az+X!iC_n6@NgHzf?!PC-Wk&<#3dV2FCdFO)t-%^8VYN{Br&S|M_ zJ!XfQc7}*ayva)KP{0u=hOC6b#Z_?gKR9ggB}L)HaSxEDr^6dFW{mua^0gUZwT#}3>yccqpy(`D;Th`WM(EnjrjgD z$2DT>JSpimRK764lu$Ehn&}}S;T9{k{x^U4FcKu~FUO7@Db)hr{Jbe>!A>_7ACf<#nw5cUEM+-Q%Fh59yWrhjXC1tt~0fBv{P{RBL})kGcx&4 zMj#oQgnOmI3D2B6QP4o3y|!v#O~x%LJ_d}g~8b8MDC z(?pkjCJKJ&kaIU_eAZ%Tg1vj}Dr#$sSt>;P`C#5Yl-jA_sN%O+S=5u8FCBC$vbVP> zudXg)<5Y2R>VRseEmd5d4*f~Um zU%>BILlGJp06$+Z>~pezv)Fi19O-iIq{e3r8<^WDD=Tx9dV51dIa51V=Web}P2{_Q z+P?#g6rpoA>E-$p$jD8WF?pU#mV$(Y#HbO2ioQS&RVDNMJ33}l2B_Mp$dnWnPrui} zBY9a}ZT6+)ndd^~PFmioJaKJoW75?{(-%U#4TT zudi1Z)j&kVMasbNl{``~ar;SsaK3aYh*#1*9np&) pa`VSTfaEJ%73~!t@?7q$e*k>p?a4!+b>RR2002ovPDHLkV1mjZY+(QZ literal 0 HcmV?d00001 diff --git a/files/opencs/dialogoue-journal.png b/files/opencs/dialogoue-journal.png new file mode 100644 index 0000000000000000000000000000000000000000..b6a95c53848b787d5e857c1f8c3a38238e2518e6 GIT binary patch literal 1991 zcmV;&2RQhNP)N2bPDNB8 zb~7$DE-^4L^m3s900%=!L_t(oN3B;2P?XmhT~V3EA(pZ)c9-R`AS{ALC4eZ18j25$ zAP+^FSG)0rC=o+cY;hn-#W7)qh^BG0c4BLVNmFZs5{r#d9wIMAP*_lqS3m_M3Kqeh ze)l#%*+mekGV>4YaQ}PGJ>R+C`Bo%)h93(H3lEu08sqQhduYu&Z{{Z_?`TR(`{==e z10UnlPxtii-ksFBZCjinA|fQmP3N+E^5n@YCQO(hd4{b=UNV0CcngJG9{=VWQ8zL( z|A5BEtLW%xKzDa5?%%(I2M_Mj)4~7l?ruY8XA|1mYSGYe1$lX=@ZpC$2YkF=`Mag1 zWx$w;Oqw*wCwg^6b$R)D+`HF=-rg?s_x~FYA9mB{R@}aQ6W@PdjppVm+`4szo(fK| zx%oPgsN?@{ZLNX9a0#FPJ`K~SdmJT2UK*8%nVH!*jjcNQvjd+Dbagf2(W71he#lSQ z-fo~xuc4)-ihwH7)O3}DH#A&EeSJA@-Yi31T?uMyi#f2tP)wvM`BPZ<4OWCMyGd$z zj!1&Q$GcB;`%_-tX_B=a0|Wi|;Rgm>L#L{SkFyrb0#!&{C&hv}wpik+L4>O#!d)E@ z=Hh_)(=`a1t3phK6mvb*sII<ZU)}j zd20}yojgjXMcQwza4g*t(SB-VcxaIBZi}?3w%F^YMygJQ=-EpAZLc}jhDry)D=YJG z_38yq;L4TnkdUy6k(g~lLSk*L&(6+7PfrJdKO(c$n}9RfSLqy~kCG39Cj=<5X{iDm z7b~zKNP%^M3anWu$KqKk1pC==Kmoj>;yf;2K8N!1Z&6x$77^jgo5>SD<0Q!KmhZ-G z=axe1z>Ev7em55%T#Fw9lQI#dahHwd@{T0~aq{RFgs$s#) z%KpU(kez{-l;lDHFDm+mRQN08GT9Chb+zW6o=$$%nA=CX zY7yl0SBZdNI0l~LqC{+{1cwvFc-Ke9!Q-`Z1Zp)V;7oR7@QW97P*89RUS6|Ki1ugf zeZ(5f-MjTqz31VKfYzS7T>#%TMTwZ#B=|f*j7{D$4j$(yqjef?xS_JMlMCSa`Pm3r zzNDBD=>M1u5KG1hxZIrs*9 zDdszBxZ9rwe&NDD;N$IiQnWfMJh!9c7Vg}s=k0YkaMoT|I8(PH0>`mAXT3d?2n0CV;eBT%f_-fe;$y>W zu3u!0;5l-yYb1-ojU<4`)zY`bJ-vP7Q@p#+_MS_a>xgjJXV?P?BqhKEhhq-S6X4$Tb5Wn zo$mjSh7)9G;DI^?b}lu?vY8To&xgv+z_-1>xsSpq@QFku66U}D)h`>Ho3BwnFqnX| zV410Pz&uYCUJsPQ+e3{xIyHAYGaReAr?VP9Q&k*%#uW9i;P1T`+eg6{HR4RLZtdIk zEiKo1DU9=cxKtCG%xG?BhGULjwQ@xpoqYaNry{-njk>0$Dn3qKzh3x6q_X~Q+~J0T z4`;ZHeW{o=^X0Fp=F(9|GRo=VhK362h}HiWIIBA|-09QDk&?U}ety2+Sy@?yj0!9) zm_6I;L~U&eFM+Y_Wo6%j#_>DhVXsy0OpG7M$k>A~zSxhf%tQFgv4c2xFb#WBldv&H ze}A6;oHLYi+vtu@d1hc?p8oxlBI?z1-n2p&?0hZ^i&Kg_WkDqJfvAnEvbvcrse~P+b2{+uy zlYa))arIdCc&@c1rFB$PSc@>l9zFUQ>)8vRYtym5%*N)_)TD=OrpwAY%oKQbCyy0u zr1g{!u}6;V!`ZW6F#>TfYTq&Kqf#k%rKkVyKhvhU9~;w)FLLqE$$<2gt&wHLi`-Y( Z>%YE4D0;;cY#smr002ovPDHLkV1jGJ%=rKS literal 0 HcmV?d00001 diff --git a/files/opencs/dialogoue-regular.png b/files/opencs/dialogoue-regular.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b8d252d368f16aad97beabd89aee50a53a6760 GIT binary patch literal 1486 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 Vb_lquM&tkh002ovPDHLkV1n32&YS=M literal 0 HcmV?d00001 diff --git a/files/opencs/dialogue-speech.png b/files/opencs/dialogue-speech.png new file mode 100644 index 0000000000000000000000000000000000000000..11eb9f1ca8163670aab67bb916490c145ccf9340 GIT binary patch literal 1987 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 literal 0 HcmV?d00001 diff --git a/files/opencs/globvar.png b/files/opencs/globvar.png new file mode 100644 index 0000000000000000000000000000000000000000..646145f0f44a1f5c5f3546f19697773543c102a7 GIT binary patch literal 2394 zcmV-g38nUlP)$-?`^}=bY~{rfFg!znbdms-n6@ds$X(50rH0emlLAfO~wY|!DEUN8#-mAgY9?o$Q=!!yLS52-LL%WYs^Fb z3IwM|a5XxDsjC^B`B;GJcpm2Tez=MxBr@Lwc$Wo!!w7n3ITrRp9}G2%ME{3zGI(mJ zzjK~9*xM(*{+-Q#sBY!={NjxrOfgxYBh-nZsUTEMLpG&DS5#}qHaielEHh5hxeIY7Cm2JZNlm!{cG`+cz%a!gwnbby*&`%Qgc)|0Q02 z$%eKz0UaG_y!(+Gm#(iNp*t3V9A0{Z6FCo1!qJ!;#Gu~rB@5gzOlZ>rs;c}DIRSzV z*t#`97WEM$9BAJjfZq|z19xzfSY7o6_I~KYGtW3tUe1uah+=P)Y?lYT>xv;(9LNhn z^XlebQ?^sWU7YA6JJKw0>h}8Y^7yhVh(legaIkX&Uj11g5($ZXrICgGD0NKafmhnU zz>jyj@y9<+W8c0R^z~(MF>Vbie{pO?V%hv zy_58YOvu;$R~8BNS-3NQ#@dxm?AhID8L@BQb^PY-W=L8I)>j|I#tjS(9d)56v=$B; z3h#BqQ+7n8hi>x3P=I*H>EVHnHkQVo78!@&#Axi=JaB`IxdH})L$Vggx_4l3)Q7RL zlx09$n*-(Eeymvhl?A^4um?S38(=avq|{;rr<(G?=^Y&Lg0qES7qYaxuH9OJv6*oz z)ousRjWyOzCI|;>^Su;iMit8oOIq#VnGxu&r|t+&@4;|2;lV5sJstx^ z-sHVweusGzyvC>EGEzweI$Mj$%fny=28C5N2*L!i*{sE8x&UKF;S^4iSWbiY_~1wv zS-YPNgNlHkyxac(;8q1D9*|Q8hPsnb`9~2S=OINkoclNpPGCv0gshhYAqban2$dVt zsNOEZkfLa)4B?Y~2@9MWv389P2YYSd;MTLsTa|F2OC%M_2FBHdbW8^o9?`KHXv}P* z5%iO&eNu$Y#aJP#baGg>)WnI7EU5?bTs;6PO0F#!eAWZJ#-<~hZ1=CSUdSjdm>lpS z9adm>41y>cYhGsBaOJZsvNJkTXJs_harnnkjua>mA}VwBz<}2o1EY^aC>R27o`+5E z25*py8J-VL?u?P1;C#hpj~U|XYEE!NlV#}qGBBJDIWmd@agva55%jDI#cV)qAVYSa zvN~b+)kh(-QE=p&#~(8+BTk-_Fl7%zERMigm4v-AjdCLbvKk?JMLxKm0ISb@z-Fi8 z-;=KQC{#w>aGh+lf+=nX?<54AK7i8NIF68xnio#Z5ws(-G z#r7FQm}q!)R}Am}#erDDj&oGHCpbtm>uI@}16Lp@y%E-k=OkI4EU#@?w~?w>Dj)?d z1fMvFX{p*GoaH)W$VxF+wS|DnrJUwMXN^d}2*&r^DRzu{wAg<0pkCOSJ8q(&= zEyHcfl_YDVp12z9Ieyo3fhC=ZdWEOOO*NdUB?)K zB_SyQBaq73C|P1pC-2E;J&=_~@aiy$5&Qkn;EBEWJ(yV1nc?^IzKUYIvj^@v7QC0F z7C#?+wuPHH5liQ2xb?Yt^`aBz3>P7jPv5%pg&fTa3;eE2_EII_SSd{hW?TpEgN`WlfXqMM8Ow7Py71`(FVD0Pl`!t`S?FN2bPDNB8b~7$DE-^4L^m3s900h@bL_t(o zN41yhPm^~P$NdxbC$NOeQ`$Zh=>0);(XCpgnrKXp6~gdUk?Dl zf%p0OFe)laXXiDkt=t)Vo?yw6O|GUNPFxp=Vm1^8&g6T6%e3(-g+6|q0{bePw9q-8 z2{)eSQ=eSuoy~!Yiz!g%Re?-Pto?5VP@R5|nk{J6Irx9Rx>hp`{Zs(oFO|T+TrPYy znE_wivw(L{585;?lzb`yV+L=_;N)80xd2l}0;x1|$K7R;jq6jnF!u5|+*&Av?#C|p z^1cPG-ZR6MQ4`d3q|orjehri~N$^8zo6Y3{k04p`Kq9Q&I4@|Y0xrm z3k(1JwiZ&|{MTwLhul{IY74L3RV02hyif{Lf1H8A=Xucn&>j|U&f?RZBfPdt2}&bp z#DD8pDWK4EReA@xeC>e;rq^m=WU&~!rkr8n+lGI`nIrt-O$}HM@n55Y5fy-4S2XIj ze)Lt-a`#MULB}IUSor0;MrzI++Hl+Ovz-c17>R)H!sAcWuUeZ8@rQl&k<0U?Zw2(DaLrkghM!HJ9W|Ed~bhB zfZ=fFC_BQdJH(Xyv3u@*P!zk0MJp(OxWnQPN7<{IcsAT$@s&MUzUG?$;D%YmtRc+sg8N}0VB}Zcr)MqTomw(@`q!{ zq~(%~@S1BPkZ59FF*!fTgw&gTq;J*(En_zN0l8neqlo(t<@_o((g!G@PUX5k`_={> z4;=w;e7&;mJgb5S5^YS#%x64CITfNeJx{ZC_8bit30xqKeiBLN!N(|_x7dI4B$G}! z+;gT?L$_D93BlkZHYwSg_5%-i5een7OEoPz(Al|+A%lC4tCl2-eknIFhfUa9fR2@_ z37@y$2!(Z0FuHiF){por2ahB`dJzdFULk!_?S(whJ2`);EOCp}nvKYf?*`r(fm}zd zUAkog=i$V+QZ3QoUo93#eKaxn3wOT~GyUHI>Ni>gnH>E}tcqimTufgW>EHhaNE@=hQK5h>h)_@~Ai9Vqx~VY^w>e?rq-@Kkw6)zX*~+9HIotN zyUu?d1VO%33XuhJ(8^xp1tPIaJ`Iw0E}o8uAX9_S`;1kf_7Je*Vxj)~A1|yRGbt=O z1eJt9khB7V9N;s6t9F9FQ4f zi`!vE>WHd-g2KuYY0zRFre-j%q8AS&73nec!&KG8O1nUXsv00RjwFC7Km#~AJ3tbs z5I|?$5LI#xD>h((NWK!qYe!TXV^4QQNu@C&ZA8r=rDcpE(qW1_A{(#LO1t&}hK8#N zauc~gfhf|V0Y=&r3L@YEv<2;mLQMo9|N4BCK#eMB50`fDmlz@iN)%uy>HHUfsWDT; z`bdE~0+3Yn#MYWA((Y)`C{Tt2KZPn(u?{2Y+*e}2oigBnQ4$ahI51kMLGcubLN%&L ziz(Eg`3iKQ8eOD}5VVH3UuP<VoNvF8sG3Ns9il34 zCdthdg*6fQEH}pi{cYEniW`Z*pJofA^%}Ef>|hHZ8CtQc+C*-)(3?i-RRg3Z3%#aI}1^SM8j&IL&(WHFLJ-kvVIFmC!{Z%Mt~?jm|?9WLc( zIdASY*@Hq$BW0$-^|}Vxl#9i zfwms8Chx?3HW1=*JRyzp&(?_$jv)_iwNr!1i&kY2ucQ}JhcM_;~W4gw6 z(OTOGinbJ{*1OGSTVk`wij>6Ua;oT{{$XE#S;)YpM;jC!xW2I?M^-1Nr{v>~o}Qku zoh+tcZg-G6lF2&5d`R+`o)cm~FN3G2gs$VqojRSS&V#yRfd{9b9f zds}G?XGvQ6+&t!bocaFb)#e9`IUf{K6=6k=u^34sV0*#dO`#hat4bLJjP_hwB|rNvQ6{@|41(x|Mg8-lW2FJ1i0zIVXQ?G%zyg;^QGY+NQk8zcw; z4@bh_Xc!`b9ge{vz(Rz=5jZ&fhqSPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000CtNkl7<%6}bqdVVy0*fsBb<+>i|f2h)iILePi=bzWGqI2RM+ z6rJ-H6XOSk@JSORD}Ud&%OP#0qimCY_@AD0`o8D)JkR@FSO8e@6pQr<9*C<5{L#3I zz{PPDf$QTc0?&)92;3f55qNc6Mc}@>p$EIh2iZs4rtTg5ymLd}Ba1ukME6h5_e=8A z7OPKWpl#BEy(JbAOy4DoUWwEr9YY_=D++$)GV>wo6meN)#))n?h> zXD*lHt@#EVna)Maj0r8%W~5oA%L&gu|LLvv2md3Nu~6|XxeF!FsWALSDV`Zfhs>U{ z7`cXd7Uih_qVVA><)}EPLfLC7I7gHyJ)?koJQGLTwQS9zN22 zEpq?rGr74;CG=D-_|F81IQPd}gwO0nQQMSBg;NmyT{;*&2@NGhK=O3;v!wQ8To68P^d)`Td z`)w_>R#{-n`LBMyXL{-SV|LArcfUInJoC`7uLZZfBt?F^1OlUKneL^$Fl`(8Xwh7w zS-J3&A1_=qt_iQ7(xUR58bWL4GS6!K=hVjzoSd`81UGj}Vd|71w^f8By)r=HzlG_E zGTjP2^T@C>o>O@3qz2U!sW6la;XajxiK}&Ry`f!AxM-d;@FzROFdi2py+MGT`-*N5 z1O8l9(^z&)aA&^~88$Jd<~^vNNZ&9#=a>jttwLxIaFI~v0x{sGD*9AW!_IhKHAb>I zhl7#NTxfsKa@%mjQ6Vy#1(4gt*yiuOX+ZhQs?}^?E9?~R=u^OVJ`equoOcXQZ{lOO zj}QJHF1DVY0n2$(87#GEaM!3hSm*T2D_&0xHknw@oC!PQIRn>wc}Q#If|IKx2Aoi? z3y-DLA`@;sxW>bUtRx96M>lDkq|QULoraz9{QrWh-5f}5iC~p6Jx zF=e&RH_LMhPpL_UsE8P_zau5sWHuWvt4e}k?=G1(8onRHVN;fpsn86ZDo!<)1JHSSg zi5O7OBE4(vmFaM_$*c$Gl(LbSPYf`)gfKNrknfiu&qv1QVG(k?B4js;km(V^&_D)A zy#Raa_;|dQ^zj-#^iT7ktK>m@kPA%(2kJ5oR89^QPm%I+BnLYjZ8EgZX{pg{rwK>T ioQ9oxPT}nI9rzcKfP0qJYGhad0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000EQNkl+24s_Dfo&mbwm3~joWzBgSh9_uVHAGT-zbK+?VoI+g+AI^t!l5>9V^E~hS{tpKLXT2|5LV`V$$NSa0 zd-wXo2{?Fs*RH428#chsRnv!@TKkB@tDIw^Uj@5-Fx|f4^~K7;Yf<)blkj z;CbP3?EwN$HtpN@XRONOIt4U5De0f*g~!DKHh3CwB3kBgodQ-kae{gt>jAgo6qxd) zmu*F|xtt2c&z3^zguyAcGarrzJZc1#edYq`*lU+_@cB#&1}3Y~Ig$_0tLg=lNBUvB z;H(8uaGg~&-+9AJ!-IFTaO#c?t+#Dxxn;%vMm0#oA+q7pp4qOp3IhhW_`cpHzOT&` zmBkXnvIr>nxtl&#c;KT9n39v(;3|E#c)}gfp#EA84h~pgKPZFRA)HvP85b3h;gXC- zQ_c!cPWqPsREl)LeC0(84KIC9j|070__{U7ZBs&S6wIwuM7RL!e%bJe{@j?ArxPcP zFG?1q>eRogyKM+uaiZj1T^L?;QG>#_)yNGhp>hfz>5D|HlR+0?%#{SII!p_9emu1- zb2jA^ysX!N>cKQP%2X&P>e=A==Tyk;R3f`w4uwPTNK+_WRs<(KTVgM$(>$i&Z-ojL zHQZ|O%J&T@>(@h>9UN8*PJ6xKQ!P?C1E-XGJJm4ci=)CF?K0TfWH2^LAjwF57}*n?_D|gOoHL_V zQm)69?jl_4^`WPy8{^~S$Wtm24bC*2vtAB!g%nGbGjKC;AfrhFZH)*bEq^Y27)8!` zpw)<}FJ8gI5AFErUL9@?6vJ+_K&MfMGmlixz!}@MZV|FtQEY?H{42aO1Y~;0i|6)XC4i%J|cwj zumEB&9|9eJn8R$irq3)me$<4&r<%j?yB`#x?{p@LJG869scxr~n-5EK{-YQ0kMBUg>+x}JxTZ)<4f6nv!LgDRgErG0w3+gBR3 zNZXYz;eyOA@Q}>41n!Jn$pr2s@Q|>I4}N({ABTcB+%%)^Y&r(NslSQaJrm6!++s zDxW2AZRE#E=01}7&@ Tq^~E300000NkvXXu0mjf43Bmj literal 0 HcmV?d00001 diff --git a/files/opencs/leveled-creature.png b/files/opencs/leveled-creature.png old mode 100755 new mode 100644 diff --git a/files/opencs/light.png b/files/opencs/light.png old mode 100755 new mode 100644 index c606fcd98737296fdd6d642e343e95f50108ca58..2765ef1d33d8507c67d64e913e19fcc629c12325 GIT binary patch delta 1174 zcmV;H1Zn&01+NK^85ITq0047(dh`GQ00DDSM?wIu&K&8HArpTIa7bBm000XT000XT z0n*)m`~Uy|8gxZibW?9;ba!ELWdKlNX>N2bPDNB8b~7$DE-^4L^m3s900bUML_t(o zN4=L{OjB1J#~b3Si@qTEL0q@z$uZTVCFSP)TRQ^y7b7&0LI8Q|zp z7?4|{Y+?{m1R;Mi0Yy-dKSRNV4laX%OASUt7T>-*w~2k&mXI~ec{mR@x#xU7-}5`? zo^yEsc-FSqSo=Y)S=*oMXEi)pZZEB=+55J-eD7O%guT>S39ALPN&Adj8#XX4*dQTh zpOLCSy3W?EwsH@)XLxu$!b4;Jdq|eqx>+M()eNX&?eu@YKHi0mdLA~<^Dy7G3yP2J z^wb1oVf&f&ejBW3^YBv6!*Zz&!X^6|Y6590TeqVjcCRk_?Z)?RyAkJQx0NWRSb}#+ z`3?>`u33}(T_3B~fL5bKdviTn^wntowh}E3RnRD-$(aBBn_`s!2j4a=;nnZYU}ER6 zX`DuVMKOOp0Yg(AOe?cknHk2?mZpcz$vOCgzN`53L>fH- zeRU}o9}ijJ!#A%WJ0pdjz=g`MF#mACoScK-?J|Ghluk=epsu_KGo!aH@cyf<$VyA3 zCs6Zs0VYZPx#S%D)|Dn4Pl=}|P+5|P@qsQ2{JP;gq-)jm1S*PhasPIwIXMUKY`K7A zi7I*mWd-MOucyNT@3{00Qsb5M1kUH3!C+UrIXMS6=qr(|R?rhD&dnk9Z?nK#>&uWB zNAZ6+E36ulY9Cr9sfL!$+*uPB5%Mn+HIOLFvHYi%$m=iqgv zc~HqC{~rNGl(;A|RK##CB1FW52aA}nAR!ZaM972$3Yp*lCq@-5B_AFcQZymZ9t}c* z@(4l$-68dLWc+;ujK8;l@$(Wez7hfB(#ygm4g*C9T6<`@0_#QevVEH%OP#h)9+ z*j_Kh>(zX0E$8B;@htxMB?lV|C$aW46RUGNEYGB3X(|cNAH|b$v7>-S>3n1L=K{R>tppp3YOKwxurjM8uo!XO84T7sBO(TG^BTEr&C3EB8qA*)t6u`0PEtBi7F6*5OQIzqrk oh4WciD4!+CjUMg}|N0007YG|xzM3qDoB#j-07*qoM6N<$g38At`Tzg` literal 747 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvI6;x#X;^) z4C~IxyacIC_6YK2V5m}KU}$JzVE6?TYIwoGP-?)y@G60U!Dss^Zy@@{=eG)|JtPgpN{?i`||&{Q~#eY{CBJ7|LwZ} zua^D)aqs`vz5gHd{(n~T_io|;`xE~Ec<}%0zW)z8{y#4Gdq4mGz3%^iU;O`e`v1e; z|Bnj(-pl)czyJULSO0%J`Tuy{zh||7AJzVUwBY}3^IumT9v^aeeWC8n#imCG?S5aj zJ-x>0?+w?#H{Ji<^!Rfp`tQS{zt8*sKgj$0v}xZ${T;K-ch0f=ddcJ5M%%L+tpD7O z{QDs9&y(iA4@>_(p8)hudYNSnkg_TX@(X5QU>38oW6=uPxhYsKaPr4D-TE2({{G#q zmwxo$-y_ogoBsaYz^qpD`*#)d^vi$$UXJ(@7Z*6~)^k4TvPuR!pec+=-tI089jvk* zKn`btM`STDW`2V(BX_y!Y@pyAPZ!4!i_>pUxk@z!NVGoW){sbOU}Rg+#K;!wwfVoP zWx#mQ{&{c%6UuqIPNT3vuaa; z;exzbyO?Ev2v^uYXk_^5D8XiTNaSeYmAHKYp$6@oi!yY9?o=&tjVMV;EJ?LWE=mPb z3`Pcq#<~Wkx<+OphUQjAKxCwCU}R-ra6eKu9z{cLeoAIqC2kGtSe8BpYLEok5S*V@ pQl40p%1~Zju9umYU7Va)kgAtols@~NjTBH3gQu&X%Q~loCIGkaSGE8E diff --git a/files/opencs/lockpick.png b/files/opencs/lockpick.png old mode 100755 new mode 100644 diff --git a/files/opencs/magic-effect.png b/files/opencs/magic-effect.png new file mode 100644 index 0000000000000000000000000000000000000000..e672ffccb3bc9f8203a7a0ebf8954ab17b5ffbf9 GIT binary patch literal 1702 zcmZ8ic~}x=7^gXPNw_VK%L#WbBqAs(P&9!&^DO>AYJX|*W~@1<#L z&C!-tT$8_xnA+-}^pa&Itqzq@<|?002O6 z4_7}~)cwo8P>^|CN{Uz(w&DC>&HzUL-g#N_c{J1;3INm>0;S>dvV8klk6;`C0NnYP zZ5x_Om&y(`@oqu*lZjDyVt5h;a3UO=fQKO5{B;TD5KG7rQ&VwL6#$^126u(}2f^r+ z^IoGE)kmAP^id}&=oA~>b`29zLpAX+1@~fN3?~9nha>9=?rK*{OC1feS^k z>%wO7xm8{um)@%p7!&E&UAX~ z6wx=K=m0aeeahppLkp-kVlUA$h69Um8H{830-1$9vdoKIrpXPOj)YI*wEC$wn zU?NfTU78@f%i!uOa&Ti-1SXFPh; zw0vfNpv%ac_L93+s5RV+&#+HJu?yi$4L$Ae4VLUNyB&`tg>`gZ$WsW3`NhG;F5B zP42M8pw+p!rD5i<{yifvXrWSI<}jJEuAoA2$g>bqB74r|+x(kC>~we&MeK^OXy3 z4^$JYEpTLOEmpQ?%Ww8{A^0|{kzK3v0ohH3hB|n>kBXy8vALiIj(8*lFS5oF zJj;ZkFFji}YRrX(xM_#Y44Li_&6uhjE6cjM6-`=}0jG~J{zIIl>5Ns$J{-&W=XL1% zZ0m9pe?#M=P8ANvhzc~y)4rs@=eZ>mvp0Jfc6o`t!ErgOt#W4tKV49##hknt;z$g0 z_3zIZzdi-oXnb}PB<$O7?q%J6hO-3o>mK*p94%Mw==@Iy881ZLgB6f77yrxG`Y??*QTg)Z(?NnJu8v%-VzlgAlqUcgbz| zbP=^>VVt(?<^1W0@KQHkzi$AzSCi~k%BhUtJNir8$z)>uu=+~p;E5eYDiy)Jkg)s9 zxogjW{2fz?tjTd&G0E4RKa_DG7ts;#8?7W0ZqBXe!i4;}R%JMaPI4J7weD^E|P&)ZsYZ6Hhl6ffGOrUfNQB)-05It;n!pw>5RJ_)UXo$rH}LqmmXCKcE?uZoI2I4`JOu6(@gi5lW~7P0-&JNe&M0`}?MzXb>{;=| oB_i_=g4g@-x5<4v2-u?2mQo5pLDlek**5}!yCGZ|&SBsE3EgiyE&u=k literal 0 HcmV?d00001 diff --git a/files/opencs/magicrabbit.png b/files/opencs/magicrabbit.png new file mode 100644 index 0000000000000000000000000000000000000000..d1d7c8270b2fec8dd98806f591bf5bf4aa70331d GIT binary patch literal 1820 zcmV+%2jlpOP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000JyNklC^@s{=4Ko|d>FYoIl8d~R<2l~J9zLQu3x_n zoleIDl<%zqywTZ)2D$(h<>koJYFox`p0jFIOWCenc=6%|Dk>`YQIo1`(nGvi(UvX7 zVFFtU3;Fk`ch{|3XJi6KqmkS6#{KaKnM{Di*VosFlP6DN*Up`9WLQ;Ig=0sL;?}KO zNK&bOdhZork*&ze>Suv%-n<$4Yt}TX)oOiaW~N@F(KMD*Ypz_rjD-03zy3?4?_2@i zfPCO~XJ;pRdV28c)hiK$gM%0t7(iE77al%*h>ucJZv+FOs183dRAv= zXAiu7{TgLuWvH*O7lM2K{5k5*oDpq#_Usw*^YdT2xw=-nxw&ci-HFJ&L4d#%GMP+A z(c&$a_k;uoBPuEi2?+_PIduw$Xw=vf8fYp`pFWM++FJ3O*Y@w<4;ErbNC6_xn3x!ly`sOrA2b01kT%6< z#l^y$_&2X@Sic@kO-+bcv+1`-TrSACy0{EFIXOLba&%liV#O>NnU_~v zRAeMbPy#rPz{11B5fl^zsZPefvlRGhXJ;qY_-b!&4+jSa zy#-}pWblZHh!Jq^A-^*rN6nHQR&(p&Lvu4c_;M1p1hoz+@ z3Tgh?Y%2HcK{-tVS0yhm4?DJR$F{9oap1rK(3v1IWMB@?lnJ=IyN?2&GiMGQ?CrZO zNa=~B*gqMRGv_P!J}fLu2#9;g!n=3x9`^0qhpHn-(A(Q9=AK)@m3Z{%k+{Ei?_N|^ zRth&HqY`E3_qp%ItP>6ZwapTBRtN#&mbTp{40@#k* zAQ6J=q^#>GMtQ-wPMEoD?a-mhI;5#`5EGG%(4c4p_yuEuGK};=Gfkr6V6E_Yxw^Q+ zTe<);PbGY$!3dB?BSevcbGpj?6V*?CT&Q6xeq_;jA%I4fx08VqxP$((0%b6 zPV8<&b!jWU-u3`r7LhhK-p1~NX6)27VMq22lw|&b!eu{WL+TZ1BYJ-?a_u1Pq94};di+k-~h!DHO-gK=9xf;8}W1_g#7A}k(DA~O&hxg6@0 z?I>RTJqojHu|ZvfwV&vazw}#ZQ%*qj!6qtqDgu4t2{;rITSxG?kq!)Iw}1{MgG!}> zzrVk5MIK2O8hg42_1#|)jzA^p!Z(t7zmP>X;&iNbHW~(J|FE^OF`odP4~BSB{=dQb zfZ?-&3Gi&Q_;|kAY=&)iEcoo%vteUxZ9V~VNJDIF>`3Ns3(jsz_G>-?@&v=;#fwGR z-vxZej2Ub|<`eKF0{kKJuHe(AO=A}{pMZzEyKxbnfN#@tE<0z=;8Ukg^HL7Y3%_;y|tB9;zVD>eE)AGZZSMjInD?G0000< KMNUMnLSTXwuTk3o literal 0 HcmV?d00001 diff --git a/files/opencs/map.png b/files/opencs/map.png new file mode 100644 index 0000000000000000000000000000000000000000..3653797cca076d1ef7a1983d109e67e2fc4ab52c GIT binary patch literal 1477 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 delta 2113 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 literal 0 HcmV?d00001 diff --git a/files/opencs/random-item.png b/files/opencs/random-item.png new file mode 100644 index 0000000000000000000000000000000000000000..7b8e68e60543867519ed7518d0061c8a21be3b60 GIT binary patch literal 1698 zcmV;T23`4yP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000INNklc2^rkbttJT4A zbfl385<)_Ngb+x=5)#8=2_T>#P(VZ~;BJvBt;L0cD6$q2M5z=gRZyxFMX0qbiW&mQ zCKgaD;B=mz@64PGArO)aF21XioZs_q&wIX)0DNT0`FzzXfvdny8mJamM@RaklK*Og zB-Y^}vL=6}s5LmyeMIibYcThn7QsV{={T_f#EO%59A?&w#>9(7Yl7!Zgy6xwjAT;axBOn;FII^b<^vHsa0LJ-mC}jaRxF1gJzhDoY=) zh=8qr!sdtf&f(wJ&3HS06aNfV((viAHX5EsWk%)eqBa*!erHh$NMs6c=V4v%MNABo zVq9B{(dUI2?km7h?*;fPg*r>%77Jh+E;3B^zOMSP9^Tu27Nr-G5bW>t$BGM}val+^ z=hF{IldTXD%=zFevzrSEu%C_9dj-Koi?iZuA={O9-cq?5q+KK@TC0=dhTb_ z@W*$*!=pPVabR!Ydxeajznln@0s_@;`FrBG&P)u{P_y1a&3y}oo)j+&?`%GShc`2E z;$R2_j_ejwB9;^&7IIoH<|I%NH{s3rBfRRbr|Nv3hPO3k;c$950@ZTxcs!_;o=A-K z$F1v!z`!3gW}vO%7|QeFp^)=CmU72M1$asM4XwAn$J8isxelt%)p~egUNYR>h2Zn~ zG@Q%jg2Um!-rgQgd@fFBMuCC1)*Zp!8;4MGE)F~nYh*DIMgpjsS2zBAoQk@gh7b3Z z8AQGm+|JGpwzjr#p>K+k1NzPz_6oXq*1+GD6JNel7niC}q4sBLPWq zDlM_sf$k!c4#&)SX>Ovv=1kfNoNe<3DyZ3C3VxL;!8V0JYb0QItWrz7-ITq~H<{v` zc!QcV@WLOWO~Na4b|J`j5dn!YO6};g+9kbxp~DrPjnmhhz@x+DxKXrcS$M^nC@4I* z#wCahl?@K{RxP?%7Q%_i6lBNH-A>@^*RMxTW`tSr^6VW5@a7wrfcntreDT*MYNh5G zY_-MU#AJT0NJW632wt8}Q2Dr^=F)C@&dI3FZ#YtOl6Dd~ftQ_%gqst))u;z#636ta z;;-?%vp~O6mx416mwR#t5_kIGY{qu8;U`kmM1X!x>&K9IbkuhF^wS5q^gcHSzHZ$* ztX;bnR#sNXKB8GR@{+7@sHEKK`TM}Yiv7F=`K7rD%fgAnk;obNnl)<>9qK`w44L!A z(oW#t?o~m+Vg0n^E+7xYuJ*dhf;~nnb>U(mX(y2r`0CZGk+pxDNqFATVDPqB8{Hd> z)-g$sL}=fcc|c>dQWttVNjr&rIXH=2$g?q8#U?K%B4@h@xrE!7nxI1QnHZDazEs-t zzX?G?mk07*qoM6N<$f?F6ad;kCd literal 0 HcmV?d00001 diff --git a/files/opencs/random.png b/files/opencs/random.png new file mode 100644 index 0000000000000000000000000000000000000000..2667630f5c27ba416a3810aab36cbf9d8e872b3c GIT binary patch literal 1892 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 delta 1733 zcmV;$20HoU3G59aiBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj!~3k}x* z01ejxLMWSfkwzzf25Ct|K~!jg<(f@wR8!|6pi2eqMl@0o z48(PJC28wMfHXoc6l7_fB75 z-+S}kOj{P-q-i>xIrslN_q==0J!cFd1Yw6^7zThS=ffU<_R6(og#Dah7!jaK{S<&{ zA;ff9lS@ZbD_c`QAuLEJ0K+h<025dSM1ef;Ct!tzP>!er9#Ow@z+K>87+Zk>l=xbp z0Z0K)0hfUvfa}0y(214!81MwptZZh0pMY^77Z^eaQSt}5#4%tk@D6YX5WpY6TS`O> zhy<_|0qT{119kzwD_g$-dz5qPgV+*6lm<}Zqre(qA8-#4anlrP;vBG7K}7u~R^lI0 zB6k53fT*jfvD?}m1|q2E*8p#8@vW(pxZTquT9Qfo#JkkQt}9{ld`gL&0K{_*4dUjZ zLt;Zylik)H<&b(*n1=>%gv~y?_{qLLA^Q8pL~pNu6Joc5odx0L`E`ke_~-CpA^Q78 z?#K~0h>|Pe`ViY5*aYwzZ~&-nO{Msvy&bcp$Zs74?&jGNBZ&c#>D;AAU;8^KqnA;zOj*!&Q4$PJ`nFASK>O5*ARvf zLLV$T=C>2V^CciG^|Bd8ybnYgIEh?|ybwZvMAUmDz*6Ml@@Bc>0pg~~*^Ulcl1Y%^ zXugn4h87PHU9yBzJ9e<4sR`s6qtA$?$Q%j{ptsD`!1B0hGThb{TD%)XOESqwM@MM! zc8Jf~+Ni6k0a&3l)&UVirLh=>u>^PwcosMYtY}FlIor`eyv&I~hLZ*=cif$vflN2v04@Tzgb)S20{;Sk0hfRyK>k7|!=}N(qKI-v+%zi|zwy{HEj|Z)2#hMN zQ=mdf<=}bXCU6EgG+z*vivRxFH7$NW@D*|wvV`r32S9C0Iph<568XgE9t6aMWzjlY zd>RM@|^8YjR#+ZVuP7-gv}Zv?6~_yVXTFAh8oYyi4{0CPT0 zX+2zWr!L?{WW~Z%8o~oON*|k%+gWTr#p~gKh#@zPEy(P+)(^tY#Vt&bC6$vzq6J_+wd?} zp-_?d3z-a+rX5zHK-=)J{`@WAXJnak%3hV2Mqbk{14jXCWOS5mLqnl|AzaETW#>*- zp}@AGAx1_=QKCNrepFfuFmt7xR+EhZp94MRK)4jPjshQ3Mi%QL{sUxTYaCS*0{7Bl z9dgfo9a&O0D=aNe11}-Zlt8J7i+Ej?y8&cfON$POD6&4fJqUzHaaZ4AtB~8XF7En5 zczFH<9u;c8@_L|^a1q~sjqMJLOpEK8eY(3sxQKrr_!1Y-7e|Q(M;v$t84i>9H#oA$ zGh|MyiJ1mRGqOCG1w>0SDJFV*h3M}WlYM=nHI>q~^2lDC?$UU-tpc=|;=t3$uqZ+} zT1;7BC$hHc*J9ETd(~=*mSj@g?&)!g--qnz b*VcbxKi86U^taRu00000NkvXXu0mjfXUG~7 diff --git a/files/opencs/repair.png b/files/opencs/repair.png old mode 100755 new mode 100644 diff --git a/files/opencs/resources.qrc b/files/opencs/resources.qrc index 56e25b2c1..eadcf9697 100644 --- a/files/opencs/resources.qrc +++ b/files/opencs/resources.qrc @@ -1,30 +1,61 @@ opencs.png - added.png - modified.png - removed.png - base.png activator.png - apparatus.png - armor.png - book.png - clothing.png - container.png - creature.png - door.png - ingredient.png - leveled-creature.png - leveled-item.png - light.png - lockpick.png - miscellaneous.png - npc.png - potion.png - probe.png - repair.png - static.png - weapon.png + added.png + apparatus.png + armor.png + attribute.png + base.png + birthsign.png + body-part.png + book.png + cell.png + class.png + clothing.png + container.png + creature.png + dialogoue-info.png + dialogoue-journal.png + dialogoue-regular.png + dialogue-greeting.png + dialogue-persuasion.png + dialogue-speech.png + door.png + enchantment.png + faction.png + filter.png + globvar.png + GMST.png + Info.png + ingredient.png + landpaint.png + land.png + LandTexture.png + leveled-creature.png + light.png + lockpick.png + magic-effect.png + magicrabbit.png + map.png + miscellaneous.png + modified.png + npc.png + PathGrid.png + potion.png + probe.png + race.png + random-item.png + random.png + removed.png + repair.png + script.png + skill.png + soundgen.png + sound.png + spell.png + static.png + weapon.png raster/startup/big/create-addon.png raster/startup/big/new-game.png raster/startup/big/edit-content.png diff --git a/files/opencs/script.png b/files/opencs/script.png new file mode 100644 index 0000000000000000000000000000000000000000..297da40210490e4345d2ef8adda136cc8a404db4 GIT binary patch literal 952 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 KMNUMnLSTXe=@Tgc literal 0 HcmV?d00001 diff --git a/files/opencs/soundgen.png b/files/opencs/soundgen.png new file mode 100644 index 0000000000000000000000000000000000000000..222fc4c7fe4b18f2a8db0b175c7fb173bc090d6f GIT binary patch literal 2149 zcmV-r2%7haP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000NnNklb`O^YcG(-tW!XEhTz1ig<+7k$BL!K)eMF5~Dz3 z0>&6H700F~LzSr1+KHw!CDSoazwdOHE=W?0)BN$xIfprWe$V^9&-;EK8~~i3YANLM zEPsZX;BvX=UCf^hE*6XHDTj zJB~Xa_u<~Br}6j60bJ?di+G*t_QILN2@DMEkBo?zmWah;VG>E5%P0$9Of`C68{D}P z4)gD@zp((lZTTp*d1AC<1(ebt6c!e;@ae04Ed0xlj^fXkkKoq(hcP*H5TBF#1G_3= zOVVv}|2Bs>bs{S(3l$X=a5x+=8Vs~$W<(;<7%@{75hSq2#@u{!&o)p27~)`b&k77S zk^5l|CJ()Y>OvFN*^_Yj)b2&$pIzLK@eBL#$>3fXV-(-b6F}=Jm&vw^f`Vp925yr3 zC&WZZOiYB?Y=%;yfJv`KhRurXq*w8HWEmcRxD0pSTMk_3V6bB)1`coe-pJkISKety zyk154{~iBq8xj$x-CBhX38_#h{8S;8Jd8K$5FHf>;%bmGK^7*0IK&T185fTymtnAb zB?{7||1)w5Kend|nX8RZikQ4P6FP^8eSwf>vobEuY$e7z$PmiTCx)iQ)|y`DHZN_L#OrW3h$m7;mIN!{Mp zS&x5y@d3WRaTbq0dmDcpKZWi_8%B?73ODSj}p*)~=`Rhb`q9NKl4C&i97c$Fq^$4V`m(l`HjbS*THpga6jJrHp*c zfUd?0eDY2w>-Mf4R^+dd%)v+dcVkce2H33zWUVnFldP147&KI`V{2}=>TslEBl%7Y zqDTgIs>M+Ga!TJto#?Ke$j<@6Oo>uI5qX3(VGf|jrMQN@L1zE`` zFGxj}Ee?*}ayZl1<0Vrria^45#Mjk0^R^vocG*TnOSa^=jh*qt1F72+!-3{kTJB4cn-m^M^ck;Y8TuLc4 z4FC3x;xwF1(V{moimkaVMh=}KWJz$E_AnpMuOs-L+UGu$(jRCUe(~mL>9<4avGWX9 zL)wlS?)xI&stQCL<1;Ju@f@RRf96EAl;~aWXoUP?9m9W6N*w(|HK%Sbm-|B}+gQ}(=w b7mD~dG%8@IxwiGh00000NkvXXu0mjfleqwj literal 0 HcmV?d00001 diff --git a/files/opencs/spell.png b/files/opencs/spell.png new file mode 100644 index 0000000000000000000000000000000000000000..69c8971805c431bdf29c4db04ab9feffdd358e2b GIT binary patch literal 2071 zcmV+y2Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000MuNkljp1N8(PCpQM{Oxot<gHDtkis{dz%jzz zNFkcfY z4}?|#wc?dX@iM$aZyfE-3|Go^fltWN8$@4F5DD1RB0k%lZb<>hXjbCE?$j1SD*(B# z-i)eH2U0Feu7>bq4yw)nM$}JX@-GZE#KG)enMC-ox|D^wka;n4w1LnHAk)j>F6t@B zBlKpZUM#uPhb6z=_8KrqmJbu%(?A69*>|(T4T@CxO9{~Zd-QeE&}jIOHAlD|jE@(H5viM}S+-qMAe!LA_6pl-P=ED6B3 zHLABVH<^=hnK|3N4acA)w|_(-FHRpL*MFul{*h>kXhd@)JdV+{s+PdDkT!K^sq1Db zEqeqTEY|)I&tuL>+}NEX4aAfHpoeJSf056U&uJn$8+{Zwn~ditl?*jNuAlxWeGEh! zp9QfjK!E+~W>vNh9M&0sqpBp4b&@5YYtCF%t&ew#4ba#5b6|-4ev3lbRu*uPd_ScD zh<0VR5dhu`14uTLma3*;ZL#*DdH}VPvyNlqkd-^`y5*v8Qv&LBZ4u*Of*YrFpe!RT zO3#Ut6p8}%`bi!A_)-8eH|8)Z$hrILtJB(%xeD)@`2)M!F&}mmKUgN<``<+2<6n9p z(aBhop>rfd#~2{S2;-29EKvu`9ziap)!~Nu3n+eEzGd#+E4>Q6F(tRAn7)Ig!s+ycnIh>_Pko-)5c ztw*`eo4Ay+5|h7YAk3YG$vq6jxG=k)8({y=Z6{0wD<{1xW-q+|sq4>K@X$$&CS7tt=vaIFCn!@O-ILboq#cE!!!|EwAFch2KP zo-b}^kg2E8WMMzo2wz#o;;WTD>a^35)8;2A3xt@h1)9ix(E>c^JBNn@9hmDoi+}eV!_;R75$f@V24WxCxSD}vD^pz1v0pGh%&>sO z&=eme{{lEl?kQ&=g=aXC=x%7UEWn=3&>;+dfJb*P<39r*V(#`?47OJyD^`e8RS6jF zD8q2O0wrO#Xq3LLK8ndI1{7R2Qq~zG)yxFx95x0O1dv2dzpjNlv&KaZnn(1L`ZXC! zL{AMRsx(77G~d^R_v>>pbMpuu^c=#!x@+;x<$d^5MLgnyd3g8Wc8p(Epra-d*?w<8 zPFj*SQsomBXjBuX2N}=kQIxy!&BqTRAD0d8JV)!XXy45bgsvMpv!pK5jk|*<1RU$6 zg|}jPddSdh?{Ub}f)~u`v`=2&kAHMkV&ZB!>Iy?qm>@)NOE&Ib+Kv9RxkwALpU?C) z>rUNjdR^>l-W4fyDkssIKHk{h!&c7Qyzb!_r}B^!CBSLLHjKQ#2h}?SvpfgOPdPRg z>bEDVBuz5Zdrpqi2a?p0FE*zm|E{AH1Lt?5HZK?jao(uO5#dT*Jp8zJGY7JR?Loe6a-mEoo@X^MQw*ML$)X5;XMfl`3_? zJ(>2$k^evQ4Xidk!nN;LNa3Krepj9r$=SL!Ot04-1JsyFY6i=iDJK{@D%v3$dRE#Oo8Nmk2VX0*7R>+Nl8mO^BHU?`q3;i| z3+Cw(4h|;spe)*|Hs2TLf-p~;2|pL>F21AXQ{6$uOSX(%X~;rVwgk;(F}T%QpgwbL z%==F!s?F)h8}fz72yuqY-vQ@Je32652oHP9sjbe|e-=1dEmZyD)}+!Sy%S0G^5_co z-{R=L&EK^#CeW=nBZ5D^H^pzE;1);Tbtn>tvV_PCbw!5M1?35(CgQn>^R*uh;@WhJ zJT@#jf*0Cwxk*KX#fx0)d_6V|7slNs80GnkN7N002ovPDHLkV1lGv B*sA~l literal 0 HcmV?d00001 diff --git a/files/opencs/static.png b/files/opencs/static.png old mode 100755 new mode 100644 index b53be12d9a8abad9272fdd7c6a75b1d3a6a494ba..aedf2d30eeed220acb1c5eb82b457f29354ed124 GIT binary patch delta 1262 zcmV1;MAa*k@H7+qQF!XYv000DlNkloADTs|mAvH#$F&d3VqcIwd(fBWXFzH`^ z;9=qk&)c<-lblRuK8S(L!^(tj_-5_B*FJ0SqeMit6Ky4D;%Xt2d9jhp>2+W!mD;_V z&F(zu>e7#aH-WWGMy~?P>GU4nNTu{pELMMn&xb@ZsUIW~`aWkF}% zo+mmx^<7{t8r{R}KFX2EUy9^^o;@pne*n+ZY1!`Wm0wSvmS2FMPo0vVfFE-?`5~K? z?}6{Sy5tr7{Y@q#Ujtv^oiBkeQYrZy_$--}Pk{=aeVjG5nSj`MZ(Ge*rwrW;Mxwe*?CV z!TSiHRpumT<_w@!<|Jq4WB9FBnUnk-V3Gk;lF9lVRA3GP5VcE}WESP0LFuP~3P`6e zT-Yl+iHW&$=j3HPzrBwM1a%AFv+T^Axnw2DK_D5_Mbig^L$u3VIsNN1eYCBm+sce+h_2P z^Drp-yOXyU5zs-JGYDpXzT)@GGSKJs?kY|-r@^v{s8?_@4jL?tCeuuFR>zRP?(@m8 z->(%%s?%UuK?#>(#Rm02c`}%hwR$D$0EnXPgab z>us`r==I72;GV}LgI=#z++xfkah!UyzW(8~(&rea?h4zoxcrr|1F%@KgDIm>Ryr%s%Z9ut6l zTlqgjrCGy`VgDNip{==1K8XMd9UWSYgu^d*SDT4MG;bDGfp%P72+nGjrK~1%lmvg*WB)19yNA58}2&5vNLm%pLe3o>!~g&Q delta 1500 zcmV<21ta>A3hoP#B!2{FK}|sb0I`n?{9y$E0004VQb$4nuFf3k0000WV@Og>004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00006VoOIv00000008+zyMF)x z010qNS#tmY4f_B94f_ELcQu;;00h2CL_t(o!|hhjZ_`K={(ojXaoadfaZ%b7wWv@v zqC!Z(1%W8)ffK##UxW6-Wp68S=dyPWfH-nN2&o*P2o(VmAP`hE6$?qzpRwb_es2$n zCyo<`?s<2l(TvB>&+pCq=9^Fav9!d@3_6^L8=p6tMGZ=t$9)BCI2lgNU&6 z@}&+gX`>tmnL>egU%wVYqhwYq#z(70y9He7KCXE ze|wuX1`a=bkehe!c0tnaBFb=NdKwc~u5kIm1Cg)+06_r2jKYl@yz}Z68b5yY)Et0} zaAKc5i%hXdmB){D=~Ym#BdFI?w_3R_!d8nz*A@CS3@8t^S_nN4q35Og3Oo<8(Lm5> zXg?B(T7Mq3c1Hmn2F*K1GFn&JQVF?INq-z|X_Tc|EJE3~u;%BHdY%DfY#Z6RImodw zy-tbX#%5<>7K<32nbB+F=Hem)T_SOomQerl1#Y?AmsK>MSY8GP0aaI5We-usY}EKT z@)s^p<;fEnB^CD*1*Z<)zwg<`?3pt-`1nx=Fn<7e7@3(t7=}3b{J94cacrn#$1r;O zH0m20=|>qcA{s;($$7l?$yyG=Mo-o$7*oo&dyIr>!pP-d(D?aN+o9tt z;)hJ303(+Z&ZSFj-eHFLeR(;Ivs(WAdEr+o?3T+tY)7%VRVoPzLq7QQDQ+XElO6$3 z`8-BvXR-U{O^*WVTy$E6scH-m48X|ev9rD|ysfSDZO&vsLBKmNUL<)$15k~RV}HW3 zXm5R84)CGvWFLueKN1E3?nsyzLRL|eN4e#Gh32&OD>=ph#Gkirg^fxD+#wL5ln9$m ztyqkF9xMd>TCJTq5nvdCnGv>H-CE}J%wdS;-k#9JlgWsn+2lAm38mog?R8bLyRjj+ z9zH|_9>iW|ipcX2cwX24pxdr*jH#x73%EW^ zBo&c8KTo;&`EK?x)dRGNXw-3FpE^Z-;ESDxF~>nTH^-)Bi9x|JfZWNG$bS?H+}zxx zNOg(7?%er}V-%?!N6*ZVrYT#E1|d$%vG)KV45KaQiF$+UFkWm&G!YFuLI1b^PWuNL z>S^MF3P{KR001R)MObuXVRU6WV{&C-bY%cCFflVNFf%PPF;p=yIxsdmH90FVGCD9Y z`o*k10000bbVXQnWMOn=I#q3NWNBu305UK!Gc7PPEi*AxF)%tXHaayqD=;!TFffal z6oLQ%02y>eSaefwW^{L9a%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*0000 Date: Tue, 24 Sep 2013 09:40:35 +0200 Subject: [PATCH 11/81] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index c766c34c3..6e8e36612 100644 --- a/credits.txt +++ b/credits.txt @@ -62,6 +62,7 @@ Roman Proskuryakov (humbug) Sandy Carter (bwrsandman) Sebastian Wick (swick) Sergey Shambir +sir_herrbatka Sylvain Thesnieres (Garvek) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) From 1363e868281a94f9e967a81cb94fbc249e0f6b7d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 27 Sep 2013 10:08:09 +0200 Subject: [PATCH 12/81] made verifier ignore deleted records --- apps/opencs/model/tools/birthsigncheck.cpp | 7 ++++++- apps/opencs/model/tools/classcheck.cpp | 7 ++++++- apps/opencs/model/tools/factioncheck.cpp | 7 ++++++- apps/opencs/model/tools/racecheck.cpp | 7 ++++++- apps/opencs/model/tools/regioncheck.cpp | 7 ++++++- apps/opencs/model/tools/skillcheck.cpp | 7 ++++++- apps/opencs/model/tools/soundcheck.cpp | 7 ++++++- apps/opencs/model/tools/spellcheck.cpp | 7 ++++++- 8 files changed, 48 insertions(+), 8 deletions(-) diff --git a/apps/opencs/model/tools/birthsigncheck.cpp b/apps/opencs/model/tools/birthsigncheck.cpp index b673c93de..59c65086e 100644 --- a/apps/opencs/model/tools/birthsigncheck.cpp +++ b/apps/opencs/model/tools/birthsigncheck.cpp @@ -19,7 +19,12 @@ int CSMTools::BirthsignCheckStage::setup() void CSMTools::BirthsignCheckStage::perform (int stage, std::vector& messages) { - const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get(); + const CSMWorld::Record& record = mBirthsigns.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::BirthSign& birthsign = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId); diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index da2e9f19a..6923b3153 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -20,7 +20,12 @@ int CSMTools::ClassCheckStage::setup() void CSMTools::ClassCheckStage::perform (int stage, std::vector& messages) { - const ESM::Class& class_= mClasses.getRecord (stage).get(); + const CSMWorld::Record& record = mClasses.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Class& class_ = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId); diff --git a/apps/opencs/model/tools/factioncheck.cpp b/apps/opencs/model/tools/factioncheck.cpp index af26904ef..c219e5610 100644 --- a/apps/opencs/model/tools/factioncheck.cpp +++ b/apps/opencs/model/tools/factioncheck.cpp @@ -20,7 +20,12 @@ int CSMTools::FactionCheckStage::setup() void CSMTools::FactionCheckStage::perform (int stage, std::vector& messages) { - const ESM::Faction& faction = mFactions.getRecord (stage).get(); + const CSMWorld::Record& record = mFactions.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Faction& faction = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId); diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 1e7a4cab4..413de5ef0 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -9,7 +9,12 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) { - const ESM::Race& race = mRaces.getRecord (stage).get(); + const CSMWorld::Record& record = mRaces.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Race& race = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId); diff --git a/apps/opencs/model/tools/regioncheck.cpp b/apps/opencs/model/tools/regioncheck.cpp index ac64ac027..4398e00ef 100644 --- a/apps/opencs/model/tools/regioncheck.cpp +++ b/apps/opencs/model/tools/regioncheck.cpp @@ -19,7 +19,12 @@ int CSMTools::RegionCheckStage::setup() void CSMTools::RegionCheckStage::perform (int stage, std::vector& messages) { - const ESM::Region& region = mRegions.getRecord (stage).get(); + const CSMWorld::Record& record = mRegions.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Region& region = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Region, region.mId); diff --git a/apps/opencs/model/tools/skillcheck.cpp b/apps/opencs/model/tools/skillcheck.cpp index 897aeab47..28fc24fd3 100644 --- a/apps/opencs/model/tools/skillcheck.cpp +++ b/apps/opencs/model/tools/skillcheck.cpp @@ -18,7 +18,12 @@ int CSMTools::SkillCheckStage::setup() void CSMTools::SkillCheckStage::perform (int stage, std::vector& messages) { - const ESM::Skill& skill = mSkills.getRecord (stage).get(); + const CSMWorld::Record& record = mSkills.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Skill& skill = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId); diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp index 52834e659..dce2d2b6f 100644 --- a/apps/opencs/model/tools/soundcheck.cpp +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -18,7 +18,12 @@ int CSMTools::SoundCheckStage::setup() void CSMTools::SoundCheckStage::perform (int stage, std::vector& messages) { - const ESM::Sound& sound = mSounds.getRecord (stage).get(); + const CSMWorld::Record& record = mSounds.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Sound& sound = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId); diff --git a/apps/opencs/model/tools/spellcheck.cpp b/apps/opencs/model/tools/spellcheck.cpp index 3adee0a4e..a2cc7c8d2 100644 --- a/apps/opencs/model/tools/spellcheck.cpp +++ b/apps/opencs/model/tools/spellcheck.cpp @@ -19,7 +19,12 @@ int CSMTools::SpellCheckStage::setup() void CSMTools::SpellCheckStage::perform (int stage, std::vector& messages) { - const ESM::Spell& spell = mSpells.getRecord (stage).get(); + const CSMWorld::Record& record = mSpells.getRecord (stage); + + if (record.isDeleted()) + return; + + const ESM::Spell& spell = record.get(); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId); From 9ea092927fca60c1b92b8d4fbc7305eda672c8db Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 28 Sep 2013 09:25:54 +0200 Subject: [PATCH 13/81] added basic scene subview (no functionality yet) --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 5 +- apps/opencs/view/doc/view.cpp | 9 ++++ apps/opencs/view/doc/view.hpp | 2 + apps/opencs/view/world/scenesubview.cpp | 72 +++++++++++++++++++++++++ apps/opencs/view/world/scenesubview.hpp | 37 +++++++++++++ apps/opencs/view/world/scenetoolbar.cpp | 8 +++ apps/opencs/view/world/scenetoolbar.hpp | 20 +++++++ apps/opencs/view/world/subviews.cpp | 2 + 10 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 apps/opencs/view/world/scenesubview.cpp create mode 100644 apps/opencs/view/world/scenesubview.hpp create mode 100644 apps/opencs/view/world/scenetoolbar.cpp create mode 100644 apps/opencs/view/world/scenetoolbar.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 00547a2ba..2fbceac96 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -59,7 +59,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator - cellcreator referenceablecreator referencecreator + cellcreator referenceablecreator referencecreator scenesubview scenetoolbar ) opencs_units_noqt (view/world diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 60a8485f8..c9edd0c16 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -87,6 +87,7 @@ namespace static const TypeData sIndexArg[] = { { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, + { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index aa0cdacc0..246640733 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -86,10 +86,11 @@ namespace CSMWorld Type_Reference, Type_RegionMap, Type_Filter, - Type_Filters + Type_Filters, + Type_Scene }; - enum { NumberOfTypes = Type_Filters+1 }; + enum { NumberOfTypes = Type_Scene+1 }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 7183753e1..b29250d20 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -115,6 +115,10 @@ void CSVDoc::View::setupWorldMenu() world->addSeparator(); // items that don't represent single record lists follow here + QAction *scene = new QAction (tr ("Scene"), this); + connect (scene, SIGNAL (triggered()), this, SLOT (addSceneSubView())); + world->addAction (scene); + QAction *regionMap = new QAction (tr ("Region Map"), this); connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView())); world->addAction (regionMap); @@ -403,6 +407,11 @@ void CSVDoc::View::addFiltersSubView() addSubView (CSMWorld::UniversalId::Type_Filters); } +void CSVDoc::View::addSceneSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Scene); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 29a1d52f7..6f3c38daa 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -164,6 +164,8 @@ namespace CSVDoc void addFiltersSubView(); + void addSceneSubView(); + void toggleShowStatusBar (bool show); }; } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp new file mode 100644 index 000000000..bb77fec2e --- /dev/null +++ b/apps/opencs/view/world/scenesubview.cpp @@ -0,0 +1,72 @@ + +#include "scenesubview.hpp" + +#include +#include +#include + +#include "../../model/doc/document.hpp" + +#include "../filter/filterbox.hpp" + +#include "tablebottombox.hpp" +#include "creator.hpp" +#include "scenetoolbar.hpp" + +CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) +: SubView (id) +{ + QVBoxLayout *layout = new QVBoxLayout; + + layout->setContentsMargins (QMargins (0, 0, 0, 0)); + + layout->addWidget (mBottom = + new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, + this), 0); + + QHBoxLayout *layout2 = new QHBoxLayout; + + layout2->setContentsMargins (QMargins (0, 0, 0, 0)); + + SceneToolbar *toolbar = new SceneToolbar (this); + layout2->addWidget (toolbar, 0); + + /// \todo replace with rendering widget + QPalette palette2 (palette()); + palette2.setColor (QPalette::Background, Qt::white); + QLabel *placeholder = new QLabel ("Here goes the 3D scene", this); + placeholder->setAutoFillBackground (true); + placeholder->setPalette (palette2); + placeholder->setAlignment (Qt::AlignHCenter); + + layout2->addWidget (placeholder, 1); + + layout->insertLayout (0, layout2, 1); + + CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); + + layout->insertWidget (0, filterBox); + + QWidget *widget = new QWidget; + + widget->setLayout (layout); + + setWidget (widget); +} + +void CSVWorld::SceneSubView::setEditLock (bool locked) +{ + + +} + +void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue) +{ + + +} + +void CSVWorld::SceneSubView::setStatusBar (bool show) +{ + mBottom->setStatusBar (show); +} \ No newline at end of file diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp new file mode 100644 index 000000000..a0fed908d --- /dev/null +++ b/apps/opencs/view/world/scenesubview.hpp @@ -0,0 +1,37 @@ +#ifndef CSV_WORLD_SCENESUBVIEW_H +#define CSV_WORLD_SCENESUBVIEW_H + +#include "../doc/subview.hpp" + +class QModelIndex; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVWorld +{ + class Table; + class TableBottomBox; + class CreatorFactoryBase; + + class SceneSubView : public CSVDoc::SubView + { + Q_OBJECT + + TableBottomBox *mBottom; + + public: + + SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + + virtual void setEditLock (bool locked); + + virtual void updateEditorSetting (const QString& key, const QString& value); + + virtual void setStatusBar (bool show); + }; +} + +#endif diff --git a/apps/opencs/view/world/scenetoolbar.cpp b/apps/opencs/view/world/scenetoolbar.cpp new file mode 100644 index 000000000..6ced03a9f --- /dev/null +++ b/apps/opencs/view/world/scenetoolbar.cpp @@ -0,0 +1,8 @@ + +#include "scenetoolbar.hpp" + +CSVWorld::SceneToolbar::SceneToolbar (QWidget *parent) : QWidget (parent) +{ + setFixedWidth (52); + +} diff --git a/apps/opencs/view/world/scenetoolbar.hpp b/apps/opencs/view/world/scenetoolbar.hpp new file mode 100644 index 000000000..2fb288100 --- /dev/null +++ b/apps/opencs/view/world/scenetoolbar.hpp @@ -0,0 +1,20 @@ +#ifndef CSV_WORLD_SCENETOOLBAR_H +#define CSV_WORLD_SCENETOOLBAR_H + +#include + +namespace CSVWorld +{ + class SceneToolbar : public QWidget + { + Q_OBJECT + + public: + + SceneToolbar (QWidget *parent); + + + }; +} + +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index d22e07d89..0e3465b38 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -13,6 +13,7 @@ #include "cellcreator.hpp" #include "referenceablecreator.hpp" #include "referencecreator.hpp" +#include "scenesubview.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -62,4 +63,5 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory); } \ No newline at end of file From 84cadc10f4a32a752426f106d75db9078f160c10 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 28 Sep 2013 11:06:56 +0200 Subject: [PATCH 14/81] added scene toolbar buttons (still not doing anything) --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/scenesubview.cpp | 5 +++++ apps/opencs/view/world/scenetool.cpp | 9 +++++++++ apps/opencs/view/world/scenetool.hpp | 19 +++++++++++++++++++ apps/opencs/view/world/scenetoolbar.cpp | 17 ++++++++++++++++- apps/opencs/view/world/scenetoolbar.hpp | 8 +++++++- 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 apps/opencs/view/world/scenetool.cpp create mode 100644 apps/opencs/view/world/scenetool.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 2fbceac96..2bb31be9f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -59,7 +59,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator - cellcreator referenceablecreator referencecreator scenesubview scenetoolbar + cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index bb77fec2e..3b15326ab 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -12,6 +12,7 @@ #include "tablebottombox.hpp" #include "creator.hpp" #include "scenetoolbar.hpp" +#include "scenetool.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id) @@ -29,6 +30,10 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout2->setContentsMargins (QMargins (0, 0, 0, 0)); SceneToolbar *toolbar = new SceneToolbar (this); +toolbar->addTool (new SceneTool (this)); // test +toolbar->addTool (new SceneTool (this)); +toolbar->addTool (new SceneTool (this)); +toolbar->addTool (new SceneTool (this)); layout2->addWidget (toolbar, 0); /// \todo replace with rendering widget diff --git a/apps/opencs/view/world/scenetool.cpp b/apps/opencs/view/world/scenetool.cpp new file mode 100644 index 000000000..12743c52c --- /dev/null +++ b/apps/opencs/view/world/scenetool.cpp @@ -0,0 +1,9 @@ + +#include "scenetool.hpp" + +CSVWorld::SceneTool::SceneTool (QWidget *parent) : QPushButton (parent) +{ + setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); + setFixedSize (48, 48); + +} \ No newline at end of file diff --git a/apps/opencs/view/world/scenetool.hpp b/apps/opencs/view/world/scenetool.hpp new file mode 100644 index 000000000..ae440b579 --- /dev/null +++ b/apps/opencs/view/world/scenetool.hpp @@ -0,0 +1,19 @@ +#ifndef CSV_WORLD_SCENETOOL_H +#define CSV_WORLD_SCENETOOL_H + +#include + +namespace CSVWorld +{ + class SceneTool : public QPushButton + { + Q_OBJECT + + public: + + SceneTool (QWidget *parent = 0); + + }; +} + +#endif diff --git a/apps/opencs/view/world/scenetoolbar.cpp b/apps/opencs/view/world/scenetoolbar.cpp index 6ced03a9f..7c716b5fc 100644 --- a/apps/opencs/view/world/scenetoolbar.cpp +++ b/apps/opencs/view/world/scenetoolbar.cpp @@ -1,8 +1,23 @@ #include "scenetoolbar.hpp" +#include + +#include "scenetool.hpp" + CSVWorld::SceneToolbar::SceneToolbar (QWidget *parent) : QWidget (parent) { - setFixedWidth (52); + setFixedWidth (48); + + mLayout = new QVBoxLayout (this); + mLayout->setAlignment (Qt::AlignTop); + mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); + + setLayout (mLayout); } + +void CSVWorld::SceneToolbar::addTool (SceneTool *tool) +{ + mLayout->addWidget (tool, 0, Qt::AlignTop); +} \ No newline at end of file diff --git a/apps/opencs/view/world/scenetoolbar.hpp b/apps/opencs/view/world/scenetoolbar.hpp index 2fb288100..00631c360 100644 --- a/apps/opencs/view/world/scenetoolbar.hpp +++ b/apps/opencs/view/world/scenetoolbar.hpp @@ -3,17 +3,23 @@ #include +class QVBoxLayout; + namespace CSVWorld { + class SceneTool; + class SceneToolbar : public QWidget { Q_OBJECT + QVBoxLayout *mLayout; + public: SceneToolbar (QWidget *parent); - + void addTool (SceneTool *tool); }; } From 0c5f07a65addf90c4fd033b2d4e4e03424f26e24 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 28 Sep 2013 11:27:24 +0200 Subject: [PATCH 15/81] added SceneToolMode class --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/world/scenesubview.cpp | 10 +++++----- apps/opencs/view/world/scenetool.cpp | 1 - apps/opencs/view/world/scenetool.hpp | 1 + apps/opencs/view/world/scenetoolmode.cpp | 6 ++++++ apps/opencs/view/world/scenetoolmode.hpp | 19 +++++++++++++++++++ 6 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 apps/opencs/view/world/scenetoolmode.cpp create mode 100644 apps/opencs/view/world/scenetoolmode.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 2bb31be9f..f918cfebf 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -60,6 +60,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool + scenetoolmode ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 3b15326ab..8f3ecab21 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -12,7 +12,7 @@ #include "tablebottombox.hpp" #include "creator.hpp" #include "scenetoolbar.hpp" -#include "scenetool.hpp" +#include "scenetoolmode.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id) @@ -30,10 +30,10 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout2->setContentsMargins (QMargins (0, 0, 0, 0)); SceneToolbar *toolbar = new SceneToolbar (this); -toolbar->addTool (new SceneTool (this)); // test -toolbar->addTool (new SceneTool (this)); -toolbar->addTool (new SceneTool (this)); -toolbar->addTool (new SceneTool (this)); +toolbar->addTool (new SceneToolMode (this)); // test +toolbar->addTool (new SceneToolMode (this)); +toolbar->addTool (new SceneToolMode (this)); +toolbar->addTool (new SceneToolMode (this)); layout2->addWidget (toolbar, 0); /// \todo replace with rendering widget diff --git a/apps/opencs/view/world/scenetool.cpp b/apps/opencs/view/world/scenetool.cpp index 12743c52c..f67e4fa45 100644 --- a/apps/opencs/view/world/scenetool.cpp +++ b/apps/opencs/view/world/scenetool.cpp @@ -5,5 +5,4 @@ CSVWorld::SceneTool::SceneTool (QWidget *parent) : QPushButton (parent) { setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); setFixedSize (48, 48); - } \ No newline at end of file diff --git a/apps/opencs/view/world/scenetool.hpp b/apps/opencs/view/world/scenetool.hpp index ae440b579..c3e9e3b4b 100644 --- a/apps/opencs/view/world/scenetool.hpp +++ b/apps/opencs/view/world/scenetool.hpp @@ -5,6 +5,7 @@ namespace CSVWorld { + ///< \brief Tool base class class SceneTool : public QPushButton { Q_OBJECT diff --git a/apps/opencs/view/world/scenetoolmode.cpp b/apps/opencs/view/world/scenetoolmode.cpp new file mode 100644 index 000000000..a6b9b5a28 --- /dev/null +++ b/apps/opencs/view/world/scenetoolmode.cpp @@ -0,0 +1,6 @@ + +#include "scenetoolmode.hpp" + +CSVWorld::SceneToolMode::SceneToolMode (QWidget *parent) +: SceneTool (parent) +{} \ No newline at end of file diff --git a/apps/opencs/view/world/scenetoolmode.hpp b/apps/opencs/view/world/scenetoolmode.hpp new file mode 100644 index 000000000..d54ec76b2 --- /dev/null +++ b/apps/opencs/view/world/scenetoolmode.hpp @@ -0,0 +1,19 @@ +#ifndef CSV_WORLD_SCENETOOL_MODE_H +#define CSV_WORLD_SCENETOOL_MODE_H + +#include "scenetool.hpp" + +namespace CSVWorld +{ + ///< \brief Mode selector tool + class SceneToolMode : public SceneTool + { + Q_OBJECT + + public: + + SceneToolMode (QWidget *parent = 0); + }; +} + +#endif From 7be1f1afc2a9e5ce7f6e0d95d22483fc544d90ac Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 28 Sep 2013 13:10:42 +0200 Subject: [PATCH 16/81] implemented SceneToolMode as a horizontal panel with radiobutton-type buttons --- apps/opencs/view/world/scenesubview.cpp | 7 +++- apps/opencs/view/world/scenetool.cpp | 14 ++++++- apps/opencs/view/world/scenetool.hpp | 9 +++++ apps/opencs/view/world/scenetoolmode.cpp | 47 +++++++++++++++++++++++- apps/opencs/view/world/scenetoolmode.hpp | 20 ++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 8f3ecab21..36ace68f0 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -30,7 +30,12 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout2->setContentsMargins (QMargins (0, 0, 0, 0)); SceneToolbar *toolbar = new SceneToolbar (this); -toolbar->addTool (new SceneToolMode (this)); // test +// test +SceneToolMode *tool = new SceneToolMode (this); +tool->addButton (":door.png", "a"); +tool->addButton (":GMST.png", "b"); +tool->addButton (":Info.png", "c"); +toolbar->addTool (tool); toolbar->addTool (new SceneToolMode (this)); toolbar->addTool (new SceneToolMode (this)); toolbar->addTool (new SceneToolMode (this)); diff --git a/apps/opencs/view/world/scenetool.cpp b/apps/opencs/view/world/scenetool.cpp index f67e4fa45..d7d37c98f 100644 --- a/apps/opencs/view/world/scenetool.cpp +++ b/apps/opencs/view/world/scenetool.cpp @@ -5,4 +5,16 @@ CSVWorld::SceneTool::SceneTool (QWidget *parent) : QPushButton (parent) { setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); setFixedSize (48, 48); -} \ No newline at end of file + + connect (this, SIGNAL (clicked()), this, SLOT (openRequest())); +} + +void CSVWorld::SceneTool::updateIcon (const QIcon& icon) +{ + setIcon (icon); +} + +void CSVWorld::SceneTool::openRequest() +{ + showPanel (parentWidget()->mapToGlobal (pos())); +} diff --git a/apps/opencs/view/world/scenetool.hpp b/apps/opencs/view/world/scenetool.hpp index c3e9e3b4b..d5c9dd5d2 100644 --- a/apps/opencs/view/world/scenetool.hpp +++ b/apps/opencs/view/world/scenetool.hpp @@ -14,6 +14,15 @@ namespace CSVWorld SceneTool (QWidget *parent = 0); + virtual void showPanel (const QPoint& position) = 0; + + protected slots: + + void updateIcon (const QIcon& icon); + + private slots: + + void openRequest(); }; } diff --git a/apps/opencs/view/world/scenetoolmode.cpp b/apps/opencs/view/world/scenetoolmode.cpp index a6b9b5a28..b4277bcbe 100644 --- a/apps/opencs/view/world/scenetoolmode.cpp +++ b/apps/opencs/view/world/scenetoolmode.cpp @@ -1,6 +1,51 @@ #include "scenetoolmode.hpp" +#include +#include +#include + CSVWorld::SceneToolMode::SceneToolMode (QWidget *parent) : SceneTool (parent) -{} \ No newline at end of file +{ + mPanel = new QFrame (this, Qt::Popup); + + mLayout = new QHBoxLayout (mPanel); + + mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); + + mPanel->setLayout (mLayout); +} + +void CSVWorld::SceneToolMode::showPanel (const QPoint& position) +{ + mPanel->move (position); + mPanel->show(); +} + +void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::string& id) +{ + QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel); + button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); + button->setFixedSize (48, 48); + + mLayout->addWidget (button); + + mButtons.insert (std::make_pair (button, id)); + + connect (button, SIGNAL (clicked()), this, SLOT (selected())); +} + +void CSVWorld::SceneToolMode::selected() +{ + std::map::const_iterator iter = + mButtons.find (dynamic_cast (sender())); + + if (iter!=mButtons.end()) + { + mPanel->hide(); + + emit updateIcon (iter->first->icon()); + emit modeChanged (iter->second); + } +} \ No newline at end of file diff --git a/apps/opencs/view/world/scenetoolmode.hpp b/apps/opencs/view/world/scenetoolmode.hpp index d54ec76b2..feee78376 100644 --- a/apps/opencs/view/world/scenetoolmode.hpp +++ b/apps/opencs/view/world/scenetoolmode.hpp @@ -3,6 +3,10 @@ #include "scenetool.hpp" +#include + +class QHBoxLayout; + namespace CSVWorld { ///< \brief Mode selector tool @@ -10,9 +14,25 @@ namespace CSVWorld { Q_OBJECT + QWidget *mPanel; + QHBoxLayout *mLayout; + std::map mButtons; // widget, id + public: SceneToolMode (QWidget *parent = 0); + + virtual void showPanel (const QPoint& position); + + void addButton (const std::string& icon, const std::string& id); + + signals: + + void modeChanged (const std::string& id); + + private slots: + + void selected(); }; } From fd169c2399ba2ccc103361696b61c662d88b901b Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 29 Sep 2013 15:49:47 +0100 Subject: [PATCH 17/81] fixed issue with cds where subfolders of Data Files were contained outside the Data Files folder --- apps/launcher/unshieldthread.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/launcher/unshieldthread.cpp b/apps/launcher/unshieldthread.cpp index 6ddad7a21..33bdf44f4 100644 --- a/apps/launcher/unshieldthread.cpp +++ b/apps/launcher/unshieldthread.cpp @@ -268,6 +268,27 @@ namespace strptime(time, "%d %B %Y", &tms); return mktime(&tms); } + + // Some cds have cab files which have the Data Files subfolders outside the Data Files folder + void install_dfiles_outside(const bfs::path& from, const bfs::path& dFiles) + { + bfs::path fonts = findFile(from, "fonts", false); + if(fonts.string() != "") + installToPath(fonts, dFiles / "Fonts"); + + bfs::path music = findFile(from, "music", false); + if(music.string() != "") + installToPath(music, dFiles / "Music"); + + bfs::path sound = findFile(from, "sound", false); + if(sound.string() != "") + installToPath(sound, dFiles / "Sound"); + + bfs::path splash = findFile(from, "splash", false); + if(splash.string() != "") + installToPath(splash, dFiles / "Splash"); + } + } bool UnshieldThread::SetMorrowindPath(const std::string& path) @@ -365,6 +386,8 @@ bool UnshieldThread::extract() installToPath(dFilesDir, outputDataFilesDir); + install_dfiles_outside(mwExtractPath, outputDataFilesDir); + // Videos are often kept uncompressed on the cd bfs::path videosPath = findFile(mMorrowindPath.parent_path(), "video", false); if(videosPath.string() != "") @@ -399,6 +422,8 @@ bool UnshieldThread::extract() installToPath(dFilesDir, outputDataFilesDir); + install_dfiles_outside(tbExtractPath, outputDataFilesDir); + // Mt GOTY CD has Sounds in a seperate folder from the rest of the data files bfs::path soundsPath = findFile(tbExtractPath, "sounds", false); if(soundsPath.string() != "") @@ -426,6 +451,8 @@ bool UnshieldThread::extract() bfs::path dFilesDir = findFile(bmExtractPath, "bloodmoon.esm").parent_path(); installToPath(dFilesDir, outputDataFilesDir); + + install_dfiles_outside(bmExtractPath, outputDataFilesDir); // My GOTY CD contains a folder within cab files called Tribunal patch, // which contains Tribunal.esm From dd0a41624970b657a4159cffdb7b2a120636a023 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 29 Sep 2013 16:59:52 +0100 Subject: [PATCH 18/81] cleaned up bloodmoon_fix_ini --- apps/launcher/unshieldthread.cpp | 143 ++++++++++++++++--------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/apps/launcher/unshieldthread.cpp b/apps/launcher/unshieldthread.cpp index 33bdf44f4..69b241365 100644 --- a/apps/launcher/unshieldthread.cpp +++ b/apps/launcher/unshieldthread.cpp @@ -77,6 +77,8 @@ namespace ini.insert(loc, setting + "=" + val + "\r\n"); } + #define FIX(setting) add_setting(category, setting, get_setting(category, setting, inx), ini) + void bloodmoon_fix_ini(std::string& ini, const bfs::path inxPath) { std::string inx = read_to_string(inxPath); @@ -88,95 +90,94 @@ namespace ini.erase(start, end-start); std::string category; - std::string setting; category = "General"; { - setting = "Werewolf FOV"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Werewolf FOV"); } category = "Moons"; { - setting = "Script Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Script Color"); } category = "Weather"; { - setting = "Snow Ripples"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Ripple Radius"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Ripples Per Flake"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Ripple Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Ripple Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Gravity Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow High Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Low Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Snow Ripples"); + FIX("Snow Ripple Radius"); + FIX("Snow Ripples Per Flake"); + FIX("Snow Ripple Scale"); + FIX("Snow Ripple Speed"); + FIX("Snow Gravity Scale"); + FIX("Snow High Kill"); + FIX("Snow Low Kill"); } category = "Weather Blight"; { - setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Ambient Loop Sound ID"); } category = "Weather Snow"; { - setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Diameter"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Height Min"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Height Max"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Snow Entrance Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Max Snowflakes"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Sky Sunrise Color"); + FIX("Sky Day Color"); + FIX("Sky Sunset Color"); + FIX("Sky Night Color"); + FIX("Fog Sunrise Color"); + FIX("Fog Day Color"); + FIX("Fog Sunset Color"); + FIX("Fog Night Color"); + FIX("Ambient Sunrise Color"); + FIX("Ambient Day Color"); + FIX("Ambient Sunset Color"); + FIX("Ambient Night Color"); + FIX("Sun Sunrise Color"); + FIX("Sun Day Color"); + FIX("Sun Sunset Color"); + FIX("Sun Night Color"); + FIX("Sun Disc Sunset Color"); + FIX("Transition Delta"); + FIX("Land Fog Day Depth"); + FIX("Land Fog Night Depth"); + FIX("Clouds Maximum Percent"); + FIX("Wind Speed"); + FIX("Cloud Speed"); + FIX("Glare View"); + FIX("Cloud Texture"); + FIX("Ambient Loop Sound ID"); + FIX("Snow Threshold"); + FIX("Snow Diameter"); + FIX("Snow Height Min"); + FIX("Snow Height Max"); + FIX("Snow Entrance Speed"); + FIX("Max Snowflakes"); } category = "Weather Blizzard"; { - setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini); - setting = "Storm Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini); + FIX("Sky Sunrise Color"); + FIX("Sky Day Color"); + FIX("Sky Sunset Color"); + FIX("Sky Night Color"); + FIX("Fog Sunrise Color"); + FIX("Fog Day Color"); + FIX("Fog Sunset Color"); + FIX("Fog Night Color"); + FIX("Ambient Sunrise Color"); + FIX("Ambient Day Color"); + FIX("Ambient Sunset Color"); + FIX("Ambient Night Color"); + FIX("Sun Sunrise Color"); + FIX("Sun Day Color"); + FIX("Sun Sunset Color"); + FIX("Sun Night Color"); + FIX("Sun Disc Sunset Color"); + FIX("Transition Delta"); + FIX("Land Fog Day Depth"); + FIX("Land Fog Night Depth"); + FIX("Clouds Maximum Percent"); + FIX("Wind Speed"); + FIX("Cloud Speed"); + FIX("Glare View"); + FIX("Cloud Texture"); + FIX("Ambient Loop Sound ID"); + FIX("Storm Threshold"); } } From bffbfff41c791c18a182e49d1f11710b6c46a3b2 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 00:32:06 -0400 Subject: [PATCH 19/81] My own fix to make it hackily compile --- apps/launcher/main.cpp | 16 ++++++++++++++++ apps/opencs/view/doc/adjusterwidget.cpp | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index f67f5edcf..a5cda7647 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,3 +62,19 @@ int main(int argc, char *argv[]) return returnValue; } + +#include +#include + +#ifdef __GNUC__ +#define _stdcall __attribute__((stdcall)) +#endif + +int _stdcall +WinMain (struct HINSTANCE__ *hInstance, + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) +{ + return main (__argc, __argv); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index 910819700..c97f06672 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -61,7 +61,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (path.parent_path().string()==mLocalData.string()) { // path already points to the local data directory - message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; } @@ -70,7 +70,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) // path points somewhere else or is a leaf name. path = mLocalData / path.filename(); - message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; From 4cdb57e3883051b9dc4dcc6ca16668aa4961ee28 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 30 Sep 2013 10:30:40 +0400 Subject: [PATCH 20/81] workaround segfault on --new-game switch --- apps/openmw/engine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a2eccbaf9..e1fd3a0af 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -399,8 +399,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding); mEnvironment.setWindowManager (window); - if (mNewGame) - mEnvironment.getWindowManager()->setNewGame(true); // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, @@ -410,6 +408,10 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) input->setPlayer(&mEnvironment.getWorld()->getPlayer()); window->initUI(); + if (mNewGame) + // still redundant work here: recreate CharacterCreation(), + // double update visibility etc. + window->setNewGame(true); window->renderWorldMap(); //Load translation data From 00a776a1a8585c2205c86f958bbe2dc7ba9e64c6 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 02:54:20 -0400 Subject: [PATCH 21/81] Fixed compilation failure on my machine Fixed shared records not being populated before the player record is moved. --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f3d4c81b7..8e8f68f70 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -225,8 +225,8 @@ namespace MWWorld if (mEsm[0].getFormat() == 0) ensureNeededRecords(); - mStore.movePlayerRecord(); mStore.setUp(); + mStore.movePlayerRecord(); mGlobalVariables = new Globals (mStore); From eae02ea00dc9823fed63366709ef9c857f4e1956 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 03:33:31 -0400 Subject: [PATCH 22/81] Cleaned up my hackish code for WinMain --- apps/launcher/main.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index a5cda7647..73bdb95da 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,19 +62,14 @@ int main(int argc, char *argv[]) return returnValue; } - -#include -#include - -#ifdef __GNUC__ -#define _stdcall __attribute__((stdcall)) -#endif - -int _stdcall -WinMain (struct HINSTANCE__ *hInstance, - struct HINSTANCE__ *hPrevInstance, - char *lpszCmdLine, - int nCmdShow) +#ifdef _WINDOWS +// If the system compiles for main(), then main will be used. +// If it wants WinMain, this will call main anyways. +int _stdcall WinMain(struct HINSTANCE__ *hInstance, + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) { - return main (__argc, __argv); -} \ No newline at end of file + return main(__argc, __argv); +} +#endif From 4496244b1428cb43d9d5d41d191360b7b98e2cb0 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 05:36:13 -0400 Subject: [PATCH 23/81] Tabs to spaces My own code uses only tabs - I forgot to change the setting on my IDE, sorry! --- apps/launcher/main.cpp | 2 +- apps/opencs/view/doc/adjusterwidget.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 73bdb95da..df7aa11d4 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -72,4 +72,4 @@ int _stdcall WinMain(struct HINSTANCE__ *hInstance, { return main(__argc, __argv); } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index c97f06672..9e01f685c 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -61,7 +61,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (path.parent_path().string()==mLocalData.string()) { // path already points to the local data directory - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; } @@ -70,7 +70,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) // path points somewhere else or is a leaf name. path = mLocalData / path.filename(); - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; From 296abfd48faec66aa77490f58d6f0e868bb4f17f Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 10:48:34 -0400 Subject: [PATCH 24/81] Bug #840, First Person Sneaking Camera Height Also, added comments to existing code in the area. --- apps/openmw/mwrender/npcanimation.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 13b5971e2..7b5a105c0 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -443,11 +443,31 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); + + // We have to make a few adjustments to the first person animation, since the armature + // is partly driven by code. if(mViewMode == VM_FirstPerson && mCamera) { + // Bend his neck and shoulders so his eyes don't go into his torso. float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); + + // If NPC is sneaking, his head and shoulders must lower to adjust his camera. + const MWWorld::Class *npcClass = &MWWorld::Class::get(mPtr); + const MWBase::World *world = MWBase::Environment::get().getWorld(); + + bool isSneaking = npcClass->getStance(mPtr, MWWorld::Class::Sneak); + bool isInAir = !world->isOnGround(mPtr); + bool isSwimming = world->isSwimming(mPtr); + + if(isSneaking && !(isSwimming || isInAir)) + { + Ogre::Node *headNode = baseinst->getBone("Bip01 Neck"); + Ogre::Vector3 position = headNode->getPosition(); + position.x -= 9.5f; + headNode->setPosition(position); + } } for(size_t i = 0;i < ESM::PRT_Count;i++) From 0ddb5097fc48f5e4f87ac08121fa6c02b3f25c16 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 11:44:45 -0400 Subject: [PATCH 25/81] Revert "Bug #840, First Person Sneaking Camera Height" This reverts commit 296abfd48faec66aa77490f58d6f0e868bb4f17f. --- apps/openmw/mwrender/npcanimation.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 7b5a105c0..13b5971e2 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -443,31 +443,11 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - - // We have to make a few adjustments to the first person animation, since the armature - // is partly driven by code. if(mViewMode == VM_FirstPerson && mCamera) { - // Bend his neck and shoulders so his eyes don't go into his torso. float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); - - // If NPC is sneaking, his head and shoulders must lower to adjust his camera. - const MWWorld::Class *npcClass = &MWWorld::Class::get(mPtr); - const MWBase::World *world = MWBase::Environment::get().getWorld(); - - bool isSneaking = npcClass->getStance(mPtr, MWWorld::Class::Sneak); - bool isInAir = !world->isOnGround(mPtr); - bool isSwimming = world->isSwimming(mPtr); - - if(isSneaking && !(isSwimming || isInAir)) - { - Ogre::Node *headNode = baseinst->getBone("Bip01 Neck"); - Ogre::Vector3 position = headNode->getPosition(); - position.x -= 9.5f; - headNode->setPosition(position); - } } for(size_t i = 0;i < ESM::PRT_Count;i++) From b8c60dabb3cc1d2e6c377d9807d5b1c654d6918b Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Tue, 1 Oct 2013 23:35:34 +0200 Subject: [PATCH 26/81] Reintroduce Acrobatics changes made by Glorf Advance Acrobatics skill on jump and on landing, apply fall damage on landing. --- apps/openmw/mwclass/npc.cpp | 28 ++++++++++++++++ apps/openmw/mwclass/npc.hpp | 3 ++ apps/openmw/mwmechanics/character.cpp | 47 ++++++++++++++++++++++++++- apps/openmw/mwmechanics/character.hpp | 3 ++ apps/openmw/mwworld/class.cpp | 5 +++ apps/openmw/mwworld/class.hpp | 3 ++ 6 files changed, 88 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 073d1b1b9..505c902db 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -769,6 +769,34 @@ namespace MWClass return x; } + float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const + { + const float fallDistanceMin = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDamageDistanceMin")->getFloat(); + + if (fallHeight>=fallDistanceMin) + { + const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); + const CustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); + const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(9/*jump*/)).mMagnitude; + const float fallAcroBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFallAcroBase")->getFloat(); + const float fallAcroMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFallAcroMult")->getFloat(); + const float fallDistanceBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDistanceBase")->getFloat(); + const float fallDistanceMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDistanceMult")->getFloat(); + + float x = fallHeight - fallDistanceMin; + x -= (1.5 * acrobaticsSkill) + jumpSpellBonus; + x = std::max(0.0f, x); + + float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill); + x = fallDistanceBase + fallDistanceMult * x; + x *= a; + + return x; + } + + return 0; + } + MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const { ensureCustomData (ptr); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 3591d7c68..c39ca42ef 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -97,6 +97,9 @@ namespace MWClass virtual float getJump(const MWWorld::Ptr &ptr) const; ///< Return jump velocity (not accounting for movement) + virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const; + ///< Return amount of health points lost when falling + virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; ///< Return desired movement. diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ec2bb1b59..2753b09c2 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -767,10 +767,17 @@ void CharacterController::update(float duration) } if(sneak || inwater || flying) + { vec.z = 0.0f; + mFallHeight = 0.0f; + } if(!onground && !flying && !inwater) { + // The player is in the air (either getting up —ascending part of jump— or falling). + + mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]); + const MWWorld::Store &gmst = world->getStore().get(); forcestateupdate = (mJumpState != JumpState_Falling); @@ -794,6 +801,8 @@ void CharacterController::update(float duration) } else if(vec.z > 0.0f && mJumpState == JumpState_None) { + // The player has started a jump. + float z = cls.getJump(mPtr); if(vec.x == 0 && vec.y == 0) vec = Ogre::Vector3(0.0f, 0.0f, z); @@ -803,13 +812,49 @@ void CharacterController::update(float duration) vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f; } - //decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult; + // advance acrobatics + MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); + + // decrease fatigue + const float fatigueJumpBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFatigueJumpBase")->getFloat(); + const float fatigueJumpMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFatigueJumpMult")->getFloat(); + const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr); + const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; + DynamicStat fatigue = cls.getCreatureStats(mPtr).getDynamic(2); + fatigue.setModified(fatigue.getModified() - fatigueDecrease, 0); + fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); + cls.getCreatureStats(mPtr).setDynamic(2, fatigue); } else if(mJumpState == JumpState_Falling) { + // The player is landing. + forcestateupdate = true; mJumpState = JumpState_Landing; vec.z = 0.0f; + + float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]); + if (healthLost > 0.0f) + { + // inflict fall damages + DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); + int current = health.getCurrent(); + int realHealthLost = healthLost * (1.0f - 0.25 * 1.25f /* * fatigueTerm */); + health.setModified(health.getModified() - realHealthLost, 0); + health.setCurrent(current - realHealthLost); + cls.getCreatureStats(mPtr).setHealth(health); + + // report acrobatics progression + cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); + + const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified(); + if (healthLost > (acrobaticsSkill * 1.25f /* * fatigueTerm */)) + { + //TODO: actor falls over + } + } + + mFallHeight = 0; } else { diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index c943b9597..7b9dda49a 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -154,6 +154,9 @@ class CharacterController float mSecondsOfSwimming; float mSecondsOfRunning; + // used for acrobatics progress and fall damages + float mFallHeight; + std::string mAttackType; // slash, chop or thrust void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c739ea831..de5093547 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -167,6 +167,11 @@ namespace MWWorld throw std::runtime_error ("class does not support enchanting"); } + float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const + { + return 0; + } + MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const { throw std::runtime_error ("movement settings not supported by class"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 28e37cbf3..1db09647e 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -175,6 +175,9 @@ namespace MWWorld virtual float getJump(const MWWorld::Ptr &ptr) const; ///< Return jump velocity (not accounting for movement) + virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const; + ///< Return amount of health points lost when falling + virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const; ///< Return desired movement. From ed0c31b4854cc19d474402127d434ea379c374c1 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 2 Oct 2013 05:16:52 -0400 Subject: [PATCH 27/81] Refactored, moved logic out of NpcAnimation The logic is now handled by RenderingManager, and Camera sets its animation's first person offset height. Due to how NpcAnimation seems to be updated, it has to be the one to actually set its own nodes, in the case of the hands. Otherwise, the hands would not move without a messier hack. --- apps/openmw/mwrender/camera.cpp | 6 ++++++ apps/openmw/mwrender/camera.hpp | 6 ++++++ apps/openmw/mwrender/npcanimation.cpp | 13 ++++++++++++- apps/openmw/mwrender/npcanimation.hpp | 7 +++++++ apps/openmw/mwrender/renderingmanager.cpp | 9 +++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 36f53c0fe..232b95c69 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -187,6 +187,12 @@ namespace MWRender rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); } + void Camera::setSneakOffset() + { + if(mAnimation) + mAnimation->addFirstPersonOffset(Ogre::Vector3(-9.8f, 0.f, 0.f)); + } + float Camera::getYaw() { if(mVanity.enabled || mPreviewMode) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index dc552371e..baf2f3685 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -79,6 +79,12 @@ namespace MWRender void togglePreviewMode(bool enable); + /// \brief Lowers the camera for sneak. + /// As animation is tied to the camera, this needs + /// to be set each frame after the animation is + /// applied. + void setSneakOffset(); + bool isFirstPerson() const { return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 13b5971e2..84e89773c 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -84,7 +84,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mWeapon(inv.end()), mShield(inv.end()), mViewMode(viewMode), - mShowWeapons(false) + mShowWeapons(false), + mFirstPersonOffset(0.f, 0.f, 0.f) { mNpc = mPtr.get()->mBase; @@ -392,6 +393,11 @@ void NpcAnimation::updateParts(bool forceupdate) } } +void NpcAnimation::addFirstPersonOffset(const Ogre::Vector3 &offset) +{ + mFirstPersonOffset += offset; +} + class SetObjectGroup { int mGroup; @@ -448,7 +454,12 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); + + // This has to be done before this function ends; + // updateSkeletonInstance, below, touches the hands. + node->translate(mFirstPersonOffset); } + mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. for(size_t i = 0;i < ESM::PRT_Count;i++) { diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 24205acaf..b1abf97af 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -64,6 +64,8 @@ private: int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty int mPartPriorities[ESM::PRT_Count]; + Ogre::Vector3 mFirstPersonOffset; + void updateNpcBase(); NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); @@ -89,6 +91,11 @@ public: void updateParts(bool forceupdate = false); + /// \brief Applies a translation to the arms and hands. + /// This may be called multiple times before the animation + /// is updated to add additional offsets. + void addFirstPersonOffset(const Ogre::Vector3 &offset); + /// Rebuilds the NPC, updating their root model, animation sources, and equipment. void rebuild(); }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e03b2ccfc..261fd45c8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -354,6 +354,15 @@ void RenderingManager::update (float duration, bool paused) mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } + // Sink the camera while sneaking + bool isSneaking = MWWorld::Class::get(player).getStance(player, MWWorld::Class::Sneak); + bool isInAir = !world->isOnGround(player); + bool isSwimming = world->isSwimming(player); + + if(isSneaking && !(isSwimming || isInAir)) + mCamera->setSneakOffset(); + + mOcclusionQuery->update(duration); mVideoPlayer->update (); From f1b4c2e400743dfb207f8b9bbad19e50af6b95ed Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 2 Oct 2013 07:03:39 -0400 Subject: [PATCH 28/81] Fixed first person offset to use world transform It slipped my mind that some necks might not be perfectly vertical. --- apps/openmw/mwrender/camera.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 232b95c69..9af3987a8 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -190,7 +190,7 @@ namespace MWRender void Camera::setSneakOffset() { if(mAnimation) - mAnimation->addFirstPersonOffset(Ogre::Vector3(-9.8f, 0.f, 0.f)); + mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -9.8f)); } float Camera::getYaw() diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 84e89773c..9ffe53eab 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -457,7 +457,7 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) // This has to be done before this function ends; // updateSkeletonInstance, below, touches the hands. - node->translate(mFirstPersonOffset); + node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); } mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. From 496f786c2a6e5c202027429b5cc14af0f089c2a0 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 15:12:41 +0200 Subject: [PATCH 29/81] Implement Disable/EnableLevitation script functions Totally copied on Disable/EnableTeleporting implementation. Thanks KittyCat! --- apps/openmw/mwbase/world.hpp | 6 ++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +++- apps/openmw/mwscript/miscextensions.cpp | 15 ++++++++++++++- apps/openmw/mwworld/worldimp.cpp | 10 ++++++++++ apps/openmw/mwworld/worldimp.hpp | 7 +++++++ components/compiler/extensions0.cpp | 2 ++ components/compiler/opcodes.hpp | 2 ++ 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index f8453afed..d7b013a84 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -389,6 +389,12 @@ namespace MWBase /// Returns true if teleport spell effects are allowed. virtual bool isTeleportingEnabled() const = 0; + /// Enables or disables use of levitation spell effect. + virtual void enableLevitation(bool enable) = 0; + + /// Returns true if levitation spell effect is allowed. + virtual bool isLevitationEnabled() const = 0; + /// Turn actor into werewolf or normal form. virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index ff3b60ca6..7bbb33699 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -352,5 +352,7 @@ op 0x200021c: SetWerewolfAcrobaticsExplicit op 0x200021d: ShowVars op 0x200021e: ShowVarsExplicit op 0x200021f: ToggleGodMode +op 0x2000220: DisableLevitation +op 0x2000221: EnableLevitation -opcodes 0x2000220-0x3ffffff unused +opcodes 0x2000222-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index a8d8a5f2b..4ae1136e2 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -635,7 +635,18 @@ namespace MWScript world->enableTeleporting(Enable); } }; - + + template + class OpEnableLevitation : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + world->enableLevitation(Enable); + } + }; template class OpShowVars : public Interpreter::Opcode0 @@ -789,6 +800,8 @@ namespace MWScript interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars); interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars); interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode); + interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation); + interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation); } } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f3d4c81b7..1ba209663 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1877,6 +1877,16 @@ namespace MWWorld return mTeleportEnabled; } + void World::enableLevitation(bool enable) + { + mLevitationEnabled = enable; + } + + bool World::isLevitationEnabled() const + { + return mLevitationEnabled; + } + void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf) { MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 53b01f1ab..8f80d90d6 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -116,6 +116,7 @@ namespace MWWorld int mPlayIntro; bool mTeleportEnabled; + bool mLevitationEnabled; public: @@ -438,6 +439,12 @@ namespace MWWorld /// Returns true if teleport spell effects are allowed. virtual bool isTeleportingEnabled() const; + /// Enables or disables use of levitation spell effect. + virtual void enableLevitation(bool enable); + + /// Returns true if levitation spell effect is allowed. + virtual bool isLevitationEnabled() const; + virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf); virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 415f8d168..65f6e112a 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -260,6 +260,8 @@ namespace Compiler extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit); extensions.registerInstruction("tgm", "", opcodeToggleGodMode); extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode); + extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation); + extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 5eb54208a..aca24e0d3 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -222,6 +222,8 @@ namespace Compiler const int opcodeShowVars = 0x200021d; const int opcodeShowVarsExplicit = 0x200021e; const int opcodeToggleGodMode = 0x200021f; + const int opcodeDisableLevitation = 0x2000220; + const int opcodeEnableLevitation = 0x2000221; } namespace Sky From 073f64c8bb4abf7cc8653f3fa0b70a6d69f241e7 Mon Sep 17 00:00:00 2001 From: mckibbenta Date: Wed, 2 Oct 2013 13:46:33 -0400 Subject: [PATCH 30/81] stop weapon condition degredation (for the player) with tgm on --- apps/openmw/mwclass/npc.cpp | 7 ++++--- apps/openmw/mwmechanics/actors.cpp | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 073d1b1b9..3d8bdf16f 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -396,9 +396,10 @@ namespace MWClass MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}"); MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f); } - weapon.getCellRef().mCharge -= std::min(std::max(1, - (int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), - weapon.getCellRef().mCharge); + + if (!MWBase::Environment::get().getWorld()->getGodModeState()) + weapon.getCellRef().mCharge -= std::min(std::max(1, + (int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge); } healthdmg = true; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ca26e88ce..f9b5b695a 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -276,7 +276,8 @@ namespace MWMechanics } // If it's the player and God Mode is turned on, keep it alive - if(iter->first.getRefData().getHandle()=="player" && MWBase::Environment::get().getWorld()->getGodModeState()) + if(iter->first.getRefData().getHandle()=="player" && + MWBase::Environment::get().getWorld()->getGodModeState()) { MWMechanics::DynamicStat stat(stats.getHealth()); From 486051486599e80bc0731252a7191095226b1eaf Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 12:58:34 +0200 Subject: [PATCH 31/81] Acrobatics: cosmetic changes --- apps/openmw/mwclass/npc.cpp | 18 +++++++++++------- apps/openmw/mwmechanics/character.cpp | 14 +++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 505c902db..0110bef88 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -7,6 +7,7 @@ #include +#include #include #include "../mwbase/environment.hpp" @@ -771,17 +772,20 @@ namespace MWClass float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const { - const float fallDistanceMin = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDamageDistanceMin")->getFloat(); + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Store &gmst = world->getStore().get(); + + const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat(); - if (fallHeight>=fallDistanceMin) + if (fallHeight >= fallDistanceMin) { const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); const CustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); - const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(9/*jump*/)).mMagnitude; - const float fallAcroBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFallAcroBase")->getFloat(); - const float fallAcroMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFallAcroMult")->getFloat(); - const float fallDistanceBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDistanceBase")->getFloat(); - const float fallDistanceMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFallDistanceMult")->getFloat(); + const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude; + const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat(); + const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat(); + const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat(); + const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat(); float x = fallHeight - fallDistanceMin; x -= (1.5 * acrobaticsSkill) + jumpSpellBonus; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2753b09c2..efd3b94cc 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -813,17 +813,18 @@ void CharacterController::update(float duration) } // advance acrobatics - MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); + cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); // decrease fatigue - const float fatigueJumpBase = MWBase::Environment::get().getWorld()->getStore().get().find("fFatigueJumpBase")->getFloat(); - const float fatigueJumpMult = MWBase::Environment::get().getWorld()->getStore().get().find("fFatigueJumpMult")->getFloat(); + const MWWorld::Store &gmst = world->getStore().get(); + const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat(); + const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat(); const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr); const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; - DynamicStat fatigue = cls.getCreatureStats(mPtr).getDynamic(2); + DynamicStat fatigue = cls.getCreatureStats(mPtr).getFatigue(); fatigue.setModified(fatigue.getModified() - fatigueDecrease, 0); fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); - cls.getCreatureStats(mPtr).setDynamic(2, fatigue); + cls.getCreatureStats(mPtr).setFatigue(fatigue); } else if(mJumpState == JumpState_Falling) { @@ -838,10 +839,9 @@ void CharacterController::update(float duration) { // inflict fall damages DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); - int current = health.getCurrent(); int realHealthLost = healthLost * (1.0f - 0.25 * 1.25f /* * fatigueTerm */); health.setModified(health.getModified() - realHealthLost, 0); - health.setCurrent(current - realHealthLost); + health.setCurrent(health.getCurrent() - realHealthLost); cls.getCreatureStats(mPtr).setHealth(health); // report acrobatics progression From 4c151e59a26caed2d77d1f74e446472b3e78863c Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 13:00:47 +0200 Subject: [PATCH 32/81] Acrobatics: do not touch modified stats --- apps/openmw/mwmechanics/character.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index efd3b94cc..14eed2641 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -822,7 +822,6 @@ void CharacterController::update(float duration) const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr); const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; DynamicStat fatigue = cls.getCreatureStats(mPtr).getFatigue(); - fatigue.setModified(fatigue.getModified() - fatigueDecrease, 0); fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); cls.getCreatureStats(mPtr).setFatigue(fatigue); } @@ -840,7 +839,6 @@ void CharacterController::update(float duration) // inflict fall damages DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); int realHealthLost = healthLost * (1.0f - 0.25 * 1.25f /* * fatigueTerm */); - health.setModified(health.getModified() - realHealthLost, 0); health.setCurrent(health.getCurrent() - realHealthLost); cls.getCreatureStats(mPtr).setHealth(health); From 2b992ef3b5e8dd27c5b4edee3e98323be230079e Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 13:02:14 +0200 Subject: [PATCH 33/81] Acrobatics: use calculated fatigueTerm --- apps/openmw/mwmechanics/character.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 14eed2641..5b4d316e5 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -836,9 +836,11 @@ void CharacterController::update(float duration) float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]); if (healthLost > 0.0f) { + const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm(); + // inflict fall damages DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); - int realHealthLost = healthLost * (1.0f - 0.25 * 1.25f /* * fatigueTerm */); + int realHealthLost = healthLost * (1.0f - 0.25 * fatigueTerm); health.setCurrent(health.getCurrent() - realHealthLost); cls.getCreatureStats(mPtr).setHealth(health); @@ -846,7 +848,7 @@ void CharacterController::update(float duration) cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified(); - if (healthLost > (acrobaticsSkill * 1.25f /* * fatigueTerm */)) + if (healthLost > (acrobaticsSkill * fatigueTerm)) { //TODO: actor falls over } From 6e09a5fb4af2ac97330020f92172c5a712b84356 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 22:36:28 +0200 Subject: [PATCH 34/81] Acrobatics: reinit fall height at current height rather than zero To prevent problems. --- apps/openmw/mwmechanics/character.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 5b4d316e5..0924e36b9 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -769,7 +769,7 @@ void CharacterController::update(float duration) if(sneak || inwater || flying) { vec.z = 0.0f; - mFallHeight = 0.0f; + mFallHeight = mPtr.getRefData().getPosition().pos[2]; } if(!onground && !flying && !inwater) @@ -854,7 +854,7 @@ void CharacterController::update(float duration) } } - mFallHeight = 0; + mFallHeight = mPtr.getRefData().getPosition().pos[2]; } else { From 4265dddc40923d1fbcdbb848a0e06a5df4e66308 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 22:53:29 +0200 Subject: [PATCH 35/81] Add MWWorld::isSlowFalling(Ptr) --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwworld/worldimp.cpp | 13 +++++++++++++ apps/openmw/mwworld/worldimp.hpp | 1 + 3 files changed, 15 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index f8453afed..db03cb7bf 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -324,6 +324,7 @@ namespace MWBase virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0; virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0; + virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0; virtual bool isSwimming(const MWWorld::Ptr &object) const = 0; ///Is the head of the creature underwater? virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f3d4c81b7..34ac01102 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1582,6 +1582,19 @@ namespace MWWorld return false; } + bool + World::isSlowFalling(const MWWorld::Ptr &ptr) const + { + if(!ptr.getClass().isActor()) + return false; + + const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); + if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0) + return true; + + return false; + } + bool World::isSubmerged(const MWWorld::Ptr &object) const { float *fpos = object.getRefData().getPosition().pos; diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 53b01f1ab..333beb831 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -355,6 +355,7 @@ namespace MWWorld virtual void processChangedSettings(const Settings::CategorySettingVector& settings); virtual bool isFlying(const MWWorld::Ptr &ptr) const; + virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const; ///Is the head of the creature underwater? virtual bool isSubmerged(const MWWorld::Ptr &object) const; virtual bool isSwimming(const MWWorld::Ptr &object) const; From 2abe5c1c9a304bae549d4591f0c11ccd84286c9b Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Oct 2013 22:54:36 +0200 Subject: [PATCH 36/81] Acrobatics: do not apply fall damages when slowfalling spell effect is active If spell effect ends up in mid-air, calculate fall height from then. --- apps/openmw/mwmechanics/character.cpp | 10 +++++++++- apps/openmw/mwmechanics/character.hpp | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 0924e36b9..c4260d907 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -776,7 +776,15 @@ void CharacterController::update(float duration) { // The player is in the air (either getting up —ascending part of jump— or falling). - mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]); + if (world->isSlowFalling(mPtr)) + { + // SlowFalling spell effect is active, do not keep previous fall height + mFallHeight = mPtr.getRefData().getPosition().pos[2]; + } + else + { + mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]); + } const MWWorld::Store &gmst = world->getStore().get(); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 7b9dda49a..8670b385e 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -3,6 +3,8 @@ #include +#include + #include "../mwworld/ptr.hpp" namespace MWWorld From 75991fedfdc17eacaf0e08c5032ecee550434d16 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 4 Oct 2013 12:33:55 +0200 Subject: [PATCH 37/81] removed some garbage --- issue912 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 issue912 diff --git a/issue912 b/issue912 deleted file mode 100644 index 604cc392c..000000000 --- a/issue912 +++ /dev/null @@ -1 +0,0 @@ -branch for issue912 From 6983a55a16db58c882c654766006ac98a83bc7b3 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sun, 6 Oct 2013 19:32:40 -0500 Subject: [PATCH 38/81] Magic effect display improvement. Related to Bug #794. Show the "x INT" notation for Fortify Max. Magicka. Show "%" notation for weakness / resistance effects. --- apps/openmw/mwgui/spellicons.cpp | 25 ++++++++++++++++++++----- apps/openmw/mwgui/widgets.cpp | 29 ++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 9812c0f8a..e7a1f32a4 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -171,11 +171,26 @@ namespace MWGui if (!(effect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { - std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); - std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); - - sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); - sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); + if (it->first == 84) // special handling for fortify maximum magicka + { + std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); + sourcesDescription += " " + boost::lexical_cast(effectIt->mMagnitude / 10.0f) + timesInt; + } + else + { + std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); + std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); + std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); + const bool usePct = ( + (it->first >= 28 && it->first <= 36) || // Weakness effects + (it->first >= 90 && it->first <= 99) ); // Resistance effects + + sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude) + " "; + if ( usePct ) + sourcesDescription += pct; + else + sourcesDescription += ((effectIt->mMagnitude > 1) ? pts : pt); + } } } diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index dea64ae8c..d435dd6f9 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -405,6 +405,7 @@ namespace MWGui std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); + std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " "; std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", ""); std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", ""); @@ -423,11 +424,33 @@ namespace MWGui if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { - if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts); + // Fortify Maximum Magicka display rules: + if ( mEffectParams.mEffectID == 84 ) + { + std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); + std::string times = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimes", ""); + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin / 10.0f) + timesInt; + else + { + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin / 10.0f) + times + " " + to + boost::lexical_cast(mEffectParams.mMagnMax / 10.0f) + timesInt; + } + } else { - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax) + " " + pts; + const bool usePct = ( + (mEffectParams.mEffectID >= 28 && mEffectParams.mEffectID <= 36) || // Weakness effects + (mEffectParams.mEffectID >= 90 && mEffectParams.mEffectID <= 99) ); // Resistance effects + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + " "; + else + { + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax) + " "; + } + if ( usePct ) + spellLine += pct; + else + spellLine += ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); } } From 707f45aa8e758ef34da14cffc83dbf6c992f4008 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sun, 6 Oct 2013 19:46:04 -0500 Subject: [PATCH 39/81] Magic Effect Display improvement. Related to Bug #794. Always show one decimal point precision for Fortify Max. Magicka effect. --- apps/openmw/mwgui/spellicons.cpp | 7 ++++++- apps/openmw/mwgui/widgets.cpp | 17 +++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index e7a1f32a4..93727ed7f 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -2,6 +2,9 @@ #include +#include +#include + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -174,7 +177,9 @@ namespace MWGui if (it->first == 84) // special handling for fortify maximum magicka { std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); - sourcesDescription += " " + boost::lexical_cast(effectIt->mMagnitude / 10.0f) + timesInt; + std::stringstream formatter; + formatter << std::fixed << std::setprecision(1) << " " << (effectIt->mMagnitude / 10.0f) << timesInt; + sourcesDescription += formatter.str(); } else { diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index d435dd6f9..e46838a64 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -2,6 +2,9 @@ #include +#include +#include + #include #include #include @@ -429,12 +432,14 @@ namespace MWGui { std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); std::string times = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimes", ""); - if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin / 10.0f) + timesInt; - else - { - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin / 10.0f) + times + " " + to + boost::lexical_cast(mEffectParams.mMagnMax / 10.0f) + timesInt; - } + std::stringstream formatter; + + formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f); + if (mEffectParams.mMagnMin != mEffectParams.mMagnMax) + formatter << times << " " << to << " " << (mEffectParams.mMagnMax / 10.0f); + formatter << timesInt; + + spellLine += formatter.str(); } else { From 6303e56ce4521fda92bc25dc6bc32b8ad4bdfcbb Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sun, 6 Oct 2013 20:35:59 -0500 Subject: [PATCH 40/81] Magic Effect Display cleanup: Don't put spaces in percentages. --- apps/openmw/mwgui/spellicons.cpp | 4 ++-- apps/openmw/mwgui/widgets.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 93727ed7f..3b3057248 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -190,11 +190,11 @@ namespace MWGui (it->first >= 28 && it->first <= 36) || // Weakness effects (it->first >= 90 && it->first <= 99) ); // Resistance effects - sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude) + " "; + sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); if ( usePct ) sourcesDescription += pct; else - sourcesDescription += ((effectIt->mMagnitude > 1) ? pts : pt); + sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); } } } diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index e46838a64..e942aa703 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -447,15 +447,15 @@ namespace MWGui (mEffectParams.mEffectID >= 28 && mEffectParams.mEffectID <= 36) || // Weakness effects (mEffectParams.mEffectID >= 90 && mEffectParams.mEffectID <= 99) ); // Resistance effects if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + " "; + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin); else { - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax) + " "; + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax); } if ( usePct ) spellLine += pct; else - spellLine += ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); + spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); } } From 4d6c3cdf09faf49cd36f9d0607c657f17c8e10b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 Oct 2013 08:55:04 +0200 Subject: [PATCH 41/81] removed more garbage --- apps/opencs/ocspropertywidget.cpp | 6 ------ apps/opencs/ocspropertywidget.hpp | 18 ------------------ 2 files changed, 24 deletions(-) delete mode 100644 apps/opencs/ocspropertywidget.cpp delete mode 100644 apps/opencs/ocspropertywidget.hpp diff --git a/apps/opencs/ocspropertywidget.cpp b/apps/opencs/ocspropertywidget.cpp deleted file mode 100644 index 68315201a..000000000 --- a/apps/opencs/ocspropertywidget.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "ocspropertywidget.hpp" - -OcsPropertyWidget::OcsPropertyWidget(QObject *parent) : - QObject(parent) -{ -} diff --git a/apps/opencs/ocspropertywidget.hpp b/apps/opencs/ocspropertywidget.hpp deleted file mode 100644 index fc64a0a69..000000000 --- a/apps/opencs/ocspropertywidget.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef OCSPROPERTYWIDGET_HPP -#define OCSPROPERTYWIDGET_HPP - -#include - -class OcsPropertyWidget : public QObject -{ - Q_OBJECT -public: - explicit OcsPropertyWidget(QObject *parent = 0); - -signals: - -public slots: - -}; - -#endif // OCSPROPERTYWIDGET_HPP From 74cee662731d0004adbfdaa657eed3bdc8c45986 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 7 Oct 2013 11:14:11 +0200 Subject: [PATCH 42/81] consolidated magic numbers for button size --- apps/opencs/view/world/scenesubview.cpp | 10 +++++----- apps/opencs/view/world/scenetool.cpp | 6 ++++-- apps/opencs/view/world/scenetool.hpp | 4 +++- apps/opencs/view/world/scenetoolbar.cpp | 10 ++++++++-- apps/opencs/view/world/scenetoolbar.hpp | 5 ++++- apps/opencs/view/world/scenetoolmode.cpp | 8 +++++--- apps/opencs/view/world/scenetoolmode.hpp | 5 ++++- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 36ace68f0..e3618c549 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -29,16 +29,16 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout2->setContentsMargins (QMargins (0, 0, 0, 0)); - SceneToolbar *toolbar = new SceneToolbar (this); + SceneToolbar *toolbar = new SceneToolbar (48, this); // test -SceneToolMode *tool = new SceneToolMode (this); +SceneToolMode *tool = new SceneToolMode (toolbar); tool->addButton (":door.png", "a"); tool->addButton (":GMST.png", "b"); tool->addButton (":Info.png", "c"); toolbar->addTool (tool); -toolbar->addTool (new SceneToolMode (this)); -toolbar->addTool (new SceneToolMode (this)); -toolbar->addTool (new SceneToolMode (this)); +toolbar->addTool (new SceneToolMode (toolbar)); +toolbar->addTool (new SceneToolMode (toolbar)); +toolbar->addTool (new SceneToolMode (toolbar)); layout2->addWidget (toolbar, 0); /// \todo replace with rendering widget diff --git a/apps/opencs/view/world/scenetool.cpp b/apps/opencs/view/world/scenetool.cpp index d7d37c98f..2140cd1e0 100644 --- a/apps/opencs/view/world/scenetool.cpp +++ b/apps/opencs/view/world/scenetool.cpp @@ -1,10 +1,12 @@ #include "scenetool.hpp" -CSVWorld::SceneTool::SceneTool (QWidget *parent) : QPushButton (parent) +#include "scenetoolbar.hpp" + +CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent) { setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); - setFixedSize (48, 48); + setFixedSize (parent->getButtonSize(), parent->getButtonSize()); connect (this, SIGNAL (clicked()), this, SLOT (openRequest())); } diff --git a/apps/opencs/view/world/scenetool.hpp b/apps/opencs/view/world/scenetool.hpp index d5c9dd5d2..2e83b0c6d 100644 --- a/apps/opencs/view/world/scenetool.hpp +++ b/apps/opencs/view/world/scenetool.hpp @@ -5,6 +5,8 @@ namespace CSVWorld { + class SceneToolbar; + ///< \brief Tool base class class SceneTool : public QPushButton { @@ -12,7 +14,7 @@ namespace CSVWorld public: - SceneTool (QWidget *parent = 0); + SceneTool (SceneToolbar *parent); virtual void showPanel (const QPoint& position) = 0; diff --git a/apps/opencs/view/world/scenetoolbar.cpp b/apps/opencs/view/world/scenetoolbar.cpp index 7c716b5fc..2972c5391 100644 --- a/apps/opencs/view/world/scenetoolbar.cpp +++ b/apps/opencs/view/world/scenetoolbar.cpp @@ -5,9 +5,10 @@ #include "scenetool.hpp" -CSVWorld::SceneToolbar::SceneToolbar (QWidget *parent) : QWidget (parent) +CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent) +: QWidget (parent), mButtonSize (buttonSize) { - setFixedWidth (48); + setFixedWidth (mButtonSize); mLayout = new QVBoxLayout (this); mLayout->setAlignment (Qt::AlignTop); @@ -20,4 +21,9 @@ CSVWorld::SceneToolbar::SceneToolbar (QWidget *parent) : QWidget (parent) void CSVWorld::SceneToolbar::addTool (SceneTool *tool) { mLayout->addWidget (tool, 0, Qt::AlignTop); +} + +int CSVWorld::SceneToolbar::getButtonSize() const +{ + return mButtonSize; } \ No newline at end of file diff --git a/apps/opencs/view/world/scenetoolbar.hpp b/apps/opencs/view/world/scenetoolbar.hpp index 00631c360..f713ca3df 100644 --- a/apps/opencs/view/world/scenetoolbar.hpp +++ b/apps/opencs/view/world/scenetoolbar.hpp @@ -14,12 +14,15 @@ namespace CSVWorld Q_OBJECT QVBoxLayout *mLayout; + int mButtonSize; public: - SceneToolbar (QWidget *parent); + SceneToolbar (int buttonSize, QWidget *parent = 0); void addTool (SceneTool *tool); + + int getButtonSize() const; }; } diff --git a/apps/opencs/view/world/scenetoolmode.cpp b/apps/opencs/view/world/scenetoolmode.cpp index b4277bcbe..2435a8e35 100644 --- a/apps/opencs/view/world/scenetoolmode.cpp +++ b/apps/opencs/view/world/scenetoolmode.cpp @@ -5,8 +5,10 @@ #include #include -CSVWorld::SceneToolMode::SceneToolMode (QWidget *parent) -: SceneTool (parent) +#include "scenetoolbar.hpp" + +CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent) +: SceneTool (parent), mButtonSize (parent->getButtonSize()) { mPanel = new QFrame (this, Qt::Popup); @@ -27,7 +29,7 @@ void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::str { QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel); button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); - button->setFixedSize (48, 48); + button->setFixedSize (mButtonSize, mButtonSize); mLayout->addWidget (button); diff --git a/apps/opencs/view/world/scenetoolmode.hpp b/apps/opencs/view/world/scenetoolmode.hpp index feee78376..a8fe2b5a6 100644 --- a/apps/opencs/view/world/scenetoolmode.hpp +++ b/apps/opencs/view/world/scenetoolmode.hpp @@ -9,6 +9,8 @@ class QHBoxLayout; namespace CSVWorld { + class SceneToolbar; + ///< \brief Mode selector tool class SceneToolMode : public SceneTool { @@ -17,10 +19,11 @@ namespace CSVWorld QWidget *mPanel; QHBoxLayout *mLayout; std::map mButtons; // widget, id + int mButtonSize; public: - SceneToolMode (QWidget *parent = 0); + SceneToolMode (SceneToolbar *parent); virtual void showPanel (const QPoint& position); From 065f435225c66bb9b51dd4eb0660d8f081b1b6a4 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Mon, 7 Oct 2013 20:02:20 -0500 Subject: [PATCH 43/81] Format fix: remove extra spaces from ranged TimesINT formatting. --- apps/openmw/mwgui/widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index e942aa703..9278c1a56 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -436,7 +436,7 @@ namespace MWGui formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f); if (mEffectParams.mMagnMin != mEffectParams.mMagnMax) - formatter << times << " " << to << " " << (mEffectParams.mMagnMax / 10.0f); + formatter << times << to << (mEffectParams.mMagnMax / 10.0f); formatter << timesInt; spellLine += formatter.str(); From 6ab7002908b66098afc260d6ef3a8f235f58ce17 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Mon, 7 Oct 2013 22:28:55 -0500 Subject: [PATCH 44/81] MagicEffect: Put magnitude type into ESM::MagicEffect helper. --- apps/openmw/mwgui/spellicons.cpp | 41 ++++++++++++++------------------ apps/openmw/mwgui/widgets.cpp | 28 ++++++++-------------- components/esm/loadmgef.cpp | 11 +++++++++ components/esm/loadmgef.hpp | 8 +++++++ 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 3b3057248..0e59230c7 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -172,30 +172,25 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->getGameSettingString( ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")"; - if (!(effect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) + int displayType = effect->getMagnitudeDisplayType(); + if (displayType == ESM::MagicEffect::MDT_TimesInt) { - if (it->first == 84) // special handling for fortify maximum magicka - { - std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); - std::stringstream formatter; - formatter << std::fixed << std::setprecision(1) << " " << (effectIt->mMagnitude / 10.0f) << timesInt; - sourcesDescription += formatter.str(); - } - else - { - std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); - std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); - std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); - const bool usePct = ( - (it->first >= 28 && it->first <= 36) || // Weakness effects - (it->first >= 90 && it->first <= 99) ); // Resistance effects - - sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); - if ( usePct ) - sourcesDescription += pct; - else - sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); - } + std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); + std::stringstream formatter; + formatter << std::fixed << std::setprecision(1) << " " << (effectIt->mMagnitude / 10.0f) << timesInt; + sourcesDescription += formatter.str(); + } + else if ( displayType != ESM::MagicEffect::MDT_None ) + { + std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); + std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); + std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); + + sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); + if ( displayType == ESM::MagicEffect::MDT_Percentage ) + sourcesDescription += pct; + else // ESM::MagicEffect::MDT_Points + sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); } } diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 9278c1a56..f3eda4b22 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -425,11 +425,9 @@ namespace MWGui spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); } - if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) - { - // Fortify Maximum Magicka display rules: - if ( mEffectParams.mEffectID == 84 ) - { + if (mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) { + int displayType = magicEffect->getMagnitudeDisplayType(); + if ( displayType == ESM::MagicEffect::MDT_TimesInt ) { std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); std::string times = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimes", ""); std::stringstream formatter; @@ -441,20 +439,14 @@ namespace MWGui spellLine += formatter.str(); } - else - { - const bool usePct = ( - (mEffectParams.mEffectID >= 28 && mEffectParams.mEffectID <= 36) || // Weakness effects - (mEffectParams.mEffectID >= 90 && mEffectParams.mEffectID <= 99) ); // Resistance effects - if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin); - else - { - spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax); - } - if ( usePct ) + else if ( displayType != ESM::MagicEffect::MDT_None ) { + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin); + if (mEffectParams.mMagnMin != mEffectParams.mMagnMax) + spellLine += to + boost::lexical_cast(mEffectParams.mMagnMax); + + if ( displayType == ESM::MagicEffect::MDT_Percentage ) spellLine += pct; - else + else // ESM::MagicEffect::MDT_Points spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); } } diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 060645b5f..0dfc2be9c 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -274,5 +274,16 @@ short MagicEffect::effectStringToId(const std::string &effect) return name->first; } +MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const { + if ( mData.mFlags & NoMagnitude ) + return MDT_None; + if ( mIndex == 84 ) + return MDT_TimesInt; + if ( ( mIndex >= 28 && mIndex <= 36 ) + || ( mIndex >= 90 && mIndex <= 99 ) ) + return MDT_Percentage; + + return MDT_Points; +} } diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index b74efb466..c3af56e3a 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -32,6 +32,13 @@ struct MagicEffect Negative = 0x0800 // A harmful effect. Will determine whether // eg. NPCs regard this spell as an attack. (same as 0x10?) }; + enum MagnitudeDisplayType + { + MDT_None, + MDT_Points, + MDT_Percentage, + MDT_TimesInt + }; struct MEDTstruct { @@ -47,6 +54,7 @@ struct MagicEffect static const std::string &effectIdToString(short effectID); static short effectStringToId(const std::string &effect); + MagnitudeDisplayType getMagnitudeDisplayType() const; MEDTstruct mData; From 296b2ab87025c0d26d5010dd38a8b3cb01e2ecda Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Tue, 8 Oct 2013 23:55:14 -0500 Subject: [PATCH 45/81] Magic Effect: Recognize other display types. Fill out the list of effects which use percentage formatting. Add in types which use Feet and level labels. --- components/esm/loadmgef.cpp | 9 ++++++++- components/esm/loadmgef.hpp | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 0dfc2be9c..19d535600 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -279,8 +279,15 @@ MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const { return MDT_None; if ( mIndex == 84 ) return MDT_TimesInt; + if ( mIndex == 59 || + ( mIndex >= 64 && mIndex <= 66) ) + return MDT_Feet; + if ( mIndex == 118 || mIndex == 119 ) + return MDT_Level; if ( ( mIndex >= 28 && mIndex <= 36 ) - || ( mIndex >= 90 && mIndex <= 99 ) ) + || ( mIndex >= 90 && mIndex <= 99 ) + || mIndex == 40 || mIndex == 47 + || mIndex == 57 || mIndex == 68 ) return MDT_Percentage; return MDT_Points; diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index c3af56e3a..f139fa32c 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -35,8 +35,10 @@ struct MagicEffect enum MagnitudeDisplayType { MDT_None, - MDT_Points, + MDT_Feet, + MDT_Level, MDT_Percentage, + MDT_Points, MDT_TimesInt }; From 6e4978643c7e209e0b2a82af0fdf04aa44c50bf4 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Wed, 9 Oct 2013 00:08:11 -0500 Subject: [PATCH 46/81] Magic Effect descriptions: support feet / level modes. Show proper suffixes for all magnitudes. Drop extra 'times' symbol in 'timesInt format (not consistent with other magnitude displays). --- apps/openmw/mwgui/spellicons.cpp | 23 ++++++++++++++++------- apps/openmw/mwgui/widgets.cpp | 12 +++++++++--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 0e59230c7..0c303485a 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -172,7 +172,7 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->getGameSettingString( ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")"; - int displayType = effect->getMagnitudeDisplayType(); + ESM::MagicEffect::MagnitudeDisplayType displayType = effect->getMagnitudeDisplayType(); if (displayType == ESM::MagicEffect::MDT_TimesInt) { std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); @@ -182,15 +182,24 @@ namespace MWGui } else if ( displayType != ESM::MagicEffect::MDT_None ) { - std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); - std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); - std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); - sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); + if ( displayType == ESM::MagicEffect::MDT_Percentage ) - sourcesDescription += pct; + sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); + else if ( displayType == ESM::MagicEffect::MDT_Feet ) + sourcesDescription += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", ""); + else if ( displayType == ESM::MagicEffect::MDT_Level ) + { + sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? + MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "") : + MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "") ); + } else // ESM::MagicEffect::MDT_Points - sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); + { + sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? + MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "") : + MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "") ); + } } } diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index f3eda4b22..3fc3187e8 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -409,6 +409,9 @@ namespace MWGui std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", ""); + std::string ft = MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", ""); + std::string lvl = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", ""); + std::string lvls = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", ""); std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " "; std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", ""); std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", ""); @@ -426,15 +429,14 @@ namespace MWGui } if (mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) { - int displayType = magicEffect->getMagnitudeDisplayType(); + ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType(); if ( displayType == ESM::MagicEffect::MDT_TimesInt ) { std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); - std::string times = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimes", ""); std::stringstream formatter; formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f); if (mEffectParams.mMagnMin != mEffectParams.mMagnMax) - formatter << times << to << (mEffectParams.mMagnMax / 10.0f); + formatter << to << (mEffectParams.mMagnMax / 10.0f); formatter << timesInt; spellLine += formatter.str(); @@ -446,6 +448,10 @@ namespace MWGui if ( displayType == ESM::MagicEffect::MDT_Percentage ) spellLine += pct; + else if ( displayType == ESM::MagicEffect::MDT_Feet ) + spellLine += " " + ft; + else if ( displayType == ESM::MagicEffect::MDT_Level ) + spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? lvl : lvls ); else // ESM::MagicEffect::MDT_Points spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); } From 5ce1f50fab6456afcd5adc781a0e141ea13e6e5b Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Thu, 10 Oct 2013 23:06:37 +0200 Subject: [PATCH 47/81] Cleanup in MWGui::WindowManager constructor initialzation list. Corrected order of initialization list, and added missing member field initializations - without this openmw crashes when installer is interrupted and there are no valid data path in openmw.cfg, as reported by BrotherBrick in: https://forum.openmw.org/viewtopic.php?f=20&p=19501#p19499 Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwgui/windowmanagerimp.cpp | 33 ++++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index bf8b664da..4b4d2dfd1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -61,20 +61,23 @@ namespace MWGui const Compiler::Extensions& extensions, int fpsLevel, OEngine::Render::OgreRenderer *ogre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding) - : mGuiManager(NULL) - , mConsoleOnlyScripts(consoleOnlyScripts) + : mConsoleOnlyScripts(consoleOnlyScripts) + , mGuiManager(NULL) , mRendering(ogre) , mHud(NULL) , mMap(NULL) , mMenu(NULL) - , mStatsWindow(NULL) , mToolTips(NULL) + , mStatsWindow(NULL) , mMessageBoxManager(NULL) , mConsole(NULL) , mJournal(NULL) , mDialogueWindow(NULL) - , mBookWindow(NULL) + , mContainerWindow(NULL) + , mDragAndDrop(NULL) + , mInventoryWindow(NULL) , mScrollWindow(NULL) + , mBookWindow(NULL) , mCountDialog(NULL) , mTradeWindow(NULL) , mSpellBuyingWindow(NULL) @@ -83,27 +86,37 @@ namespace MWGui , mConfirmationDialog(NULL) , mAlchemyWindow(NULL) , mSpellWindow(NULL) + , mQuickKeysMenu(NULL) , mLoadingScreen(NULL) - , mCharGen(NULL) , mLevelupDialog(NULL) , mWaitDialog(NULL) , mSpellCreationDialog(NULL) , mEnchantingDialog(NULL) , mTrainingWindow(NULL) , mMerchantRepair(NULL) - , mRepair(NULL) , mSoulgemDialog(NULL) + , mRepair(NULL) , mCompanionWindow(NULL) + , mTranslationDataStorage (translationDataStorage) + , mSoftwareCursor(NULL) + , mCharGen(NULL) + , mInputBlocker(NULL) + , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) + , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) + , mHudEnabled(true) + , mCursorVisible(true) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() - , mPlayerMajorSkills() , mPlayerMinorSkills() + , mPlayerMajorSkills() , mPlayerSkillValues() , mPlayerHealth() , mPlayerMagicka() , mPlayerFatigue() , mGui(NULL) + , mGuiModes() + , mCursorManager(NULL) , mGarbageDialogs() , mShown(GW_ALL) , mForceHidden(GW_None) @@ -113,13 +126,7 @@ namespace MWGui , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) - , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) - , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) - , mHudEnabled(true) - , mTranslationDataStorage (translationDataStorage) - , mCursorManager(NULL) , mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")) - , mCursorVisible(true) { // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); From a77044cda43e368789bfd036978eb2aa78bb8e66 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 12 Oct 2013 16:15:47 +0200 Subject: [PATCH 48/81] fixed column numbering --- apps/opencs/model/world/columns.cpp | 2 +- apps/opencs/model/world/columns.hpp | 214 ++++++++++++++-------------- 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 25047807a..ca37840ad 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -51,7 +51,7 @@ namespace CSMWorld { ColumnId_FactionIndex, "Faction Index" }, { ColumnId_Charges, "Charges" }, { ColumnId_Enchantment, "Enchantment" }, - { ColumnId_Value, "Coin Value" }, + { ColumnId_CoinValue, "Coin Value" }, { ColumnId_Teleport, "Teleport" }, { ColumnId_TeleportCell, "Teleport Cell" }, { ColumnId_LockLevel, "Lock Level" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 582f5102b..9b26cac4c 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -45,113 +45,113 @@ namespace CSMWorld ColumnId_Charges = 32, ColumnId_Enchantment = 33, ColumnId_CoinValue = 34, - ColumnId_Teleport = 25, - ColumnId_TeleportCell = 26, - ColumnId_LockLevel = 27, - ColumnId_Key = 28, - ColumnId_Trap = 29, - ColumnId_BeastRace = 30, - ColumnId_AutoCalc = 31, - ColumnId_StarterSpell = 32, - ColumnId_AlwaysSucceeds = 33, - ColumnId_SleepForbidden = 34, - ColumnId_InteriorWater = 35, - ColumnId_InteriorSky = 36, - ColumnId_Model = 37, - ColumnId_Script = 38, - ColumnId_Icon = 39, - ColumnId_Weight = 40, - ColumnId_EnchantmentPoints = 31, - ColumnId_Quality = 32, - ColumnId_Ai = 33, - ColumnId_AiHello = 34, - ColumnId_AiFlee = 35, - ColumnId_AiFight = 36, - ColumnId_AiAlarm = 37, - ColumnId_BuysWeapons = 38, - ColumnId_BuysArmor = 39, - ColumnId_BuysClothing = 40, - ColumnId_BuysBooks = 41, - ColumnId_BuysIngredients = 42, - ColumnId_BuysLockpicks = 43, - ColumnId_BuysProbes = 44, - ColumnId_BuysLights = 45, - ColumnId_BuysApparati = 46, - ColumnId_BuysRepairItems = 47, - ColumnId_BuysMiscItems = 48, - ColumnId_BuysPotions = 49, - ColumnId_BuysMagicItems = 50, - ColumnId_SellsSpells = 51, - ColumnId_Trainer = 52, - ColumnId_Spellmaking = 53, - ColumnId_EnchantingService = 54, - ColumnId_RepairService = 55, - ColumnId_ApparatusType = 56, - ColumnId_ArmorType = 57, - ColumnId_Health = 58, - ColumnId_ArmorValue = 59, - ColumnId_Scroll = 60, - ColumnId_ClothingType = 61, - ColumnId_WeightCapacity = 62, - ColumnId_OrganicContainer = 63, - ColumnId_Respawn = 64, - ColumnId_CreatureType = 65, - ColumnId_SoulPoints = 66, - ColumnId_OriginalCreature = 67, - ColumnId_Biped = 68, - ColumnId_HasWeapon = 69, - ColumnId_NoMovement = 70, - ColumnId_Swims = 71, - ColumnId_Flies = 72, - ColumnId_Walks = 73, - ColumnId_Essential = 74, - ColumnId_SkeletonBlood = 75, - ColumnId_MetalBlood = 76, - ColumnId_OpenSound = 77, - ColumnId_CloseSound = 78, - ColumnId_Duration = 79, - ColumnId_Radius = 80, - ColumnId_Colour = 81, - ColumnId_Sound = 82, - ColumnId_Dynamic = 83, - ColumnId_Portable = 84, - ColumnId_NegativeLight = 85, - ColumnId_Flickering = 86, - ColumnId_SlowFlickering = 87, - ColumnId_Pulsing = 88, - ColumnId_SlowPulsing = 89, - ColumnId_Fire = 90, - ColumnId_OffByDefault = 91, - ColumnId_IsKey = 92, - ColumnId_Race = 93, - ColumnId_Class = 94, - Columnid_Hair = 95, - ColumnId_Head = 96, - ColumnId_Female = 97, - ColumnId_WeaponType = 98, - ColumnId_WeaponSpeed = 99, - ColumnId_WeaponReach = 100, - ColumnId_MinChop = 101, - ColumnId_MaxChip = 102, - Columnid_MinSlash = 103, - ColumnId_MaxSlash = 104, - ColumnId_MinThrust = 105, - ColumnId_MaxThrust = 106, - ColumnId_Magical = 107, - ColumnId_Silver = 108, - ColumnId_Filter = 109, - ColumnId_PositionXPos = 110, - ColumnId_PositionYPos = 111, - ColumnId_PositionZPos = 112, - ColumnId_PositionXRot = 113, - ColumnId_PositionYRot = 114, - ColumnId_PositionZRot = 115, - ColumnId_DoorPositionXPos = 116, - ColumnId_DoorPositionYPos = 117, - ColumnId_DoorPositionZPos = 118, - ColumnId_DoorPositionXRot = 119, - ColumnId_DoorPositionYRot = 120, - ColumnId_DoorPositionZRot = 121, + ColumnId_Teleport = 35, + ColumnId_TeleportCell = 36, + ColumnId_LockLevel = 37, + ColumnId_Key = 38, + ColumnId_Trap = 39, + ColumnId_BeastRace = 40, + ColumnId_AutoCalc = 41, + ColumnId_StarterSpell = 42, + ColumnId_AlwaysSucceeds = 43, + ColumnId_SleepForbidden = 44, + ColumnId_InteriorWater = 45, + ColumnId_InteriorSky = 46, + ColumnId_Model = 47, + ColumnId_Script = 48, + ColumnId_Icon = 49, + ColumnId_Weight = 50, + ColumnId_EnchantmentPoints = 51, + ColumnId_Quality = 52, + ColumnId_Ai = 53, + ColumnId_AiHello = 54, + ColumnId_AiFlee = 55, + ColumnId_AiFight = 56, + ColumnId_AiAlarm = 57, + ColumnId_BuysWeapons = 58, + ColumnId_BuysArmor = 59, + ColumnId_BuysClothing = 60, + ColumnId_BuysBooks = 61, + ColumnId_BuysIngredients = 62, + ColumnId_BuysLockpicks = 63, + ColumnId_BuysProbes = 64, + ColumnId_BuysLights = 65, + ColumnId_BuysApparati = 66, + ColumnId_BuysRepairItems = 67, + ColumnId_BuysMiscItems = 68, + ColumnId_BuysPotions = 69, + ColumnId_BuysMagicItems = 70, + ColumnId_SellsSpells = 71, + ColumnId_Trainer = 72, + ColumnId_Spellmaking = 73, + ColumnId_EnchantingService = 74, + ColumnId_RepairService = 75, + ColumnId_ApparatusType = 76, + ColumnId_ArmorType = 77, + ColumnId_Health = 78, + ColumnId_ArmorValue = 79, + ColumnId_Scroll = 80, + ColumnId_ClothingType = 81, + ColumnId_WeightCapacity = 82, + ColumnId_OrganicContainer = 83, + ColumnId_Respawn = 84, + ColumnId_CreatureType = 85, + ColumnId_SoulPoints = 86, + ColumnId_OriginalCreature = 87, + ColumnId_Biped = 88, + ColumnId_HasWeapon = 89, + ColumnId_NoMovement = 90, + ColumnId_Swims = 91, + ColumnId_Flies = 92, + ColumnId_Walks = 93, + ColumnId_Essential = 94, + ColumnId_SkeletonBlood = 95, + ColumnId_MetalBlood = 96, + ColumnId_OpenSound = 97, + ColumnId_CloseSound = 98, + ColumnId_Duration = 99, + ColumnId_Radius = 100, + ColumnId_Colour = 101, + ColumnId_Sound = 102, + ColumnId_Dynamic = 103, + ColumnId_Portable = 104, + ColumnId_NegativeLight = 105, + ColumnId_Flickering = 106, + ColumnId_SlowFlickering = 107, + ColumnId_Pulsing = 108, + ColumnId_SlowPulsing = 109, + ColumnId_Fire = 110, + ColumnId_OffByDefault = 111, + ColumnId_IsKey = 112, + ColumnId_Race = 113, + ColumnId_Class = 114, + Columnid_Hair = 115, + ColumnId_Head = 116, + ColumnId_Female = 117, + ColumnId_WeaponType = 118, + ColumnId_WeaponSpeed = 119, + ColumnId_WeaponReach = 120, + ColumnId_MinChop = 121, + ColumnId_MaxChip = 122, + Columnid_MinSlash = 123, + ColumnId_MaxSlash = 124, + ColumnId_MinThrust = 125, + ColumnId_MaxThrust = 126, + ColumnId_Magical = 127, + ColumnId_Silver = 128, + ColumnId_Filter = 129, + ColumnId_PositionXPos = 130, + ColumnId_PositionYPos = 131, + ColumnId_PositionZPos = 132, + ColumnId_PositionXRot = 133, + ColumnId_PositionYRot = 134, + ColumnId_PositionZRot = 135, + ColumnId_DoorPositionXPos = 136, + ColumnId_DoorPositionYPos = 137, + ColumnId_DoorPositionZPos = 138, + ColumnId_DoorPositionXRot = 139, + ColumnId_DoorPositionYRot = 140, + ColumnId_DoorPositionZRot = 141, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. From a29b8667efc3485e33e83d63ccf680d300ddc6a6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 12 Oct 2013 16:29:36 +0200 Subject: [PATCH 49/81] fixed string filter on boolean columns when testing against the value false --- apps/opencs/model/filter/textnode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index f3d98ce53..133208b31 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -47,7 +47,7 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row, } else if (data.type()==QVariant::Bool) { - string = data.toBool() ? "true" : " false"; + string = data.toBool() ? "true" : "false"; } else return false; From b5d620a8dcb9ea6a9cdcacab70784ebfce78d3f8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 12 Oct 2013 16:35:59 +0200 Subject: [PATCH 50/81] fixed string filter on enum column when column is empty --- apps/opencs/model/filter/textnode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index 133208b31..e335f7ea7 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -34,7 +34,7 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row, { string = data.toString(); } - else if (data.type()==QVariant::Int || data.type()==QVariant::UInt || + else if ((data.type()==QVariant::Int || data.type()==QVariant::UInt) && CSMWorld::Columns::hasEnums (static_cast (mColumnId))) { int value = data.toInt(); From cfc30933202a7804be0c5ff5a5de23f908175218 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Sat, 12 Oct 2013 10:46:44 -0400 Subject: [PATCH 51/81] Reverted conditional compiling --- apps/launcher/main.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index df7aa11d4..f67f5edcf 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,14 +62,3 @@ int main(int argc, char *argv[]) return returnValue; } -#ifdef _WINDOWS -// If the system compiles for main(), then main will be used. -// If it wants WinMain, this will call main anyways. -int _stdcall WinMain(struct HINSTANCE__ *hInstance, - struct HINSTANCE__ *hPrevInstance, - char *lpszCmdLine, - int nCmdShow) -{ - return main(__argc, __argv); -} -#endif \ No newline at end of file From 141382b8c0b879803bffa0e41f54556b2f9f3d6c Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Sat, 12 Oct 2013 14:48:37 -0500 Subject: [PATCH 52/81] COC Command: Exterior cell selection fix. Return the northernmost cell of the easternmost matching column for Ext. cells. --- apps/openmw/mwworld/store.hpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 2ee23dbd6..90452f661 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -656,26 +656,38 @@ namespace MWWorld return iterator(mSharedExt.end()); } - /// \todo implement appropriate index + // Return the northernmost cell in the easternmost column. const ESM::Cell *searchExtByName(const std::string &id) const { + ESM::Cell *cell = 0; std::vector::const_iterator it = mSharedExt.begin(); for (; it != mSharedExt.end(); ++it) { if (Misc::StringUtils::ciEqual((*it)->mName, id)) { - return *it; + if ( cell == 0 || + ( (*it)->mData.mX > cell->mData.mX ) || + ( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) ) + { + cell = *it; + } } } - return 0; + return cell; } - /// \todo implement appropriate index + // Return the northernmost cell in the easternmost column. const ESM::Cell *searchExtByRegion(const std::string &id) const { + ESM::Cell *cell = 0; std::vector::const_iterator it = mSharedExt.begin(); for (; it != mSharedExt.end(); ++it) { if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) { - return *it; + if ( cell == 0 || + ( (*it)->mData.mX > cell->mData.mX ) || + ( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) ) + { + cell = *it; + } } } - return 0; + return cell; } size_t getSize() const { From dcfff7946064b47610b9c88b4133b4cce2cc524f Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 13 Oct 2013 00:32:28 +0200 Subject: [PATCH 53/81] Regenerate fatigue over time --- apps/openmw/mwmechanics/actors.cpp | 52 +++++++++++++++++------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f9b5b695a..70b820f8c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -31,11 +31,14 @@ namespace MWMechanics calculateDynamicStats (ptr); calculateCreatureStatModifiers (ptr); - // AI if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) { + // AI CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); creatureStats.getAiSequence().execute (ptr); + + // fatigue restoration + calculateRestoration(ptr, duration); } } @@ -93,39 +96,29 @@ namespace MWMechanics void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration) { CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + const MWWorld::Store& settings = MWBase::Environment::get().getWorld()->getStore().get(); + + int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); + + float capacity = MWWorld::Class::get(ptr).getCapacity(ptr); + float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr); + float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); + if (normalizedEncumbrance > 1) + normalizedEncumbrance = 1; if (duration == 3600) { - bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0; + // the actor is sleeping, restore health and magicka - int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); + bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0; DynamicStat health = stats.getHealth(); health.setCurrent (health.getCurrent() + 0.1 * endurance); stats.setHealth (health); - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - - float fFatigueReturnBase = store.get().find("fFatigueReturnBase")->getFloat (); - float fFatigueReturnMult = store.get().find("fFatigueReturnMult")->getFloat (); - float fEndFatigueMult = store.get().find("fEndFatigueMult")->getFloat (); - - float capacity = MWWorld::Class::get(ptr).getCapacity(ptr); - float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr); - float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); - if (normalizedEncumbrance > 1) - normalizedEncumbrance = 1; - - float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); - x *= fEndFatigueMult * endurance; - - DynamicStat fatigue = stats.getFatigue(); - fatigue.setCurrent (fatigue.getCurrent() + 3600 * x); - stats.setFatigue (fatigue); - if (!stunted) { - float fRestMagicMult = store.get().find("fRestMagicMult")->getFloat (); + float fRestMagicMult = settings.find("fRestMagicMult")->getFloat (); DynamicStat magicka = stats.getMagicka(); magicka.setCurrent (magicka.getCurrent() @@ -133,6 +126,19 @@ namespace MWMechanics stats.setMagicka (magicka); } } + + // restore fatigue + + float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat (); + float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat (); + float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat (); + + float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); + x *= fEndFatigueMult * endurance; + + DynamicStat fatigue = stats.getFatigue(); + fatigue.setCurrent (fatigue.getCurrent() + duration * x); + stats.setFatigue (fatigue); } void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr) From c8d0fb8c4e6a5a1230261c661b3c7b1fda47537b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 13 Oct 2013 14:43:59 +0200 Subject: [PATCH 54/81] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 6e8e36612..bd0c6ca74 100644 --- a/credits.txt +++ b/credits.txt @@ -12,6 +12,7 @@ Marc Zinnschlag (Zini) - Lead Programmer/Project Manager Adam Hogan (aurix) Aleksandar Jovanov +Alex Haddad (rainChu) Alex McKibben (WeirdSexy) Alexander Nadeau (wareya) Alexander Olofsson (Ace) From 4624bed899568f8465399048502b1e0ef9aa073c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 13 Oct 2013 15:41:48 +0200 Subject: [PATCH 55/81] changed handling of scene toolbar button icons --- apps/opencs/view/world/scenetool.cpp | 5 ----- apps/opencs/view/world/scenetool.hpp | 4 ---- apps/opencs/view/world/scenetoolmode.cpp | 5 ++++- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/world/scenetool.cpp b/apps/opencs/view/world/scenetool.cpp index 2140cd1e0..320deb1ba 100644 --- a/apps/opencs/view/world/scenetool.cpp +++ b/apps/opencs/view/world/scenetool.cpp @@ -11,11 +11,6 @@ CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent) connect (this, SIGNAL (clicked()), this, SLOT (openRequest())); } -void CSVWorld::SceneTool::updateIcon (const QIcon& icon) -{ - setIcon (icon); -} - void CSVWorld::SceneTool::openRequest() { showPanel (parentWidget()->mapToGlobal (pos())); diff --git a/apps/opencs/view/world/scenetool.hpp b/apps/opencs/view/world/scenetool.hpp index 2e83b0c6d..07e8b58d7 100644 --- a/apps/opencs/view/world/scenetool.hpp +++ b/apps/opencs/view/world/scenetool.hpp @@ -18,10 +18,6 @@ namespace CSVWorld virtual void showPanel (const QPoint& position) = 0; - protected slots: - - void updateIcon (const QIcon& icon); - private slots: void openRequest(); diff --git a/apps/opencs/view/world/scenetoolmode.cpp b/apps/opencs/view/world/scenetoolmode.cpp index 2435a8e35..281d703b6 100644 --- a/apps/opencs/view/world/scenetoolmode.cpp +++ b/apps/opencs/view/world/scenetoolmode.cpp @@ -36,6 +36,9 @@ void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::str mButtons.insert (std::make_pair (button, id)); connect (button, SIGNAL (clicked()), this, SLOT (selected())); + + if (mButtons.size()==1) + setIcon (button->icon()); } void CSVWorld::SceneToolMode::selected() @@ -47,7 +50,7 @@ void CSVWorld::SceneToolMode::selected() { mPanel->hide(); - emit updateIcon (iter->first->icon()); + setIcon (iter->first->icon()); emit modeChanged (iter->second); } } \ No newline at end of file From f504ab42feb40382228390b4b3a62874303b3de0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 Oct 2013 17:52:14 +0200 Subject: [PATCH 56/81] Turn off vsync while in the loading screen --- apps/openmw/mwgui/loadingscreen.cpp | 22 +++++++++++++++++++++- apps/openmw/mwgui/loadingscreen.hpp | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 9b63dfa76..d2ebcd109 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -23,6 +23,7 @@ namespace MWGui , mLastWallpaperChangeTime(0.f) , mFirstLoad(true) , mProgress(0) + , mVSyncWasEnabled(false) { getWidget(mLoadingText, "LoadingText"); getWidget(mProgressBar, "ProgressBar"); @@ -67,6 +68,14 @@ namespace MWGui void LoadingScreen::loadingOn() { + // Temporarily turn off VSync, we want to do actual loading rather than waiting for the screen to sync. + // Threaded loading would be even better, of course - especially because some drivers force VSync to on and we can't change it. + // In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/ + mVSyncWasEnabled = mWindow->isVSyncEnabled(); + #if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) + mWindow->setVSyncEnabled(false); + #endif + setVisible(true); if (mFirstLoad) @@ -83,6 +92,12 @@ namespace MWGui void LoadingScreen::loadingOff() { + // Re-enable vsync now. + // In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/ + #if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) + mWindow->setVSyncEnabled(mVSyncWasEnabled); + #endif + setVisible(false); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); @@ -212,7 +227,12 @@ namespace MWGui // caused a sync / flush and would be expensive). // We're doing this so we can do some actual loading while the GPU is busy with the render. // This means the render is lagging a frame behind, but this is hardly noticable. - mWindow->swapBuffers(false); // never Vsync, makes no sense here +#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) + mWindow->swapBuffers(); +#else + // In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged when using GLX. Not much we can do :/ + mWindow->swapBuffers(false); +#endif mWindow->update(false); if (!hasCompositor) diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index dde8ff63a..2d1d7431f 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -57,6 +57,8 @@ namespace MWGui Ogre::StringVector mResources; + bool mVSyncWasEnabled; + void changeWallpaper(); void draw(); From fa264935ff2ff9d05a7da8334e8836fa53a088ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 Oct 2013 17:56:26 +0200 Subject: [PATCH 57/81] We can apply vsync at runtime now that the Ogre bug is fixed. --- apps/openmw/mwgui/settingswindow.cpp | 4 ++++ apps/openmw/mwrender/renderingmanager.cpp | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3dfa17bad..923b9d01d 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -363,8 +363,12 @@ namespace MWGui else if (_sender == mVSyncButton) { Settings::Manager::setBool("vsync", "Video", newState); + // Ogre::Window::setVSyncEnabled is bugged in 1.8 +#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0) MWBase::Environment::get().getWindowManager()-> messageBox("VSync will be applied after a restart", std::vector()); +#endif + apply(); } else { diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e03b2ccfc..8396e70d7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -760,6 +760,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = true; + else if (it->first == "Video" && it->second == "vsync") + { + // setVSyncEnabled is bugged in 1.8 +#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) + mRendering.getWindow()->setVSyncEnabled(Settings::Manager::getBool("vsync", "Video")); +#endif + } else if (it->second == "field of view" && it->first == "General") mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); else if ((it->second == "texture filtering" && it->first == "General") From 2fb059e2fa067f34efc88b8cfb23aafe3f138e55 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 Oct 2013 18:20:55 +0200 Subject: [PATCH 58/81] Don't destroy the SDL window twice --- extern/sdl4ogre/sdlinputwrapper.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index 931d6aca3..df74bba3b 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -30,9 +30,6 @@ namespace SFO InputWrapper::~InputWrapper() { - if(mSDLWindow != NULL) - SDL_DestroyWindow(mSDLWindow); - mSDLWindow = NULL; } void InputWrapper::capture(bool windowEventsOnly) From 683ad40e219f30650440ddee577cec14cf30e4fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 Oct 2013 18:28:22 +0200 Subject: [PATCH 59/81] No need for this ifdef since there is a default argument. --- apps/openmw/mwgui/loadingscreen.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index d2ebcd109..4bd383c2f 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -227,12 +227,8 @@ namespace MWGui // caused a sync / flush and would be expensive). // We're doing this so we can do some actual loading while the GPU is busy with the render. // This means the render is lagging a frame behind, but this is hardly noticable. -#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) mWindow->swapBuffers(); -#else - // In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged when using GLX. Not much we can do :/ - mWindow->swapBuffers(false); -#endif + mWindow->update(false); if (!hasCompositor) From 4905f1c8ab0291be80f5546177318cba266e1633 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 13 Oct 2013 21:54:36 +0200 Subject: [PATCH 60/81] make testing empty cells against an empty string yield true --- apps/opencs/model/filter/textnode.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index e335f7ea7..7d1a4845f 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -49,6 +49,8 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row, { string = data.toBool() ? "true" : "false"; } + else if (mText.empty() && !data.isValid()) + return true; else return false; From 9b0766b6789434e8134b1c0551972223e79e7890 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 14 Oct 2013 10:58:11 +0200 Subject: [PATCH 61/81] minor fix in ValueNode::toString --- apps/opencs/model/filter/valuenode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 7eeb6beab..464fc8ec4 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -68,7 +68,7 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const << CSMWorld::Columns::getName (static_cast (mColumnId)) << "\""; - stream << ", \""; + stream << ", "; if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite) stream << mLower; From 679754b305070ac17a81250f7e6d59aa2d54e374 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 14 Oct 2013 11:06:59 +0200 Subject: [PATCH 62/81] corrected an error message --- apps/opencs/model/filter/valuenode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 464fc8ec4..66f76efcb 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -17,7 +17,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row, const std::map::const_iterator iter = columns.find (mColumnId); if (iter==columns.end()) - throw std::logic_error ("invalid column in test value test"); + throw std::logic_error ("invalid column in value node test"); if (iter->second==-1) return true; From db7ea30483f126047c014dfdce807994c0ceb4e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 14 Oct 2013 11:15:36 +0200 Subject: [PATCH 63/81] allow float values in cell for value tests --- apps/opencs/model/filter/valuenode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 66f76efcb..fdcce00ab 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -27,7 +27,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row, QVariant data = table.data (index); if (data.type()!=QVariant::Double && data.type()!=QVariant::Bool && data.type()!=QVariant::Int && - data.type()!=QVariant::UInt) + data.type()!=QVariant::UInt && data.type()!=static_cast (QMetaType::Float)) return false; double value = data.toDouble(); From ba4b8a37e2301f1ecb0633c361b3cb5c73bd1cdc Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 14 Oct 2013 11:15:23 +0200 Subject: [PATCH 64/81] Remember pressed message box button longer Remember which button was pressed until a new interactive message box is displayed or until the pressed button number is read. Before that, it was not possible to get the pressed button after the message box was hidden/destroyed. --- apps/openmw/mwgui/messagebox.cpp | 15 +++++++-------- apps/openmw/mwgui/messagebox.hpp | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 45da1bf17..48d7ec171 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -14,6 +14,7 @@ namespace MWGui mMessageBoxSpeed = 0.1; mInterMessageBoxe = NULL; mStaticMessageBox = NULL; + mLastButtonPressed = -1; } void MessageBoxManager::onFrame (float frameDuration) @@ -62,6 +63,7 @@ namespace MWGui } if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { + mLastButtonPressed = mInterMessageBoxe->readPressedButton(); delete mInterMessageBoxe; mInterMessageBoxe = NULL; MWBase::Environment::get().getInputManager()->changeInputMode( @@ -107,6 +109,7 @@ namespace MWGui } mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons); + mLastButtonPressed = -1; return true; } @@ -154,11 +157,9 @@ namespace MWGui int MessageBoxManager::readPressedButton () { - if(mInterMessageBoxe != NULL) - { - return mInterMessageBoxe->readPressedButton(); - } - return -1; + int pressed = mLastButtonPressed; + mLastButtonPressed = -1; + return pressed; } @@ -421,9 +422,7 @@ namespace MWGui int InteractiveMessageBox::readPressedButton () { - int pressed = mButtonPressed; - mButtonPressed = -1; - return pressed; + return mButtonPressed; } } diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 4ef645f5e..63840cfe2 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -56,6 +56,7 @@ namespace MWGui MessageBox* mStaticMessageBox; std::vector mTimers; float mMessageBoxSpeed; + int mLastButtonPressed; }; class MessageBox : public OEngine::GUI::Layout From 30ee3c5cf6e98982743de01cff0d1c8adbd57cb5 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 15 Oct 2013 15:23:42 -0400 Subject: [PATCH 65/81] Equipped torches and lights run out of fuel --- apps/openmw/mwclass/light.cpp | 47 ++++++++++++++++++++++++++++++ apps/openmw/mwclass/light.hpp | 8 +++++ apps/openmw/mwmechanics/actors.cpp | 32 ++++++++++++++++++++ apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwworld/class.cpp | 10 +++++++ apps/openmw/mwworld/class.hpp | 8 +++++ 6 files changed, 107 insertions(+) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 7eefc6167..21d83d62e 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -16,12 +16,27 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/customdata.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +namespace +{ + struct CustomData : public MWWorld::CustomData + { + float mTime; + ///< Time remaining + + virtual MWWorld::CustomData *clone() const + { + return new CustomData (*this); + } + }; +} + namespace MWClass { void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -182,6 +197,24 @@ namespace MWClass return action; } + void Light::setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const + { + ensureCustomData(ptr); + + float &timeCharge = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + + // TODO time it in vanilla, see if 1 second is really one unit. + timeCharge = duration; + } + + float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const + { + ensureCustomData(ptr); + + ESM::CellRef &ref = ptr.getCellRef(); + return dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + } + MWWorld::Ptr Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { @@ -191,6 +224,20 @@ namespace MWClass return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell); } + void Light::ensureCustomData (const MWWorld::Ptr& ptr) const + { + if (!ptr.getRefData().getCustomData()) + { + MWWorld::LiveCellRef *ref = ptr.get(); + + CustomData *data = new CustomData; + + data->mTime = ref->mBase->mData.mTime; + + ptr.getRefData().setCustomData(data); + } + } + bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const { return npcServices & ESM::NPC::Lights; diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 79d662763..c15228a6a 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -10,6 +10,8 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + void ensureCustomData (const MWWorld::Ptr& ptr) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; @@ -56,6 +58,12 @@ namespace MWClass const; ///< Generate action for using via inventory menu + virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const; + ///< Sets the remaining duration of the object. + + virtual float getRemainingUsageTime (const MWWorld::Ptr& ptr) const; + ///< Returns the remaining duration of the object. + virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual float getWeight (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ca26e88ce..fb632159c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -42,7 +42,13 @@ namespace MWMechanics void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) { if(!paused) + { updateDrowning(ptr, duration); + + // Only update the light of the player. + if(ptr.getRefData().getHandle()=="player") + updateEquippedLight(ptr, duration); + } } void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) @@ -196,6 +202,32 @@ namespace MWMechanics stats.setTimeToStartDrowning(20); } + void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) + { + //If holding a light... + MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr); + MWWorld::ContainerStoreIterator heldIter = + inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + + if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) + { + // ... then use some "fuel" from the timer + float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); + + // If it's already -1, then it should be an infinite light. + // TODO see what happens for other negative values. + if(timeRemaining >= 0.0f) + { + timeRemaining -= duration; + + if(timeRemaining > 0.0f) + heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); + else + heldIter->getRefData().setCount(0); // remove it + } + } + } + Actors::Actors() : mDuration (0) {} void Actors::addActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 69878a000..a77e52ba3 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -44,6 +44,8 @@ namespace MWMechanics void updateDrowning (const MWWorld::Ptr& ptr, float duration); + void updateEquippedLight (const MWWorld::Ptr& ptr, float duration); + public: Actors(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c739ea831..c73662bb1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -132,6 +132,16 @@ namespace MWWorld throw std::runtime_error ("class does not support unlocking"); } + void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const + { + throw std::runtime_error ("class does not support time-based uses."); + } + + float Class::getRemainingUsageTime (const Ptr& ptr) const + { + throw std::runtime_error ("class does not support time-based uses."); + } + std::string Class::getScript (const Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 28e37cbf3..1b7b8518a 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -156,6 +156,14 @@ namespace MWWorld virtual void unlock (const Ptr& ptr) const; ///< Unlock object (default implementation: throw an exception) + virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const; + ///< Sets the remaining duration of the object, such as an equippable light + /// source. (default implementation: throw an exception) + + virtual float getRemainingUsageTime (const Ptr& ptr) const; + ///< Returns the remaining duration of the object, such as an equippable light + /// source. (default implementation: throw an exception) + virtual std::string getScript (const Ptr& ptr) const; ///< Return name of the script attached to ptr (default implementation: return an empty /// string). From 2643214ca6370a102ce69cb9788b9ef656006c50 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 15 Oct 2013 20:56:42 -0400 Subject: [PATCH 66/81] Lights extinguish underwater --- apps/openmw/mwclass/light.cpp | 6 ++--- apps/openmw/mwmechanics/actors.cpp | 42 ++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 21d83d62e..4cf4ae37e 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -201,10 +201,8 @@ namespace MWClass { ensureCustomData(ptr); - float &timeCharge = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; - - // TODO time it in vanilla, see if 1 second is really one unit. - timeCharge = duration; + float &timeRemaining = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + timeRemaining = duration; } float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index fb632159c..0adc97606 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -44,10 +44,7 @@ namespace MWMechanics if(!paused) { updateDrowning(ptr, duration); - - // Only update the light of the player. - if(ptr.getRefData().getHandle()=="player") - updateEquippedLight(ptr, duration); + updateEquippedLight(ptr, duration); } } @@ -211,19 +208,36 @@ namespace MWMechanics if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) { - // ... then use some "fuel" from the timer - float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); + // Use time from the player's light + bool isPlayer = ptr.getRefData().getHandle()=="player"; + if(isPlayer) + { + float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); + + // -1 is infinite light source. Other negative values are treated as 0. + if(timeRemaining != -1.0f) + { + timeRemaining -= duration; + + if(timeRemaining > 0.0f) + heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); + else + { + heldIter->getRefData().setCount(0); // remove it + return; + } + } + } - // If it's already -1, then it should be an infinite light. - // TODO see what happens for other negative values. - if(timeRemaining >= 0.0f) + // Both NPC and player lights extinguish in water. + if(MWBase::Environment::get().getWorld()->isSwimming(ptr)) { - timeRemaining -= duration; + heldIter->getRefData().setCount(0); // remove it - if(timeRemaining > 0.0f) - heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); - else - heldIter->getRefData().setCount(0); // remove it + // ...But, only the player makes a sound. + if(isPlayer) + MWBase::Environment::get().getSoundManager()->playSound("torch out", + 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoEnv); } } } From 8d8ba0257e17a34fb959c7e6bd420301540a7bb9 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 15 Oct 2013 22:17:50 -0700 Subject: [PATCH 67/81] Added common untracked files to .gitignore --- .gitignore | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.gitignore b/.gitignore index 9f2cba3bf..4a3545f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,20 @@ CMakeLists.txt.user .project .settings/ .directory +*.install +*.desktop +*.cfg +*.cxx_parameters +*qrc_launcher.cxx +*qrc_resources.cxx +*__* +*ui_datafilespage.h +*ui_graphicspage.h +*ui_mainwindow.h +*ui_playpage.h +resources +esmtool +mwiniimport +omwlauncher +openmw +opencs From 5f4e2d2cf2da826c79acb2c07cce21a880564408 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 15 Oct 2013 22:29:51 -0700 Subject: [PATCH 68/81] Organize .gitignore to make it easier to add to --- .gitignore | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 4a3545f2c..c460743e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,43 @@ -build -*~ -Doxygen -prebuilt -apps/openmw/config.hpp -Docs/mainpage.hpp +## make CMakeFiles */CMakeFiles CMakeCache.txt -moc_*.cxx cmake_install.cmake -*.[ao] +CMakeLists.txt.user Makefile makefile -data +build +prebuilt + +## doxygen +Doxygen + +## ides/editors +*~ *.kdev4 -CMakeLists.txt.user *.swp *.swo *.kate-swp .cproject .project -.settings/ +.settings .directory -*.install -*.desktop + +## resources +data +resources + +## binaries +esmtool +mwiniimport +omwlauncher +openmw +opencs + +## generated objects +apps/openmw/config.hpp +Docs/mainpage.hpp +moc_*.cxx *.cfg *.cxx_parameters *qrc_launcher.cxx @@ -33,9 +47,7 @@ CMakeLists.txt.user *ui_graphicspage.h *ui_mainwindow.h *ui_playpage.h -resources -esmtool -mwiniimport -omwlauncher -openmw -opencs +*.install +*.desktop +*.[ao] +*.so From 8995cd8543ebdeb903b78afe1f6f1cb0c4df7b6b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Oct 2013 20:35:39 +0200 Subject: [PATCH 69/81] reverted gitignore changes --- .gitignore | 51 +++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index c460743e7..9f2cba3bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,53 +1,24 @@ -## make +build +*~ +Doxygen +prebuilt +apps/openmw/config.hpp +Docs/mainpage.hpp CMakeFiles */CMakeFiles CMakeCache.txt +moc_*.cxx cmake_install.cmake -CMakeLists.txt.user +*.[ao] Makefile makefile -build -prebuilt - -## doxygen -Doxygen - -## ides/editors -*~ +data *.kdev4 +CMakeLists.txt.user *.swp *.swo *.kate-swp .cproject .project -.settings +.settings/ .directory - -## resources -data -resources - -## binaries -esmtool -mwiniimport -omwlauncher -openmw -opencs - -## generated objects -apps/openmw/config.hpp -Docs/mainpage.hpp -moc_*.cxx -*.cfg -*.cxx_parameters -*qrc_launcher.cxx -*qrc_resources.cxx -*__* -*ui_datafilespage.h -*ui_graphicspage.h -*ui_mainwindow.h -*ui_playpage.h -*.install -*.desktop -*.[ao] -*.so From e11da5c0a3aec68078dd967fc0582f7908311941 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 16 Oct 2013 15:13:36 -0400 Subject: [PATCH 70/81] Added a constructor to Light CustomData --- apps/openmw/mwclass/light.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 4cf4ae37e..906ae8a1c 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -30,6 +30,13 @@ namespace float mTime; ///< Time remaining + CustomData(MWWorld::Ptr ptr) + { + MWWorld::LiveCellRef *ref = ptr.get(); + mTime = ref->mBase->mData.mTime; + } + ///< Constructs this CustomData from the base values for Ptr. + virtual MWWorld::CustomData *clone() const { return new CustomData (*this); @@ -225,15 +232,7 @@ namespace MWClass void Light::ensureCustomData (const MWWorld::Ptr& ptr) const { if (!ptr.getRefData().getCustomData()) - { - MWWorld::LiveCellRef *ref = ptr.get(); - - CustomData *data = new CustomData; - - data->mTime = ref->mBase->mData.mTime; - - ptr.getRefData().setCustomData(data); - } + ptr.getRefData().setCustomData(new CustomData(ptr)); } bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const From 65818155d8bb34640942ede25c3d9128baf07b08 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 16 Oct 2013 15:14:35 -0400 Subject: [PATCH 71/81] Fixed punctuation consistency --- apps/openmw/mwworld/class.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c73662bb1..da98f99f1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -134,12 +134,12 @@ namespace MWWorld void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const { - throw std::runtime_error ("class does not support time-based uses."); + throw std::runtime_error ("class does not support time-based uses"); } float Class::getRemainingUsageTime (const Ptr& ptr) const { - throw std::runtime_error ("class does not support time-based uses."); + throw std::runtime_error ("class does not support time-based uses"); } std::string Class::getScript (const Ptr& ptr) const From 8c139783b74a29a4d6299ee9ed874dc3fe651c83 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Oct 2013 21:33:11 +0200 Subject: [PATCH 72/81] silenced a warning --- apps/openmw/mwclass/light.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 906ae8a1c..a593eb295 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -216,7 +216,6 @@ namespace MWClass { ensureCustomData(ptr); - ESM::CellRef &ref = ptr.getCellRef(); return dynamic_cast (*ptr.getRefData().getCustomData()).mTime; } From 04735a67340604f8c517582c0d7b6cc390c36d57 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 15 Oct 2013 22:17:50 -0700 Subject: [PATCH 73/81] Extend .gitignore Organize .gitignore to make it easier to add to Ignore only binaries, not directories Removed some invalid ignores (.cfg, .desktop, etc) Better globbing --- .gitignore | 51 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 9f2cba3bf..f22f1bd49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,53 @@ -build -*~ -Doxygen -prebuilt -apps/openmw/config.hpp -Docs/mainpage.hpp +## make CMakeFiles */CMakeFiles CMakeCache.txt -moc_*.cxx cmake_install.cmake -*.[ao] +CMakeLists.txt.user Makefile makefile -data +build +prebuilt + +## doxygen +Doxygen + +## ides/editors +*~ *.kdev4 -CMakeLists.txt.user *.swp *.swo *.kate-swp .cproject .project -.settings/ +.settings .directory + +## resources +data +resources +/*.cfg +/*.desktop +/*.install + +## binaries +/esmtool +/mwiniimport +/omwlauncher +/openmw +/opencs + +## generated objects +apps/openmw/config.hpp +Docs/mainpage.hpp +moc_*.cxx +*.cxx_parameters +*qrc_launcher.cxx +*qrc_resources.cxx +*__* +*ui_datafilespage.h +*ui_graphicspage.h +*ui_mainwindow.h +*ui_playpage.h +*.[ao] +*.so From 3a3f2a37c85302a9353effb7ca811fb98deb2ce8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 17 Oct 2013 12:39:26 +0200 Subject: [PATCH 74/81] Add cut, copy & paste of text --- apps/openmw/mwinput/inputmanagerimp.cpp | 35 +++++++++++++++++++++++++ files/mygui/openmw_console.layout | 1 + 2 files changed, 36 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 43f2bcc15..4746260ed 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -468,6 +468,41 @@ namespace MWInput bool InputManager::keyPressed( const SDL_KeyboardEvent &arg ) { + // Cut, copy & paste + MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); + if (focus) + { + MyGUI::EditBox* edit = focus->castType(false); + if (edit && !edit->getEditReadOnly()) + { + if (arg.keysym.sym == SDLK_v && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL))) + { + char* text = SDL_GetClipboardText(); + + if (text) + { + edit->addText(MyGUI::UString(text)); + SDL_free(text); + } + } + if (arg.keysym.sym == SDLK_x && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL))) + { + std::string text = edit->getTextSelection(); + if (text.length()) + { + SDL_SetClipboardText(text.c_str()); + edit->deleteTextSelection(); + } + } + if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL))) + { + std::string text = edit->getTextSelection(); + if (text.length()) + SDL_SetClipboardText(text.c_str()); + } + } + } + mInputBinder->keyPressed (arg); if(arg.keysym.sym == SDLK_RETURN diff --git a/files/mygui/openmw_console.layout b/files/mygui/openmw_console.layout index bfda40c68..7d24a283e 100644 --- a/files/mygui/openmw_console.layout +++ b/files/mygui/openmw_console.layout @@ -9,6 +9,7 @@ + From ebf77329128ac86833586ce4e00ceec2916d3e1e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 20 Oct 2013 15:48:39 +0200 Subject: [PATCH 75/81] some cleanup --- apps/opencs/model/world/idcollection.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 04e65eea7..72aafb91f 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -14,14 +14,11 @@ namespace CSMWorld { public: - void load (ESM::ESMReader& reader, bool base, - UniversalId::Type type = UniversalId::Type_None); - ///< \param type Will be ignored, unless the collection supports multiple record types + void load (ESM::ESMReader& reader, bool base); }; template - void IdCollection::load (ESM::ESMReader& reader, bool base, - UniversalId::Type type) + void IdCollection::load (ESM::ESMReader& reader, bool base) { std::string id = reader.getHNOString ("NAME"); From adf3a41a835af0315adf53ab7a31f3a1c2356cfc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 20 Oct 2013 17:13:31 +0200 Subject: [PATCH 76/81] added topic and journal tables --- apps/opencs/model/world/data.cpp | 58 ++++++++++++++++++++++++ apps/opencs/model/world/data.hpp | 11 +++++ apps/opencs/model/world/idcollection.hpp | 46 +++++++++++-------- apps/opencs/model/world/universalid.cpp | 4 ++ apps/opencs/model/world/universalid.hpp | 4 ++ apps/opencs/view/doc/view.cpp | 18 ++++++++ apps/opencs/view/doc/view.hpp | 4 ++ apps/opencs/view/world/subviews.cpp | 2 + components/esm/loaddial.cpp | 5 ++ components/esm/loaddial.hpp | 3 ++ 10 files changed, 136 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 1e290d45f..2af76cfa7 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -141,6 +141,12 @@ CSMWorld::Data::Data() : mRefs (mCells) mSpells.addColumn (new FlagColumn (Columns::ColumnId_StarterSpell, 0x2)); mSpells.addColumn (new FlagColumn (Columns::ColumnId_AlwaysSucceeds, 0x4)); + mTopics.addColumn (new StringIdColumn); + mTopics.addColumn (new RecordStateColumn); + + mJournals.addColumn (new StringIdColumn); + mJournals.addColumn (new RecordStateColumn); + mCells.addColumn (new StringIdColumn); mCells.addColumn (new RecordStateColumn); mCells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Cell)); @@ -196,6 +202,8 @@ CSMWorld::Data::Data() : mRefs (mCells) addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region); addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign); addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell); + addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic); + addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal); addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell); addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables, UniversalId::Type_Referenceable); @@ -319,6 +327,28 @@ CSMWorld::IdCollection& CSMWorld::Data::getSpells() return mSpells; } + +const CSMWorld::IdCollection& CSMWorld::Data::getTopcis() const +{ + return mTopics; +} + +CSMWorld::IdCollection& CSMWorld::Data::getTopcis() +{ + return mTopics; +} + +const CSMWorld::IdCollection& CSMWorld::Data::getJournals() const +{ + return mJournals; +} + +CSMWorld::IdCollection& CSMWorld::Data::getJournals() +{ + return mJournals; +} + + const CSMWorld::IdCollection& CSMWorld::Data::getCells() const { return mCells; @@ -447,6 +477,30 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break; case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break; + case ESM::REC_DIAL: + { + std::string id = reader.getHNOString ("NAME"); + + ESM::Dialogue record; + record.mId = id; + record.load (reader); + + if (record.mType==ESM::Dialogue::Journal) + { + mJournals.load (record, base); + } + else if (record.mType==ESM::Dialogue::Deleted) + { + /// \todo handle deleted records + } + else + { + mTopics.load (record, base); + } + + break; + } + default: /// \todo throw an exception instead, once all records are implemented @@ -469,6 +523,8 @@ bool CSMWorld::Data::hasId (const std::string& id) const getRegions().searchId (id)!=-1 || getBirthsigns().searchId (id)!=-1 || getSpells().searchId (id)!=-1 || + getTopcis().searchId (id)!=-1 || + getJournals().searchId (id)!=-1 || getCells().searchId (id)!=-1 || getReferenceables().searchId (id)!=-1; } @@ -487,6 +543,8 @@ std::vector CSMWorld::Data::getIds (bool listDeleted) const appendIds (ids, mRegions, listDeleted); appendIds (ids, mBirthsigns, listDeleted); appendIds (ids, mSpells, listDeleted); + appendIds (ids, mTopics, listDeleted); + appendIds (ids, mJournals, listDeleted); appendIds (ids, mCells, listDeleted); appendIds (ids, mReferenceables, listDeleted); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index e900bb10f..74304e029 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "../filter/filter.hpp" @@ -48,6 +49,8 @@ namespace CSMWorld IdCollection mRegions; IdCollection mBirthsigns; IdCollection mSpells; + IdCollection mTopics; + IdCollection mJournals; IdCollection mCells; RefIdCollection mReferenceables; RefCollection mRefs; @@ -116,6 +119,14 @@ namespace CSMWorld IdCollection& getSpells(); + const IdCollection& getTopcis() const; + + IdCollection& getTopcis(); + + const IdCollection& getJournals() const; + + IdCollection& getJournals(); + const IdCollection& getCells() const; IdCollection& getCells(); diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 72aafb91f..b6ae04572 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -15,6 +15,8 @@ namespace CSMWorld public: void load (ESM::ESMReader& reader, bool base); + + void load (const ESXRecordT& record, bool base); }; template @@ -53,29 +55,35 @@ namespace CSMWorld IdAccessorT().getId (record) = id; record.load (reader); - int index = this->searchId (IdAccessorT().getId (record)); + load (record, base); + } + } - if (index==-1) - { - // new record - Record record2; - record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; - (base ? record2.mBase : record2.mModified) = record; + template + void IdCollection::load (const ESXRecordT& record, bool base) + { + int index = this->searchId (IdAccessorT().getId (record)); - this->appendRecord (record2); - } - else - { - // old record - Record record2 = Collection::getRecord (index); + if (index==-1) + { + // new record + Record record2; + record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; + (base ? record2.mBase : record2.mModified) = record; + + this->appendRecord (record2); + } + else + { + // old record + Record record2 = Collection::getRecord (index); - if (base) - record2.mBase = record; - else - record2.setModified (record); + if (base) + record2.mBase = record; + else + record2.setModified (record); - this->setRecord (index, record2); - } + this->setRecord (index, record2); } } } diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index c9edd0c16..6201a3cda 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -29,6 +29,8 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Referenceables", 0 }, @@ -54,6 +56,8 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 246640733..ffd99e572 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -87,6 +87,10 @@ namespace CSMWorld Type_RegionMap, Type_Filter, Type_Filters, + Type_Topics, + Type_Topic, + Type_Journals, + Type_Journal, Type_Scene }; diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index b29250d20..5713449f2 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -163,6 +163,14 @@ void CSVDoc::View::setupMechanicsMenu() QAction *spells = new QAction (tr ("Spells"), this); connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView())); mechanics->addAction (spells); + + QAction *topics = new QAction (tr ("Topics"), this); + connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView())); + mechanics->addAction (topics); + + QAction *journals = new QAction (tr ("Journals"), this); + connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView())); + mechanics->addAction (journals); } void CSVDoc::View::setupAssetsMenu() @@ -412,6 +420,16 @@ void CSVDoc::View::addSceneSubView() addSubView (CSMWorld::UniversalId::Type_Scene); } +void CSVDoc::View::addTopicsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Topics); +} + +void CSVDoc::View::addJournalsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Journals); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 6f3c38daa..2a31d9d80 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -166,6 +166,10 @@ namespace CSVDoc void addSceneSubView(); + void addTopicsSubView(); + + void addJournalsSubView(); + void toggleShowStatusBar (bool show); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 0e3465b38..417a7258f 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -36,6 +36,8 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, + CSMWorld::UniversalId::Type_Topics, + CSMWorld::UniversalId::Type_Journals, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index fb50d5e9f..f6c63efd2 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -36,4 +36,9 @@ void Dialogue::save(ESMWriter &esm) } } + void Dialogue::blank() + { + mInfo.clear(); + } + } diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 61f3f763d..0f4ceb6ac 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -35,6 +35,9 @@ struct Dialogue void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID and does not change the type). }; } #endif From 75c5316ad779a2ac5e6b989aea03e752c8198e26 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 20 Oct 2013 17:26:09 +0200 Subject: [PATCH 77/81] added dialogue type column to topics table --- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/columnimp.hpp | 27 ++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 7 +++++++ apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + apps/opencs/view/doc/viewmanager.cpp | 3 ++- 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index c1b423c94..9b8d7dafb 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -43,7 +43,8 @@ namespace CSMWorld Display_CreatureType, Display_WeaponType, Display_RecordState, - Display_RefRecordType + Display_RefRecordType, + Display_DialogueType }; int mColumnId; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index a13ac9a8a..eec0a41e2 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1284,6 +1284,33 @@ namespace CSMWorld return true; } }; + + template + struct DialogueTypeColumn : public Column + { + DialogueTypeColumn() + : Column (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType) + {} + + virtual QVariant get (const Record& record) const + { + return static_cast (record.get().mType); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mType = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return false; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index ca37840ad..ae4136bd9 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -159,6 +159,7 @@ namespace CSMWorld { ColumnId_DoorPositionXRot, "Teleport Rot X" }, { ColumnId_DoorPositionYRot, "Teleport Rot Y" }, { ColumnId_DoorPositionZRot, "Teleport Rot Z" }, + { ColumnId_DialogueType, "Dialogue Type" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, @@ -269,6 +270,11 @@ namespace "unknown", "none", "short", "integer", "long", "float", "string", 0 }; + static const char *sDialogueTypeEnums[] = + { + "Topic", "Voice", "Greeting", "Persuasion", 0 + }; + const char **getEnumNames (CSMWorld::Columns::ColumnId column) { switch (column) @@ -283,6 +289,7 @@ namespace case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes; case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums; case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums; + case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums; default: return 0; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 9b26cac4c..111931fa8 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -152,6 +152,7 @@ namespace CSMWorld ColumnId_DoorPositionXRot = 139, ColumnId_DoorPositionYRot = 140, ColumnId_DoorPositionZRot = 141, + ColumnId_DialogueType = 142, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 2af76cfa7..284e756f0 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -143,6 +143,7 @@ CSMWorld::Data::Data() : mRefs (mCells) mTopics.addColumn (new StringIdColumn); mTopics.addColumn (new RecordStateColumn); + mTopics.addColumn (new DialogueTypeColumn); mJournals.addColumn (new StringIdColumn); mJournals.addColumn (new RecordStateColumn); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 83cd93e5d..a4849795b 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -74,7 +74,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false }, { CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false }, { CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false }, - { CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false } + { CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false }, + { CSMWorld::ColumnBase::Display_DialogueType, CSMWorld::Columns::ColumnId_DialogueType, false } }; for (std::size_t i=0; i Date: Mon, 21 Oct 2013 13:39:13 +0200 Subject: [PATCH 78/81] set dialogue type for newly created dialogue records --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/columnimp.hpp | 10 ++++-- apps/opencs/model/world/data.cpp | 1 + apps/opencs/view/world/dialoguecreator.cpp | 35 ++++++++++++++++++ apps/opencs/view/world/dialoguecreator.hpp | 41 ++++++++++++++++++++++ apps/opencs/view/world/subviews.cpp | 9 +++-- 6 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/view/world/dialoguecreator.cpp create mode 100644 apps/opencs/view/world/dialoguecreator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f918cfebf..541b3b5a2 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -66,7 +66,7 @@ opencs_units (view/world opencs_units_noqt (view/world dialoguesubview subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate - scripthighlighter idvalidator + scripthighlighter idvalidator dialoguecreator ) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index eec0a41e2..23c529b3e 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1288,8 +1288,9 @@ namespace CSMWorld template struct DialogueTypeColumn : public Column { - DialogueTypeColumn() - : Column (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType) + DialogueTypeColumn (bool hidden = false) + : Column (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType, + hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue) {} virtual QVariant get (const Record& record) const @@ -1307,6 +1308,11 @@ namespace CSMWorld } virtual bool isEditable() const + { + return true; + } + + virtual bool isUserEditable() const { return false; } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 284e756f0..70e0e891d 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -147,6 +147,7 @@ CSMWorld::Data::Data() : mRefs (mCells) mJournals.addColumn (new StringIdColumn); mJournals.addColumn (new RecordStateColumn); + mJournals.addColumn (new DialogueTypeColumn (true)); mCells.addColumn (new StringIdColumn); mCells.addColumn (new RecordStateColumn); diff --git a/apps/opencs/view/world/dialoguecreator.cpp b/apps/opencs/view/world/dialoguecreator.cpp new file mode 100644 index 000000000..c16214283 --- /dev/null +++ b/apps/opencs/view/world/dialoguecreator.cpp @@ -0,0 +1,35 @@ + +#include "dialoguecreator.hpp" + +#include + +#include "../../model/world/data.hpp" +#include "../../model/world/commands.hpp" +#include "../../model/world/columns.hpp" +#include "../../model/world/idtable.hpp" + +void CSVWorld::DialogueCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const +{ + int index = + dynamic_cast (*getData().getTableModel (getCollectionId())). + findColumnIndex (CSMWorld::Columns::ColumnId_DialogueType); + + command.addValue (index, mType); +} + +CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id, int type) +: GenericCreator (data, undoStack, id), mType (type) +{} + +CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data, + QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +{ + return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic); +} + +CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data, + QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +{ + return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal); +} \ No newline at end of file diff --git a/apps/opencs/view/world/dialoguecreator.hpp b/apps/opencs/view/world/dialoguecreator.hpp new file mode 100644 index 000000000..26f866909 --- /dev/null +++ b/apps/opencs/view/world/dialoguecreator.hpp @@ -0,0 +1,41 @@ +#ifndef CSV_WORLD_DIALOGUECREATOR_H +#define CSV_WORLD_DIALOGUECREATOR_H + +#include "genericcreator.hpp" + +namespace CSVWorld +{ + class DialogueCreator : public GenericCreator + { + int mType; + + protected: + + virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + + public: + + DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id, int type); + }; + + class TopicCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; + + class JournalCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; +} + +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 417a7258f..3d98cf73c 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -14,6 +14,7 @@ #include "referenceablecreator.hpp" #include "referencecreator.hpp" #include "scenesubview.hpp" +#include "dialoguecreator.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -36,8 +37,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, - CSMWorld::UniversalId::Type_Topics, - CSMWorld::UniversalId::Type_Journals, CSMWorld::UniversalId::Type_None // end marker }; @@ -55,6 +54,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_References, new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Topics, + new CSVDoc::SubViewFactoryWithCreator); + + manager.add (CSMWorld::UniversalId::Type_Journal, + new CSVDoc::SubViewFactoryWithCreator); + // Subviews for editing/viewing individual records manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); From c0e550143108e81ffcb6ee896e1ea0dfaeffaff8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Oct 2013 13:58:47 +0200 Subject: [PATCH 79/81] disallow the deletion of non-topic, non-journal dialogue records --- apps/opencs/view/world/table.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 6167c084a..a58eb873f 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -87,19 +87,33 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const { QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); + // check record state CSMWorld::RecordBase::State state = static_cast ( mModel->data (mModel->index (index.row(), 1)).toInt()); - if (state!=CSMWorld::RecordBase::State_Deleted) - { - int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); + if (state==CSMWorld::RecordBase::State_Deleted) + continue; - std::string id = mModel->data (mModel->index (index.row(), columnIndex)). - toString().toUtf8().constData(); + // check other columns (only relevant for a subset of the tables) + int dialogueTypeIndex = + mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType); - deletableIds.push_back (id); + if (dialogueTypeIndex!=-1) + { + int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt(); + + if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal) + continue; } + + // add the id to the collection + int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); + + std::string id = mModel->data (mModel->index (index.row(), columnIndex)). + toString().toUtf8().constData(); + + deletableIds.push_back (id); } } From dc12648a3efd8da82e148d2610536753434eff73 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Oct 2013 14:26:54 +0200 Subject: [PATCH 80/81] add fixed dialogue records when creating a new omwgame file --- apps/opencs/model/doc/document.cpp | 73 ++++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 6 +-- apps/opencs/model/world/data.hpp | 4 +- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d7138f671..64f627b5a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2137,6 +2137,79 @@ void CSMDoc::Document::createBase() getData().getSkills().add (record); } + + static const char *sVoice[] = + { + "Intruder", + "Attack", + "Hello", + "Thief", + "Alarm", + "Idle", + "Flee", + "Hit", + 0 + }; + + for (int i=0; sVoice[i]; ++i) + { + ESM::Dialogue record; + record.mId = sVoice[i]; + record.mType = ESM::Dialogue::Voice; + record.blank(); + + getData().getTopics().add (record); + } + + static const char *sGreetings[] = + { + "Greeting 0", + "Greeting 1", + "Greeting 2", + "Greeting 3", + "Greeting 4", + "Greeting 5", + "Greeting 6", + "Greeting 7", + "Greeting 8", + "Greeting 9", + 0 + }; + + for (int i=0; sGreetings[i]; ++i) + { + ESM::Dialogue record; + record.mId = sGreetings[i]; + record.mType = ESM::Dialogue::Greeting; + record.blank(); + + getData().getTopics().add (record); + } + + static const char *sPersuasion[] = + { + "Intimidate Success", + "Intimidate Fail", + "Service Refusal", + "Admire Success", + "Taunt Success", + "Bribe Success", + "Info Refusal", + "Admire Fail", + "Taunt Fail", + "Bribe Fail", + 0 + }; + + for (int i=0; sPersuasion[i]; ++i) + { + ESM::Dialogue record; + record.mId = sPersuasion[i]; + record.mType = ESM::Dialogue::Persuasion; + record.blank(); + + getData().getTopics().add (record); + } } CSMDoc::Document::Document (const std::vector& files, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 70e0e891d..c854711b1 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -330,12 +330,12 @@ CSMWorld::IdCollection& CSMWorld::Data::getSpells() } -const CSMWorld::IdCollection& CSMWorld::Data::getTopcis() const +const CSMWorld::IdCollection& CSMWorld::Data::getTopics() const { return mTopics; } -CSMWorld::IdCollection& CSMWorld::Data::getTopcis() +CSMWorld::IdCollection& CSMWorld::Data::getTopics() { return mTopics; } @@ -525,7 +525,7 @@ bool CSMWorld::Data::hasId (const std::string& id) const getRegions().searchId (id)!=-1 || getBirthsigns().searchId (id)!=-1 || getSpells().searchId (id)!=-1 || - getTopcis().searchId (id)!=-1 || + getTopics().searchId (id)!=-1 || getJournals().searchId (id)!=-1 || getCells().searchId (id)!=-1 || getReferenceables().searchId (id)!=-1; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 74304e029..cf31c9494 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -119,9 +119,9 @@ namespace CSMWorld IdCollection& getSpells(); - const IdCollection& getTopcis() const; + const IdCollection& getTopics() const; - IdCollection& getTopcis(); + IdCollection& getTopics(); const IdCollection& getJournals() const; From 3b85d970872afc58954c1f5b9e3ec2951b5a2fb5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Oct 2013 15:38:13 +0200 Subject: [PATCH 81/81] handle deleted dialogue records --- apps/opencs/model/world/data.cpp | 13 +++++++++- apps/opencs/model/world/idcollection.hpp | 32 +++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c854711b1..130ce334f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -493,7 +493,18 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) } else if (record.mType==ESM::Dialogue::Deleted) { - /// \todo handle deleted records + if (mJournals.tryDelete (id)) + { + /// \todo handle info records + } + else if (mTopics.tryDelete (id)) + { + /// \todo handle info records + } + else + { + /// \todo report deletion of non-existing record + } } else { diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index b6ae04572..0d723bef1 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -7,7 +7,6 @@ namespace CSMWorld { - /// \brief Single type collection of top level records template > class IdCollection : public Collection @@ -17,6 +16,11 @@ namespace CSMWorld void load (ESM::ESMReader& reader, bool base); void load (const ESXRecordT& record, bool base); + + bool tryDelete (const std::string& id); + ///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored. + /// + /// \return Has the ID been deleted? }; template @@ -86,6 +90,32 @@ namespace CSMWorld this->setRecord (index, record2); } } + + template + bool IdCollection::tryDelete (const std::string& id) + { + int index = this->searchId (id); + + if (index==-1) + return false; + + Record record = Collection::getRecord (index); + + if (record.isDeleted()) + return false; + + if (record.mState==RecordBase::State_ModifiedOnly) + { + Collection::removeRows (index, 1); + } + else + { + record.mState = RecordBase::State_Deleted; + setRecord (index, record); + } + + return true; + } } #endif