mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Merge remote-tracking branch 'zini/master' into rotation
This commit is contained in:
commit
7611caa6eb
@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags)
|
|||||||
std::string properties = "";
|
std::string properties = "";
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0) properties += "[None] ";
|
||||||
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
|
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
|
||||||
if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable ";
|
if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
|
||||||
int unused = (0xFFFFFFFF ^
|
int unused = (0xFFFFFFFF ^
|
||||||
(ESM::BodyPart::BPF_Female|
|
(ESM::BodyPart::BPF_Female|
|
||||||
ESM::BodyPart::BPF_Playable));
|
ESM::BodyPart::BPF_NotPlayable));
|
||||||
if (flags & unused) properties += "Invalid ";
|
if (flags & unused) properties += "Invalid ";
|
||||||
properties += str(boost::format("(0x%08X)") % flags);
|
properties += str(boost::format("(0x%08X)") % flags);
|
||||||
return properties;
|
return properties;
|
||||||
|
@ -207,7 +207,7 @@ void CSMDoc::Document::createBase()
|
|||||||
{
|
{
|
||||||
ESM::Skill record;
|
ESM::Skill record;
|
||||||
record.mIndex = i;
|
record.mIndex = i;
|
||||||
record.mId = ESM::Skill::getIndexToId (record.mIndex);
|
record.mId = ESM::Skill::indexToId (record.mIndex);
|
||||||
record.blank();
|
record.blank();
|
||||||
|
|
||||||
getData().getSkills().add (record);
|
getData().getSkills().add (record);
|
||||||
|
@ -33,7 +33,8 @@ namespace CSMWorld
|
|||||||
Display_GmstVarType,
|
Display_GmstVarType,
|
||||||
Display_GlobalVarType,
|
Display_GlobalVarType,
|
||||||
Display_Specialisation,
|
Display_Specialisation,
|
||||||
Display_Attribute
|
Display_Attribute,
|
||||||
|
Display_Boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string mTitle;
|
std::string mTitle;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef CSM_WOLRD_COLUMNS_H
|
#ifndef CSM_WOLRD_COLUMNS_H
|
||||||
#define CSM_WOLRD_COLUMNS_H
|
#define CSM_WOLRD_COLUMNS_H
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
@ -285,6 +287,128 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct NameColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
NameColumn() : Column<ESXRecordT> ("Name", ColumnBase::Display_String) {}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8 (record.get().mName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mName = data.toString().toUtf8().constData();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct AttributesColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
int mIndex;
|
||||||
|
|
||||||
|
AttributesColumn (int index)
|
||||||
|
: Column<ESXRecordT> ("Attribute #" + boost::lexical_cast<std::string> (index),
|
||||||
|
ColumnBase::Display_Attribute), mIndex (index) {}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mData.mAttribute[mIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mData.mAttribute[mIndex] = data.toInt();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct SkillsColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
int mIndex;
|
||||||
|
bool mMajor;
|
||||||
|
|
||||||
|
SkillsColumn (int index, bool major)
|
||||||
|
: Column<ESXRecordT> ((major ? "Major Skill #" : "Minor Skill #")+
|
||||||
|
boost::lexical_cast<std::string> (index), ColumnBase::Display_String),
|
||||||
|
mIndex (index), mMajor (major)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
int skill = record.get().mData.mSkills[mIndex][mMajor ? 1 : 0];
|
||||||
|
|
||||||
|
return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
std::istringstream stream (data.toString().toUtf8().constData());
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
stream >> c >> index;
|
||||||
|
|
||||||
|
if (index!=-1)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mData.mSkills[mIndex][mMajor ? 1 : 0] = index;
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct PlayableColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
PlayableColumn() : Column<ESXRecordT> ("Playable", ColumnBase::Display_Boolean) {}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mData.mIsPlayable!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mData.mIsPlayable = data.toInt();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -44,9 +44,23 @@ CSMWorld::Data::Data()
|
|||||||
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
|
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
|
||||||
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
|
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
|
||||||
|
|
||||||
|
mClasses.addColumn (new StringIdColumn<ESM::Class>);
|
||||||
|
mClasses.addColumn (new RecordStateColumn<ESM::Class>);
|
||||||
|
mClasses.addColumn (new NameColumn<ESM::Class>);
|
||||||
|
mClasses.addColumn (new AttributesColumn<ESM::Class> (0));
|
||||||
|
mClasses.addColumn (new AttributesColumn<ESM::Class> (1));
|
||||||
|
mClasses.addColumn (new SpecialisationColumn<ESM::Class>);
|
||||||
|
for (int i=0; i<5; ++i)
|
||||||
|
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, true));
|
||||||
|
for (int i=0; i<5; ++i)
|
||||||
|
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, false));
|
||||||
|
mClasses.addColumn (new PlayableColumn<ESM::Class>);
|
||||||
|
mClasses.addColumn (new DescriptionColumn<ESM::Class>);
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
|
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
|
||||||
|
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::~Data()
|
CSMWorld::Data::~Data()
|
||||||
@ -122,6 +136,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
|||||||
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
|
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
|
||||||
case ESM::REC_GMST: mGmsts.load (reader, base); break;
|
case ESM::REC_GMST: mGmsts.load (reader, base); break;
|
||||||
case ESM::REC_SKIL: mSkills.load (reader, base); break;
|
case ESM::REC_SKIL: mSkills.load (reader, base); break;
|
||||||
|
case ESM::REC_CLAS: mClasses.load (reader, base); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <components/esm/loadglob.hpp>
|
#include <components/esm/loadglob.hpp>
|
||||||
#include <components/esm/loadgmst.hpp>
|
#include <components/esm/loadgmst.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
#include <components/esm/loadclas.hpp>
|
||||||
|
|
||||||
#include "idcollection.hpp"
|
#include "idcollection.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
@ -22,6 +23,7 @@ namespace CSMWorld
|
|||||||
IdCollection<ESM::Global> mGlobals;
|
IdCollection<ESM::Global> mGlobals;
|
||||||
IdCollection<ESM::GameSetting> mGmsts;
|
IdCollection<ESM::GameSetting> mGmsts;
|
||||||
IdCollection<ESM::Skill> mSkills;
|
IdCollection<ESM::Skill> mSkills;
|
||||||
|
IdCollection<ESM::Class> mClasses;
|
||||||
std::vector<QAbstractItemModel *> mModels;
|
std::vector<QAbstractItemModel *> mModels;
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
|
{ 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_Gmsts, "Game Settings" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" },
|
||||||
|
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||||
};
|
};
|
||||||
@ -29,6 +30,7 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
|
{ 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_Gmst, "Game Setting" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" },
|
||||||
|
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,9 @@ namespace CSMWorld
|
|||||||
Type_Gmsts,
|
Type_Gmsts,
|
||||||
Type_Gmst,
|
Type_Gmst,
|
||||||
Type_Skills,
|
Type_Skills,
|
||||||
Type_Skill
|
Type_Skill,
|
||||||
|
Type_Classes,
|
||||||
|
Type_Class
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -90,6 +90,10 @@ void CSVDoc::View::setupWorldMenu()
|
|||||||
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
|
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
|
||||||
world->addAction (skills);
|
world->addAction (skills);
|
||||||
|
|
||||||
|
QAction *classes = new QAction (tr ("Classes"), this);
|
||||||
|
connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView()));
|
||||||
|
world->addAction (classes);
|
||||||
|
|
||||||
mVerify = new QAction (tr ("&Verify"), this);
|
mVerify = new QAction (tr ("&Verify"), this);
|
||||||
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
|
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
|
||||||
world->addAction (mVerify);
|
world->addAction (mVerify);
|
||||||
@ -253,6 +257,11 @@ void CSVDoc::View::addSkillsSubView()
|
|||||||
addSubView (CSMWorld::UniversalId::Type_Skills);
|
addSubView (CSMWorld::UniversalId::Type_Skills);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addClassesSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Classes);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::abortOperation (int type)
|
void CSVDoc::View::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mDocument->abortOperation (type);
|
mDocument->abortOperation (type);
|
||||||
|
@ -117,6 +117,8 @@ namespace CSVDoc
|
|||||||
void addGmstsSubView();
|
void addGmstsSubView();
|
||||||
|
|
||||||
void addSkillsSubView();
|
void addSkillsSubView();
|
||||||
|
|
||||||
|
void addClassesSubView();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||||||
manager.add (CSMWorld::UniversalId::Type_Skills,
|
manager.add (CSMWorld::UniversalId::Type_Skills,
|
||||||
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
|
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
|
||||||
|
|
||||||
manager.add (CSMWorld::UniversalId::Type_Global,
|
manager.add (CSMWorld::UniversalId::Type_Classes,
|
||||||
new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
|
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (true));
|
||||||
|
|
||||||
|
// manager.add (CSMWorld::UniversalId::Type_Global,
|
||||||
|
// new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
|
||||||
}
|
}
|
@ -23,6 +23,18 @@
|
|||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool isGold (const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
return Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001")
|
||||||
|
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005")
|
||||||
|
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010")
|
||||||
|
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025")
|
||||||
|
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
@ -109,25 +121,15 @@ namespace MWClass
|
|||||||
|
|
||||||
std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const
|
std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
if (isGold(ptr))
|
||||||
ptr.get<ESM::Miscellaneous>();
|
|
||||||
|
|
||||||
if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGold")->getString())
|
|
||||||
{
|
|
||||||
return std::string("Item Gold Up");
|
return std::string("Item Gold Up");
|
||||||
}
|
|
||||||
return std::string("Item Misc Up");
|
return std::string("Item Misc Up");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const
|
std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
if (isGold(ptr))
|
||||||
ptr.get<ESM::Miscellaneous>();
|
|
||||||
|
|
||||||
if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGold")->getString())
|
|
||||||
{
|
|
||||||
return std::string("Item Gold Down");
|
return std::string("Item Gold Down");
|
||||||
}
|
|
||||||
return std::string("Item Misc Down");
|
return std::string("Item Misc Down");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,19 +160,15 @@ namespace MWClass
|
|||||||
|
|
||||||
int count = ptr.getRefData().getCount();
|
int count = ptr.getRefData().getCount();
|
||||||
|
|
||||||
bool isGold = Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001")
|
bool gold = isGold(ptr);
|
||||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005")
|
|
||||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010")
|
|
||||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025")
|
|
||||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100");
|
|
||||||
|
|
||||||
if (isGold && ptr.getCellRef().mGoldValue != 1)
|
if (gold && ptr.getCellRef().mGoldValue != 1)
|
||||||
count = ptr.getCellRef().mGoldValue;
|
count = ptr.getCellRef().mGoldValue;
|
||||||
else if (isGold)
|
else if (gold)
|
||||||
count *= ref->mBase->mData.mValue;
|
count *= ref->mBase->mData.mValue;
|
||||||
|
|
||||||
std::string countString;
|
std::string countString;
|
||||||
if (!isGold)
|
if (!gold)
|
||||||
countString = MWGui::ToolTips::getCountString(count);
|
countString = MWGui::ToolTips::getCountString(count);
|
||||||
else // gold displays its count also if it's 1.
|
else // gold displays its count also if it's 1.
|
||||||
countString = " (" + boost::lexical_cast<std::string>(count) + ")";
|
countString = " (" + boost::lexical_cast<std::string>(count) + ")";
|
||||||
@ -186,7 +184,7 @@ namespace MWClass
|
|||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
if (!isGold)
|
if (!gold)
|
||||||
{
|
{
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||||
@ -210,7 +208,7 @@ namespace MWClass
|
|||||||
const MWWorld::ESMStore &store =
|
const MWWorld::ESMStore &store =
|
||||||
MWBase::Environment::get().getWorld()->getStore();
|
MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
|
||||||
if (MWWorld::Class::get(ptr).getName(ptr) == store.get<ESM::GameSetting>().find("sGold")->getString()) {
|
if (isGold(ptr)) {
|
||||||
int goldAmount = ptr.getRefData().getCount();
|
int goldAmount = ptr.getRefData().getCount();
|
||||||
|
|
||||||
std::string base = "Gold_001";
|
std::string base = "Gold_001";
|
||||||
|
@ -140,13 +140,8 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
|
|||||||
|
|
||||||
if (isInventory())
|
if (isInventory())
|
||||||
{
|
{
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
|
||||||
|
|
||||||
// the player is trying to sell an item, check if the merchant accepts it
|
// the player is trying to sell an item, check if the merchant accepts it
|
||||||
// also, don't allow selling gold (let's be better than Morrowind at this, can we?)
|
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object))
|
||||||
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object) ||
|
|
||||||
MWWorld::Class::get(object).getName(object) == gmst.find("sGold")->getString())
|
|
||||||
{
|
{
|
||||||
// user notification "i don't buy this item"
|
// user notification "i don't buy this item"
|
||||||
MWBase::Environment::get().getWindowManager()->
|
MWBase::Environment::get().getWindowManager()->
|
||||||
|
@ -19,6 +19,49 @@
|
|||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
using namespace Widgets;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int wrap(int index, int max)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
return max - 1;
|
||||||
|
else if (index >= max)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countParts(const std::string &part, const std::string &race, bool male)
|
||||||
|
{
|
||||||
|
/// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs
|
||||||
|
const MWWorld::Store<ESM::BodyPart> &store =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||||
|
|
||||||
|
std::string prefix =
|
||||||
|
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
||||||
|
|
||||||
|
std::string suffix;
|
||||||
|
suffix.reserve(prefix.size() + 3);
|
||||||
|
|
||||||
|
int count = -1;
|
||||||
|
do {
|
||||||
|
++count;
|
||||||
|
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
||||||
|
}
|
||||||
|
while (store.search(prefix + suffix) != 0);
|
||||||
|
|
||||||
|
if (count == 0 && part == "hair") {
|
||||||
|
count = -1;
|
||||||
|
do {
|
||||||
|
++count;
|
||||||
|
suffix = (boost::format("%02d") % (count + 1)).str();
|
||||||
|
}
|
||||||
|
while (store.search(prefix + suffix) != 0);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
|
RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
|
||||||
: WindowModal("openmw_chargen_race.layout", parWindowManager)
|
: WindowModal("openmw_chargen_race.layout", parWindowManager)
|
||||||
, mGenderIndex(0)
|
, mGenderIndex(0)
|
||||||
@ -144,45 +187,6 @@ void RaceDialog::setRaceId(const std::string &raceId)
|
|||||||
updateSpellPowers();
|
updateSpellPowers();
|
||||||
}
|
}
|
||||||
|
|
||||||
int wrap(int index, int max)
|
|
||||||
{
|
|
||||||
if (index < 0)
|
|
||||||
return max - 1;
|
|
||||||
else if (index >= max)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int countParts(const std::string &part, const std::string &race, bool male)
|
|
||||||
{
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &store =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
|
||||||
|
|
||||||
std::string prefix =
|
|
||||||
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
|
||||||
|
|
||||||
std::string suffix;
|
|
||||||
suffix.reserve(prefix.size() + 3);
|
|
||||||
|
|
||||||
int count = -1;
|
|
||||||
do {
|
|
||||||
++count;
|
|
||||||
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
|
||||||
}
|
|
||||||
while (store.search(prefix + suffix) != 0);
|
|
||||||
|
|
||||||
if (count == 0 && part == "hair") {
|
|
||||||
count = -1;
|
|
||||||
do {
|
|
||||||
++count;
|
|
||||||
suffix = (boost::format("%02d") % (count + 1)).str();
|
|
||||||
}
|
|
||||||
while (store.search(prefix + suffix) != 0);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RaceDialog::close()
|
void RaceDialog::close()
|
||||||
{
|
{
|
||||||
delete mPreview;
|
delete mPreview;
|
||||||
@ -229,28 +233,67 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*)
|
|||||||
|
|
||||||
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
do
|
||||||
|
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
||||||
|
while (!isFacePlayable());
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
do
|
||||||
|
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||||
|
while (!isFacePlayable());
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
do
|
||||||
|
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
||||||
|
while (!isHairPlayable());
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
do
|
||||||
|
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||||
|
while (!isHairPlayable());
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RaceDialog::isFacePlayable()
|
||||||
|
{
|
||||||
|
std::string prefix =
|
||||||
|
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||||
|
|
||||||
|
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
||||||
|
|
||||||
|
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||||
|
|
||||||
|
if (parts.search(prefix + "head_" + headIndex) == 0)
|
||||||
|
return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||||
|
else
|
||||||
|
return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RaceDialog::isHairPlayable()
|
||||||
|
{
|
||||||
|
std::string prefix =
|
||||||
|
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||||
|
|
||||||
|
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
||||||
|
|
||||||
|
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||||
|
if (parts.search(prefix + "hair_" + hairIndex) == 0)
|
||||||
|
return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||||
|
else
|
||||||
|
return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||||
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
@ -273,11 +316,16 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
|||||||
|
|
||||||
void RaceDialog::recountParts()
|
void RaceDialog::recountParts()
|
||||||
{
|
{
|
||||||
|
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
||||||
|
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
||||||
|
|
||||||
mFaceIndex = 0;
|
mFaceIndex = 0;
|
||||||
mHairIndex = 0;
|
mHairIndex = 0;
|
||||||
|
|
||||||
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
while (!isHairPlayable())
|
||||||
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||||
|
while (!isFacePlayable())
|
||||||
|
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update widget content
|
// update widget content
|
||||||
|
@ -81,6 +81,9 @@ namespace MWGui
|
|||||||
void updatePreview();
|
void updatePreview();
|
||||||
void recountParts();
|
void recountParts();
|
||||||
|
|
||||||
|
bool isHairPlayable();
|
||||||
|
bool isFacePlayable();
|
||||||
|
|
||||||
MyGUI::ImageBox* mPreviewImage;
|
MyGUI::ImageBox* mPreviewImage;
|
||||||
MyGUI::ListBox* mRaceList;
|
MyGUI::ListBox* mRaceList;
|
||||||
MyGUI::ScrollBar* mHeadRotate;
|
MyGUI::ScrollBar* mHeadRotate;
|
||||||
|
@ -129,13 +129,10 @@ namespace MWGui
|
|||||||
MWWorld::Ptr gold;
|
MWWorld::Ptr gold;
|
||||||
MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore();
|
MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore();
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
|
||||||
|
|
||||||
for (MWWorld::ContainerStoreIterator it = playerStore.begin();
|
for (MWWorld::ContainerStoreIterator it = playerStore.begin();
|
||||||
it != playerStore.end(); ++it)
|
it != playerStore.end(); ++it)
|
||||||
{
|
{
|
||||||
if (MWWorld::Class::get(*it).getName(*it) == gmst.find("sGold")->getString())
|
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
|
||||||
{
|
{
|
||||||
goldFound = true;
|
goldFound = true;
|
||||||
gold = *it;
|
gold = *it;
|
||||||
@ -342,6 +339,9 @@ namespace MWGui
|
|||||||
|
|
||||||
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
|
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
|
if (Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001"))
|
||||||
|
return false;
|
||||||
|
|
||||||
int services = 0;
|
int services = 0;
|
||||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
{
|
{
|
||||||
|
@ -316,5 +316,7 @@ op 0x20001f9: Drop, explicit reference
|
|||||||
op 0x20001fa: DropSoulGem
|
op 0x20001fa: DropSoulGem
|
||||||
op 0x20001fb: DropSoulGem, explicit reference
|
op 0x20001fb: DropSoulGem, explicit reference
|
||||||
op 0x20001fc: OnDeath
|
op 0x20001fc: OnDeath
|
||||||
|
op 0x20001fd: IsWerewolf
|
||||||
|
op 0x20001fe: IsWerewolf, explicit reference
|
||||||
|
|
||||||
opcodes 0x20001fd-0x3ffffff unused
|
opcodes 0x20001ff-0x3ffffff unused
|
||||||
|
@ -1046,6 +1046,18 @@ namespace MWScript
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpIsWerewolf : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
runtime.push(MWWorld::Class::get(ptr).getNpcStats(ptr).isWerewolf());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const int numberOfAttributes = 8;
|
const int numberOfAttributes = 8;
|
||||||
|
|
||||||
const int opcodeGetAttribute = 0x2000027;
|
const int opcodeGetAttribute = 0x2000027;
|
||||||
@ -1137,6 +1149,9 @@ namespace MWScript
|
|||||||
|
|
||||||
const int opcodeOnDeath = 0x20001fc;
|
const int opcodeOnDeath = 0x20001fc;
|
||||||
|
|
||||||
|
const int opcodeIsWerewolf = 0x20001fd;
|
||||||
|
const int opcodeIsWerewolfExplicit = 0x20001fe;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
static const char *attributes[numberOfAttributes] =
|
static const char *attributes[numberOfAttributes] =
|
||||||
@ -1252,6 +1267,8 @@ namespace MWScript
|
|||||||
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
|
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
|
||||||
|
|
||||||
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath);
|
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath);
|
||||||
|
|
||||||
|
extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
@ -1368,6 +1385,9 @@ namespace MWScript
|
|||||||
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
|
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
|
||||||
|
|
||||||
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath);
|
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath);
|
||||||
|
|
||||||
|
interpreter.installSegment5 (opcodeIsWerewolf, new OpIsWerewolf<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeIsWerewolfExplicit, new OpIsWerewolf<ExplicitRef>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ struct BodyPart
|
|||||||
enum Flags
|
enum Flags
|
||||||
{
|
{
|
||||||
BPF_Female = 1,
|
BPF_Female = 1,
|
||||||
BPF_Playable = 2
|
BPF_NotPlayable = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MeshType
|
enum MeshType
|
||||||
|
@ -35,4 +35,18 @@ void Class::save(ESMWriter &esm)
|
|||||||
esm.writeHNOString("DESC", mDescription);
|
esm.writeHNOString("DESC", mDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Class::blank()
|
||||||
|
{
|
||||||
|
mName.clear();
|
||||||
|
mDescription.clear();
|
||||||
|
|
||||||
|
mData.mAttribute[0] = mData.mAttribute[1] = 0;
|
||||||
|
mData.mSpecialization = 0;
|
||||||
|
mData.mIsPlayable = 0;
|
||||||
|
mData.mCalc = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<5; ++i)
|
||||||
|
for (int i2=0; i2<2; ++i2)
|
||||||
|
mData.mSkills[i][i2] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,10 @@ struct Class
|
|||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm);
|
||||||
|
|
||||||
|
void blank();
|
||||||
|
///< Set record to default state (does not touch the ID/index).
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
@ -103,8 +105,9 @@ void Skill::load(ESMReader &esm)
|
|||||||
|
|
||||||
// create an ID from the index and the name (only used in the editor and likely to change in the
|
// create an ID from the index and the name (only used in the editor and likely to change in the
|
||||||
// future)
|
// future)
|
||||||
mId = getIndexToId (mIndex);
|
mId = indexToId (mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skill::save(ESMWriter &esm)
|
void Skill::save(ESMWriter &esm)
|
||||||
{
|
{
|
||||||
esm.writeHNT("INDX", mIndex);
|
esm.writeHNT("INDX", mIndex);
|
||||||
@ -120,7 +123,7 @@ void Skill::save(ESMWriter &esm)
|
|||||||
mDescription.clear();
|
mDescription.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Skill::getIndexToId (int index)
|
std::string Skill::indexToId (int index)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ struct Skill
|
|||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID/index).
|
///< Set record to default state (does not touch the ID/index).
|
||||||
|
|
||||||
static std::string getIndexToId (int index);
|
static std::string indexToId (int index);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user