Merge branch 'master' into graphics

actorid
scrawl 12 years ago
commit 7ad1e962e0

1
.gitignore vendored

@ -17,3 +17,4 @@ data
CMakeLists.txt.user
*.swp
*.swo
*.kate-swp

@ -227,7 +227,10 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
std::cout << " Refnum: " << ref.mRefnum << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n";
std::cout << " Owner: '" << ref.mOwner << "'\n";
std::cout << " INTV: " << ref.mIntv << " NAM9: " << ref.mIntv << std::endl;
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
}
}

@ -275,7 +275,7 @@ RecordBase::create(ESM::NAME type)
}
case ESM::REC_LOCK:
{
record = new EsmTool::Record<ESM::Tool>;
record = new EsmTool::Record<ESM::Lockpick>;
break;
}
case ESM::REC_LTEX:
@ -864,14 +864,13 @@ void Record<ESM::Light>::print()
}
template<>
void Record<ESM::Tool>::print()
void Record<ESM::Lockpick>::print()
{
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -886,8 +885,6 @@ void Record<ESM::Probe>::print()
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
// BUG? No Type Label?
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -902,7 +899,6 @@ void Record<ESM::Repair>::print()
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;

@ -104,7 +104,7 @@ namespace EsmTool
template<> void Record<ESM::CreatureLevList>::print();
template<> void Record<ESM::ItemLevList>::print();
template<> void Record<ESM::Light>::print();
template<> void Record<ESM::Tool>::print();
template<> void Record<ESM::Lockpick>::print();
template<> void Record<ESM::Probe>::print();
template<> void Record<ESM::Repair>::print();
template<> void Record<ESM::LandTexture>::print();

@ -22,3 +22,8 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(mwiniimport gcov)
endif()
if(DPKG_PROGRAM)
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
endif()

@ -35,7 +35,7 @@ opencs_units (model/tools
)
opencs_units_noqt (model/tools
stage verifier mandatoryid
stage verifier mandatoryid skillcheck
)

@ -2,7 +2,7 @@
#include "document.hpp"
#include <cassert>
#include <QDebug>
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
{
@ -150,6 +150,10 @@ void CSMDoc::Document::addOptionalGlobals()
ESM::Global global;
global.mId = sGlobals[i];
global.mValue.setType (ESM::VT_Long);
if (i==0)
global.mValue.setInteger (1); // dayspassed starts counting at 1
addOptionalGlobal (global);
}
}
@ -189,15 +193,25 @@ void CSMDoc::Document::createBase()
record.mId = sGlobals[i];
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int);
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Long);
if (i==0)
if (i==0 || i==1)
record.mValue.setInteger (1);
getData().getGlobals().add (record);
}
/// \todo add GMSTs
for (int i=0; i<27; ++i)
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::Skill::getIndexToId (record.mIndex);
record.blank();
getData().getSkills().add (record);
}
}
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
@ -214,7 +228,7 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
if (new_ && files.size()==1)
createBase();
else if (files.size()>1)
else
{
std::vector<boost::filesystem::path>::const_iterator end = files.end();

@ -0,0 +1,37 @@
#include "skillcheck.hpp"
#include <sstream>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
: mSkills (skills)
{}
int CSMTools::SkillCheckStage::setup()
{
return mSkills.getSize();
}
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);
for (int i=0; i<4; ++i)
if (skill.mData.mUseValue[i]<0)
{
std::ostringstream stream;
stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative";
messages.push_back (stream.str());
}
if (skill.mDescription.empty())
messages.push_back (id.toString() + "|" + skill.mId + " has an empty description");
}

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SKILLCHECK_H
#define CSM_TOOLS_SKILLCHECK_H
#include <components/esm/loadskil.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that skill records are internally consistent
class SkillCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
public:
SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

@ -12,6 +12,7 @@
#include "reportmodel.hpp"
#include "mandatoryid.hpp"
#include "skillcheck.hpp"
CSMTools::Operation *CSMTools::Tools::get (int type)
{
@ -51,6 +52,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills()));
}
return mVerifier;

@ -31,7 +31,9 @@ namespace CSMWorld
Display_Float,
Display_Var,
Display_GmstVarType,
Display_GlobalVarType
Display_GlobalVarType,
Display_Specialisation,
Display_Attribute
};
std::string mTitle;

@ -1,6 +1,8 @@
#ifndef CSM_WOLRD_COLUMNS_H
#define CSM_WOLRD_COLUMNS_H
#include <boost/lexical_cast.hpp>
#include "columnbase.hpp"
namespace CSMWorld
@ -35,7 +37,7 @@ namespace CSMWorld
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mId.c_str();
return QString::fromUtf8 (record.get().mId.c_str());
}
virtual bool isEditable() const
@ -127,17 +129,17 @@ namespace CSMWorld
{
case ESM::VT_String:
return record.get().mValue.getString().c_str(); break;
return QString::fromUtf8 (record.get().mValue.getString().c_str());
case ESM::VT_Int:
case ESM::VT_Short:
case ESM::VT_Long:
return record.get().mValue.getInteger(); break;
return record.get().mValue.getInteger();
case ESM::VT_Float:
return record.get().mValue.getFloat(); break;
return record.get().mValue.getFloat();
default: return QVariant();
}
@ -177,6 +179,112 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct DescriptionColumn : public Column<ESXRecordT>
{
DescriptionColumn() : Column<ESXRecordT> ("Description", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mDescription.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mDescription = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SpecialisationColumn : public Column<ESXRecordT>
{
SpecialisationColumn() : Column<ESXRecordT> ("Specialisation", ColumnBase::Display_Specialisation) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mSpecialization;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mSpecialization = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct UseValueColumn : public Column<ESXRecordT>
{
int mIndex;
UseValueColumn (int index)
: Column<ESXRecordT> ("Use value #" + boost::lexical_cast<std::string> (index),
ColumnBase::Display_Float), mIndex (index)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mUseValue[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mUseValue[mIndex] = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AttributeColumn : public Column<ESXRecordT>
{
AttributeColumn() : Column<ESXRecordT> ("Attribute", ColumnBase::Display_Attribute) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAttribute;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAttribute = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -1,7 +1,7 @@
#include "commands.hpp"
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include "idtableproxymodel.hpp"
#include "idtable.hpp"

@ -3,7 +3,7 @@
#include <stdexcept>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp>
@ -12,7 +12,7 @@
#include "idtable.hpp"
#include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractTableModel *model, UniversalId::Type type1,
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2)
{
mModels.push_back (model);
@ -36,13 +36,22 @@ CSMWorld::Data::Data()
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
mSkills.addColumn (new StringIdColumn<ESM::Skill>);
mSkills.addColumn (new RecordStateColumn<ESM::Skill>);
mSkills.addColumn (new AttributeColumn<ESM::Skill>);
mSkills.addColumn (new SpecialisationColumn<ESM::Skill>);
for (int i=0; i<4; ++i)
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
}
CSMWorld::Data::~Data()
{
for (std::vector<QAbstractTableModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
delete *iter;
}
@ -66,9 +75,19 @@ CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
return mGmsts;
}
QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id)
const CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills() const
{
return mSkills;
}
CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills()
{
std::map<UniversalId::Type, QAbstractTableModel *>::iterator iter = mModelIndex.find (id.getType());
return mSkills;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
if (iter==mModelIndex.end())
throw std::logic_error ("No table model available for " + id.toString());
@ -102,7 +121,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
{
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
case ESM::REC_GMST: mGmsts.load (reader, base); break;
case ESM::REC_SKIL: mSkills.load (reader, base); break;
default:

@ -8,11 +8,12 @@
#include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp>
#include "idcollection.hpp"
#include "universalid.hpp"
class QAbstractTableModel;
class QAbstractItemModel;
namespace CSMWorld
{
@ -20,14 +21,15 @@ namespace CSMWorld
{
IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts;
std::vector<QAbstractTableModel *> mModels;
std::map<UniversalId::Type, QAbstractTableModel *> mModelIndex;
IdCollection<ESM::Skill> mSkills;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
// not implemented
Data (const Data&);
Data& operator= (const Data&);
void addModel (QAbstractTableModel *model, UniversalId::Type type1,
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None);
public:
@ -44,7 +46,11 @@ namespace CSMWorld
IdCollection<ESM::GameSetting>& getGmsts();
QAbstractTableModel *getTableModel (const UniversalId& id);
const IdCollection<ESM::Skill>& getSkills() const;
IdCollection<ESM::Skill>& getSkills();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///
/// \note The returned table may either be the model for the ID itself or the model that

@ -74,6 +74,8 @@ namespace CSMWorld
virtual const RecordBase& getRecord (const std::string& id) const = 0;
virtual const RecordBase& getRecord (int index) const = 0;
virtual void load (ESM::ESMReader& reader, bool base) = 0;
};
@ -139,7 +141,9 @@ namespace CSMWorld
///
/// \attention Throw san exception, if the type of \a record does not match.
virtual const RecordBase& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base);
@ -373,11 +377,18 @@ namespace CSMWorld
}
template<typename ESXRecordT>
const RecordBase& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
{
int index = getIndex (id);
return mRecords.at (index);
}
template<typename ESXRecordT>
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (int index) const
{
return mRecords.at (index);
}
}
#endif

@ -96,6 +96,25 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren
return true;
}
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
{
if (parent.isValid())
return QModelIndex();
if (row<0 || row>=mIdCollection->getSize())
return QModelIndex();
if (column<0 || column>=mIdCollection->getColumns())
return QModelIndex();
return createIndex (row, column);
}
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
{
return QModelIndex();
}
void CSMWorld::IdTable::addRecord (const std::string& id)
{
int index = mIdCollection->getSize();

@ -1,14 +1,14 @@
#ifndef CSM_WOLRD_IDTABLE_H
#define CSM_WOLRD_IDTABLE_H
#include <QAbstractTableModel>
#include <QAbstractItemModel>
namespace CSMWorld
{
class IdCollectionBase;
class RecordBase;
class IdTable : public QAbstractTableModel
class IdTable : public QAbstractItemModel
{
Q_OBJECT
@ -39,6 +39,11 @@ namespace CSMWorld
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex())
const;
virtual QModelIndex parent (const QModelIndex& index) const;
void addRecord (const std::string& id);
QModelIndex getModelIndex (const std::string& id, int column) const;

@ -62,7 +62,7 @@ namespace CSMWorld
if (mState==State_Erased)
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly ? mBase : mModified;
return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
}
template <typename ESXRecordT>
@ -81,9 +81,7 @@ namespace CSMWorld
throw std::logic_error ("attempt to modify a deleted record");
mModified = modified;
if (mState!=State_ModifiedOnly)
mState = mBase==mModified ? State_BaseOnly : State_Modified;
mState = State_Modified;
}
template <typename ESXRecordT>

@ -19,6 +19,7 @@ namespace
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -27,6 +28,7 @@ namespace
{
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -43,7 +45,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId)
{
std::string::size_type index = universalId.find (':');
if (index==std::string::npos)
if (index!=std::string::npos)
{
std::string type = universalId.substr (0, index);

@ -37,8 +37,9 @@ namespace CSMWorld
Type_Global,
Type_VerificationResults,
Type_Gmsts,
Type_Gmst
Type_Gmst,
Type_Skills,
Type_Skill
};
private:

@ -86,6 +86,10 @@ void CSVDoc::View::setupWorldMenu()
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
world->addAction (gmsts);
QAction *skills = new QAction (tr ("Skills"), this);
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
world->addAction (skills);
mVerify = new QAction (tr ("&Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
world->addAction (mVerify);
@ -244,6 +248,11 @@ void CSVDoc::View::addGmstsSubView()
addSubView (CSMWorld::UniversalId::Type_Gmsts);
}
void CSVDoc::View::addSkillsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Skills);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -116,6 +116,7 @@ namespace CSVDoc
void addGmstsSubView();
void addSkillsSubView();
};
}

@ -38,6 +38,17 @@ void CSVDoc::ViewManager::updateIndices()
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{
static const char *sSpecialisations[] =
{
"Combat", "Magic", "Stealth", 0
};
static const char *sAttributes[] =
{
"Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
"Luck", 0
};
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
@ -45,6 +56,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
new CSVWorld::EnumDelegateFactory (sSpecialisations));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
new CSVWorld::EnumDelegateFactory (sAttributes));
}
CSVDoc::ViewManager::~ViewManager()

@ -3,7 +3,7 @@
#include <QGridLayout>
#include <QLabel>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QLineEdit>
@ -24,7 +24,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
widget->setLayout (layout);
QAbstractTableModel *model = document.getData().getTableModel (id);
QAbstractItemModel *model = document.getData().getTableModel (id);
int columns = model->columnCount();

@ -1,6 +1,7 @@
#include "enumdelegate.hpp"
#include <cassert>
#include <stdexcept>
#include <QComboBox>
@ -89,6 +90,16 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte
}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names)
{
assert (names);
for (int i=0; names[i]; ++i)
add (i, names[i]);
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{

@ -45,6 +45,11 @@ namespace CSVWorld
public:
EnumDelegateFactory();
EnumDelegateFactory (const char **names);
///< \param names Array of char pointer with a 0-pointer as end mark
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.

@ -14,6 +14,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Gmsts,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Skills,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Global,
new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
}

@ -31,6 +31,7 @@ add_openmw_dir (mwgui
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons
merchantrepair repair
)
add_openmw_dir (mwdialogue
@ -53,7 +54,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback
esmstore store recordcmp fallback actionrepair
)
add_openmw_dir (mwclass
@ -64,7 +65,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate
aiescort aiactivate repair enchanting
)
add_openmw_dir (mwbase

@ -238,6 +238,8 @@ namespace MWBase
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
virtual void startTraining(MWWorld::Ptr actor) = 0;
virtual void startRepair(MWWorld::Ptr actor) = 0;
virtual void startRepairItem(MWWorld::Ptr item) = 0;
virtual void changePointer (const std::string& name) = 0;

@ -244,27 +244,44 @@ namespace MWBase
///< Toggle a render mode.
///< \return Resulting mode
virtual const ESM::Potion *createRecord (const ESM::Potion& record)
= 0;
///< Create a new recrod (of type potion) in the ESM store.
virtual const ESM::Potion *createRecord (const ESM::Potion& record) = 0;
///< Create a new record (of type potion) in the ESM store.
/// \return pointer to created record
virtual const ESM::Spell *createRecord (const ESM::Spell& record)
= 0;
///< Create a new recrod (of type spell) in the ESM store.
virtual const ESM::Spell *createRecord (const ESM::Spell& record) = 0;
///< Create a new record (of type spell) in the ESM store.
/// \return pointer to created record
virtual const ESM::Class *createRecord (const ESM::Class& record)
= 0;
///< Create a new recrod (of type class) in the ESM store.
virtual const ESM::Class *createRecord (const ESM::Class& record) = 0;
///< Create a new record (of type class) in the ESM store.
/// \return pointer to created record
virtual const ESM::Cell *createRecord (const ESM::Cell& record) = 0;
///< Create a new recrod (of type cell) in the ESM store.
///< Create a new record (of type cell) in the ESM store.
/// \return pointer to created record
virtual const ESM::NPC *createRecord(const ESM::NPC &record) = 0;
///< Create a new recrod (of type npc) in the ESM store.
///< Create a new record (of type npc) in the ESM store.
/// \return pointer to created record
virtual const ESM::Armor *createRecord (const ESM::Armor& record) = 0;
///< Create a new record (of type armor) in the ESM store.
/// \return pointer to created record
virtual const ESM::Weapon *createRecord (const ESM::Weapon& record) = 0;
///< Create a new record (of type weapon) in the ESM store.
/// \return pointer to created record
virtual const ESM::Clothing *createRecord (const ESM::Clothing& record) = 0;
///< Create a new record (of type clothing) in the ESM store.
/// \return pointer to created record
virtual const ESM::Enchantment *createRecord (const ESM::Enchantment& record) = 0;
///< Create a new record (of type enchantment) in the ESM store.
/// \return pointer to created record
virtual const ESM::Book *createRecord (const ESM::Book& record) = 0;
///< Create a new record (of type book) in the ESM store.
/// \return pointer to created record
virtual void update (float duration, bool paused) = 0;

@ -247,8 +247,9 @@ namespace MWClass
text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor);
/// \todo store the current armor health somewhere
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth;
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/"
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")";
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -273,6 +274,20 @@ namespace MWClass
return ref->mBase->mEnchant;
}
std::string Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{
MWWorld::LiveCellRef<ESM::Armor> *ref =
ptr.get<ESM::Armor>();
ESM::Armor newItem = *ref->mBase;
newItem.mId="";
newItem.mName=newName;
newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId;
const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId;
}
boost::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const
{
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
@ -290,4 +305,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell);
}
short Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Armor> *ref =
ptr.get<ESM::Armor>();
return ref->mBase->mData.mEnchant;
}
}

@ -65,11 +65,15 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
};
}

@ -147,6 +147,21 @@ namespace MWClass
return ref->mBase->mEnchant;
}
std::string Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{
MWWorld::LiveCellRef<ESM::Book> *ref =
ptr.get<ESM::Book>();
ESM::Book newItem = *ref->mBase;
newItem.mId="";
newItem.mName=newName;
newItem.mData.mIsScroll = 1;
newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId;
const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId;
}
boost::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr) const
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionRead(ptr));
@ -160,4 +175,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell);
}
short Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Book> *ref =
ptr.get<ESM::Book>();
return ref->mBase->mData.mEnchant;
}
}

@ -51,10 +51,14 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
};
}

@ -221,6 +221,20 @@ namespace MWClass
return ref->mBase->mEnchant;
}
std::string Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{
MWWorld::LiveCellRef<ESM::Clothing> *ref =
ptr.get<ESM::Clothing>();
ESM::Clothing newItem = *ref->mBase;
newItem.mId="";
newItem.mName=newName;
newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId;
const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId;
}
boost::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const
{
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
@ -238,4 +252,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell);
}
short Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Clothing> *ref =
ptr.get<ESM::Clothing>();
return ref->mBase->mData.mEnchant;
}
}

@ -59,11 +59,15 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
};
}

@ -1,7 +1,7 @@
#include "lockpick.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadlock.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -41,8 +41,8 @@ namespace MWClass
std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
assert(ref->mBase != NULL);
const std::string &model = ref->mBase->mModel;
@ -54,8 +54,8 @@ namespace MWClass
std::string Lockpick::getName (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mName;
}
@ -75,8 +75,8 @@ namespace MWClass
std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mScript;
}
@ -92,8 +92,8 @@ namespace MWClass
int Lockpick::getValue (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mData.mValue;
}
@ -102,7 +102,7 @@ namespace MWClass
{
boost::shared_ptr<Class> instance (new Lockpick);
registerClass (typeid (ESM::Tool).name(), instance);
registerClass (typeid (ESM::Lockpick).name(), instance);
}
std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr) const
@ -117,24 +117,24 @@ namespace MWClass
std::string Lockpick::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mIcon;
}
bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return (ref->mBase->mName != "");
}
MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
MWGui::ToolTipInfo info;
info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
@ -142,9 +142,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -171,8 +171,8 @@ namespace MWClass
MWWorld::Ptr
Lockpick::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell);
}

@ -89,7 +89,15 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();
return ref->mBase->mData.mValue;
int value = (ptr.getCellRef().mGoldValue == 1) ? ref->mBase->mData.mValue : ptr.getCellRef().mGoldValue;
if (ptr.getCellRef().mSoul != "")
{
const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(ref->mRef.mSoul);
value *= creature->mData.mSoul;
}
return value;
}
void Miscellaneous::registerSelf()
@ -151,8 +159,10 @@ namespace MWClass
int count = ptr.getRefData().getCount();
bool isGold = (ref->mBase->mName == store.get<ESM::GameSetting>().find("sGold")->getString());
if (isGold && count == 1)
count = ref->mBase->mData.mValue;
if (isGold && ptr.getCellRef().mGoldValue != 1)
count = ptr.getCellRef().mGoldValue;
else if (isGold)
count *= ref->mBase->mData.mValue;
std::string countString;
if (!isGold)
@ -174,7 +184,7 @@ namespace MWClass
if (!isGold)
{
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
}
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
@ -214,7 +224,8 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
newRef.getPtr().get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
newPtr.getRefData ().setCount(goldAmount);
newPtr.getRefData ().setCount(1);
newPtr.getCellRef().mGoldValue = goldAmount;
} else {
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();

@ -1,7 +1,7 @@
#include "probe.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadprob.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -141,9 +141,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");

@ -1,7 +1,7 @@
#include "repair.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadrepa.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -12,6 +12,7 @@
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/actionrepair.hpp"
#include "../mwgui/tooltips.hpp"
@ -120,6 +121,19 @@ namespace MWClass
return (ref->mBase->mName != "");
}
bool Repair::hasItemHealth (const MWWorld::Ptr& ptr) const
{
return true;
}
int Repair::getItemMaxHealth (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
ptr.get<ESM::Repair>();
return ref->mBase->mData.mUses;
}
MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
@ -131,9 +145,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -156,4 +170,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mRepairs.insert(*ref), &cell);
}
boost::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr) const
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionRepair(ptr));
}
}

@ -49,6 +49,18 @@ namespace MWClass
///< Return name of inventory icon.
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu (default implementation: return a
/// null action).
virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const;
///< \return Item health data available? (default implementation: false)
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
/// (default implementation: throw an exceoption)
};
}

@ -75,7 +75,10 @@ namespace MWClass
bool Weapon::hasItemHealth (const MWWorld::Ptr& ptr) const
{
return true;
MWWorld::LiveCellRef<ESM::Weapon> *ref =
ptr.get<ESM::Weapon>();
return (ref->mBase->mData.mType < 11); // thrown weapons and arrows/bolts don't have health, only quantity
}
int Weapon::getItemMaxHealth (const MWWorld::Ptr& ptr) const
@ -334,9 +337,12 @@ namespace MWClass
}
}
/// \todo store the current weapon health somewhere
if (ref->mBase->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
{
int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth;
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/"
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
}
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -361,6 +367,20 @@ namespace MWClass
return ref->mBase->mEnchant;
}
std::string Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{
MWWorld::LiveCellRef<ESM::Weapon> *ref =
ptr.get<ESM::Weapon>();
ESM::Weapon newItem = *ref->mBase;
newItem.mId="";
newItem.mName=newName;
newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId;
const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId;
}
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
{
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
@ -378,4 +398,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mWeapons.insert(*ref), &cell);
}
short Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Weapon> *ref =
ptr.get<ESM::Weapon>();
return ref->mBase->mData.mEnchant;
}
}

@ -65,11 +65,15 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
};
}

@ -367,6 +367,9 @@ namespace MWDialogue
if (services & ESM::NPC::Enchanting)
windowServices |= MWGui::DialogueWindow::Service_Enchant;
if (services & ESM::NPC::Repair)
windowServices |= MWGui::DialogueWindow::Service_Repair;
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->setServices (windowServices);

@ -136,8 +136,12 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
{
if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name())
return select.isInverted();
if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name()))
// If the actor is a creature, we do not test the conditions applicable
// only to NPCs. Such conditions can never be satisfied, apart
// inverted ones (NotClass, NotRace, NotFaction return true
// because creatures are not of any race, class or faction).
return select.getType() == SelectWrapper::Type_Inverted;
switch (select.getType())
{
@ -145,6 +149,9 @@ bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select));
case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select);
case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select));
// We must not do the comparison for inverted functions (eg. Function_NotClass)
case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select);
}
return true;
@ -433,6 +440,30 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
return Misc::StringUtils::lowerCase (mActor.getCell()->mCell->mName)!=select.getName();
case SelectWrapper::Function_NotLocal:
{
std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor);
if (scriptName.empty())
// This actor has no attached script, so there is no local variable
return true;
const ESM::Script *script =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName);
std::string name = select.getName();
int i = 0;
for (; i < static_cast<int> (script->mVarNames.size()); ++i)
if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name)
break;
if (i >= static_cast<int> (script->mVarNames.size()))
return true; // script does not have a variable of this name
return false;
}
case SelectWrapper::Function_SameGender:
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==

@ -117,7 +117,7 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() con
case '9': return Function_NotClass;
case 'A': return Function_NotRace;
case 'B': return Function_NotCell;
case 'C': return Function_Local;
case 'C': return Function_NotLocal;
}
return Function_None;
@ -219,7 +219,6 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
static const Function booleanFunctions[] =
{
Function_False,
Function_NotId, Function_NotFaction, Function_NotClass, Function_NotRace, Function_NotCell,
Function_SameGender, Function_SameRace, Function_SameFaction,
Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus,
Function_PcExpelled,
@ -231,6 +230,13 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
Function_None // end marker
};
static const Function invertedBooleanFunctions[] =
{
Function_NotId, Function_NotFaction, Function_NotClass,
Function_NotRace, Function_NotCell, Function_NotLocal,
Function_None // end marker
};
Function function = getFunction();
for (int i=0; integerFunctions[i]!=Function_None; ++i)
@ -245,21 +251,18 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
if (booleanFunctions[i]==function)
return Type_Boolean;
return Type_None;
}
bool MWDialogue::SelectWrapper::isInverted() const
{
char type = mSelect.mSelectRule[1];
for (int i=0; invertedBooleanFunctions[i]!=Function_None; ++i)
if (invertedBooleanFunctions[i]==function)
return Type_Inverted;
return type=='7' || type=='8' || type=='9' || type=='A' || type=='B' || type=='C';
return Type_None;
}
bool MWDialogue::SelectWrapper::isNpcOnly() const
{
static const Function functions[] =
{
Function_NotFaction, SelectWrapper::Function_NotClass, SelectWrapper::Function_NotRace,
Function_NotFaction, Function_NotClass, Function_NotRace,
Function_SameGender, Function_SameRace, Function_SameFaction,
Function_PcSkill,
Function_PcExpelled,
@ -283,17 +286,17 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const
bool MWDialogue::SelectWrapper::selectCompare (int value) const
{
return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR
return selectCompareImp (mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare (float value) const
{
return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR
return selectCompareImp (mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare (bool value) const
{
return selectCompareImp (mSelect, static_cast<int> (value))!=isInverted(); // logic XOR
return selectCompareImp (mSelect, static_cast<int> (value));
}
std::string MWDialogue::SelectWrapper::getName() const

@ -22,6 +22,7 @@ namespace MWDialogue
Function_NotClass,
Function_NotRace,
Function_NotCell,
Function_NotLocal,
Function_Local,
Function_Global,
Function_SameGender, Function_SameRace, Function_SameFaction,
@ -50,7 +51,8 @@ namespace MWDialogue
Type_None,
Type_Integer,
Type_Numeric,
Type_Boolean
Type_Boolean,
Type_Inverted
};
private:
@ -67,8 +69,6 @@ namespace MWDialogue
Type getType() const;
bool isInverted() const;
bool isNpcOnly() const;
///< \attention Do not call any of the select functions for this select struct!

@ -45,7 +45,7 @@ namespace
mapping.push_back( typeid(ESM::Book).name() );
mapping.push_back( typeid(ESM::Light).name() );
mapping.push_back( typeid(ESM::Miscellaneous).name() );
mapping.push_back( typeid(ESM::Tool).name() );
mapping.push_back( typeid(ESM::Lockpick).name() );
mapping.push_back( typeid(ESM::Repair).name() );
mapping.push_back( typeid(ESM::Probe).name() );
@ -68,6 +68,16 @@ namespace
return compareType(left.getTypeName(), right.getTypeName());
}
}
bool isChargedSoulstone (MWWorld::Ptr ptr)
{
if (ptr.getTypeName() != typeid(ESM::Miscellaneous).name())
return false;
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();
return (ref->mRef.mSoul != "");
}
}
@ -345,7 +355,7 @@ void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel)
mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0));
}
void ContainerBase::setFilter(ContainerBase::Filter filter)
void ContainerBase::setFilter(int filter)
{
mFilter = filter;
drawItems();
@ -369,29 +379,34 @@ void ContainerBase::drawItems()
int maxHeight = mItemView->getSize().height - 58;
bool onlyMagic = false;
bool noMagic = false;
int categories = 0;
if (mFilter == Filter_All)
categories = MWWorld::ContainerStore::Type_All;
else if (mFilter == Filter_Weapon)
categories = MWWorld::ContainerStore::Type_Weapon;
else if (mFilter == Filter_Apparel)
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor;
else if (mFilter == Filter_Magic)
if (mFilter & Filter_All)
categories |= MWWorld::ContainerStore::Type_All;
if (mFilter & Filter_Weapon)
categories |= MWWorld::ContainerStore::Type_Weapon;
if (mFilter & Filter_Apparel)
categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor;
if (mFilter & Filter_Magic)
{
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor
+ MWWorld::ContainerStore::Type_Weapon + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Potion;
categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor
| MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Book
| MWWorld::ContainerStore::Type_Potion;
onlyMagic = true;
}
else if (mFilter == Filter_Misc)
if (mFilter & Filter_Misc)
{
categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair
+ MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light
+ MWWorld::ContainerStore::Type_Apparatus + MWWorld::ContainerStore::Type_Probe;
categories |= MWWorld::ContainerStore::Type_Miscellaneous | MWWorld::ContainerStore::Type_Book
| MWWorld::ContainerStore::Type_Ingredient | MWWorld::ContainerStore::Type_Repair
| MWWorld::ContainerStore::Type_Lockpick | MWWorld::ContainerStore::Type_Light
| MWWorld::ContainerStore::Type_Apparatus | MWWorld::ContainerStore::Type_Probe;
}
else if (mFilter == Filter_Ingredients)
categories = MWWorld::ContainerStore::Type_Ingredient;
if (mFilter & Filter_Ingredients)
categories |= MWWorld::ContainerStore::Type_Ingredient;
if (mFilter & Filter_ChargedSoulstones)
categories |= MWWorld::ContainerStore::Type_Miscellaneous;
if (mFilter & Filter_NoMagic)
noMagic = true;
/// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
@ -466,12 +481,29 @@ void ContainerBase::drawItems()
{
const MWWorld::Ptr* iter = &((*it).first);
if (onlyMagic
&& it->second != ItemState_Barter
&& MWWorld::Class::get(*iter).getEnchantment(*iter) == ""
&& iter->getTypeName() != typeid(ESM::Potion).name())
continue;
if (noMagic
&& it->second != ItemState_Barter
&& (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""
|| iter->getTypeName() == typeid(ESM::Potion).name()))
continue;
if ( (mFilter & Filter_ChargedSoulstones)
&& !isChargedSoulstone(*iter))
continue;
int displayCount = iter->getRefData().getCount();
if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>())
{
displayCount -= mDragAndDrop->mDraggedCount;
}
if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name()))
if(displayCount > 0)
{
std::string path = std::string("icons\\");
path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);

@ -48,16 +48,17 @@ namespace MWGui
ContainerBase(DragAndDrop* dragAndDrop);
virtual ~ContainerBase();
enum Filter
{
Filter_All = 0x01,
Filter_Weapon = 0x02,
Filter_Apparel = 0x03,
Filter_Magic = 0x04,
Filter_Misc = 0x05,
Filter_Ingredients = 0x06
};
// basic types (inclusive)
static const int Filter_All = (1<<0);
static const int Filter_Weapon = (1<<1);
static const int Filter_Apparel = (1<<2);
static const int Filter_Ingredients = (1<<3);
static const int Filter_Misc = (1<<4);
// special filtering (exclusive)
static const int Filter_Magic = (1<<5);
static const int Filter_NoMagic = (1<<6);
static const int Filter_ChargedSoulstones = (1<<7);
enum ItemState
{
@ -78,7 +79,7 @@ namespace MWGui
MWWorld::ContainerStore& getBoughtItems() { return mBoughtItems; }
void openContainer(MWWorld::Ptr container);
void setFilter(Filter filter); ///< set category filter
void setFilter(int filter); ///< set category filter
void drawItems();
protected:
@ -92,7 +93,7 @@ namespace MWGui
DragAndDrop* mDragAndDrop;
Filter mFilter;
int mFilter;
// bought items are put in a separate ContainerStore so that they don't stack with other (not bought) items.
MWWorld::ContainerStore mBoughtItems;

@ -230,14 +230,14 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
{
if (!mEnabled) return;
int separatorPos = mTopicsList->getItemCount();
int separatorPos = 0;
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
{
if (mTopicsList->getItemNameAt(i) == "")
separatorPos = i;
}
if (id > separatorPos)
if (id >= separatorPos)
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
else
{
@ -280,6 +280,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
mWindowManager.pushGuiMode(GM_Training);
mWindowManager.startTraining (mPtr);
}
else if (topic == gmst.find("sRepair")->getString())
{
mWindowManager.pushGuiMode(GM_MerchantRepair);
mWindowManager.startRepair (mPtr);
}
}
}
}
@ -321,12 +326,15 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (mServices & Service_CreateSpells)
mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString());
// if (mServices & Service_Enchant)
// mTopicsList->addItem(gmst.find("sEnchanting")->getString());
if (mServices & Service_Enchant)
mTopicsList->addItem(gmst.find("sEnchanting")->getString());
if (mServices & Service_Training)
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
if (mServices & Service_Repair)
mTopicsList->addItem(gmst.find("sRepair")->getString());
if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name())
mTopicsList->addSeparator();
@ -381,10 +389,17 @@ std::string DialogueWindow::parseText(const std::string& text)
std::vector<std::string> topics;
bool hasSeparator = false;
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
{
if (mTopicsList->getItemNameAt(i) == "")
hasSeparator = true;
}
for(unsigned int i = 0;i<mTopicsList->getItemCount();i++)
{
std::string keyWord = mTopicsList->getItemNameAt(i);
if (separatorReached)
if (separatorReached || !hasSeparator)
topics.push_back(keyWord);
else if (keyWord == "")
separatorReached = true;

@ -81,7 +81,8 @@ namespace MWGui
Service_CreateSpells = 0x04,
Service_Enchant = 0x08,
Service_Training = 0x10,
Service_Travel = 0x20
Service_Travel = 0x20,
Service_Repair = 0x40
};
protected:

@ -1,5 +1,15 @@
#include "enchantingdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "itemselection.hpp"
#include "container.hpp"
#include "inventorywindow.hpp"
namespace MWGui
{
@ -8,19 +18,71 @@ namespace MWGui
EnchantingDialog::EnchantingDialog(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_enchanting_dialog.layout", parWindowManager)
, EffectEditorBase(parWindowManager)
, mItemSelectionDialog(NULL)
, mEnchanting(MWBase::Environment::get().getWorld()->getPlayer().getPlayer())
{
getWidget(mName, "NameEdit");
getWidget(mCancelButton, "CancelButton");
getWidget(mAvailableEffectsList, "AvailableEffects");
getWidget(mUsedEffectsView, "UsedEffects");
getWidget(mItemBox, "ItemBox");
getWidget(mSoulBox, "SoulBox");
getWidget(mEnchantmentPoints, "Enchantment");
getWidget(mCastCost, "CastCost");
getWidget(mCharge, "Charge");
getWidget(mTypeButton, "TypeButton");
getWidget(mBuyButton, "BuyButton");
getWidget(mPrice, "PriceLabel");
setWidgets(mAvailableEffectsList, mUsedEffectsView);
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onCancelButtonClicked);
mItemBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectItem);
mSoulBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectSoul);
mBuyButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onBuyButtonClicked);
mTypeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onTypeButtonClicked);
}
EnchantingDialog::~EnchantingDialog()
{
delete mItemSelectionDialog;
}
void EnchantingDialog::open()
{
center();
onRemoveItem(NULL);
onRemoveSoul(NULL);
}
void EnchantingDialog::updateLabels()
{
mEnchantmentPoints->setCaption(boost::lexical_cast<std::string>(mEnchanting.getEnchantCost())
+ " / " + boost::lexical_cast<std::string>(mEnchanting.getMaxEnchantValue()));
mCharge->setCaption(boost::lexical_cast<std::string>(mEnchanting.getGemCharge()));
mCastCost->setCaption(boost::lexical_cast<std::string>(mEnchanting.getEnchantCost()));
switch(mEnchanting.getEnchantType())
{
case 0:
mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastOnce","Cast Once"));
mAddEffectDialog.constantEffect=false;
break;
case 1:
mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenStrikes", "When Strikes"));
mAddEffectDialog.constantEffect=false;
break;
case 2:
mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenUsed", "When Used"));
mAddEffectDialog.constantEffect=false;
break;
case 3:
mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastConstant", "Cast Constant"));
mAddEffectDialog.constantEffect=true;
break;
}
}
void EnchantingDialog::startEnchanting (MWWorld::Ptr actor)
@ -40,4 +102,159 @@ namespace MWGui
{
mWindowManager.removeGuiMode (GM_Enchanting);
}
void EnchantingDialog::onSelectItem(MyGUI::Widget *sender)
{
delete mItemSelectionDialog;
mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}",
ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic, mWindowManager);
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected);
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel);
mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mItemSelectionDialog->drawItems ();
}
void EnchantingDialog::onItemSelected(MWWorld::Ptr item)
{
mItemSelectionDialog->setVisible(false);
while (mItemBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0));
MyGUI::ImageBox* image = mItemBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(item).getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setUserString ("ToolTipType", "ItemPtr");
image->setUserData(item);
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem);
mEnchanting.setOldItem(item);
mEnchanting.nextEnchantType();
updateLabels();
}
void EnchantingDialog::onRemoveItem(MyGUI::Widget *sender)
{
while (mItemBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0));
mEnchanting.setOldItem(MWWorld::Ptr());
updateLabels();
}
void EnchantingDialog::onItemCancel()
{
mItemSelectionDialog->setVisible(false);
}
void EnchantingDialog::onSoulSelected(MWWorld::Ptr item)
{
mItemSelectionDialog->setVisible(false);
mEnchanting.setSoulGem(item);
if(mEnchanting.getGemCharge()==0)
{
mWindowManager.messageBox ("#{sNotifyMessage32}", std::vector<std::string>());
return;
}
while (mSoulBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0));
MyGUI::ImageBox* image = mSoulBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(item).getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setUserString ("ToolTipType", "ItemPtr");
image->setUserData(item);
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul);
updateLabels();
}
void EnchantingDialog::onRemoveSoul(MyGUI::Widget *sender)
{
while (mSoulBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0));
mEnchanting.setSoulGem(MWWorld::Ptr());
updateLabels();
}
void EnchantingDialog::onSoulCancel()
{
mItemSelectionDialog->setVisible(false);
}
void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender)
{
delete mItemSelectionDialog;
mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}",
ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones, mWindowManager);
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected);
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel);
mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mItemSelectionDialog->drawItems ();
//mWindowManager.messageBox("#{sInventorySelectNoSoul}");
}
void EnchantingDialog::notifyEffectsChanged ()
{
mEffectList.mList = mEffects;
mEnchanting.setEffect(mEffectList);
updateLabels();
}
void EnchantingDialog::onTypeButtonClicked(MyGUI::Widget* sender)
{
mEnchanting.nextEnchantType();
updateLabels();
}
void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender)
{
if (mEffects.size() <= 0)
{
mWindowManager.messageBox ("#{sNotifyMessage30}", std::vector<std::string>());
return;
}
if (mName->getCaption ().empty())
{
mWindowManager.messageBox ("#{sNotifyMessage10}", std::vector<std::string>());
return;
}
if (boost::lexical_cast<int>(mPrice->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold())
{
mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector<std::string>());
return;
}
if (mEnchanting.soulEmpty())
{
mWindowManager.messageBox ("#{sNotifyMessage52}", std::vector<std::string>());
return;
}
if (mEnchanting.itemEmpty())
{
mWindowManager.messageBox ("#{sNotifyMessage11}", std::vector<std::string>());
return;
}
mEnchanting.setNewItemName(mName->getCaption());
mEnchanting.setEffect(mEffectList);
mEnchanting.create();
mWindowManager.messageBox ("#{sEnchantmentMenu12}", std::vector<std::string>());
mWindowManager.removeGuiMode (GM_Enchanting);
}
}

@ -7,23 +7,57 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/enchanting.hpp"
namespace MWGui
{
class ItemSelectionDialog;
class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase
{
public:
EnchantingDialog(MWBase::WindowManager& parWindowManager);
virtual ~EnchantingDialog();
virtual void open();
void startEnchanting(MWWorld::Ptr actor);
protected:
virtual void onReferenceUnavailable();
virtual void notifyEffectsChanged ();
void onCancelButtonClicked(MyGUI::Widget* sender);
void onSelectItem (MyGUI::Widget* sender);
void onSelectSoul (MyGUI::Widget* sender);
void onRemoveItem (MyGUI::Widget* sender);
void onRemoveSoul (MyGUI::Widget* sender);
void onItemSelected(MWWorld::Ptr item);
void onItemCancel();
void onSoulSelected(MWWorld::Ptr item);
void onSoulCancel();
void onBuyButtonClicked(MyGUI::Widget* sender);
void updateLabels();
void onTypeButtonClicked(MyGUI::Widget* sender);
ItemSelectionDialog* mItemSelectionDialog;
MyGUI::Button* mCancelButton;
MyGUI::ImageBox* mItemBox;
MyGUI::ImageBox* mSoulBox;
MyGUI::Button* mTypeButton;
MyGUI::Button* mBuyButton;
MyGUI::TextBox* mName;
MyGUI::TextBox* mEnchantmentPoints;
MyGUI::TextBox* mCastCost;
MyGUI::TextBox* mCharge;
MyGUI::TextBox* mPrice;
MWMechanics::Enchanting mEnchanting;
ESM::EffectList mEffectList;
};
}

@ -308,7 +308,7 @@ namespace MWGui
&& (type != typeid(ESM::Ingredient).name())
&& (type != typeid(ESM::Light).name())
&& (type != typeid(ESM::Miscellaneous).name())
&& (type != typeid(ESM::Tool).name())
&& (type != typeid(ESM::Lockpick).name())
&& (type != typeid(ESM::Probe).name())
&& (type != typeid(ESM::Repair).name())
&& (type != typeid(ESM::Weapon).name())

@ -3,7 +3,7 @@
namespace MWGui
{
ItemSelectionDialog::ItemSelectionDialog(const std::string &label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager)
ItemSelectionDialog::ItemSelectionDialog(const std::string &label, int filter, MWBase::WindowManager& parWindowManager)
: ContainerBase(NULL)
, WindowModal("openmw_itemselection_dialog.layout", parWindowManager)
{

@ -8,7 +8,7 @@ namespace MWGui
class ItemSelectionDialog : public ContainerBase, public WindowModal
{
public:
ItemSelectionDialog(const std::string& label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager);
ItemSelectionDialog(const std::string& label, int filter, MWBase::WindowManager& parWindowManager);
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
typedef MyGUI::delegates::CMultiDelegate1<MWWorld::Ptr> EventHandle_Item;

@ -0,0 +1,132 @@
#include "merchantrepair.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "list.hpp"
#include "inventorywindow.hpp"
#include "tradewindow.hpp"
namespace MWGui
{
MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_merchantrepair.layout", parWindowManager)
{
getWidget(mList, "RepairView");
getWidget(mOkButton, "OkButton");
getWidget(mGoldLabel, "PlayerGold");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick);
}
void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
{
mActor = actor;
while (mList->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0));
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
{
if (MWWorld::Class::get(*iter).hasItemHealth(*iter))
{
int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter);
int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge;
if (maxDurability == durability)
continue;
int basePrice = MWWorld::Class::get(*iter).getValue(*iter);
float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairMult")->getFloat();
float p = std::max(1, basePrice);
float r = std::max(1, static_cast<int>(maxDurability / p));
int x = ((maxDurability - durability) / r);
x = (fRepairMult * x);
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true);
std::string name = MWWorld::Class::get(*iter).getName(*iter)
+ " - " + boost::lexical_cast<std::string>(price)
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sgp")->getString();;
MyGUI::Button* button =
mList->createWidget<MyGUI::Button>(
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
0,
currentY,
0,
18,
MyGUI::Align::Default
);
currentY += 18;
button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold());
button->setUserString("Price", boost::lexical_cast<std::string>(price));
button->setUserData(*iter);
button->setCaptionWithReplacing(name);
button->setSize(button->getTextSize().width,18);
button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel);
button->setUserString("ToolTipType", "ItemPtr");
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
}
}
mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
mGoldLabel->setCaptionWithReplacing("#{sGold}: "
+ boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
}
void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mList->getViewOffset().top + _rel*0.3 > 0)
mList->setViewOffset(MyGUI::IntPoint(0, 0));
else
mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3));
}
void MerchantRepair::open()
{
center();
}
void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
{
// repair
MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();
item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item);
MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
int price = boost::lexical_cast<int>(sender->getUserString("Price"));
mWindowManager.getTradeWindow()->addOrRemoveGold(-price);
startRepair(mActor);
}
void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode(GM_MerchantRepair);
}
}

@ -0,0 +1,37 @@
#ifndef OPENMW_MWGUI_MERCHANTREPAIR_H
#define OPENMW_MWGUI_MERCHANTREPAIR_H
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui
{
class MerchantRepair : public WindowBase
{
public:
MerchantRepair(MWBase::WindowManager &parWindowManager);
virtual void open();
void startRepair(const MWWorld::Ptr& actor);
private:
MyGUI::ScrollView* mList;
MyGUI::Button* mOkButton;
MyGUI::TextBox* mGoldLabel;
MWWorld::Ptr mActor;
protected:
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onRepairButtonClick(MyGUI::Widget* sender);
void onOkButtonClick(MyGUI::Widget* sender);
};
}
#endif

@ -16,6 +16,7 @@ namespace MWGui
GM_Scroll, // Read scroll
GM_Book, // Read book
GM_Alchemy, // Make potions
GM_Repair,
GM_Dialogue, // NPC interaction
GM_Barter,
@ -26,6 +27,7 @@ namespace MWGui
GM_SpellCreation,
GM_Enchanting,
GM_Training,
GM_MerchantRepair,
GM_Levelup,

@ -0,0 +1,157 @@
#include "repair.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "widgets.hpp"
namespace MWGui
{
Repair::Repair(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_repair.layout", parWindowManager)
{
getWidget(mRepairBox, "RepairBox");
getWidget(mRepairView, "RepairView");
getWidget(mToolBox, "ToolBox");
getWidget(mToolIcon, "ToolIcon");
getWidget(mUsesLabel, "UsesLabel");
getWidget(mQualityLabel, "QualityLabel");
getWidget(mCancelButton, "CancelButton");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onCancel);
}
void Repair::open()
{
center();
}
void Repair::startRepairItem(const MWWorld::Ptr &item)
{
mRepair.setTool(item);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(item).getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
mToolIcon->setImageTexture (path);
mToolIcon->setUserString("ToolTipType", "ItemPtr");
mToolIcon->setUserData(item);
updateRepairView();
}
void Repair::updateRepairView()
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
mRepair.getTool().get<ESM::Repair>();
int uses = (mRepair.getTool().getCellRef().mCharge != -1) ? mRepair.getTool().getCellRef().mCharge : ref->mBase->mData.mUses;
float quality = ref->mBase->mData.mQuality;
std::stringstream qualityStr;
qualityStr << std::setprecision(3) << quality;
mUsesLabel->setCaptionWithReplacing("#{sUses} " + boost::lexical_cast<std::string>(uses));
mQualityLabel->setCaptionWithReplacing("#{sQuality} " + qualityStr.str());
bool toolBoxVisible = (mRepair.getTool().getRefData().getCount() != 0);
mToolBox->setVisible(toolBoxVisible);
bool toolBoxWasVisible = (mRepairBox->getPosition().top != mToolBox->getPosition().top);
if (toolBoxVisible && !toolBoxWasVisible)
{
// shrink
mRepairBox->setPosition(mRepairBox->getPosition() + MyGUI::IntPoint(0,mToolBox->getSize().height));
mRepairBox->setSize(mRepairBox->getSize() - MyGUI::IntSize(0,mToolBox->getSize().height));
}
else if (!toolBoxVisible && toolBoxWasVisible)
{
// expand
mRepairBox->setPosition(MyGUI::IntPoint (mRepairBox->getPosition().left, mToolBox->getPosition().top));
mRepairBox->setSize(mRepairBox->getSize() + MyGUI::IntSize(0,mToolBox->getSize().height));
}
while (mRepairView->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mRepairView->getChildAt(0));
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor;
for (MWWorld::ContainerStoreIterator iter (store.begin(categories));
iter!=store.end(); ++iter)
{
if (MWWorld::Class::get(*iter).hasItemHealth(*iter))
{
int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter);
int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge;
if (maxDurability == durability)
continue;
MyGUI::TextBox* text = mRepairView->createWidget<MyGUI::TextBox> (
"SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default);
text->setCaption(MWWorld::Class::get(*iter).getName(*iter));
text->setNeedMouseFocus(false);
currentY += 19;
MyGUI::ImageBox* icon = mRepairView->createWidget<MyGUI::ImageBox> (
"ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
icon->setImageTexture (path);
icon->setUserString("ToolTipType", "ItemPtr");
icon->setUserData(*iter);
icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem);
icon->eventMouseWheel += MyGUI::newDelegate(this, &Repair::onMouseWheel);
Widgets::MWDynamicStatPtr chargeWidget = mRepairView->createWidget<Widgets::MWDynamicStat>
("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default);
chargeWidget->setValue(durability, maxDurability);
chargeWidget->setNeedMouseFocus(false);
currentY += 32 + 4;
}
}
mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY)));
}
void Repair::onCancel(MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode(GM_Repair);
}
void Repair::onRepairItem(MyGUI::Widget *sender)
{
if (!mRepair.getTool().getRefData().getCount())
return;
mRepair.repair(*sender->getUserData<MWWorld::Ptr>());
updateRepairView();
}
void Repair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mRepairView->getViewOffset().top + _rel*0.3 > 0)
mRepairView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mRepairView->setViewOffset(MyGUI::IntPoint(0, mRepairView->getViewOffset().top + _rel*0.3));
}
}

@ -0,0 +1,46 @@
#ifndef OPENMW_MWGUI_REPAIR_H
#define OPENMW_MWGUI_REPAIR_H
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwmechanics/repair.hpp"
namespace MWGui
{
class Repair : public WindowBase
{
public:
Repair(MWBase::WindowManager &parWindowManager);
virtual void open();
void startRepairItem (const MWWorld::Ptr& item);
protected:
MyGUI::Widget* mRepairBox;
MyGUI::ScrollView* mRepairView;
MyGUI::Widget* mToolBox;
MyGUI::ImageBox* mToolIcon;
MyGUI::TextBox* mUsesLabel;
MyGUI::TextBox* mQualityLabel;
MyGUI::Button* mCancelButton;
MWMechanics::Repair mRepair;
void updateRepairView();
void onRepairItem (MyGUI::Widget* sender);
void onCancel (MyGUI::Widget* sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
};
}
#endif

@ -32,20 +32,9 @@ namespace MWGui
getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold");
getWidget(mSelect, "Select");
getWidget(mSpells, "Spells");
getWidget(mSpellsView, "SpellsView");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked);
mSpells->setCoord(450/2-mSpells->getTextSize().width/2,
mSpells->getTop(),
mSpells->getTextSize().width,
mSpells->getHeight());
mSelect->setCoord(8,
mSelect->getTop(),
mSelect->getTextSize().width,
mSelect->getHeight());
}
void SpellBuyingWindow::addSpell(const std::string& spellId)

@ -28,8 +28,6 @@ namespace MWGui
protected:
MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPlayerGold;
MyGUI::TextBox* mSpells;
MyGUI::TextBox* mSelect;
MyGUI::ScrollView* mSpellsView;

@ -72,6 +72,7 @@ namespace MWGui
mMagnitudeMaxSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onMagnitudeMaxChanged);
mDurationSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onDurationChanged);
mAreaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onAreaChanged);
constantEffect=false;
}
void EditEffectDialog::open()
@ -164,7 +165,7 @@ namespace MWGui
mMagnitudeBox->setVisible (true);
curY += mMagnitudeBox->getSize().height;
}
if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)&&constantEffect==false)
{
mDurationBox->setPosition(mDurationBox->getPosition().left, curY);
mDurationBox->setVisible (true);

@ -24,7 +24,7 @@ namespace MWGui
void newEffect (const ESM::MagicEffect* effect);
void editEffect (ESM::ENAMstruct effect);
bool constantEffect;
typedef MyGUI::delegates::CMultiDelegate1<ESM::ENAMstruct> EventHandle_Effect;
EventHandle_Effect eventEffectAdded;
@ -69,7 +69,6 @@ namespace MWGui
void onMagnitudeMaxChanged (MyGUI::ScrollBar* sender, size_t pos);
void onDurationChanged (MyGUI::ScrollBar* sender, size_t pos);
void onAreaChanged (MyGUI::ScrollBar* sender, size_t pos);
void setMagicEffect(const ESM::MagicEffect* effect);
void updateBoxes();

@ -139,12 +139,13 @@ namespace MWGui
}
}
parent->setVisible(effects.size() != 0);
int w=2;
if (adjustSize)
{
int s = effects.size() * 16+4;
if (!effects.size())
s = 0;
int diff = parent->getWidth() - s;
parent->setSize(s, parent->getHeight());
parent->setPosition(parent->getLeft()+diff, parent->getTop());

@ -368,7 +368,7 @@ namespace MWGui
return services & ESM::NPC::Books;
else if (item.getTypeName() == typeid(ESM::Ingredient).name())
return services & ESM::NPC::Ingredients;
else if (item.getTypeName() == typeid(ESM::Tool).name())
else if (item.getTypeName() == typeid(ESM::Lockpick).name())
return services & ESM::NPC::Picks;
else if (item.getTypeName() == typeid(ESM::Probe).name())
return services & ESM::NPC::Probes;

@ -132,7 +132,7 @@ namespace MWGui
case 11:
month = "#{sMonthEveningstar}";
break;
default:
default:
break;
}
int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour ();
@ -142,7 +142,7 @@ namespace MWGui
std::string dateTimeText =
boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getDay ()) + " "
+ month + " (#{sDay} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay ()+1)
+ month + " (#{sDay} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay())
+ ") " + boost::lexical_cast<std::string>(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
mDateTimeText->setCaptionWithReplacing (dateTimeText);
@ -156,13 +156,13 @@ namespace MWGui
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats stats = MWWorld::Class::get(player).getCreatureStats(player);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
// this massive duplication is why it has to be put into helper functions instead
float fFatigueReturnBase = store.get<ESM::GameSetting>().find("fFatigueReturnBase")->getFloat();
float fFatigueReturnMult = store.get<ESM::GameSetting>().find("fFatigueReturnMult")->getFloat();
@ -174,7 +174,7 @@ namespace MWGui
normalizedEncumbrance = 1;
float hourlyFatigueDelta = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
hourlyFatigueDelta *= 3600 * fEndFatigueMult * stats.getAttribute(ESM::Attribute::Endurance).getModified();
float healthHours = hourlyHealthDelta >= 0.0
? (stats.getHealth().getBase() - stats.getHealth().getCurrent()) / hourlyHealthDelta
: 1.0f;
@ -185,9 +185,9 @@ namespace MWGui
float fatigueHours = hourlyFatigueDelta >= 0.0
? (stats.getFatigue().getBase() - stats.getFatigue().getCurrent()) / hourlyFatigueDelta
: 1.0f;
int autoHours = int(std::ceil( std::max(std::max(healthHours, magickaHours), std::max(fatigueHours, 1.0f)) )); // this should use a variadic max if possible
startWaiting(autoHours);
}
@ -201,11 +201,11 @@ namespace MWGui
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2);
setVisible(false);
mProgressBar.setVisible (true);
mWaiting = true;
mCurHour = 0;
mHours = hoursToWait;
mRemainingTime = 0.05;
mProgressBar.setProgress (0, mHours);
}

@ -55,6 +55,8 @@
#include "exposedwindow.hpp"
#include "cursor.hpp"
#include "spellicons.hpp"
#include "merchantrepair.hpp"
#include "repair.hpp"
using namespace MWGui;
@ -90,6 +92,8 @@ WindowManager::WindowManager(
, mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL)
, mTrainingWindow(NULL)
, mMerchantRepair(NULL)
, mRepair(NULL)
, mPlayerName()
, mPlayerRaceId()
, mPlayerAttributes()
@ -180,6 +184,8 @@ WindowManager::WindowManager(
mSpellCreationDialog = new SpellCreationDialog(*this);
mEnchantingDialog = new EnchantingDialog(*this);
mTrainingWindow = new TrainingWindow(*this);
mMerchantRepair = new MerchantRepair(*this);
mRepair = new Repair(*this);
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this);
mLoadingScreen->onResChange (w,h);
@ -245,6 +251,8 @@ WindowManager::~WindowManager()
delete mTrainingWindow;
delete mCountDialog;
delete mQuickKeysMenu;
delete mMerchantRepair;
delete mRepair;
delete mCursor;
cleanupGarbage();
@ -303,6 +311,8 @@ void WindowManager::updateVisible()
mSpellCreationDialog->setVisible(false);
mEnchantingDialog->setVisible(false);
mTrainingWindow->setVisible(false);
mMerchantRepair->setVisible(false);
mRepair->setVisible(false);
mHud->setVisible(mHudEnabled);
@ -428,6 +438,12 @@ void WindowManager::updateVisible()
case GM_Training:
mTrainingWindow->setVisible(true);
break;
case GM_MerchantRepair:
mMerchantRepair->setVisible(true);
break;
case GM_Repair:
mRepair->setVisible(true);
break;
case GM_InterMessageBox:
break;
case GM_Journal:
@ -1132,6 +1148,16 @@ void WindowManager::startTraining(MWWorld::Ptr actor)
mTrainingWindow->startTraining(actor);
}
void WindowManager::startRepair(MWWorld::Ptr actor)
{
mMerchantRepair->startRepair(actor);
}
void WindowManager::startRepairItem(MWWorld::Ptr item)
{
mRepair->startRepairItem(item);
}
const Translation::Storage& WindowManager::getTranslationDataStorage() const
{
return mTranslationDataStorage;

@ -74,6 +74,8 @@ namespace MWGui
class TrainingWindow;
class Cursor;
class SpellIcons;
class MerchantRepair;
class Repair;
class WindowManager : public MWBase::WindowManager
{
@ -229,6 +231,8 @@ namespace MWGui
virtual void startSpellMaking(MWWorld::Ptr actor);
virtual void startEnchanting(MWWorld::Ptr actor);
virtual void startTraining(MWWorld::Ptr actor);
virtual void startRepair(MWWorld::Ptr actor);
virtual void startRepairItem(MWWorld::Ptr item);
virtual void changePointer (const std::string& name);
@ -266,6 +270,9 @@ namespace MWGui
SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow;
MerchantRepair* mMerchantRepair;
Repair* mRepair;
Translation::Storage& mTranslationDataStorage;
Cursor* mCursor;

@ -0,0 +1,167 @@
#include "enchanting.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
namespace MWMechanics
{
Enchanting::Enchanting(MWWorld::Ptr enchanter):
mEnchanter(enchanter),
mEnchantType(0)
{}
void Enchanting::setOldItem(MWWorld::Ptr oldItem)
{
mOldItemPtr=oldItem;
if(!itemEmpty())
{
mObjectType = mOldItemPtr.getTypeName();
mOldItemId = mOldItemPtr.getCellRef().mRefID;
}
else
{
mObjectType="";
mOldItemId="";
}
}
void Enchanting::setNewItemName(std::string s)
{
mNewItemName=s;
}
void Enchanting::setEffect(ESM::EffectList effectList)
{
mEffectList=effectList;
}
int Enchanting::getEnchantType()
{
return mEnchantType;
}
void Enchanting::setSoulGem(MWWorld::Ptr soulGem)
{
mSoulGemPtr=soulGem;
}
void Enchanting::create()
{
mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1);
mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1);
mEnchantment.mData.mCharge = getGemCharge();
if(mEnchantType==3)
{
mEnchantment.mData.mCharge=0;
}
mEnchantment.mData.mType = mEnchantType;
mEnchantment.mData.mCost = getEnchantCost();
mEnchantment.mEffects = mEffectList;
const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment);
std::string newobjId = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName);
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobjId);
MWWorld::Ptr newobjPtr = ref.getPtr();
MWWorld::Ptr result = mOldItemPtr;
result.mPtr = newobjPtr.mPtr;
MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (result);
}
void Enchanting::nextEnchantType()
{
mEnchantType++;
if (itemEmpty())
{
mEnchantType = 0;
return;
}
if ((mObjectType == typeid(ESM::Armor).name())||(mObjectType == typeid(ESM::Clothing).name()))
{
switch(mEnchantType)
{
case 1:
mEnchantType = 2;
case 3:
if(getGemCharge()<400)
mEnchantType=2;
case 4:
mEnchantType = 2;
}
}
else if(mObjectType == typeid(ESM::Weapon).name())
{
switch(mEnchantType)
{
case 3:
mEnchantType = 1;
}
}
else if(mObjectType == typeid(ESM::Book).name())
{
mEnchantType=0;
}
}
int Enchanting::getEnchantCost()
{
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
float cost = 0;
std::vector<ESM::ENAMstruct> mEffects = mEffectList.mList;
int i=mEffects.size();
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{
const ESM::MagicEffect* effect = store.get<ESM::MagicEffect>().find(it->mEffectID);
float cost1 = ((it->mMagnMin + it->mMagnMax)*it->mDuration*effect->mData.mBaseCost*0.025);
float cost2 = (std::max(1, it->mArea)*0.125*effect->mData.mBaseCost);
if(mEnchantType==3)
{
cost1 *= 100;
cost2 *= 2;
}
if(effect->mData.mFlags & ESM::MagicEffect::CastTarget)
cost1 *= 1.5;
float fullcost = cost1+cost2;
fullcost*= i;
i--;
cost+=fullcost;
}
return cost;
}
int Enchanting::getGemCharge()
{
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
if(soulEmpty())
return 0;
if(mSoulGemPtr.getCellRef().mSoul=="")
return 0;
const ESM::Creature* soul = store.get<ESM::Creature>().find(mSoulGemPtr.getCellRef().mSoul);
return soul->mData.mSoul;
}
int Enchanting::getMaxEnchantValue()
{
if (itemEmpty())
return 0;
return MWWorld::Class::get(mOldItemPtr).getEnchantmentPoints(mOldItemPtr);
}
bool Enchanting::soulEmpty()
{
if (mSoulGemPtr.isEmpty())
return true;
return false;
}
bool Enchanting::itemEmpty()
{
if(mOldItemPtr.isEmpty())
return true;
return false;
}
}

@ -0,0 +1,41 @@
#ifndef GAME_MWMECHANICS_ENCHANTING_H
#define GAME_MWMECHANICS_ENCHANTING_H
#include <string>
#include "../mwworld/ptr.hpp"
#include <components/esm/effectlist.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWMechanics
{
class Enchanting
{
MWWorld::Ptr mOldItemPtr;
MWWorld::Ptr mSoulGemPtr;
MWWorld::Ptr mEnchanter;
const MWWorld::Ptr *mNewItemPtr;
int mEnchantType;
ESM::EffectList mEffectList;
ESM::Enchantment mEnchantment;
std::string mNewItemName;
std::string mObjectType;
std::string mOldItemId;
public:
Enchanting(MWWorld::Ptr enchanter);
void setOldItem(MWWorld::Ptr oldItem);
void setNewItemName(std::string s);
void setEffect(ESM::EffectList effectList);
void setSoulGem(MWWorld::Ptr soulGem);
void create();
void nextEnchantType();
int getEnchantType();
int getEnchantCost();
int getMaxEnchantValue();
int getGemCharge();
bool soulEmpty();
bool itemEmpty();
};
}
#endif

@ -0,0 +1,110 @@
#include "repair.hpp"
#include <boost/format.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
namespace MWMechanics
{
void Repair::repair(const MWWorld::Ptr &itemToRepair)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::LiveCellRef<ESM::Repair> *ref =
mTool.get<ESM::Repair>();
// reduce number of uses left
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
mTool.getCellRef().mCharge = uses-1;
// unstack tool if required
if (mTool.getRefData().getCount() > 1 && uses == ref->mBase->mData.mUses)
{
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
MWWorld::ContainerStoreIterator it = store.add(mTool);
it->getRefData().setCount(mTool.getRefData().getCount()-1);
it->getCellRef().mCharge = -1;
mTool.getRefData().setCount(1);
}
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
float fatigueTerm = stats.getFatigueTerm();
int pcStrength = stats.getAttribute(ESM::Attribute::Strength).getModified();
int pcLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
int armorerSkill = npcStats.getSkill(ESM::Skill::Armorer).getModified();
float fRepairAmountMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairAmountMult")->getFloat();
float toolQuality = ref->mBase->mData.mQuality;
float x = (0.1 * pcStrength + 0.1 * pcLuck + armorerSkill) * fatigueTerm;
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
if (roll <= x)
{
int y = fRepairAmountMult * toolQuality * roll;
y = std::max(1, y);
// repair by 'y' points
itemToRepair.getCellRef().mCharge += y;
itemToRepair.getCellRef().mCharge = std::min(itemToRepair.getCellRef().mCharge,
MWWorld::Class::get(itemToRepair).getItemMaxHealth(itemToRepair));
// set the OnPCRepair variable on the item's script
std::string script = MWWorld::Class::get(itemToRepair).getScript(itemToRepair);
if(script != "")
itemToRepair.getRefData().getLocals().setVarByInt(script, "onpcrepair", 1);
// increase skill
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Armorer, 0);
MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairSuccess}");
}
else
{
MWBase::Environment::get().getSoundManager()->playSound("Repair Fail",1,1);
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairFailed}");
}
// tool used up?
if (mTool.getCellRef().mCharge == 0)
{
mTool.getRefData().setCount(0);
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sNotifyMessage51")->getString();
MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % MWWorld::Class::get(mTool).getName(mTool)).str());
// try to find a new tool of the same ID
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
{
if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, mTool.getCellRef().mRefID))
{
mTool = *iter;
break;
}
}
}
}
}

@ -0,0 +1,23 @@
#ifndef OPENMW_MWMECHANICS_REPAIR_H
#define OPENMW_MWMECHANICS_REPAIR_H
#include "../mwworld/ptr.hpp"
namespace MWMechanics
{
class Repair
{
public:
void setTool (const MWWorld::Ptr& tool) { mTool = tool; }
MWWorld::Ptr getTool() { return mTool; }
void repair (const MWWorld::Ptr& itemToRepair);
private:
MWWorld::Ptr mTool;
};
}
#endif

@ -1,5 +1,7 @@
#include "objects.hpp"
#include <cmath>
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
@ -271,16 +273,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre
info.time = Ogre::Math::RangeRandom(-500, +500);
info.phase = Ogre::Math::RangeRandom(-500, +500);
// changed to linear to look like morrowind
bool quadratic = false;
/*
if (!lightOutQuadInLin)
quadratic = lightQuadratic;
else
{
quadratic = !info.interior;
}
*/
bool quadratic = lightOutQuadInLin() ? !info.interior : lightQuadratic();
if (!quadratic)
{
@ -291,7 +284,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre
else
{
float r = radius * lightQuadraticRadiusMult();
float attenuation = lightQuadraticValue() / pow(r, 2);
float attenuation = lightQuadraticValue() / std::pow(r, 2);
light->setAttenuation(r*10, 0, 0, attenuation);
}

@ -59,7 +59,7 @@ namespace MWScript
store.get<ESM::CreatureLevList>().search (name) ||
store.get<ESM::ItemLevList>().search (name) ||
store.get<ESM::Light>().search (name) ||
store.get<ESM::Tool>().search (name) ||
store.get<ESM::Lockpick>().search (name) ||
store.get<ESM::Miscellaneous>().search (name) ||
store.get<ESM::NPC>().search (name) ||
store.get<ESM::Probe>().search (name) ||

@ -0,0 +1,18 @@
#include "actionrepair.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
namespace MWWorld
{
ActionRepair::ActionRepair(const Ptr &item)
: Action(false, item)
{
}
void ActionRepair::executeImp (const Ptr& actor)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair);
MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget());
}
}

@ -0,0 +1,17 @@
#ifndef GAME_MWWORLD_ACTIONREPAIR_H
#define GAME_MWWORLD_ACTIONREPAIR_H
#include "action.hpp"
namespace MWWorld
{
class ActionRepair : public Action
{
virtual void executeImp (const Ptr& actor);
public:
ActionRepair(const MWWorld::Ptr& item);
};
}
#endif

@ -206,7 +206,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
if (MWWorld::LiveCellRef<ESM::Light> *ref = cell.mLights.find (name))
ptr = Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Tool> *ref = cell.mLockpicks.find (name))
if (MWWorld::LiveCellRef<ESM::Lockpick> *ref = cell.mLockpicks.find (name))
ptr = Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = cell.mMiscItems.find (name))

@ -112,7 +112,7 @@ namespace MWWorld
CellRefList<ESM::CreatureLevList> mCreatureLists;
CellRefList<ESM::ItemLevList> mItemLists;
CellRefList<ESM::Light> mLights;
CellRefList<ESM::Tool> mLockpicks;
CellRefList<ESM::Lockpick> mLockpicks;
CellRefList<ESM::Miscellaneous> mMiscItems;
CellRefList<ESM::NPC> mNpcs;
CellRefList<ESM::Probe> mProbes;

@ -127,6 +127,11 @@ namespace MWWorld
return 0;
}
short Class::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
{
throw std::runtime_error ("class does not support enchanting");
}
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
{
throw std::runtime_error ("movement settings not supported by class");
@ -169,7 +174,7 @@ namespace MWWorld
bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const
{
return false;
return true;
}
float Class::getArmorRating (const MWWorld::Ptr& ptr) const
@ -241,6 +246,11 @@ namespace MWWorld
return "";
}
std::string Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{
throw std::runtime_error ("class can't be enchanted");
}
MWWorld::Ptr
Class::copyToCellImpl(const Ptr &ptr, CellStore &cell) const
{

@ -225,12 +225,17 @@ namespace MWWorld
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
/// (default implementation: return empty string)
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
///< @return the number of enchantment points available for possible enchanting
virtual void adjustScale(const MWWorld::Ptr& ptr,float& scale) const;
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual Ptr
copyToCell(const Ptr &ptr, CellStore &cell) const;

@ -38,12 +38,6 @@ namespace
return sum;
}
bool compare_string_ci(std::string str1, std::string str2)
{
Misc::StringUtils::toLower(str1);
return str1 == str2;
}
}
MWWorld::ContainerStore::ContainerStore() : mStateId (0), mCachedWeight (0), mWeightUpToDate (false) {}
@ -62,13 +56,17 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
{
/// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented
/// \todo add current enchantment charge here when it is implemented
if ( ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID
&& MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
&& MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
&& ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner
&& ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul
&& ptr1.mCellRef->mCharge == ptr2.mCellRef->mCharge)
// item that is already partly used up never stacks
&& (!MWWorld::Class::get(ptr1).hasItemHealth(ptr1) || ptr1.mCellRef->mCharge == -1
|| MWWorld::Class::get(ptr1).getItemMaxHealth(ptr1) == ptr1.mCellRef->mCharge)
&& (!MWWorld::Class::get(ptr2).hasItemHealth(ptr2) || ptr2.mCellRef->mCharge == -1
|| MWWorld::Class::get(ptr2).getItemMaxHealth(ptr2) == ptr2.mCellRef->mCharge))
return true;
return false;
@ -118,19 +116,20 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr)
MWWorld::LiveCellRef<ESM::Miscellaneous> *gold =
ptr.get<ESM::Miscellaneous>();
if (compare_string_ci(gold->mRef.mRefID, "gold_001")
|| compare_string_ci(gold->mRef.mRefID, "gold_005")
|| compare_string_ci(gold->mRef.mRefID, "gold_010")
|| compare_string_ci(gold->mRef.mRefID, "gold_025")
|| compare_string_ci(gold->mRef.mRefID, "gold_100"))
if (Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_001")
|| Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_005")
|| Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_010")
|| Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_025")
|| Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_100"))
{
MWWorld::ManualRef ref(esmStore, "Gold_001");
int count = (ptr.getRefData().getCount() == 1) ? gold->mBase->mData.mValue : ptr.getRefData().getCount();
int count = MWWorld::Class::get(ptr).getValue(ptr) * ptr.getRefData().getCount();
ref.getPtr().getRefData().setCount(count);
for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter)
{
if (compare_string_ci((*iter).get<ESM::Miscellaneous>()->mRef.mRefID, "gold_001"))
if (Misc::StringUtils::ciEqual((*iter).get<ESM::Miscellaneous>()->mRef.mRefID, "gold_001"))
{
(*iter).getRefData().setCount( (*iter).getRefData().getCount() + count);
flagAsModified();
@ -171,7 +170,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr
case Type_Clothing: clothes.mList.push_back (*ptr.get<ESM::Clothing>()); it = ContainerStoreIterator(this, --clothes.mList.end()); break;
case Type_Ingredient: ingreds.mList.push_back (*ptr.get<ESM::Ingredient>()); it = ContainerStoreIterator(this, --ingreds.mList.end()); break;
case Type_Light: lights.mList.push_back (*ptr.get<ESM::Light>()); it = ContainerStoreIterator(this, --lights.mList.end()); break;
case Type_Lockpick: lockpicks.mList.push_back (*ptr.get<ESM::Tool>()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break;
case Type_Lockpick: lockpicks.mList.push_back (*ptr.get<ESM::Lockpick>()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break;
case Type_Miscellaneous: miscItems.mList.push_back (*ptr.get<ESM::Miscellaneous>()); it = ContainerStoreIterator(this, --miscItems.mList.end()); break;
case Type_Probe: probes.mList.push_back (*ptr.get<ESM::Probe>()); it = ContainerStoreIterator(this, --probes.mList.end()); break;
case Type_Repair: repairs.mList.push_back (*ptr.get<ESM::Repair>()); it = ContainerStoreIterator(this, --repairs.mList.end()); break;
@ -272,7 +271,7 @@ int MWWorld::ContainerStore::getType (const Ptr& ptr)
if (ptr.getTypeName()==typeid (ESM::Light).name())
return Type_Light;
if (ptr.getTypeName()==typeid (ESM::Tool).name())
if (ptr.getTypeName()==typeid (ESM::Lockpick).name())
return Type_Lockpick;
if (ptr.getTypeName()==typeid (ESM::Miscellaneous).name())
@ -321,7 +320,7 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *contain
: mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator iterator)
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Lockpick>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator iterator)
: mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){}

@ -44,7 +44,7 @@ namespace MWWorld
MWWorld::CellRefList<ESM::Clothing> clothes;
MWWorld::CellRefList<ESM::Ingredient> ingreds;
MWWorld::CellRefList<ESM::Light> lights;
MWWorld::CellRefList<ESM::Tool> lockpicks;
MWWorld::CellRefList<ESM::Lockpick> lockpicks;
MWWorld::CellRefList<ESM::Miscellaneous> miscItems;
MWWorld::CellRefList<ESM::Probe> probes;
MWWorld::CellRefList<ESM::Repair> repairs;
@ -127,7 +127,7 @@ namespace MWWorld
MWWorld::CellRefList<ESM::Clothing>::List::iterator mClothing;
MWWorld::CellRefList<ESM::Ingredient>::List::iterator mIngredient;
MWWorld::CellRefList<ESM::Light>::List::iterator mLight;
MWWorld::CellRefList<ESM::Tool>::List::iterator mLockpick;
MWWorld::CellRefList<ESM::Lockpick>::List::iterator mLockpick;
MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator mMiscellaneous;
MWWorld::CellRefList<ESM::Probe>::List::iterator mProbe;
MWWorld::CellRefList<ESM::Repair>::List::iterator mRepair;
@ -149,7 +149,7 @@ namespace MWWorld
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Clothing>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Ingredient>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Lockpick>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Probe>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator);

@ -32,7 +32,7 @@ namespace MWWorld
Store<ESM::CreatureLevList> mCreatureLists;
Store<ESM::ItemLevList> mItemLists;
Store<ESM::Light> mLights;
Store<ESM::Tool> mLockpicks;
Store<ESM::Lockpick> mLockpicks;
Store<ESM::Miscellaneous> mMiscItems;
Store<ESM::NPC> mNpcs;
Store<ESM::LoadNPCC> mNpcChange;
@ -312,7 +312,7 @@ namespace MWWorld
}
template <>
inline const Store<ESM::Tool> &ESMStore::get<ESM::Tool>() const {
inline const Store<ESM::Lockpick> &ESMStore::get<ESM::Lockpick>() const {
return mLockpicks;
}

@ -79,7 +79,7 @@ namespace MWWorld
{
// vanilla Morrowind does not define dayspassed.
Data value;
value.mLong = 0;
value.mLong = 1; // but the addons start counting at 1 :(
mVariables.insert (std::make_pair ("dayspassed", std::make_pair ('l', value)));
}

@ -53,7 +53,7 @@ namespace MWWorld
!create (store.get<ESM::CreatureLevList>(), name) &&
!create (store.get<ESM::ItemLevList>(), name) &&
!create (store.get<ESM::Light>(), name) &&
!create (store.get<ESM::Tool>(), name) &&
!create (store.get<ESM::Lockpick>(), name) &&
!create (store.get<ESM::Miscellaneous>(), name) &&
!create (store.get<ESM::NPC>(), name) &&
!create (store.get<ESM::Probe>(), name) &&
@ -68,12 +68,12 @@ namespace MWWorld
cellRef.mRefnum = -1;
cellRef.mScale = 1;
cellRef.mFactIndex = 0;
cellRef.mCharge = 0;
cellRef.mIntv = 0;
cellRef.mNam9 = 0;
cellRef.mCharge = -1;
cellRef.mGoldValue = 1;
cellRef.mEnchantmentCharge = -1;
cellRef.mTeleport = false;
cellRef.mLockLevel = 0;
cellRef.mUnam = 0;
cellRef.mReferenceBlocked = 0;
}
const Ptr& getPtr() const

@ -41,7 +41,7 @@ namespace
++current;
if (it->mData.getCount() || it->mData.isEnabled())
if (it->mData.getCount() && it->mData.isEnabled())
{
MWWorld::Ptr ptr (&*it, &cell);

@ -101,7 +101,7 @@ namespace MWWorld
return Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Light> *ref = searchViaHandle (handle, cell.mLights))
return Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Tool> *ref = searchViaHandle (handle, cell.mLockpicks))
if (MWWorld::LiveCellRef<ESM::Lockpick> *ref = searchViaHandle (handle, cell.mLockpicks))
return Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = searchViaHandle (handle, cell.mMiscItems))
return Ptr (ref, &cell);
@ -949,6 +949,31 @@ namespace MWWorld
return ret;
}
const ESM::Armor *World::createRecord (const ESM::Armor& record)
{
return mStore.insert(record);
}
const ESM::Weapon *World::createRecord (const ESM::Weapon& record)
{
return mStore.insert(record);
}
const ESM::Clothing *World::createRecord (const ESM::Clothing& record)
{
return mStore.insert(record);
}
const ESM::Enchantment *World::createRecord (const ESM::Enchantment& record)
{
return mStore.insert(record);
}
const ESM::Book *World::createRecord (const ESM::Book& record)
{
return mStore.insert(record);
}
void World::update (float duration, bool paused)
{
mWeatherManager->update (duration);

@ -272,25 +272,44 @@ namespace MWWorld
///< \return Resulting mode
virtual const ESM::Potion *createRecord (const ESM::Potion& record);
///< Create a new recrod (of type potion) in the ESM store.
///< Create a new record (of type potion) in the ESM store.
/// \return pointer to created record
virtual const ESM::Spell *createRecord (const ESM::Spell& record);
///< Create a new recrod (of type spell) in the ESM store.
///< Create a new record (of type spell) in the ESM store.
/// \return pointer to created record
virtual const ESM::Class *createRecord (const ESM::Class& record);
///< Create a new recrod (of type class) in the ESM store.
///< Create a new record (of type class) in the ESM store.
/// \return pointer to created record
virtual const ESM::Cell *createRecord (const ESM::Cell& record);
///< Create a new recrod (of type cell) in the ESM store.
///< Create a new record (of type cell) in the ESM store.
/// \return pointer to created record
virtual const ESM::NPC *createRecord(const ESM::NPC &record);
///< Create a new recrod (of type npc) in the ESM store.
///< Create a new record (of type npc) in the ESM store.
/// \return pointer to created record
virtual const ESM::Armor *createRecord (const ESM::Armor& record);
///< Create a new record (of type armor) in the ESM store.
/// \return pointer to created record
virtual const ESM::Weapon *createRecord (const ESM::Weapon& record);
///< Create a new record (of type weapon) in the ESM store.
/// \return pointer to created record
virtual const ESM::Clothing *createRecord (const ESM::Clothing& record);
///< Create a new record (of type clothing) in the ESM store.
/// \return pointer to created record
virtual const ESM::Enchantment *createRecord (const ESM::Enchantment& record);
///< Create a new record (of type enchantment) in the ESM store.
/// \return pointer to created record
virtual const ESM::Book *createRecord (const ESM::Book& record);
///< Create a new record (of type book) in the ESM store.
/// \return pointer to created record
virtual void update (float duration, bool paused);

@ -37,7 +37,7 @@ add_component_dir (file_finder
add_component_dir (esm
attr defs esmcommon esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp loadtes3
)

@ -14,7 +14,7 @@
namespace ESM
{
/// Some overloaded copare operators.
/// Some overloaded compare operators.
bool operator==(const MovedCellRef& ref, int pRefnum)
{
return (ref.mRefnum == pRefnum);
@ -43,15 +43,14 @@ void CellRef::save(ESMWriter &esm)
esm.writeHNT("INDX", mFactIndex);
}
if (mCharge != -1.0) {
esm.writeHNT("XCHG", mCharge);
}
if (mEnchantmentCharge != -1)
esm.writeHNT("XCHG", mEnchantmentCharge);
if (mIntv != -1) {
esm.writeHNT("INTV", mIntv);
}
if (mNam9 != 0) {
esm.writeHNT("NAM9", mNam9);
if (mCharge != -1)
esm.writeHNT("INTV", mCharge);
if (mGoldValue != 1) {
esm.writeHNT("NAM9", mGoldValue);
}
if (mTeleport)
@ -66,8 +65,8 @@ void CellRef::save(ESMWriter &esm)
esm.writeHNOCString("KNAM", mKey);
esm.writeHNOCString("TNAM", mTrap);
if (mUnam != -1) {
esm.writeHNT("UNAM", mUnam);
if (mReferenceBlocked != -1) {
esm.writeHNT("UNAM", mReferenceBlocked);
}
if (mFltv != 0) {
esm.writeHNT("FLTV", mFltv);
@ -285,13 +284,15 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
ref.mFactIndex = -2;
esm.getHNOT(ref.mFactIndex, "INDX");
ref.mCharge = -1.0;
esm.getHNOT(ref.mCharge, "XCHG");
ref.mGoldValue = 1;
ref.mCharge = -1;
ref.mEnchantmentCharge = -1;
esm.getHNOT(ref.mEnchantmentCharge, "XCHG");
esm.getHNOT(ref.mCharge, "INTV");
ref.mIntv = -1;
ref.mNam9 = 0;
esm.getHNOT(ref.mIntv, "INTV");
esm.getHNOT(ref.mNam9, "NAM9");
esm.getHNOT(ref.mGoldValue, "NAM9");
// Present for doors that teleport you to another cell.
if (esm.isNextSub("DODT"))
@ -309,9 +310,9 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
ref.mKey = esm.getHNOString("KNAM");
ref.mTrap = esm.getHNOString("TNAM");
ref.mUnam = -1;
ref.mReferenceBlocked = -1;
ref.mFltv = 0;
esm.getHNOT(ref.mUnam, "UNAM");
esm.getHNOT(ref.mReferenceBlocked, "UNAM");
esm.getHNOT(ref.mFltv, "FLTV");
esm.getHNOT(ref.mPos, "DATA", 24);

@ -52,15 +52,15 @@ public:
// is -1, which I assume means "any rank".
int mFactIndex;
// Depends on context - possibly weapon health, number of uses left
// or weapon magic charge?
float mCharge;
// For weapon or armor, this is the remaining item health.
// For tools (lockpicks, probes, repair hammer) it is the remaining uses.
int mCharge;
// I have no idea, these are present some times, often along with
// owner (ANAM) and sometimes otherwise. They are often (but not
// always) 1. INTV is big for lights (possibly a float?), might have
// something to do with remaining light "charge".
int mIntv, mNam9;
// Remaining enchantment charge
float mEnchantmentCharge;
// This is 5 for Gold_005 references, 100 for Gold_100 and so on.
int mGoldValue;
// For doors - true if this door teleports to somewhere else, false
// if it should open through animation.
@ -76,8 +76,10 @@ public:
int mLockLevel;
std::string mKey, mTrap; // Key and trap ID names, if any
// No idea - occurs ONCE in Morrowind.esm, for an activator
signed char mUnam;
// This corresponds to the "Reference Blocked" checkbox in the construction set,
// which prevents editing that reference.
// -1 is not blocked, otherwise it is blocked.
signed char mReferenceBlocked;
// Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn.
int mDeleted;

@ -0,0 +1,31 @@
#include "loadlock.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
void Lockpick::load(ESMReader &esm)
{
mModel = esm.getHNString("MODL");
mName = esm.getHNString("FNAM");
esm.getHNT(mData, "LKDT", 16);
mScript = esm.getHNOString("SCRI");
mIcon = esm.getHNOString("ITEX");
}
void Lockpick::save(ESMWriter &esm)
{
esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName);
esm.writeHNT("LKDT", mData, 16);
esm.writeHNOString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
}

@ -0,0 +1,31 @@
#ifndef OPENMW_ESM_LOCK_H
#define OPENMW_ESM_LOCK_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct Lockpick
{
struct Data
{
float mWeight;
int mValue;
float mQuality;
int mUses;
}; // Size = 16
Data mData;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
}
#endif

@ -1,65 +0,0 @@
#include "loadlocks.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
void Tool::load(ESMReader &esm)
{
mModel = esm.getHNString("MODL");
mName = esm.getHNString("FNAM");
esm.getSubName();
NAME n = esm.retSubName();
// The data name varies, RIDT for repair items, LKDT for lock
// picks, PBDT for probes
esm.getHT(mData, 16);
if (n == "RIDT")
{
mType = Type_Repair;
// Swap t.data.quality and t.data.uses for repair items (sigh)
float tmp = *((float*) &mData.mUses);
mData.mUses = *((int*) &mData.mQuality);
mData.mQuality = tmp;
}
else if (n == "LKDT")
mType = Type_Pick;
else if (n == "PBDT")
mType = Type_Probe;
mScript = esm.getHNOString("SCRI");
mIcon = esm.getHNOString("ITEX");
}
void Tool::save(ESMWriter &esm)
{
esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName);
std::string typeName;
switch(mType)
{
case Type_Repair: typeName = "RIDT"; break;
case Type_Pick: typeName = "LKDT"; break;
case Type_Probe: typeName = "PBDT"; break;
}
Data write = mData;
if (mType == Type_Repair)
{
float tmp = *((float*) &write.mUses);
write.mUses = *((int*) &write.mQuality);
write.mQuality = tmp;
}
esm.writeHNT(typeName, write, 16);
esm.writeHNOString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
}

@ -1,56 +0,0 @@
#ifndef OPENMW_ESM_LOCKS_H
#define OPENMW_ESM_LOCKS_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
/*
* This file covers lockpicks (LOCK), probes (PROB) and armor repair
* items (REPA). These have nearly identical data structures.
*/
struct Tool
{
enum Type
{
Type_Pick,
Type_Probe,
Type_Repair
};
struct Data
{
float mWeight;
int mValue;
float mQuality; // And when I say nearly identical structure, I
int mUses; // mean perfectly identical except that these two
// variables are swaped for repair items. Don't ask
// me why.
}; // Size = 16
Data mData;
Type mType;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
struct Probe: Tool
{
Probe() { mType = Type_Probe; }
};
struct Repair: Tool
{
Repair() { mType = Type_Repair; }
};
}
#endif

@ -0,0 +1,30 @@
#include "loadprob.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace ESM
{
void Probe::load(ESMReader &esm)
{
mModel = esm.getHNString("MODL");
mName = esm.getHNString("FNAM");
esm.getHNT(mData, "PBDT", 16);
mScript = esm.getHNOString("SCRI");
mIcon = esm.getHNOString("ITEX");
}
void Probe::save(ESMWriter &esm)
{
esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName);
esm.writeHNT("PBDT", mData, 16);
esm.writeHNOString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
}

@ -0,0 +1,31 @@
#ifndef OPENMW_ESM_PROBE_H
#define OPENMW_ESM_PROBE_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct Probe
{
struct Data
{
float mWeight;
int mValue;
float mQuality;
int mUses;
}; // Size = 16
Data mData;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
}
#endif

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

Loading…
Cancel
Save