forked from mirror/openmw-tes3mp
Merge branch 'master' of https://github.com/zinnschlag/openmw.git into AIFix2
Conflicts: apps/openmw/mwmechanics/aitravel.cpp
This commit is contained in:
commit
7c6e27e4f9
296 changed files with 9130 additions and 2990 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -40,6 +40,7 @@ resources
|
||||||
|
|
||||||
## generated objects
|
## generated objects
|
||||||
apps/openmw/config.hpp
|
apps/openmw/config.hpp
|
||||||
|
components/version/version.hpp
|
||||||
Docs/mainpage.hpp
|
Docs/mainpage.hpp
|
||||||
moc_*.cxx
|
moc_*.cxx
|
||||||
*.cxx_parameters
|
*.cxx_parameters
|
||||||
|
|
|
@ -18,11 +18,26 @@ include (OpenMWMacros)
|
||||||
|
|
||||||
# Version
|
# Version
|
||||||
|
|
||||||
set (OPENMW_VERSION_MAJOR 0)
|
include(GetGitRevisionDescription)
|
||||||
set (OPENMW_VERSION_MINOR 27)
|
|
||||||
set (OPENMW_VERSION_RELEASE 0)
|
get_git_tag_revision(TAGHASH --tags --max-count=1)
|
||||||
|
get_git_head_revision(REFSPEC COMMITHASH)
|
||||||
|
git_describe(VERSION --tags ${TAGHASH})
|
||||||
|
|
||||||
|
string(REGEX MATCH "^openmw-[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" MATCH "${VERSION}")
|
||||||
|
if (MATCH)
|
||||||
|
string(REGEX REPLACE "^openmw-([0-9]+)\\..*" "\\1" OPENMW_VERSION_MAJOR "${VERSION}")
|
||||||
|
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_MINOR "${VERSION}")
|
||||||
|
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_RELEASE "${VERSION}")
|
||||||
|
|
||||||
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
|
||||||
|
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
|
||||||
|
|
||||||
|
message(STATUS "Configuring OpenMW ${OPENMW_VERSION}...")
|
||||||
|
else (MATCH)
|
||||||
|
message(FATAL_ERROR "Failed to get valid version information from Git")
|
||||||
|
endif (MATCH)
|
||||||
|
|
||||||
# doxygen main page
|
# doxygen main page
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,9 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||||
// Loop through all the references
|
// Loop through all the references
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
if(!quiet) std::cout << " References:\n";
|
if(!quiet) std::cout << " References:\n";
|
||||||
while(cell.getNextRef(esm, ref))
|
|
||||||
|
bool deleted = false;
|
||||||
|
while(cell.getNextRef(esm, ref, deleted))
|
||||||
{
|
{
|
||||||
if (save) {
|
if (save) {
|
||||||
info.data.mCellRefs[&cell].push_back(ref);
|
info.data.mCellRefs[&cell].push_back(ref);
|
||||||
|
@ -244,13 +246,14 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||||
|
|
||||||
if(quiet) continue;
|
if(quiet) continue;
|
||||||
|
|
||||||
std::cout << " Refnum: " << ref.mRefnum << std::endl;
|
std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl;
|
||||||
std::cout << " ID: '" << ref.mRefID << "'\n";
|
std::cout << " ID: '" << ref.mRefID << "'\n";
|
||||||
std::cout << " Owner: '" << ref.mOwner << "'\n";
|
std::cout << " Owner: '" << ref.mOwner << "'\n";
|
||||||
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
|
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
|
||||||
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
|
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
|
||||||
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||||
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
||||||
|
std::cout << " Deleted: " << deleted << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
|
#include <components/version/version.hpp>
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QDate>
|
||||||
|
#include <QTime>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
@ -67,6 +72,22 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
|
||||||
// Remove what's this? button
|
// Remove what's this? button
|
||||||
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
// Add version information to bottom of the window
|
||||||
|
QString revision(OPENMW_VERSION_COMMITHASH);
|
||||||
|
QString tag(OPENMW_VERSION_TAGHASH);
|
||||||
|
|
||||||
|
if (revision == tag) {
|
||||||
|
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
|
||||||
|
} else {
|
||||||
|
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the compile date and time
|
||||||
|
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
|
||||||
|
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
|
||||||
|
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
|
||||||
|
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
|
||||||
|
|
||||||
createIcons();
|
createIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,16 +133,10 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, std::vector<std::
|
||||||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||||
infoModified)
|
infoModified)
|
||||||
{
|
{
|
||||||
// always write the topic record
|
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||||
std::string type;
|
|
||||||
for (int i=0; i<4; ++i)
|
|
||||||
/// \todo make endianess agnostic (change ESMWriter interface?)
|
|
||||||
type += reinterpret_cast<const char *> (&topic.mModified.sRecordId)[i];
|
|
||||||
|
|
||||||
mState.getWriter().startRecord (type);
|
|
||||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||||
topic.mModified.save (mState.getWriter());
|
topic.mModified.save (mState.getWriter());
|
||||||
mState.getWriter().endRecord (type);
|
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||||
|
|
||||||
// write modified selected info records
|
// write modified selected info records
|
||||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||||
|
@ -178,15 +172,10 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, std::vector<std::
|
||||||
next->mModified.mId.substr (next->mModified.mId.find_last_of ('#')+1);
|
next->mModified.mId.substr (next->mModified.mId.find_last_of ('#')+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string type;
|
mState.getWriter().startRecord (info.sRecordId);
|
||||||
for (int i=0; i<4; ++i)
|
|
||||||
/// \todo make endianess agnostic (change ESMWriter interface?)
|
|
||||||
type += reinterpret_cast<const char *> (&info.sRecordId)[i];
|
|
||||||
|
|
||||||
mState.getWriter().startRecord (type);
|
|
||||||
mState.getWriter().writeHNCString ("INAM", info.mId);
|
mState.getWriter().writeHNCString ("INAM", info.mId);
|
||||||
info.save (mState.getWriter());
|
info.save (mState.getWriter());
|
||||||
mState.getWriter().endRecord (type);
|
mState.getWriter().endRecord (info.sRecordId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,10 +104,10 @@ namespace CSMDoc
|
||||||
/// \todo make endianess agnostic (change ESMWriter interface?)
|
/// \todo make endianess agnostic (change ESMWriter interface?)
|
||||||
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
|
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
|
||||||
|
|
||||||
mState.getWriter().startRecord (type);
|
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
|
||||||
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
||||||
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
||||||
mState.getWriter().endRecord (type);
|
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
|
||||||
}
|
}
|
||||||
else if (state==CSMWorld::RecordBase::State_Deleted)
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,6 +98,10 @@ namespace CSMWorld
|
||||||
UniversalId::Type type = UniversalId::Type_None);
|
UniversalId::Type type = UniversalId::Type_None);
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
|
|
||||||
|
virtual void cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const UniversalId::Type type);
|
||||||
|
|
||||||
virtual int searchId (const std::string& id) const;
|
virtual int searchId (const std::string& id) const;
|
||||||
////< Search record with \a id.
|
////< Search record with \a id.
|
||||||
/// \return index of record (if found) or -1 (not found)
|
/// \return index of record (if found) or -1 (not found)
|
||||||
|
@ -193,6 +197,19 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const UniversalId::Type type)
|
||||||
|
{
|
||||||
|
Record<ESXRecordT> copy;
|
||||||
|
copy.mModified = getRecord(origin).get();
|
||||||
|
copy.mState = RecordBase::State_ModifiedOnly;
|
||||||
|
copy.get().mId = destination;
|
||||||
|
|
||||||
|
insertRecord(copy, getAppendIndex(destination, type));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
Collection<ESXRecordT, IdAccessorT>::Collection()
|
Collection<ESXRecordT, IdAccessorT>::Collection()
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -74,6 +74,10 @@ namespace CSMWorld
|
||||||
UniversalId::Type type = UniversalId::Type_None) = 0;
|
UniversalId::Type type = UniversalId::Type_None) = 0;
|
||||||
///< If the record type does not match, an exception is thrown.
|
///< If the record type does not match, an exception is thrown.
|
||||||
|
|
||||||
|
virtual void cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const UniversalId::Type type) = 0;
|
||||||
|
|
||||||
virtual const RecordBase& getRecord (const std::string& id) const = 0;
|
virtual const RecordBase& getRecord (const std::string& id) const = 0;
|
||||||
|
|
||||||
virtual const RecordBase& getRecord (int index) const = 0;
|
virtual const RecordBase& getRecord (int index) const = 0;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
#include "idtable.hpp"
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index,
|
CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index,
|
||||||
const QVariant& new_, QUndoCommand* parent)
|
const QVariant& new_, QUndoCommand* parent)
|
||||||
|
@ -145,3 +145,30 @@ void CSMWorld::ReorderRowsCommand::undo()
|
||||||
|
|
||||||
mModel.reorderRows (mBaseIndex, reverse);
|
mModel.reorderRows (mBaseIndex, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model,
|
||||||
|
const std::string& idOrigin,
|
||||||
|
const std::string& IdDestination,
|
||||||
|
const CSMWorld::UniversalId::Type type,
|
||||||
|
QUndoCommand* parent) :
|
||||||
|
QUndoCommand (parent),
|
||||||
|
mModel (model),
|
||||||
|
mIdOrigin (idOrigin),
|
||||||
|
mIdDestination (Misc::StringUtils::lowerCase (IdDestination)),
|
||||||
|
mType (type)
|
||||||
|
{
|
||||||
|
setText ( ("Clone record " + idOrigin + " to the " + IdDestination).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CloneCommand::redo()
|
||||||
|
{
|
||||||
|
mModel.cloneRecord (mIdOrigin, mIdDestination, mType);
|
||||||
|
|
||||||
|
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter != mValues.end(); ++iter)
|
||||||
|
mModel.setData (mModel.getModelIndex (mIdDestination, iter->first), iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CloneCommand::undo()
|
||||||
|
{
|
||||||
|
mModel.removeRow (mModel.getModelIndex (mIdDestination, 0).row());
|
||||||
|
}
|
|
@ -39,6 +39,26 @@ namespace CSMWorld
|
||||||
virtual void undo();
|
virtual void undo();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CloneCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
IdTable& mModel;
|
||||||
|
std::string mIdOrigin;
|
||||||
|
std::string mIdDestination;
|
||||||
|
UniversalId::Type mType;
|
||||||
|
std::map<int, QVariant> mValues;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CloneCommand (IdTable& model, const std::string& idOrigin,
|
||||||
|
const std::string& IdDestination,
|
||||||
|
const UniversalId::Type type,
|
||||||
|
QUndoCommand* parent = 0);
|
||||||
|
|
||||||
|
virtual void redo();
|
||||||
|
|
||||||
|
virtual void undo();
|
||||||
|
};
|
||||||
|
|
||||||
class CreateCommand : public QUndoCommand
|
class CreateCommand : public QUndoCommand
|
||||||
{
|
{
|
||||||
IdTable& mModel;
|
IdTable& mModel;
|
||||||
|
|
|
@ -154,14 +154,17 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
|
|
||||||
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mTopics.addColumn (new FixedRecordTypeColumn<ESM::Dialogue> (UniversalId::Type_Topic));
|
||||||
mTopics.addColumn (new DialogueTypeColumn<ESM::Dialogue>);
|
mTopics.addColumn (new DialogueTypeColumn<ESM::Dialogue>);
|
||||||
|
|
||||||
mJournals.addColumn (new StringIdColumn<ESM::Dialogue>);
|
mJournals.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
mJournals.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
mJournals.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mJournals.addColumn (new FixedRecordTypeColumn<ESM::Dialogue> (UniversalId::Type_Journal));
|
||||||
mJournals.addColumn (new DialogueTypeColumn<ESM::Dialogue> (true));
|
mJournals.addColumn (new DialogueTypeColumn<ESM::Dialogue> (true));
|
||||||
|
|
||||||
mTopicInfos.addColumn (new StringIdColumn<Info> (true));
|
mTopicInfos.addColumn (new StringIdColumn<Info> (true));
|
||||||
mTopicInfos.addColumn (new RecordStateColumn<Info>);
|
mTopicInfos.addColumn (new RecordStateColumn<Info>);
|
||||||
|
mTopicInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_TopicInfo));
|
||||||
mTopicInfos.addColumn (new TopicColumn<Info> (false));
|
mTopicInfos.addColumn (new TopicColumn<Info> (false));
|
||||||
mTopicInfos.addColumn (new ActorColumn<Info>);
|
mTopicInfos.addColumn (new ActorColumn<Info>);
|
||||||
mTopicInfos.addColumn (new RaceColumn<Info>);
|
mTopicInfos.addColumn (new RaceColumn<Info>);
|
||||||
|
@ -178,6 +181,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
|
|
||||||
mJournalInfos.addColumn (new StringIdColumn<Info> (true));
|
mJournalInfos.addColumn (new StringIdColumn<Info> (true));
|
||||||
mJournalInfos.addColumn (new RecordStateColumn<Info>);
|
mJournalInfos.addColumn (new RecordStateColumn<Info>);
|
||||||
|
mJournalInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_Journal));
|
||||||
mJournalInfos.addColumn (new TopicColumn<Info> (true));
|
mJournalInfos.addColumn (new TopicColumn<Info> (true));
|
||||||
mJournalInfos.addColumn (new QuestStatusTypeColumn<Info>);
|
mJournalInfos.addColumn (new QuestStatusTypeColumn<Info>);
|
||||||
mJournalInfos.addColumn (new QuestIndexColumn<Info>);
|
mJournalInfos.addColumn (new QuestIndexColumn<Info>);
|
||||||
|
@ -194,6 +198,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
|
|
||||||
mRefs.addColumn (new StringIdColumn<CellRef> (true));
|
mRefs.addColumn (new StringIdColumn<CellRef> (true));
|
||||||
mRefs.addColumn (new RecordStateColumn<CellRef>);
|
mRefs.addColumn (new RecordStateColumn<CellRef>);
|
||||||
|
mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference));
|
||||||
mRefs.addColumn (new CellColumn<CellRef>);
|
mRefs.addColumn (new CellColumn<CellRef>);
|
||||||
mRefs.addColumn (new IdColumn<CellRef>);
|
mRefs.addColumn (new IdColumn<CellRef>);
|
||||||
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 0, false));
|
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 0, false));
|
||||||
|
@ -224,6 +229,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
|
|
||||||
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
||||||
|
mFilters.addColumn (new FixedRecordTypeColumn<CSMFilter::Filter> (UniversalId::Type_Filter));
|
||||||
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
||||||
|
|
|
@ -124,6 +124,17 @@ void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::IdTable::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
int index = mIdCollection->getAppendIndex (destination);
|
||||||
|
beginInsertRows (QModelIndex(), index, index);
|
||||||
|
mIdCollection->cloneRecord(origin, destination, type);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
||||||
{
|
{
|
||||||
return index (mIdCollection->getIndex (id), column);
|
return index (mIdCollection->getIndex (id), column);
|
||||||
|
|
|
@ -63,6 +63,10 @@ namespace CSMWorld
|
||||||
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
|
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
|
|
||||||
|
void cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
UniversalId::Type type = UniversalId::Type_None);
|
||||||
|
|
||||||
QModelIndex getModelIndex (const std::string& id, int column) const;
|
QModelIndex getModelIndex (const std::string& id, int column) const;
|
||||||
|
|
||||||
void setRecord (const std::string& id, const RecordBase& record);
|
void setRecord (const std::string& id, const RecordBase& record);
|
||||||
|
|
|
@ -8,6 +8,5 @@ void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string
|
||||||
mId = id;
|
mId = id;
|
||||||
mCell = cell.mId;
|
mCell = cell.mId;
|
||||||
|
|
||||||
if (!mDeleted)
|
|
||||||
cell.addRef (mId);
|
cell.addRef (mId);
|
||||||
}
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
|
#include "universalid.hpp"
|
||||||
|
#include "record.hpp"
|
||||||
|
|
||||||
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base)
|
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +16,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
||||||
|
|
||||||
CellRef ref;
|
CellRef ref;
|
||||||
|
|
||||||
while (cell2.getNextRef (reader, ref))
|
bool deleted = false;
|
||||||
|
while (cell2.getNextRef (reader, ref, deleted))
|
||||||
{
|
{
|
||||||
/// \todo handle deleted and moved references
|
/// \todo handle deleted and moved references
|
||||||
ref.load (reader, cell2, getNewId());
|
ref.load (reader, cell2, getNewId());
|
||||||
|
@ -35,3 +38,14 @@ std::string CSMWorld::RefCollection::getNewId()
|
||||||
stream << "ref#" << mNextId++;
|
stream << "ref#" << mNextId++;
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefCollection::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const CSMWorld::UniversalId::Type type,
|
||||||
|
const CSMWorld::UniversalId::ArgumentType argumentType)
|
||||||
|
{
|
||||||
|
Record<CSMWorld::CellRef> clone(getRecord(origin));
|
||||||
|
clone.mState = CSMWorld::RecordBase::State_ModifiedOnly;
|
||||||
|
clone.get().mId = destination;
|
||||||
|
insertRecord(clone, getAppendIndex(destination, type), type);
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
struct Cell;
|
struct Cell;
|
||||||
|
struct UniversalId;
|
||||||
|
|
||||||
/// \brief References in cells
|
/// \brief References in cells
|
||||||
class RefCollection : public Collection<CellRef>
|
class RefCollection : public Collection<CellRef>
|
||||||
|
@ -25,6 +26,11 @@ namespace CSMWorld
|
||||||
///< Load a sequence of references.
|
///< Load a sequence of references.
|
||||||
|
|
||||||
std::string getNewId();
|
std::string getNewId();
|
||||||
|
|
||||||
|
void cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const CSMWorld::UniversalId::Type type,
|
||||||
|
const CSMWorld::UniversalId::ArgumentType argumentType);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace CSMWorld
|
||||||
///< If the data type does not match an exception is thrown.
|
///< If the data type does not match an exception is thrown.
|
||||||
|
|
||||||
virtual std::string getId (const RecordBase& record) const = 0;
|
virtual std::string getId (const RecordBase& record) const = 0;
|
||||||
|
virtual void setId(RecordBase& record, const std::string& id) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual std::string getId (const RecordBase& record) const;
|
virtual std::string getId (const RecordBase& record) const;
|
||||||
|
|
||||||
|
virtual void setId (RecordBase& record, const std::string& id);
|
||||||
|
|
||||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||||
const;
|
const;
|
||||||
|
|
||||||
|
@ -50,6 +52,12 @@ namespace CSMWorld
|
||||||
: mType (type), mBase (base)
|
: mType (type), mBase (base)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template<typename RecordT>
|
||||||
|
void BaseRefIdAdapter<RecordT>::setId (RecordBase& record, const std::string& id)
|
||||||
|
{
|
||||||
|
(dynamic_cast<Record<RecordT>&> (record).get().mId) = id;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
|
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "refidcollection.hpp"
|
#include "refidcollection.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
|
@ -449,6 +450,16 @@ void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record)
|
||||||
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).clone());
|
||||||
|
newRecord->mState = RecordBase::State_ModifiedOnly;
|
||||||
|
mAdapters.find(type)->second->setId(*newRecord, destination);
|
||||||
|
mData.insertRecord(*newRecord, type, destination);
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
||||||
UniversalId::Type type)
|
UniversalId::Type type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,10 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual void removeRows (int index, int count);
|
virtual void removeRows (int index, int count);
|
||||||
|
|
||||||
|
virtual void cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination,
|
||||||
|
const UniversalId::Type type);
|
||||||
|
|
||||||
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
|
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
|
|
||||||
|
|
|
@ -331,3 +331,17 @@ const CSMWorld::RefIdDataContainer< ESM::Static >& CSMWorld::RefIdData::getStati
|
||||||
{
|
{
|
||||||
return mStatics;
|
return mStatics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdData::insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id)
|
||||||
|
{
|
||||||
|
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||||
|
mRecordContainers.find (type);
|
||||||
|
|
||||||
|
if (iter==mRecordContainers.end())
|
||||||
|
throw std::logic_error ("invalid local index type");
|
||||||
|
|
||||||
|
iter->second->insertRecord(record);
|
||||||
|
|
||||||
|
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
|
||||||
|
LocalIndex (iter->second->getSize()-1, type)));
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual void appendRecord (const std::string& id) = 0;
|
virtual void appendRecord (const std::string& id) = 0;
|
||||||
|
|
||||||
|
virtual void insertRecord (RecordBase& record) = 0;
|
||||||
|
|
||||||
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
|
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
|
||||||
|
|
||||||
virtual void erase (int index, int count) = 0;
|
virtual void erase (int index, int count) = 0;
|
||||||
|
@ -69,6 +71,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual void appendRecord (const std::string& id);
|
virtual void appendRecord (const std::string& id);
|
||||||
|
|
||||||
|
virtual void insertRecord (RecordBase& record);
|
||||||
|
|
||||||
virtual void load (int index, ESM::ESMReader& reader, bool base);
|
virtual void load (int index, ESM::ESMReader& reader, bool base);
|
||||||
|
|
||||||
virtual void erase (int index, int count);
|
virtual void erase (int index, int count);
|
||||||
|
@ -78,6 +82,13 @@ namespace CSMWorld
|
||||||
virtual void save (int index, ESM::ESMWriter& writer) const;
|
virtual void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename RecordT>
|
||||||
|
void RefIdDataContainer<RecordT>::insertRecord(RecordBase& record)
|
||||||
|
{
|
||||||
|
Record<RecordT>& newRecord = dynamic_cast<Record<RecordT>& >(record);
|
||||||
|
mContainer.push_back(newRecord);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
int RefIdDataContainer<RecordT>::getSize() const
|
int RefIdDataContainer<RecordT>::getSize() const
|
||||||
{
|
{
|
||||||
|
@ -136,15 +147,10 @@ namespace CSMWorld
|
||||||
if (state==CSMWorld::RecordBase::State_Modified ||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
{
|
{
|
||||||
std::string type;
|
writer.startRecord (mContainer.at (index).mModified.sRecordId);
|
||||||
for (int i=0; i<4; ++i)
|
|
||||||
/// \todo make endianess agnostic (change ESMWriter interface?)
|
|
||||||
type += reinterpret_cast<const char *> (&mContainer.at (index).mModified.sRecordId)[i];
|
|
||||||
|
|
||||||
writer.startRecord (type);
|
|
||||||
writer.writeHNCString ("NAME", getId (index));
|
writer.writeHNCString ("NAME", getId (index));
|
||||||
mContainer.at (index).mModified.save (writer);
|
mContainer.at (index).mModified.save (writer);
|
||||||
writer.endRecord (type);
|
writer.endRecord (mContainer.at (index).mModified.sRecordId);
|
||||||
}
|
}
|
||||||
else if (state==CSMWorld::RecordBase::State_Deleted)
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -201,6 +207,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
void erase (int index, int count);
|
void erase (int index, int count);
|
||||||
|
|
||||||
|
void insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id);
|
||||||
|
|
||||||
const RecordBase& getRecord (const LocalIndex& index) const;
|
const RecordBase& getRecord (const LocalIndex& index) const;
|
||||||
|
|
||||||
RecordBase& getRecord (const LocalIndex& index);
|
RecordBase& getRecord (const LocalIndex& index);
|
||||||
|
|
|
@ -61,6 +61,7 @@ void CSVWorld::CellCreator::reset()
|
||||||
mX->setValue (0);
|
mX->setValue (0);
|
||||||
mY->setValue (0);
|
mY->setValue (0);
|
||||||
mType->setCurrentIndex (0);
|
mType->setCurrentIndex (0);
|
||||||
|
setType(0);
|
||||||
GenericCreator::reset();
|
GenericCreator::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,3 +80,24 @@ void CSVWorld::CellCreator::valueChanged (int index)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::CellCreator::cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
CSVWorld::GenericCreator::cloneMode(originId, type);
|
||||||
|
if (*(originId.begin()) == '#') //if originid points to the exterior cell
|
||||||
|
{
|
||||||
|
setType(1); //enable x and y controls
|
||||||
|
mType->setCurrentIndex(1);
|
||||||
|
} else {
|
||||||
|
setType(0);
|
||||||
|
mType->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSVWorld::CellCreator::toggleWidgets(bool active)
|
||||||
|
{
|
||||||
|
CSVWorld::GenericCreator::toggleWidgets(active);
|
||||||
|
mType->setEnabled(active);
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
virtual void toggleWidgets(bool active = true);
|
||||||
|
|
||||||
|
virtual void cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void setType (int index);
|
void setType (int index);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CSV_WORLD_CREATOR_H
|
#define CSV_WORLD_CREATOR_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include "../../model/world/universalid.hpp"
|
||||||
|
|
||||||
class QUndoStack;
|
class QUndoStack;
|
||||||
|
|
||||||
|
@ -24,8 +25,13 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
|
virtual void cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type) = 0;
|
||||||
|
|
||||||
virtual void setEditLock (bool locked) = 0;
|
virtual void setEditLock (bool locked) = 0;
|
||||||
|
|
||||||
|
virtual void toggleWidgets(bool active = true) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void done();
|
void done();
|
||||||
|
|
|
@ -57,8 +57,15 @@ const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
const CSMWorld::UniversalId& id, bool relaxedIdRules)
|
const CSMWorld::UniversalId& id, bool relaxedIdRules):
|
||||||
: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false)
|
|
||||||
|
mData (data),
|
||||||
|
mUndoStack (undoStack),
|
||||||
|
mListId (id),
|
||||||
|
mLocked (false),
|
||||||
|
mCloneMode(false),
|
||||||
|
mClonedType(CSMWorld::UniversalId::Type_None)
|
||||||
|
|
||||||
{
|
{
|
||||||
mLayout = new QHBoxLayout;
|
mLayout = new QHBoxLayout;
|
||||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||||
|
@ -89,6 +96,7 @@ void CSVWorld::GenericCreator::setEditLock (bool locked)
|
||||||
|
|
||||||
void CSVWorld::GenericCreator::reset()
|
void CSVWorld::GenericCreator::reset()
|
||||||
{
|
{
|
||||||
|
mCloneMode = false;
|
||||||
mId->setText ("");
|
mId->setText ("");
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -120,6 +128,17 @@ void CSVWorld::GenericCreator::create()
|
||||||
{
|
{
|
||||||
if (!mLocked)
|
if (!mLocked)
|
||||||
{
|
{
|
||||||
|
if (mCloneMode)
|
||||||
|
{
|
||||||
|
std::string id = getId();
|
||||||
|
std::auto_ptr<CSMWorld::CloneCommand> command (new CSMWorld::CloneCommand (
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType));
|
||||||
|
|
||||||
|
mUndoStack.push(command.release());
|
||||||
|
|
||||||
|
emit done();
|
||||||
|
emit requestFocus(id);
|
||||||
|
} else {
|
||||||
std::string id = getId();
|
std::string id = getId();
|
||||||
|
|
||||||
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
|
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
|
||||||
|
@ -133,3 +152,16 @@ void CSVWorld::GenericCreator::create()
|
||||||
emit requestFocus (id);
|
emit requestFocus (id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::GenericCreator::cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
mCloneMode = true;
|
||||||
|
mClonedId = originId;
|
||||||
|
mClonedType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::GenericCreator::toggleWidgets(bool active)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef CSV_WORLD_GENERICCREATOR_H
|
#ifndef CSV_WORLD_GENERICCREATOR_H
|
||||||
#define CSV_WORLD_GENERICCREATOR_H
|
#define CSV_WORLD_GENERICCREATOR_H
|
||||||
|
|
||||||
|
class QString;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
|
@ -28,6 +29,11 @@ namespace CSVWorld
|
||||||
std::string mErrors;
|
std::string mErrors;
|
||||||
QHBoxLayout *mLayout;
|
QHBoxLayout *mLayout;
|
||||||
bool mLocked;
|
bool mLocked;
|
||||||
|
std::string mClonedId;
|
||||||
|
CSMWorld::UniversalId::Type mClonedType;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool mCloneMode;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -57,11 +63,15 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
virtual void toggleWidgets (bool active = true);
|
||||||
|
|
||||||
|
virtual void cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
virtual std::string getErrors() const;
|
virtual std::string getErrors() const;
|
||||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||||
/// string is returned, there is no error.
|
/// string is returned, there is no error.
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void textChanged (const QString& text);
|
void textChanged (const QString& text);
|
||||||
|
|
|
@ -41,3 +41,9 @@ void CSVWorld::ReferenceableCreator::reset()
|
||||||
mType->setCurrentIndex (0);
|
mType->setCurrentIndex (0);
|
||||||
GenericCreator::reset();
|
GenericCreator::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::ReferenceableCreator::toggleWidgets(bool active)
|
||||||
|
{
|
||||||
|
CSVWorld::GenericCreator::toggleWidgets(active);
|
||||||
|
mType->setEnabled(active);
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace CSVWorld
|
||||||
const CSMWorld::UniversalId& id);
|
const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual void toggleWidgets(bool active = true);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,20 @@ CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack&
|
||||||
|
|
||||||
void CSVWorld::ReferenceCreator::reset()
|
void CSVWorld::ReferenceCreator::reset()
|
||||||
{
|
{
|
||||||
|
GenericCreator::reset();
|
||||||
mCell->setText ("");
|
mCell->setText ("");
|
||||||
mId = getData().getReferences().getNewId();
|
mId = getData().getReferences().getNewId();
|
||||||
GenericCreator::reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSVWorld::ReferenceCreator::getErrors() const
|
std::string CSVWorld::ReferenceCreator::getErrors() const
|
||||||
{
|
{
|
||||||
std::string errors = GenericCreator::getErrors();
|
std::string errors = GenericCreator::getErrors();
|
||||||
|
|
||||||
|
if (mCloneMode)
|
||||||
|
{
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
std::string cell = mCell->text().toUtf8().constData();
|
std::string cell = mCell->text().toUtf8().constData();
|
||||||
|
|
||||||
if (cell.empty())
|
if (cell.empty())
|
||||||
|
@ -73,3 +78,16 @@ void CSVWorld::ReferenceCreator::cellChanged()
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::ReferenceCreator::toggleWidgets(bool active)
|
||||||
|
{
|
||||||
|
CSVWorld::GenericCreator::toggleWidgets(active);
|
||||||
|
mCell->setEnabled(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
CSVWorld::GenericCreator::cloneMode(originId, type);
|
||||||
|
cellChanged(); //otherwise ok button will remain disabled
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,11 @@ namespace CSVWorld
|
||||||
ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
const CSMWorld::UniversalId& id);
|
const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
virtual void cloneMode(const std::string& originId,
|
||||||
|
const CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
virtual void toggleWidgets(bool active = true);
|
||||||
|
|
||||||
virtual std::string getErrors() const;
|
virtual std::string getErrors() const;
|
||||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||||
|
|
|
@ -28,7 +28,11 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
if (!mEditLock)
|
if (!mEditLock)
|
||||||
{
|
{
|
||||||
if (selectedRows.size()==1)
|
if (selectedRows.size()==1)
|
||||||
|
{
|
||||||
menu.addAction (mEditAction);
|
menu.addAction (mEditAction);
|
||||||
|
if (mCreateAction)
|
||||||
|
menu.addAction(mCloneAction);
|
||||||
|
}
|
||||||
|
|
||||||
if (mCreateAction)
|
if (mCreateAction)
|
||||||
menu.addAction (mCreateAction);
|
menu.addAction (mCreateAction);
|
||||||
|
@ -155,7 +159,7 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||||
|
|
||||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack,
|
CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
bool createAndDelete, bool sorting)
|
bool createAndDelete, bool sorting)
|
||||||
: mUndoStack (undoStack), mCreateAction (0), mEditLock (false), mRecordStatusDisplay (0)
|
: mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0)
|
||||||
{
|
{
|
||||||
mModel = &dynamic_cast<CSMWorld::IdTable&> (*data.getTableModel (id));
|
mModel = &dynamic_cast<CSMWorld::IdTable&> (*data.getTableModel (id));
|
||||||
|
|
||||||
|
@ -199,6 +203,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
|
||||||
mCreateAction = new QAction (tr ("Add Record"), this);
|
mCreateAction = new QAction (tr ("Add Record"), this);
|
||||||
connect (mCreateAction, SIGNAL (triggered()), this, SIGNAL (createRequest()));
|
connect (mCreateAction, SIGNAL (triggered()), this, SIGNAL (createRequest()));
|
||||||
addAction (mCreateAction);
|
addAction (mCreateAction);
|
||||||
|
|
||||||
|
mCloneAction = new QAction (tr ("Clone Record"), this);
|
||||||
|
connect(mCloneAction, SIGNAL (triggered()), this, SLOT (cloneRecord()));
|
||||||
|
addAction(mCloneAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
mRevertAction = new QAction (tr ("Revert Record"), this);
|
mRevertAction = new QAction (tr ("Revert Record"), this);
|
||||||
|
@ -295,6 +303,19 @@ void CSVWorld::Table::editRecord()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::Table::cloneRecord()
|
||||||
|
{
|
||||||
|
if (!mEditLock)
|
||||||
|
{
|
||||||
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
const CSMWorld::UniversalId& toClone = getUniversalId(selectedRows.begin()->row());
|
||||||
|
if (selectedRows.size()==1 && !mModel->getRecord(toClone.getId()).isDeleted())
|
||||||
|
{
|
||||||
|
emit cloneRequest (toClone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::moveUpRecord()
|
void CSVWorld::Table::moveUpRecord()
|
||||||
{
|
{
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace CSVWorld
|
||||||
QUndoStack& mUndoStack;
|
QUndoStack& mUndoStack;
|
||||||
QAction *mEditAction;
|
QAction *mEditAction;
|
||||||
QAction *mCreateAction;
|
QAction *mCreateAction;
|
||||||
|
QAction *mCloneAction;
|
||||||
QAction *mRevertAction;
|
QAction *mRevertAction;
|
||||||
QAction *mDeleteAction;
|
QAction *mDeleteAction;
|
||||||
QAction *mMoveUpAction;
|
QAction *mMoveUpAction;
|
||||||
|
@ -73,6 +74,7 @@ namespace CSVWorld
|
||||||
/// \param modified Number of added and modified records
|
/// \param modified Number of added and modified records
|
||||||
|
|
||||||
void createRequest();
|
void createRequest();
|
||||||
|
void cloneRequest(const CSMWorld::UniversalId&);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -82,6 +84,8 @@ namespace CSVWorld
|
||||||
|
|
||||||
void editRecord();
|
void editRecord();
|
||||||
|
|
||||||
|
void cloneRecord();
|
||||||
|
|
||||||
void moveUpRecord();
|
void moveUpRecord();
|
||||||
|
|
||||||
void moveDownRecord();
|
void moveDownRecord();
|
||||||
|
|
|
@ -153,7 +153,19 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi
|
||||||
void CSVWorld::TableBottomBox::createRequest()
|
void CSVWorld::TableBottomBox::createRequest()
|
||||||
{
|
{
|
||||||
mCreator->reset();
|
mCreator->reset();
|
||||||
|
mCreator->toggleWidgets(true);
|
||||||
mLayout->setCurrentWidget (mCreator);
|
mLayout->setCurrentWidget (mCreator);
|
||||||
setVisible (true);
|
setVisible (true);
|
||||||
mCreating = true;
|
mCreating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::TableBottomBox::cloneRequest(const std::string& id,
|
||||||
|
const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
mCreator->reset();
|
||||||
|
mCreator->cloneMode(id, type);
|
||||||
|
mLayout->setCurrentWidget(mCreator);
|
||||||
|
mCreator->toggleWidgets(false);
|
||||||
|
setVisible (true);
|
||||||
|
mCreating = true;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CSV_WORLD_BOTTOMBOX_H
|
#define CSV_WORLD_BOTTOMBOX_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QStackedLayout;
|
class QStackedLayout;
|
||||||
|
@ -76,6 +77,8 @@ namespace CSVWorld
|
||||||
/// \param modified Number of added and modified records
|
/// \param modified Number of added and modified records
|
||||||
|
|
||||||
void createRequest();
|
void createRequest();
|
||||||
|
void cloneRequest(const std::string& id,
|
||||||
|
const CSMWorld::UniversalId::Type type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
#include "../filter/filterbox.hpp"
|
#include "../filter/filterbox.hpp"
|
||||||
|
|
||||||
#include "table.hpp"
|
#include "table.hpp"
|
||||||
#include "tablebottombox.hpp"
|
#include "tablebottombox.hpp"
|
||||||
#include "creator.hpp"
|
#include "creator.hpp"
|
||||||
|
@ -46,8 +45,15 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
||||||
mTable->selectionSizeUpdate();
|
mTable->selectionSizeUpdate();
|
||||||
|
|
||||||
if (mBottom->canCreateAndDelete())
|
if (mBottom->canCreateAndDelete())
|
||||||
|
{
|
||||||
connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
|
connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
|
||||||
|
|
||||||
|
connect (mTable, SIGNAL (cloneRequest(const CSMWorld::UniversalId&)), this,
|
||||||
|
SLOT(cloneRequest(const CSMWorld::UniversalId&)));
|
||||||
|
|
||||||
|
connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
|
||||||
|
mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
|
||||||
|
}
|
||||||
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
|
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
|
||||||
mTable, SLOT (requestFocus (const std::string&)));
|
mTable, SLOT (requestFocus (const std::string&)));
|
||||||
|
|
||||||
|
@ -76,3 +82,8 @@ void CSVWorld::TableSubView::setStatusBar (bool show)
|
||||||
{
|
{
|
||||||
mBottom->setStatusBar (show);
|
mBottom->setStatusBar (show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
|
||||||
|
{
|
||||||
|
emit cloneRequest(toClone.getId(), toClone.getType());
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class IdTable;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
|
@ -34,9 +39,14 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual void setStatusBar (bool show);
|
virtual void setStatusBar (bool show);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void cloneRequest(const std::string&,
|
||||||
|
const CSMWorld::UniversalId::Type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void editRequest (int row);
|
void editRequest (int row);
|
||||||
|
void cloneRequest (const CSMWorld::UniversalId& toClone);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
|
|
||||||
# config file
|
|
||||||
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/config.hpp")
|
|
||||||
|
|
||||||
# local files
|
# local files
|
||||||
set(GAME
|
set(GAME
|
||||||
main.cpp
|
main.cpp
|
||||||
|
@ -12,7 +8,6 @@ if(NOT WIN32)
|
||||||
endif()
|
endif()
|
||||||
set(GAME_HEADER
|
set(GAME_HEADER
|
||||||
engine.hpp
|
engine.hpp
|
||||||
config.hpp
|
|
||||||
)
|
)
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
|
@ -74,12 +69,16 @@ add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||||
disease pickpocket levelledlist
|
disease pickpocket levelledlist combat steering
|
||||||
|
)
|
||||||
|
|
||||||
|
add_openmw_dir (mwstate
|
||||||
|
statemanagerimp charactermanager character
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwbase
|
add_openmw_dir (mwbase
|
||||||
environment world scriptmanager dialoguemanager journal soundmanager mechanicsmanager
|
environment world scriptmanager dialoguemanager journal soundmanager mechanicsmanager
|
||||||
inputmanager windowmanager
|
inputmanager windowmanager statemanager
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <MyGUI_WidgetManager.h>
|
#include <MyGUI_WidgetManager.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <components/compiler/extensions0.hpp>
|
#include <components/compiler/extensions0.hpp>
|
||||||
|
|
||||||
#include <components/bsa/bsa_archive.hpp>
|
#include <components/bsa/bsa_archive.hpp>
|
||||||
|
@ -41,8 +43,7 @@
|
||||||
|
|
||||||
#include "mwmechanics/mechanicsmanagerimp.hpp"
|
#include "mwmechanics/mechanicsmanagerimp.hpp"
|
||||||
|
|
||||||
|
#include "mwstate/statemanagerimp.hpp"
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
void OMW::Engine::executeLocalScripts()
|
void OMW::Engine::executeLocalScripts()
|
||||||
{
|
{
|
||||||
|
@ -88,31 +89,47 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
if (mUseSound)
|
if (mUseSound)
|
||||||
MWBase::Environment::get().getSoundManager()->update(frametime);
|
MWBase::Environment::get().getSoundManager()->update(frametime);
|
||||||
|
|
||||||
|
bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
|
||||||
|
// update game state
|
||||||
|
MWBase::Environment::get().getStateManager()->update (frametime);
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||||
|
MWBase::StateManager::State_Running)
|
||||||
|
{
|
||||||
// global scripts
|
// global scripts
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
||||||
|
|
||||||
bool changed = MWBase::Environment::get().getWorld()->hasCellChanged();
|
bool changed = MWBase::Environment::get().getWorld()->hasCellChanged();
|
||||||
|
|
||||||
// local scripts
|
// local scripts
|
||||||
executeLocalScripts(); // This does not handle the case where a global script causes a cell
|
executeLocalScripts(); // This does not handle the case where a global script causes a
|
||||||
// change, followed by a cell change in a local script during the same
|
// cell change, followed by a cell change in a local script during
|
||||||
// frame.
|
// the same frame.
|
||||||
|
|
||||||
// passing of time
|
if (changed) // keep change flag for another frame, if cell changed happened in local script
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||||
|
|
||||||
|
if (!paused)
|
||||||
MWBase::Environment::get().getWorld()->advanceTime(
|
MWBase::Environment::get().getWorld()->advanceTime(
|
||||||
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
|
frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (changed) // keep change flag for another frame, if cell changed happend in local script
|
|
||||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
|
||||||
|
|
||||||
// update actors
|
// update actors
|
||||||
MWBase::Environment::get().getMechanicsManager()->update(frametime,
|
MWBase::Environment::get().getMechanicsManager()->update(frametime,
|
||||||
MWBase::Environment::get().getWindowManager()->isGuiMode());
|
paused);
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||||
|
MWBase::StateManager::State_Running)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr();
|
||||||
|
if(!paused && player.getClass().getCreatureStats(player).isDead())
|
||||||
|
MWBase::Environment::get().getStateManager()->endGame();
|
||||||
|
}
|
||||||
|
|
||||||
// update world
|
// update world
|
||||||
MWBase::Environment::get().getWorld()->update(frametime, MWBase::Environment::get().getWindowManager()->isGuiMode());
|
MWBase::Environment::get().getWorld()->update(frametime, paused);
|
||||||
|
|
||||||
// update GUI
|
// update GUI
|
||||||
Ogre::RenderWindow* window = mOgre->getWindow();
|
Ogre::RenderWindow* window = mOgre->getWindow();
|
||||||
|
@ -135,7 +152,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
: mOgre (0)
|
: mOgre (0)
|
||||||
, mFpsLevel(0)
|
, mFpsLevel(0)
|
||||||
, mVerboseScripts (false)
|
, mVerboseScripts (false)
|
||||||
, mNewGame (false)
|
, mSkipMenu (false)
|
||||||
, mUseSound (true)
|
, mUseSound (true)
|
||||||
, mCompileAll (false)
|
, mCompileAll (false)
|
||||||
, mScriptContext (0)
|
, mScriptContext (0)
|
||||||
|
@ -265,11 +282,6 @@ void OMW::Engine::setCell (const std::string& cellName)
|
||||||
|
|
||||||
void OMW::Engine::addContentFile(const std::string& file)
|
void OMW::Engine::addContentFile(const std::string& file)
|
||||||
{
|
{
|
||||||
if (file.find_last_of(".") == std::string::npos)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Missing extension in content file!");
|
|
||||||
}
|
|
||||||
|
|
||||||
mContentFiles.push_back(file);
|
mContentFiles.push_back(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,9 +290,9 @@ void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
|
||||||
mVerboseScripts = scriptsVerbosity;
|
mVerboseScripts = scriptsVerbosity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::setNewGame(bool newGame)
|
void OMW::Engine::setSkipMenu (bool skipMenu)
|
||||||
{
|
{
|
||||||
mNewGame = newGame;
|
mSkipMenu = skipMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
||||||
|
@ -326,6 +338,9 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
||||||
|
|
||||||
void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
{
|
{
|
||||||
|
mEnvironment.setStateManager (
|
||||||
|
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0)));
|
||||||
|
|
||||||
Nif::NIFFile::CacheLock cachelock;
|
Nif::NIFFile::CacheLock cachelock;
|
||||||
|
|
||||||
std::string renderSystem = settings.getString("render system", "Video");
|
std::string renderSystem = settings.getString("render system", "Video");
|
||||||
|
@ -392,10 +407,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
|
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
|
||||||
|
|
||||||
window->initUI();
|
window->initUI();
|
||||||
if (mNewGame)
|
|
||||||
// still redundant work here: recreate CharacterCreation(),
|
|
||||||
// double update visibility etc.
|
|
||||||
window->setNewGame(true);
|
|
||||||
window->renderWorldMap();
|
window->renderWorldMap();
|
||||||
|
|
||||||
//Load translation data
|
//Load translation data
|
||||||
|
@ -427,12 +438,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
mechanics->buildPlayer();
|
mechanics->buildPlayer();
|
||||||
window->updatePlayer();
|
window->updatePlayer();
|
||||||
|
|
||||||
if (!mNewGame)
|
|
||||||
{
|
|
||||||
// load cell
|
// load cell
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
if (!mCellName.empty())
|
||||||
|
{
|
||||||
if (world->findExteriorPosition(mCellName, pos)) {
|
if (world->findExteriorPosition(mCellName, pos)) {
|
||||||
world->changeToExteriorCell (pos);
|
world->changeToExteriorCell (pos);
|
||||||
}
|
}
|
||||||
|
@ -442,7 +453,11 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mEnvironment.getWorld()->startNewGame();
|
{
|
||||||
|
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
|
||||||
|
pos.rot[0] = pos.rot[1] = pos.pos[2] = 0;
|
||||||
|
world->changeToExteriorCell (pos);
|
||||||
|
}
|
||||||
|
|
||||||
Ogre::FrameEvent event;
|
Ogre::FrameEvent event;
|
||||||
event.timeSinceLastEvent = 0;
|
event.timeSinceLastEvent = 0;
|
||||||
|
@ -468,7 +483,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
|
|
||||||
void OMW::Engine::go()
|
void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
assert (!mCellName.empty());
|
|
||||||
assert (!mContentFiles.empty());
|
assert (!mContentFiles.empty());
|
||||||
assert (!mOgre);
|
assert (!mOgre);
|
||||||
|
|
||||||
|
@ -489,8 +503,14 @@ void OMW::Engine::go()
|
||||||
if (!mStartupScript.empty())
|
if (!mStartupScript.empty())
|
||||||
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
|
||||||
|
|
||||||
|
// start in main menu
|
||||||
|
if (!mSkipMenu)
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||||
|
else
|
||||||
|
MWBase::Environment::get().getStateManager()->newGame (true);
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
while (!mEnvironment.getRequestExit())
|
while (!mEnvironment.get().getStateManager()->hasQuitRequest())
|
||||||
Ogre::Root::getSingleton().renderOneFrame();
|
Ogre::Root::getSingleton().renderOneFrame();
|
||||||
|
|
||||||
// Save user settings
|
// Save user settings
|
||||||
|
@ -509,6 +529,9 @@ void OMW::Engine::activate()
|
||||||
if (ptr.isEmpty())
|
if (ptr.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ptr.getClass().getName(ptr) == "") // objects without name presented to user can never be activated
|
||||||
|
return;
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
||||||
|
|
||||||
boost::shared_ptr<MWWorld::Action> action =
|
boost::shared_ptr<MWWorld::Action> action =
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace OMW
|
||||||
std::vector<std::string> mContentFiles;
|
std::vector<std::string> mContentFiles;
|
||||||
int mFpsLevel;
|
int mFpsLevel;
|
||||||
bool mVerboseScripts;
|
bool mVerboseScripts;
|
||||||
bool mNewGame;
|
bool mSkipMenu;
|
||||||
bool mUseSound;
|
bool mUseSound;
|
||||||
bool mCompileAll;
|
bool mCompileAll;
|
||||||
std::string mFocusName;
|
std::string mFocusName;
|
||||||
|
@ -151,8 +151,7 @@ namespace OMW
|
||||||
/// Disable or enable all sounds
|
/// Disable or enable all sounds
|
||||||
void setSoundUsage(bool soundUsage);
|
void setSoundUsage(bool soundUsage);
|
||||||
|
|
||||||
/// Start as a new game.
|
void setSkipMenu (bool skipMenu);
|
||||||
void setNewGame(bool newGame);
|
|
||||||
|
|
||||||
void setGrabMouse(bool grab) { mGrab = grab; }
|
void setGrabMouse(bool grab) { mGrab = grab; }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <components/version/version.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
@ -30,8 +31,6 @@ extern int is_debugger_attached(void);
|
||||||
#include <OSX/macUtils.h>
|
#include <OSX/macUtils.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "config.hpp"
|
|
||||||
|
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
/**
|
/**
|
||||||
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
||||||
|
@ -116,7 +115,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
("resources", bpo::value<std::string>()->default_value("resources"),
|
("resources", bpo::value<std::string>()->default_value("resources"),
|
||||||
"set resources directory")
|
"set resources directory")
|
||||||
|
|
||||||
("start", bpo::value<std::string>()->default_value("Beshara"),
|
("start", bpo::value<std::string>()->default_value(""),
|
||||||
"set initial cell")
|
"set initial cell")
|
||||||
|
|
||||||
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
||||||
|
@ -137,8 +136,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
("script-run", bpo::value<std::string>()->default_value(""),
|
("script-run", bpo::value<std::string>()->default_value(""),
|
||||||
"select a file containing a list of console commands that is executed on startup")
|
"select a file containing a list of console commands that is executed on startup")
|
||||||
|
|
||||||
("new-game", bpo::value<bool>()->implicit_value(true)
|
("skip-menu", bpo::value<bool>()->implicit_value(true)
|
||||||
->default_value(false), "activate char gen/new game mechanics")
|
->default_value(false), "skip main menu on game startup")
|
||||||
|
|
||||||
("fs-strict", bpo::value<bool>()->implicit_value(true)
|
("fs-strict", bpo::value<bool>()->implicit_value(true)
|
||||||
->default_value(false), "strict file system handling (no case folding)")
|
->default_value(false), "strict file system handling (no case folding)")
|
||||||
|
@ -232,7 +231,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
|
|
||||||
// startup-settings
|
// startup-settings
|
||||||
engine.setCell(variables["start"].as<std::string>());
|
engine.setCell(variables["start"].as<std::string>());
|
||||||
engine.setNewGame(variables["new-game"].as<bool>());
|
engine.setSkipMenu (variables["skip-menu"].as<bool>());
|
||||||
|
|
||||||
// other settings
|
// other settings
|
||||||
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
||||||
|
|
|
@ -11,13 +11,14 @@
|
||||||
#include "mechanicsmanager.hpp"
|
#include "mechanicsmanager.hpp"
|
||||||
#include "inputmanager.hpp"
|
#include "inputmanager.hpp"
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
|
#include "statemanager.hpp"
|
||||||
|
|
||||||
MWBase::Environment *MWBase::Environment::sThis = 0;
|
MWBase::Environment *MWBase::Environment::sThis = 0;
|
||||||
bool MWBase::Environment::sExit = false;
|
|
||||||
|
|
||||||
MWBase::Environment::Environment()
|
MWBase::Environment::Environment()
|
||||||
: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0),
|
: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0),
|
||||||
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mFrameDuration (0)
|
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mFrameDuration (0),
|
||||||
|
mStateManager (0)
|
||||||
{
|
{
|
||||||
assert (!sThis);
|
assert (!sThis);
|
||||||
sThis = this;
|
sThis = this;
|
||||||
|
@ -69,6 +70,11 @@ void MWBase::Environment::setInputManager (InputManager *inputManager)
|
||||||
mInputManager = inputManager;
|
mInputManager = inputManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWBase::Environment::setStateManager (StateManager *stateManager)
|
||||||
|
{
|
||||||
|
mStateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
void MWBase::Environment::setFrameDuration (float duration)
|
void MWBase::Environment::setFrameDuration (float duration)
|
||||||
{
|
{
|
||||||
mFrameDuration = duration;
|
mFrameDuration = duration;
|
||||||
|
@ -122,6 +128,12 @@ MWBase::InputManager *MWBase::Environment::getInputManager() const
|
||||||
return mInputManager;
|
return mInputManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::StateManager *MWBase::Environment::getStateManager() const
|
||||||
|
{
|
||||||
|
assert (mStateManager);
|
||||||
|
return mStateManager;
|
||||||
|
}
|
||||||
|
|
||||||
float MWBase::Environment::getFrameDuration() const
|
float MWBase::Environment::getFrameDuration() const
|
||||||
{
|
{
|
||||||
return mFrameDuration;
|
return mFrameDuration;
|
||||||
|
@ -152,6 +164,9 @@ void MWBase::Environment::cleanup()
|
||||||
|
|
||||||
delete mInputManager;
|
delete mInputManager;
|
||||||
mInputManager = 0;
|
mInputManager = 0;
|
||||||
|
|
||||||
|
delete mStateManager;
|
||||||
|
mStateManager = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWBase::Environment& MWBase::Environment::get()
|
const MWBase::Environment& MWBase::Environment::get()
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace MWBase
|
||||||
class MechanicsManager;
|
class MechanicsManager;
|
||||||
class InputManager;
|
class InputManager;
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
|
class StateManager;
|
||||||
|
|
||||||
/// \brief Central hub for mw-subsystems
|
/// \brief Central hub for mw-subsystems
|
||||||
///
|
///
|
||||||
|
@ -30,10 +31,9 @@ namespace MWBase
|
||||||
DialogueManager *mDialogueManager;
|
DialogueManager *mDialogueManager;
|
||||||
Journal *mJournal;
|
Journal *mJournal;
|
||||||
InputManager *mInputManager;
|
InputManager *mInputManager;
|
||||||
|
StateManager *mStateManager;
|
||||||
float mFrameDuration;
|
float mFrameDuration;
|
||||||
|
|
||||||
static bool sExit;
|
|
||||||
|
|
||||||
Environment (const Environment&);
|
Environment (const Environment&);
|
||||||
///< not implemented
|
///< not implemented
|
||||||
|
|
||||||
|
@ -46,9 +46,6 @@ namespace MWBase
|
||||||
|
|
||||||
~Environment();
|
~Environment();
|
||||||
|
|
||||||
static void setRequestExit () { sExit = true; }
|
|
||||||
static bool getRequestExit () { return sExit; }
|
|
||||||
|
|
||||||
void setWorld (World *world);
|
void setWorld (World *world);
|
||||||
|
|
||||||
void setSoundManager (SoundManager *soundManager);
|
void setSoundManager (SoundManager *soundManager);
|
||||||
|
@ -65,6 +62,8 @@ namespace MWBase
|
||||||
|
|
||||||
void setInputManager (InputManager *inputManager);
|
void setInputManager (InputManager *inputManager);
|
||||||
|
|
||||||
|
void setStateManager (StateManager *stateManager);
|
||||||
|
|
||||||
void setFrameDuration (float duration);
|
void setFrameDuration (float duration);
|
||||||
///< Set length of current frame in seconds.
|
///< Set length of current frame in seconds.
|
||||||
|
|
||||||
|
@ -84,6 +83,8 @@ namespace MWBase
|
||||||
|
|
||||||
InputManager *getInputManager() const;
|
InputManager *getInputManager() const;
|
||||||
|
|
||||||
|
StateManager *getStateManager() const;
|
||||||
|
|
||||||
float getFrameDuration() const;
|
float getFrameDuration() const;
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
|
@ -5,10 +5,18 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <libs/platform/stdint.h>
|
||||||
|
|
||||||
#include "../mwdialogue/journalentry.hpp"
|
#include "../mwdialogue/journalentry.hpp"
|
||||||
#include "../mwdialogue/topic.hpp"
|
#include "../mwdialogue/topic.hpp"
|
||||||
#include "../mwdialogue/quest.hpp"
|
#include "../mwdialogue/quest.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
/// \brief Interface for the player's journal (implemented in MWDialogue)
|
/// \brief Interface for the player's journal (implemented in MWDialogue)
|
||||||
|
@ -46,7 +54,7 @@ namespace MWBase
|
||||||
virtual int getJournalIndex (const std::string& id) const = 0;
|
virtual int getJournalIndex (const std::string& id) const = 0;
|
||||||
///< Get the journal index.
|
///< Get the journal index.
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topicId, const std::string& infoId) = 0;
|
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName) = 0;
|
||||||
|
|
||||||
virtual TEntryIter begin() const = 0;
|
virtual TEntryIter begin() const = 0;
|
||||||
///< Iterator pointing to the begin of the main journal.
|
///< Iterator pointing to the begin of the main journal.
|
||||||
|
@ -69,6 +77,12 @@ namespace MWBase
|
||||||
|
|
||||||
virtual TTopicIter topicEnd() const = 0;
|
virtual TTopicIter topicEnd() const = 0;
|
||||||
///< Iterator pointing past the last topic.
|
///< Iterator pointing past the last topic.
|
||||||
|
|
||||||
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
|
virtual void write (ESM::ESMWriter& writer) const = 0;
|
||||||
|
|
||||||
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,12 @@ namespace MWBase
|
||||||
virtual void toggleAI() = 0;
|
virtual void toggleAI() = 0;
|
||||||
virtual bool isAIActive() = 0;
|
virtual bool isAIActive() = 0;
|
||||||
|
|
||||||
|
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
|
||||||
|
|
||||||
///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor)
|
///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor)
|
||||||
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor) = 0;
|
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
|
virtual void playerLoaded() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,6 @@ namespace MWBase
|
||||||
|
|
||||||
virtual ~ScriptManager() {}
|
virtual ~ScriptManager() {}
|
||||||
|
|
||||||
virtual void resetGlobalScripts() = 0;
|
|
||||||
|
|
||||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
||||||
///< Run the script with the given name (compile first, if not compiled yet)
|
///< Run the script with the given name (compile first, if not compiled yet)
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,10 @@ namespace MWBase
|
||||||
virtual void update(float duration) = 0;
|
virtual void update(float duration) = 0;
|
||||||
|
|
||||||
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0;
|
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0;
|
||||||
|
|
||||||
|
virtual void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated) = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
81
apps/openmw/mwbase/statemanager.hpp
Normal file
81
apps/openmw/mwbase/statemanager.hpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef GAME_MWSTATE_STATEMANAGER_H
|
||||||
|
#define GAME_MWSTATE_STATEMANAGER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace MWState
|
||||||
|
{
|
||||||
|
struct Slot;
|
||||||
|
class Character;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWBase
|
||||||
|
{
|
||||||
|
/// \brief Interface for game state manager (implemented in MWState)
|
||||||
|
class StateManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
State_NoGame,
|
||||||
|
State_Ended,
|
||||||
|
State_Running
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<MWState::Character>::const_iterator CharacterIterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
StateManager (const StateManager&);
|
||||||
|
///< not implemented
|
||||||
|
|
||||||
|
StateManager& operator= (const StateManager&);
|
||||||
|
///< not implemented
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
StateManager() {}
|
||||||
|
|
||||||
|
virtual ~StateManager() {}
|
||||||
|
|
||||||
|
virtual void requestQuit() = 0;
|
||||||
|
|
||||||
|
virtual bool hasQuitRequest() const = 0;
|
||||||
|
|
||||||
|
virtual void askLoadRecent() = 0;
|
||||||
|
|
||||||
|
virtual State getState() const = 0;
|
||||||
|
|
||||||
|
virtual void newGame (bool bypass = false) = 0;
|
||||||
|
///< Start a new game.
|
||||||
|
///
|
||||||
|
/// \param bypass Skip new game mechanics.
|
||||||
|
|
||||||
|
virtual void endGame() = 0;
|
||||||
|
|
||||||
|
virtual void saveGame (const std::string& description, const MWState::Slot *slot = 0) = 0;
|
||||||
|
///< Write a saved game to \a slot or create a new slot if \a slot == 0.
|
||||||
|
///
|
||||||
|
/// \note Slot must belong to the current character.
|
||||||
|
|
||||||
|
virtual void loadGame (const MWState::Character *character, const MWState::Slot *slot) = 0;
|
||||||
|
///< Load a saved game file from \a slot.
|
||||||
|
///
|
||||||
|
/// \note \a slot must belong to \a character.
|
||||||
|
|
||||||
|
virtual MWState::Character *getCurrentCharacter (bool create = true) = 0;
|
||||||
|
///< \param create Create a new character, if there is no current character.
|
||||||
|
|
||||||
|
virtual CharacterIterator characterBegin() = 0;
|
||||||
|
///< Any call to SaveGame and getCurrentCharacter can invalidate the returned
|
||||||
|
/// iterator.
|
||||||
|
|
||||||
|
virtual CharacterIterator characterEnd() = 0;
|
||||||
|
|
||||||
|
virtual void update (float duration) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,6 +33,8 @@ namespace OEngine
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Class;
|
struct Class;
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -55,6 +57,12 @@ namespace MWGui
|
||||||
class InventoryWindow;
|
class InventoryWindow;
|
||||||
class ContainerWindow;
|
class ContainerWindow;
|
||||||
class DialogueWindow;
|
class DialogueWindow;
|
||||||
|
|
||||||
|
enum ShowInDialogueMode {
|
||||||
|
ShowInDialogueMode_IfPossible,
|
||||||
|
ShowInDialogueMode_Only,
|
||||||
|
ShowInDialogueMode_Never
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SFO
|
namespace SFO
|
||||||
|
@ -224,7 +232,7 @@ namespace MWBase
|
||||||
virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0;
|
virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0;
|
||||||
///< Hides dialog and schedules dialog to be deleted.
|
///< Hides dialog and schedules dialog to be deleted.
|
||||||
|
|
||||||
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>(), bool showInDialogueModeOnly = false) = 0;
|
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>(), enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0;
|
||||||
virtual void staticMessageBox(const std::string& message) = 0;
|
virtual void staticMessageBox(const std::string& message) = 0;
|
||||||
virtual void removeStaticMessageBox() = 0;
|
virtual void removeStaticMessageBox() = 0;
|
||||||
virtual int readPressedButton() = 0;
|
virtual int readPressedButton() = 0;
|
||||||
|
@ -279,12 +287,19 @@ namespace MWBase
|
||||||
|
|
||||||
virtual const Translation::Storage& getTranslationDataStorage() const = 0;
|
virtual const Translation::Storage& getTranslationDataStorage() const = 0;
|
||||||
|
|
||||||
|
/// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this.
|
||||||
virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0;
|
virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0;
|
||||||
|
|
||||||
virtual Loading::Listener* getLoadingScreen() = 0;
|
virtual Loading::Listener* getLoadingScreen() = 0;
|
||||||
|
|
||||||
/// Should the cursor be visible?
|
/// Should the cursor be visible?
|
||||||
virtual bool getCursorVisible() = 0;
|
virtual bool getCursorVisible() = 0;
|
||||||
|
|
||||||
|
/// Clear all savegame-specific data
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
virtual void write (ESM::ESMWriter& writer) = 0;
|
||||||
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWBASE_WORLD_H
|
#define GAME_MWBASE_WORLD_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
@ -30,12 +31,14 @@ namespace OEngine
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
struct Position;
|
struct Position;
|
||||||
struct Cell;
|
struct Cell;
|
||||||
struct Class;
|
struct Class;
|
||||||
struct Potion;
|
struct Potion;
|
||||||
struct Spell;
|
struct Spell;
|
||||||
struct NPC;
|
struct NPC;
|
||||||
|
struct CellId;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -94,13 +97,26 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void startNewGame() = 0;
|
virtual void startNewGame() = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
|
virtual void write (ESM::ESMWriter& writer) const = 0;
|
||||||
|
|
||||||
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
|
||||||
|
const std::map<int, int>& contentFileMap) = 0;
|
||||||
|
|
||||||
virtual OEngine::Render::Fader* getFader() = 0;
|
virtual OEngine::Render::Fader* getFader() = 0;
|
||||||
///< \ŧodo remove this function. Rendering details should not be exposed.
|
///< \todo remove this function. Rendering details should not be exposed.
|
||||||
|
|
||||||
virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
|
virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
|
||||||
|
|
||||||
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;
|
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;
|
||||||
|
|
||||||
|
virtual MWWorld::CellStore *getCell (const ESM::CellId& id) = 0;
|
||||||
|
|
||||||
|
virtual void useDeathCamera() = 0;
|
||||||
|
|
||||||
virtual void setWaterHeight(const float height) = 0;
|
virtual void setWaterHeight(const float height) = 0;
|
||||||
|
|
||||||
virtual void toggleWater() = 0;
|
virtual void toggleWater() = 0;
|
||||||
|
@ -139,16 +155,26 @@ namespace MWBase
|
||||||
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0;
|
virtual bool isPositionExplored (float nX, float nY, int x, int y, bool interior) = 0;
|
||||||
///< see MWRender::LocalMap::isPositionExplored
|
///< see MWRender::LocalMap::isPositionExplored
|
||||||
|
|
||||||
virtual MWWorld::Globals::Data& getGlobalVariable (const std::string& name) = 0;
|
virtual void setGlobalInt (const std::string& name, int value) = 0;
|
||||||
|
///< Set value independently from real type.
|
||||||
|
|
||||||
virtual MWWorld::Globals::Data getGlobalVariable (const std::string& name) const = 0;
|
virtual void setGlobalFloat (const std::string& name, float value) = 0;
|
||||||
|
///< Set value independently from real type.
|
||||||
|
|
||||||
|
virtual int getGlobalInt (const std::string& name) const = 0;
|
||||||
|
///< Get value independently from real type.
|
||||||
|
|
||||||
|
virtual float getGlobalFloat (const std::string& name) const = 0;
|
||||||
|
///< Get value independently from real type.
|
||||||
|
|
||||||
virtual char getGlobalVariableType (const std::string& name) const = 0;
|
virtual char getGlobalVariableType (const std::string& name) const = 0;
|
||||||
///< Return ' ', if there is no global variable with this name.
|
///< Return ' ', if there is no global variable with this name.
|
||||||
|
|
||||||
virtual std::vector<std::string> getGlobals () const = 0;
|
virtual std::string getCellName (const MWWorld::CellStore *cell = 0) const = 0;
|
||||||
|
///< Return name of the cell.
|
||||||
virtual std::string getCurrentCellName() const = 0;
|
///
|
||||||
|
/// \note If cell==0, the cell the player is currently in will be used instead to
|
||||||
|
/// generate a name.
|
||||||
|
|
||||||
virtual void removeRefScript (MWWorld::RefData *ref) = 0;
|
virtual void removeRefScript (MWWorld::RefData *ref) = 0;
|
||||||
//< Remove the script attached to ref from mLocalScripts
|
//< Remove the script attached to ref from mLocalScripts
|
||||||
|
@ -185,8 +211,12 @@ namespace MWBase
|
||||||
virtual void setDay (int day) = 0;
|
virtual void setDay (int day) = 0;
|
||||||
///< Set in-game time day.
|
///< Set in-game time day.
|
||||||
|
|
||||||
virtual int getDay() = 0;
|
virtual int getDay() const = 0;
|
||||||
virtual int getMonth() = 0;
|
virtual int getMonth() const = 0;
|
||||||
|
virtual int getYear() const = 0;
|
||||||
|
|
||||||
|
virtual std::string getMonthName (int month = -1) const = 0;
|
||||||
|
///< Return name of month (-1: current month)
|
||||||
|
|
||||||
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
|
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
|
||||||
///< Return current in-game time stamp.
|
///< Return current in-game time stamp.
|
||||||
|
@ -215,6 +245,8 @@ namespace MWBase
|
||||||
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
||||||
///< Move to exterior cell.
|
///< Move to exterior cell.
|
||||||
|
|
||||||
|
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position) = 0;
|
||||||
|
|
||||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
||||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||||
|
|
||||||
|
@ -225,7 +257,7 @@ namespace MWBase
|
||||||
|
|
||||||
/// Returns a pointer to the object the provided object would hit (if within the
|
/// Returns a pointer to the object the provided object would hit (if within the
|
||||||
/// specified distance), and the point where the hit occurs. This will attempt to
|
/// specified distance), and the point where the hit occurs. This will attempt to
|
||||||
/// use the "Head" node as a basis.
|
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
|
||||||
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
|
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
|
||||||
|
|
||||||
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
|
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
|
||||||
|
@ -336,7 +368,7 @@ namespace MWBase
|
||||||
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
|
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
|
||||||
///Is the head of the creature underwater?
|
///Is the head of the creature underwater?
|
||||||
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
|
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
|
||||||
virtual bool isUnderwater(const MWWorld::Ptr::CellStore* cell, const Ogre::Vector3 &pos) const = 0;
|
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const = 0;
|
||||||
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
|
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
|
||||||
virtual void togglePOV() = 0;
|
virtual void togglePOV() = 0;
|
||||||
|
@ -384,6 +416,7 @@ namespace MWBase
|
||||||
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
||||||
virtual void stopVideo() = 0;
|
virtual void stopVideo() = 0;
|
||||||
virtual void frameStarted (float dt, bool paused) = 0;
|
virtual void frameStarted (float dt, bool paused) = 0;
|
||||||
|
virtual void screenshot (Ogre::Image& image, int w, int h) = 0;
|
||||||
|
|
||||||
/// Find default position inside exterior cell specified by name
|
/// Find default position inside exterior cell specified by name
|
||||||
/// \return false if exterior with given name not exists, true otherwise
|
/// \return false if exterior with given name not exists, true otherwise
|
||||||
|
@ -428,6 +461,8 @@ namespace MWBase
|
||||||
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
|
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
|
||||||
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
|
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
|
||||||
|
|
||||||
|
virtual const std::vector<std::string>& getContentFiles() const = 0;
|
||||||
|
|
||||||
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
// Are we in an exterior or pseudo-exterior cell and it's night?
|
// Are we in an exterior or pseudo-exterior cell and it's night?
|
||||||
|
@ -466,6 +501,9 @@ namespace MWBase
|
||||||
|
|
||||||
/// Spawn a blood effect for \a ptr at \a worldPosition
|
/// Spawn a blood effect for \a ptr at \a worldPosition
|
||||||
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0;
|
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0;
|
||||||
|
|
||||||
|
virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects,
|
||||||
|
const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ namespace MWClass
|
||||||
|
|
||||||
std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc);
|
||||||
|
|
||||||
if (ptr.getCellRef().mCharge == 0)
|
if (ptr.getCellRef().mCharge == 0)
|
||||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
@ -300,6 +300,8 @@ namespace MWClass
|
||||||
if (slots_.first.empty())
|
if (slots_.first.empty())
|
||||||
return std::make_pair(0, "");
|
return std::make_pair(0, "");
|
||||||
|
|
||||||
|
if (npc.getClass().isNpc())
|
||||||
|
{
|
||||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||||
|
|
||||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||||
|
@ -316,6 +318,7 @@ namespace MWClass
|
||||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||||
slot!=slots_.first.end(); ++slot)
|
slot!=slots_.first.end(); ++slot)
|
||||||
|
@ -363,12 +366,12 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell);
|
return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
||||||
ptr.get<ESM::Armor>();
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
return ref->mBase->mData.mEnchant/10.f;
|
return ref->mBase->mData.mEnchant;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace MWClass
|
||||||
|
|
||||||
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -189,12 +189,12 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell);
|
return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Book> *ref =
|
MWWorld::LiveCellRef<ESM::Book> *ref =
|
||||||
ptr.get<ESM::Book>();
|
ptr.get<ESM::Book>();
|
||||||
|
|
||||||
return ref->mBase->mData.mEnchant/10.f;
|
return ref->mBase->mData.mEnchant;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace MWClass
|
||||||
|
|
||||||
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,8 @@ namespace MWClass
|
||||||
if (slots_.first.empty())
|
if (slots_.first.empty())
|
||||||
return std::make_pair(0, "");
|
return std::make_pair(0, "");
|
||||||
|
|
||||||
|
if (npc.getClass().isNpc())
|
||||||
|
{
|
||||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||||
|
|
||||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||||
|
@ -254,6 +256,7 @@ namespace MWClass
|
||||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_pair (1, "");
|
return std::make_pair (1, "");
|
||||||
}
|
}
|
||||||
|
@ -276,12 +279,12 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell);
|
return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Clothing> *ref =
|
MWWorld::LiveCellRef<ESM::Clothing> *ref =
|
||||||
ptr.get<ESM::Clothing>();
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
return ref->mBase->mData.mEnchant/10.f;
|
return ref->mBase->mData.mEnchant;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace MWClass
|
||||||
|
|
||||||
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "container.hpp"
|
#include "container.hpp"
|
||||||
|
|
||||||
#include <components/esm/loadcont.hpp>
|
#include <components/esm/loadcont.hpp>
|
||||||
|
#include <components/esm/containerstate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -258,4 +259,26 @@ namespace MWClass
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.mContainers.insert(*ref), &cell);
|
return MWWorld::Ptr(&cell.mContainers.insert(*ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
||||||
|
readState (state2.mInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
|
||||||
|
writeState (state2.mInventory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,14 @@ namespace MWClass
|
||||||
virtual void unlock (const MWWorld::Ptr& ptr) const;
|
virtual void unlock (const MWWorld::Ptr& ptr) const;
|
||||||
///< Unlock object
|
///< Unlock object
|
||||||
|
|
||||||
|
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Read additional state from \a state into \a ptr.
|
||||||
|
|
||||||
|
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Write additional state from \a ptr into \a state.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
#include "creature.hpp"
|
#include "creature.hpp"
|
||||||
|
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
|
#include <components/esm/creaturestate.hpp>
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/magiceffects.hpp"
|
#include "../mwmechanics/magiceffects.hpp"
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
@ -26,22 +28,30 @@
|
||||||
|
|
||||||
#include "../mwgui/tooltips.hpp"
|
#include "../mwgui/tooltips.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
#include "../mwmechanics/combat.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct CustomData : public MWWorld::CustomData
|
struct CustomData : public MWWorld::CustomData
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats mCreatureStats;
|
MWMechanics::CreatureStats mCreatureStats;
|
||||||
MWWorld::ContainerStore mContainerStore;
|
MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures
|
||||||
MWMechanics::Movement mMovement;
|
MWMechanics::Movement mMovement;
|
||||||
|
|
||||||
virtual MWWorld::CustomData *clone() const;
|
virtual MWWorld::CustomData *clone() const;
|
||||||
|
|
||||||
|
CustomData() : mContainerStore(0) {}
|
||||||
|
virtual ~CustomData() { delete mContainerStore; }
|
||||||
};
|
};
|
||||||
|
|
||||||
MWWorld::CustomData *CustomData::clone() const
|
MWWorld::CustomData *CustomData::clone() const
|
||||||
{
|
{
|
||||||
return new CustomData (*this);
|
CustomData* cloned = new CustomData (*this);
|
||||||
|
cloned->mContainerStore = mContainerStore->clone();
|
||||||
|
return cloned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,15 +116,23 @@ namespace MWClass
|
||||||
data->mCreatureStats.getSpells().add (*iter);
|
data->mCreatureStats.getSpells().add (*iter);
|
||||||
|
|
||||||
// inventory
|
// inventory
|
||||||
data->mContainerStore.fill(ref->mBase->mInventory, getId(ptr), "",
|
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||||
|
data->mContainerStore = new MWWorld::InventoryStore();
|
||||||
|
else
|
||||||
|
data->mContainerStore = new MWWorld::ContainerStore();
|
||||||
|
|
||||||
|
// store
|
||||||
|
ptr.getRefData().setCustomData (data.release());
|
||||||
|
|
||||||
|
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "",
|
||||||
MWBase::Environment::get().getWorld()->getStore());
|
MWBase::Environment::get().getWorld()->getStore());
|
||||||
|
|
||||||
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
|
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
|
||||||
// (except for gold you gave him)
|
// (except for gold you gave him)
|
||||||
data->mContainerStore.add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr);
|
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr);
|
||||||
|
|
||||||
// store
|
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||||
ptr.getRefData().setCustomData (data.release());
|
getInventoryStore(ptr).autoEquip(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,8 +151,10 @@ namespace MWClass
|
||||||
|
|
||||||
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
{
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
MWRender::Actors& actors = renderingInterface.getActors();
|
MWRender::Actors& actors = renderingInterface.getActors();
|
||||||
actors.insertCreature(ptr);
|
actors.insertCreature(ptr, ref->mBase->mFlags & ESM::Creature::Weapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
||||||
|
@ -178,9 +198,40 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
MWMechanics::CreatureStats &stats = getCreatureStats(ptr);
|
||||||
|
|
||||||
|
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
||||||
|
MWWorld::Ptr weapon;
|
||||||
|
if (ptr.getClass().hasInventoryStore(ptr))
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||||
|
MWWorld::ContainerStoreIterator weaponslot = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
if (weaponslot != inv.end() && weaponslot->getTypeName() == typeid(ESM::Weapon).name())
|
||||||
|
weapon = *weaponslot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce fatigue
|
||||||
|
// somewhat of a guess, but using the weapon weight makes sense
|
||||||
|
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
|
||||||
|
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
|
||||||
|
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
|
||||||
|
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
|
||||||
|
const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr);
|
||||||
|
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||||
|
if (!weapon.isEmpty())
|
||||||
|
fatigueLoss += weapon.getClass().getWeight(weapon) * stats.getAttackStrength() * fWeaponFatigueMult;
|
||||||
|
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||||
|
stats.setFatigue(fatigue);
|
||||||
|
|
||||||
// TODO: where is the distance defined?
|
// TODO: where is the distance defined?
|
||||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, 100);
|
float dist = 200.f;
|
||||||
|
if (!weapon.isEmpty())
|
||||||
|
{
|
||||||
|
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
|
||||||
|
dist = fCombatDistance * weapon.get<ESM::Weapon>()->mBase->mData.mReach;
|
||||||
|
}
|
||||||
|
std::pair<MWWorld::Ptr, Ogre::Vector3> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, dist);
|
||||||
if (result.first.isEmpty())
|
if (result.first.isEmpty())
|
||||||
return; // Didn't hit anything
|
return; // Didn't hit anything
|
||||||
|
|
||||||
|
@ -191,7 +242,6 @@ namespace MWClass
|
||||||
|
|
||||||
Ogre::Vector3 hitPosition = result.second;
|
Ogre::Vector3 hitPosition = result.second;
|
||||||
|
|
||||||
MWMechanics::CreatureStats &stats = getCreatureStats(ptr);
|
|
||||||
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
|
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
|
||||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||||
float hitchance = ref->mBase->mData.mCombat +
|
float hitchance = ref->mBase->mData.mCombat +
|
||||||
|
@ -226,12 +276,64 @@ namespace MWClass
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I think this should be random, since attack1-3 animations don't have an attack strength like NPCs do
|
||||||
float damage = min + (max - min) * ::rand()/(RAND_MAX+1.0);
|
float damage = min + (max - min) * ::rand()/(RAND_MAX+1.0);
|
||||||
|
|
||||||
// TODO: do not do this if the attack is blocked
|
if (!weapon.isEmpty())
|
||||||
|
{
|
||||||
|
const bool weaphashealth = get(weapon).hasItemHealth(weapon);
|
||||||
|
const unsigned char *attack = NULL;
|
||||||
|
if(type == ESM::Weapon::AT_Chop)
|
||||||
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
|
||||||
|
else if(type == ESM::Weapon::AT_Slash)
|
||||||
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mSlash;
|
||||||
|
else if(type == ESM::Weapon::AT_Thrust)
|
||||||
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mThrust;
|
||||||
|
if(attack)
|
||||||
|
{
|
||||||
|
float weaponDamage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
||||||
|
weaponDamage *= 0.5f + (stats.getAttribute(ESM::Attribute::Luck).getModified() / 100.0f);
|
||||||
|
if(weaphashealth)
|
||||||
|
{
|
||||||
|
int weapmaxhealth = weapon.get<ESM::Weapon>()->mBase->mData.mHealth;
|
||||||
|
if(weapon.getCellRef().mCharge == -1)
|
||||||
|
weapon.getCellRef().mCharge = weapmaxhealth;
|
||||||
|
weaponDamage *= float(weapon.getCellRef().mCharge) / weapmaxhealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||||
|
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||||
|
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
||||||
|
|
||||||
|
// Weapon broken? unequip it
|
||||||
|
if (weapon.getCellRef().mCharge == 0)
|
||||||
|
weapon = *getInventoryStore(ptr).unequipItem(weapon, ptr);
|
||||||
|
|
||||||
|
damage += weaponDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply "On hit" enchanted weapons
|
||||||
|
std::string enchantmentName = !weapon.isEmpty() ? weapon.getClass().getEnchantment(weapon) : "";
|
||||||
|
if (!enchantmentName.empty())
|
||||||
|
{
|
||||||
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(
|
||||||
|
enchantmentName);
|
||||||
|
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
|
||||||
|
{
|
||||||
|
MWMechanics::CastSpell cast(ptr, victim);
|
||||||
|
cast.mHitPosition = hitPosition;
|
||||||
|
cast.cast(weapon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!weapon.isEmpty() && MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage))
|
||||||
|
damage = 0;
|
||||||
|
|
||||||
|
if (damage > 0)
|
||||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
||||||
|
|
||||||
victim.getClass().onHit(victim, damage, true, MWWorld::Ptr(), ptr, true);
|
victim.getClass().onHit(victim, damage, true, weapon, ptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const
|
void Creature::onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const
|
||||||
|
@ -258,6 +360,11 @@ namespace MWClass
|
||||||
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (damage > 0.0f && !object.isEmpty())
|
||||||
|
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
||||||
|
|
||||||
|
if (damage > 0.f)
|
||||||
|
{
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
||||||
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
|
@ -273,7 +380,6 @@ namespace MWClass
|
||||||
|
|
||||||
if(ishealth)
|
if(ishealth)
|
||||||
{
|
{
|
||||||
if(damage > 0.0f)
|
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
|
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
|
||||||
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
|
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
|
||||||
setActorHealth(ptr, health, attacker);
|
setActorHealth(ptr, health, attacker);
|
||||||
|
@ -285,6 +391,31 @@ namespace MWClass
|
||||||
getCreatureStats(ptr).setFatigue(fatigue);
|
getCreatureStats(ptr).setFatigue(fatigue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Creature::block(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = getInventoryStore(ptr);
|
||||||
|
MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
if (shield == inv.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
switch(shield->getClass().getEquipmentSkill(*shield))
|
||||||
|
{
|
||||||
|
case ESM::Skill::LightArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Light Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case ESM::Skill::MediumArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Medium Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case ESM::Skill::HeavyArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Heavy Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Creature::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
void Creature::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
||||||
{
|
{
|
||||||
|
@ -325,18 +456,33 @@ namespace MWClass
|
||||||
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr)
|
MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) const
|
||||||
const
|
|
||||||
{
|
{
|
||||||
ensureCustomData (ptr);
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
|
return *dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||||
|
return dynamic_cast<MWWorld::InventoryStore&>(getContainerStore(ptr));
|
||||||
|
else
|
||||||
|
throw std::runtime_error("this creature has no inventory store");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Creature::hasInventoryStore(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
return (ref->mBase->mFlags & ESM::Creature::Weapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Creature::getScript (const MWWorld::Ptr& ptr) const
|
std::string Creature::getScript (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
ptr.get<ESM::Creature>();
|
|
||||||
|
|
||||||
return ref->mBase->mScript;
|
return ref->mBase->mScript;
|
||||||
}
|
}
|
||||||
|
@ -383,8 +529,8 @@ namespace MWClass
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(normalizedEncumbrance >= 1.0f)
|
if(normalizedEncumbrance >= 1.0f)
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
|
else if(isFlying(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
|
||||||
world->isLevitationEnabled())
|
world->isLevitationEnabled()))
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||||
|
@ -613,6 +759,28 @@ namespace MWClass
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Creature::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore->
|
||||||
|
readState (state2.mInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Creature::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
ESM::CreatureState& state2 = dynamic_cast<ESM::CreatureState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore->
|
||||||
|
writeState (state2.mInventory);
|
||||||
|
}
|
||||||
|
|
||||||
const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
|
const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
|
||||||
const ESM::GameSetting* Creature::fMaxWalkSpeedCreature;
|
const ESM::GameSetting* Creature::fMaxWalkSpeedCreature;
|
||||||
const ESM::GameSetting *Creature::fEncumberedMoveEffect;
|
const ESM::GameSetting *Creature::fEncumberedMoveEffect;
|
||||||
|
|
|
@ -56,6 +56,8 @@ namespace MWClass
|
||||||
|
|
||||||
virtual void hit(const MWWorld::Ptr& ptr, int type) const;
|
virtual void hit(const MWWorld::Ptr& ptr, int type) const;
|
||||||
|
|
||||||
|
virtual void block(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
|
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
|
||||||
|
|
||||||
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
|
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
|
||||||
|
@ -68,6 +70,11 @@ namespace MWClass
|
||||||
const MWWorld::Ptr& ptr) const;
|
const MWWorld::Ptr& ptr) const;
|
||||||
///< Return container store
|
///< Return container store
|
||||||
|
|
||||||
|
virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return inventory store
|
||||||
|
|
||||||
|
virtual bool hasInventoryStore (const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
@ -118,6 +125,14 @@ namespace MWClass
|
||||||
|
|
||||||
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
||||||
virtual int getBloodTexture (const MWWorld::Ptr& ptr) const;
|
virtual int getBloodTexture (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Read additional state from \a state into \a ptr.
|
||||||
|
|
||||||
|
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Write additional state from \a ptr into \a state.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,24 @@
|
||||||
|
|
||||||
#include <components/esm/loadlevlist.hpp>
|
#include <components/esm/loadlevlist.hpp>
|
||||||
|
|
||||||
|
#include "../mwmechanics/levelledlist.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/customdata.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct CustomData : public MWWorld::CustomData
|
||||||
|
{
|
||||||
|
// TODO: save the creature we spawned here
|
||||||
|
virtual MWWorld::CustomData *clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
MWWorld::CustomData *CustomData::clone() const
|
||||||
|
{
|
||||||
|
return new CustomData (*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
std::string CreatureLevList::getName (const MWWorld::Ptr& ptr) const
|
std::string CreatureLevList::getName (const MWWorld::Ptr& ptr) const
|
||||||
|
@ -16,4 +34,33 @@ namespace MWClass
|
||||||
|
|
||||||
registerClass (typeid (ESM::CreatureLevList).name(), instance);
|
registerClass (typeid (ESM::CreatureLevList).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, MWRender::RenderingInterface &renderingInterface) const
|
||||||
|
{
|
||||||
|
ensureCustomData(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureLevList::ensureCustomData(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
if (!ptr.getRefData().getCustomData())
|
||||||
|
{
|
||||||
|
std::auto_ptr<CustomData> data (new CustomData);
|
||||||
|
|
||||||
|
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
|
||||||
|
ptr.get<ESM::CreatureLevList>();
|
||||||
|
|
||||||
|
std::string id = MWMechanics::getLevelledItem(ref->mBase, true);
|
||||||
|
|
||||||
|
if (!id.empty())
|
||||||
|
{
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
MWWorld::ManualRef ref(store, id);
|
||||||
|
ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos;
|
||||||
|
// TODO: hold on to this for respawn purposes later
|
||||||
|
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), *ptr.getCell() , ptr.getCellRef().mPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr.getRefData().setCustomData(data.release());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
class CreatureLevList : public MWWorld::Class
|
class CreatureLevList : public MWWorld::Class
|
||||||
{
|
{
|
||||||
|
void ensureCustomData (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
||||||
|
@ -14,6 +16,9 @@ namespace MWClass
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
|
///< Add reference into a cell for rendering
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "light.hpp"
|
#include "light.hpp"
|
||||||
|
|
||||||
#include <components/esm/loadligh.hpp>
|
#include <components/esm/loadligh.hpp>
|
||||||
|
#include <components/esm/lightstate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -269,4 +270,24 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
return std::make_pair(1,"");
|
return std::make_pair(1,"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Light::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const ESM::LightState& state2 = dynamic_cast<const ESM::LightState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime = state2.mTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
ESM::LightState& state2 = dynamic_cast<ESM::LightState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
state2.mTime = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,14 @@ namespace MWClass
|
||||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||||
|
|
||||||
std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||||
|
|
||||||
|
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Read additional state from \a state into \a ptr.
|
||||||
|
|
||||||
|
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Write additional state from \a ptr into \a state.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,11 +155,8 @@ namespace MWClass
|
||||||
int count = ptr.getRefData().getCount();
|
int count = ptr.getRefData().getCount();
|
||||||
|
|
||||||
bool gold = isGold(ptr);
|
bool gold = isGold(ptr);
|
||||||
|
if (gold)
|
||||||
if (gold && ptr.getCellRef().mGoldValue != 1)
|
count *= getValue(ptr);
|
||||||
count = ptr.getCellRef().mGoldValue;
|
|
||||||
else if (gold)
|
|
||||||
count *= ref->mBase->mData.mValue;
|
|
||||||
|
|
||||||
std::string countString;
|
std::string countString;
|
||||||
if (!gold)
|
if (!gold)
|
||||||
|
@ -204,7 +201,7 @@ namespace MWClass
|
||||||
MWBase::Environment::get().getWorld()->getStore();
|
MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
|
||||||
if (isGold(ptr)) {
|
if (isGold(ptr)) {
|
||||||
int goldAmount = ptr.getRefData().getCount();
|
int goldAmount = getValue(ptr) * ptr.getRefData().getCount();
|
||||||
|
|
||||||
std::string base = "Gold_001";
|
std::string base = "Gold_001";
|
||||||
if (goldAmount >= 100)
|
if (goldAmount >= 100)
|
||||||
|
@ -223,6 +220,7 @@ namespace MWClass
|
||||||
newRef.getPtr().get<ESM::Miscellaneous>();
|
newRef.getPtr().get<ESM::Miscellaneous>();
|
||||||
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
|
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
|
||||||
newPtr.getCellRef().mGoldValue = goldAmount;
|
newPtr.getCellRef().mGoldValue = goldAmount;
|
||||||
|
newPtr.getRefData().setCount(1);
|
||||||
} else {
|
} else {
|
||||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||||
ptr.get<ESM::Miscellaneous>();
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <components/esm/loadmgef.hpp>
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
|
#include <components/esm/npcstate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
#include "../mwmechanics/disease.hpp"
|
#include "../mwmechanics/disease.hpp"
|
||||||
|
#include "../mwmechanics/combat.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontalk.hpp"
|
#include "../mwworld/actiontalk.hpp"
|
||||||
|
@ -36,9 +38,6 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const Ogre::Radian kOgrePi (Ogre::Math::PI);
|
|
||||||
const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0));
|
|
||||||
|
|
||||||
struct CustomData : public MWWorld::CustomData
|
struct CustomData : public MWWorld::CustomData
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats mNpcStats;
|
MWMechanics::NpcStats mNpcStats;
|
||||||
|
@ -144,7 +143,7 @@ namespace
|
||||||
*
|
*
|
||||||
* and by adding class, race, specialization bonus.
|
* and by adding class, race, specialization bonus.
|
||||||
*/
|
*/
|
||||||
void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats)
|
void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats, const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
const ESM::Class *class_ =
|
const ESM::Class *class_ =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc->mClass);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc->mClass);
|
||||||
|
@ -193,6 +192,18 @@ namespace
|
||||||
majorMultiplier = 1.0f;
|
majorMultiplier = 1.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (class_->mData.mSkills[k][1] == skillIndex)
|
||||||
|
{
|
||||||
|
// Major skill -> add starting spells for this skill if existing
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
||||||
|
for (; it != store.get<ESM::Spell>().end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mData.mFlags & ESM::Spell::F_Autocalc
|
||||||
|
&& MWMechanics::spellSchoolToSkill(MWMechanics::getSpellSchool(&*it, ptr)) == skillIndex)
|
||||||
|
npcStats.getSpells().add(it->mId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this skill in the same Specialization as the class?
|
// is this skill in the same Specialization as the class?
|
||||||
|
@ -243,6 +254,8 @@ namespace MWClass
|
||||||
fKnockDownMult = gmst.find("fKnockDownMult");
|
fKnockDownMult = gmst.find("fKnockDownMult");
|
||||||
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
||||||
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
||||||
|
fDamageStrengthBase = gmst.find("fDamageStrengthBase");
|
||||||
|
fDamageStrengthMult = gmst.find("fDamageStrengthMult");
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +318,15 @@ namespace MWClass
|
||||||
data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation);
|
data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation);
|
||||||
|
|
||||||
autoCalculateAttributes(ref->mBase, data->mNpcStats);
|
autoCalculateAttributes(ref->mBase, data->mNpcStats);
|
||||||
autoCalculateSkills(ref->mBase, data->mNpcStats);
|
autoCalculateSkills(ref->mBase, data->mNpcStats, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// race powers
|
||||||
|
const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||||
|
for (std::vector<std::string>::const_iterator iter (race->mPowers.mList.begin());
|
||||||
|
iter!=race->mPowers.mList.end(); ++iter)
|
||||||
|
{
|
||||||
|
data->mNpcStats.getSpells().add (*iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->mNpcStats.getFactionRanks().size())
|
if (data->mNpcStats.getFactionRanks().size())
|
||||||
|
@ -450,10 +471,11 @@ namespace MWClass
|
||||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||||
getCreatureStats(ptr).setFatigue(fatigue);
|
getCreatureStats(ptr).setFatigue(fatigue);
|
||||||
|
|
||||||
|
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
|
||||||
float dist = 100.0f * (!weapon.isEmpty() ?
|
float dist = fCombatDistance * (!weapon.isEmpty() ?
|
||||||
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
||||||
gmst.find("fHandToHandReach")->getFloat());
|
gmst.find("fHandToHandReach")->getFloat());
|
||||||
|
|
||||||
// TODO: Use second to work out the hit angle
|
// TODO: Use second to work out the hit angle
|
||||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
||||||
MWWorld::Ptr victim = result.first;
|
MWWorld::Ptr victim = result.first;
|
||||||
|
@ -497,16 +519,17 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const bool weaphashealth = get(weapon).hasItemHealth(weapon);
|
const bool weaphashealth = get(weapon).hasItemHealth(weapon);
|
||||||
const unsigned char *attack = NULL;
|
const unsigned char *attack = NULL;
|
||||||
if(type == MWMechanics::CreatureStats::AT_Chop)
|
if(type == ESM::Weapon::AT_Chop)
|
||||||
attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
|
||||||
else if(type == MWMechanics::CreatureStats::AT_Slash)
|
else if(type == ESM::Weapon::AT_Slash)
|
||||||
attack = weapon.get<ESM::Weapon>()->mBase->mData.mSlash;
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mSlash;
|
||||||
else if(type == MWMechanics::CreatureStats::AT_Thrust)
|
else if(type == ESM::Weapon::AT_Thrust)
|
||||||
attack = weapon.get<ESM::Weapon>()->mBase->mData.mThrust;
|
attack = weapon.get<ESM::Weapon>()->mBase->mData.mThrust;
|
||||||
if(attack)
|
if(attack)
|
||||||
{
|
{
|
||||||
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
|
||||||
damage *= 0.5f + (stats.getAttribute(ESM::Attribute::Luck).getModified() / 100.0f);
|
damage *= fDamageStrengthBase->getFloat() +
|
||||||
|
(stats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult->getFloat() * 0.1);
|
||||||
if(weaphashealth)
|
if(weaphashealth)
|
||||||
{
|
{
|
||||||
int weapmaxhealth = weapon.get<ESM::Weapon>()->mBase->mData.mHealth;
|
int weapmaxhealth = weapon.get<ESM::Weapon>()->mBase->mData.mHealth;
|
||||||
|
@ -579,33 +602,16 @@ namespace MWClass
|
||||||
enchantmentName);
|
enchantmentName);
|
||||||
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
|
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
|
||||||
{
|
{
|
||||||
// Check if we have enough charges
|
|
||||||
const float enchantCost = enchantment->mData.mCost;
|
|
||||||
int eSkill = stats.getSkill(ESM::Skill::Enchant).getModified();
|
|
||||||
const int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10));
|
|
||||||
|
|
||||||
if (weapon.getCellRef().mEnchantmentCharge == -1)
|
|
||||||
weapon.getCellRef().mEnchantmentCharge = enchantment->mData.mCharge;
|
|
||||||
if (weapon.getCellRef().mEnchantmentCharge < castCost)
|
|
||||||
{
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
weapon.getCellRef().mEnchantmentCharge -= castCost;
|
|
||||||
|
|
||||||
MWMechanics::CastSpell cast(ptr, victim);
|
MWMechanics::CastSpell cast(ptr, victim);
|
||||||
|
cast.mHitPosition = hitPosition;
|
||||||
cast.cast(weapon);
|
cast.cast(weapon);
|
||||||
|
|
||||||
if (ptr.getRefData().getHandle() == "player")
|
|
||||||
skillUsageSucceeded (ptr, ESM::Skill::Enchant, 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do not do this if the attack is blocked
|
if (!weapon.isEmpty() && MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage))
|
||||||
if (healthdmg)
|
damage = 0;
|
||||||
|
|
||||||
|
if (healthdmg && damage > 0)
|
||||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
||||||
|
|
||||||
othercls.onHit(victim, damage, healthdmg, weapon, ptr, true);
|
othercls.onHit(victim, damage, healthdmg, weapon, ptr, true);
|
||||||
|
@ -644,6 +650,9 @@ namespace MWClass
|
||||||
if (!attacker.isEmpty())
|
if (!attacker.isEmpty())
|
||||||
MWMechanics::diseaseContact(ptr, attacker);
|
MWMechanics::diseaseContact(ptr, attacker);
|
||||||
|
|
||||||
|
if (damage > 0.0f && !object.isEmpty())
|
||||||
|
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
|
||||||
|
|
||||||
if(damage > 0.0f)
|
if(damage > 0.0f)
|
||||||
{
|
{
|
||||||
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
||||||
|
@ -715,6 +724,9 @@ namespace MWClass
|
||||||
if (armorref.mCharge == 0)
|
if (armorref.mCharge == 0)
|
||||||
inv.unequipItem(armor, ptr);
|
inv.unequipItem(armor, ptr);
|
||||||
|
|
||||||
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
|
skillUsageSucceeded(ptr, get(armor).getEquipmentSkill(armor), 0);
|
||||||
|
|
||||||
switch(get(armor).getEquipmentSkill(armor))
|
switch(get(armor).getEquipmentSkill(armor))
|
||||||
{
|
{
|
||||||
case ESM::Skill::LightArmor:
|
case ESM::Skill::LightArmor:
|
||||||
|
@ -728,6 +740,8 @@ namespace MWClass
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(ptr.getRefData().getHandle() == "player")
|
||||||
|
skillUsageSucceeded(ptr, ESM::Skill::Unarmored, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,6 +760,30 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Npc::block(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = getInventoryStore(ptr);
|
||||||
|
MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
if (shield == inv.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
switch(shield->getClass().getEquipmentSkill(*shield))
|
||||||
|
{
|
||||||
|
case ESM::Skill::LightArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Light Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case ESM::Skill::MediumArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Medium Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case ESM::Skill::HeavyArmor:
|
||||||
|
sndMgr->playSound3D(ptr, "Heavy Armor Hit", 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Npc::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
void Npc::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats &crstats = getCreatureStats(ptr);
|
MWMechanics::CreatureStats &crstats = getCreatureStats(ptr);
|
||||||
|
@ -1233,6 +1271,28 @@ namespace MWClass
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Npc::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
|
||||||
|
readState (state2.mInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Npc::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
ESM::NpcState& state2 = dynamic_cast<ESM::NpcState&> (state);
|
||||||
|
|
||||||
|
ensureCustomData (ptr);
|
||||||
|
|
||||||
|
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore.
|
||||||
|
writeState (state2.mInventory);
|
||||||
|
}
|
||||||
|
|
||||||
const ESM::GameSetting *Npc::fMinWalkSpeed;
|
const ESM::GameSetting *Npc::fMinWalkSpeed;
|
||||||
const ESM::GameSetting *Npc::fMaxWalkSpeed;
|
const ESM::GameSetting *Npc::fMaxWalkSpeed;
|
||||||
const ESM::GameSetting *Npc::fEncumberedMoveEffect;
|
const ESM::GameSetting *Npc::fEncumberedMoveEffect;
|
||||||
|
@ -1252,4 +1312,7 @@ namespace MWClass
|
||||||
const ESM::GameSetting *Npc::fKnockDownMult;
|
const ESM::GameSetting *Npc::fKnockDownMult;
|
||||||
const ESM::GameSetting *Npc::iKnockDownOddsMult;
|
const ESM::GameSetting *Npc::iKnockDownOddsMult;
|
||||||
const ESM::GameSetting *Npc::iKnockDownOddsBase;
|
const ESM::GameSetting *Npc::iKnockDownOddsBase;
|
||||||
|
const ESM::GameSetting *Npc::fDamageStrengthBase;
|
||||||
|
const ESM::GameSetting *Npc::fDamageStrengthMult;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace MWClass
|
||||||
static const ESM::GameSetting *fKnockDownMult;
|
static const ESM::GameSetting *fKnockDownMult;
|
||||||
static const ESM::GameSetting *iKnockDownOddsMult;
|
static const ESM::GameSetting *iKnockDownOddsMult;
|
||||||
static const ESM::GameSetting *iKnockDownOddsBase;
|
static const ESM::GameSetting *iKnockDownOddsBase;
|
||||||
|
static const ESM::GameSetting *fDamageStrengthBase;
|
||||||
|
static const ESM::GameSetting *fDamageStrengthMult;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -71,10 +73,14 @@ namespace MWClass
|
||||||
virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const;
|
virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return inventory store
|
///< Return inventory store
|
||||||
|
|
||||||
|
virtual bool hasInventoryStore(const MWWorld::Ptr &ptr) const { return true; }
|
||||||
|
|
||||||
virtual void hit(const MWWorld::Ptr& ptr, int type) const;
|
virtual void hit(const MWWorld::Ptr& ptr, int type) const;
|
||||||
|
|
||||||
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
|
virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const;
|
||||||
|
|
||||||
|
virtual void block(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
|
virtual void setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const;
|
||||||
|
|
||||||
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
|
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
|
||||||
|
@ -152,6 +158,14 @@ namespace MWClass
|
||||||
virtual bool isNpc() const {
|
virtual bool isNpc() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Read additional state from \a state into \a ptr.
|
||||||
|
|
||||||
|
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||||
|
const;
|
||||||
|
///< Write additional state from \a ptr into \a state.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -429,12 +429,12 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(&cell.mWeapons.insert(*ref), &cell);
|
return MWWorld::Ptr(&cell.mWeapons.insert(*ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
||||||
ptr.get<ESM::Weapon>();
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
return ref->mBase->mData.mEnchant/10.f;
|
return ref->mBase->mData.mEnchant;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace MWClass
|
||||||
|
|
||||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual float getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), title);
|
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), title);
|
||||||
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId);
|
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor.getClass().getName(mActor));
|
||||||
|
|
||||||
executeScript (info->mResultScript);
|
executeScript (info->mResultScript);
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ namespace MWDialogue
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
|
||||||
// Apply disposition change to NPC's base disposition
|
// Apply disposition change to NPC's base disposition
|
||||||
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||||
npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange);
|
npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange);
|
||||||
|
@ -451,7 +451,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse (Interpreter::fixDefinesDialog(text, interpreterContext));
|
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse (Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId);
|
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor.getClass().getName(mActor));
|
||||||
executeScript (info->mResultScript);
|
executeScript (info->mResultScript);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,6 +586,7 @@ namespace MWDialogue
|
||||||
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
|
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
|
||||||
if(winMgr->getSubtitlesEnabled())
|
if(winMgr->getSubtitlesEnabled())
|
||||||
winMgr->messageBox(info->mResponse);
|
winMgr->messageBox(info->mResponse);
|
||||||
|
if (!info->mSound.empty())
|
||||||
sndMgr->say(actor, info->mSound);
|
sndMgr->say(actor, info->mSound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
|
||||||
|
|
||||||
// internally all globals are float :(
|
// internally all globals are float :(
|
||||||
return select.selectCompare (
|
return select.selectCompare (
|
||||||
MWBase::Environment::get().getWorld()->getGlobalVariable (select.getName()).mFloat);
|
MWBase::Environment::get().getWorld()->getGlobalFloat (select.getName()));
|
||||||
|
|
||||||
case SelectWrapper::Function_Local:
|
case SelectWrapper::Function_Local:
|
||||||
{
|
{
|
||||||
|
@ -216,7 +216,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
|
||||||
float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() /
|
float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() /
|
||||||
MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified();
|
MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified();
|
||||||
|
|
||||||
return select.selectCompare (ratio);
|
return select.selectCompare (static_cast<int>(ratio*100));
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcDynamicStat:
|
case SelectWrapper::Function_PcDynamicStat:
|
||||||
|
@ -536,7 +536,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||||
|
|
||||||
case SelectWrapper::Function_CreatureTargetted:
|
case SelectWrapper::Function_CreatureTargetted:
|
||||||
|
|
||||||
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getCreatureTargetted();
|
return mActor.getClass().getCreatureStats (mActor).getCreatureTargetted();
|
||||||
|
|
||||||
case SelectWrapper::Function_Werewolf:
|
case SelectWrapper::Function_Werewolf:
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/esm/journalentry.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
@ -10,23 +12,55 @@
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
JournalEntry::JournalEntry() {}
|
Entry::Entry() {}
|
||||||
|
|
||||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId)
|
Entry::Entry (const std::string& topic, const std::string& infoId)
|
||||||
: mTopic (topic), mInfoId (infoId)
|
: mInfoId (infoId)
|
||||||
{}
|
|
||||||
|
|
||||||
std::string JournalEntry::getText (const MWWorld::ESMStore& store) const
|
|
||||||
{
|
{
|
||||||
const ESM::Dialogue *dialogue =
|
const ESM::Dialogue *dialogue =
|
||||||
store.get<ESM::Dialogue>().find (mTopic);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (topic);
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
||||||
iter!=dialogue->mInfo.end(); ++iter)
|
iter!=dialogue->mInfo.end(); ++iter)
|
||||||
if (iter->mId == mInfoId)
|
if (iter->mId == mInfoId)
|
||||||
return iter->mResponse;
|
{
|
||||||
|
/// \todo text replacement
|
||||||
|
mText = iter->mResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
throw std::runtime_error ("unknown info ID " + mInfoId + " for topic " + mTopic);
|
throw std::runtime_error ("unknown info ID " + mInfoId + " for topic " + topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry::Entry (const ESM::JournalEntry& record) : mInfoId (record.mInfo), mText (record.mText), mActorName(record.mActorName) {}
|
||||||
|
|
||||||
|
std::string Entry::getText() const
|
||||||
|
{
|
||||||
|
return mText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::write (ESM::JournalEntry& entry) const
|
||||||
|
{
|
||||||
|
entry.mInfo = mInfoId;
|
||||||
|
entry.mText = mText;
|
||||||
|
entry.mActorName = mActorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JournalEntry::JournalEntry() {}
|
||||||
|
|
||||||
|
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId)
|
||||||
|
: Entry (topic, infoId), mTopic (topic)
|
||||||
|
{}
|
||||||
|
|
||||||
|
JournalEntry::JournalEntry (const ESM::JournalEntry& record)
|
||||||
|
: Entry (record), mTopic (record.mTopic)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void JournalEntry::write (ESM::JournalEntry& entry) const
|
||||||
|
{
|
||||||
|
Entry::write (entry);
|
||||||
|
entry.mTopic = mTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index)
|
JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index)
|
||||||
|
@ -49,6 +83,7 @@ namespace MWDialogue
|
||||||
throw std::runtime_error ("unknown journal index for topic " + topic);
|
throw std::runtime_error ("unknown journal index for topic " + topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StampedJournalEntry::StampedJournalEntry()
|
StampedJournalEntry::StampedJournalEntry()
|
||||||
: mDay (0), mMonth (0), mDayOfMonth (0)
|
: mDay (0), mMonth (0), mDayOfMonth (0)
|
||||||
{}
|
{}
|
||||||
|
@ -58,11 +93,24 @@ namespace MWDialogue
|
||||||
: JournalEntry (topic, infoId), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
: JournalEntry (topic, infoId), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
StampedJournalEntry::StampedJournalEntry (const ESM::JournalEntry& record)
|
||||||
|
: JournalEntry (record), mDay (record.mDay), mMonth (record.mMonth),
|
||||||
|
mDayOfMonth (record.mDayOfMonth)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void StampedJournalEntry::write (ESM::JournalEntry& entry) const
|
||||||
|
{
|
||||||
|
JournalEntry::write (entry);
|
||||||
|
entry.mDay = mDay;
|
||||||
|
entry.mMonth = mMonth;
|
||||||
|
entry.mDayOfMonth = mDayOfMonth;
|
||||||
|
}
|
||||||
|
|
||||||
StampedJournalEntry StampedJournalEntry::makeFromQuest (const std::string& topic, int index)
|
StampedJournalEntry StampedJournalEntry::makeFromQuest (const std::string& topic, int index)
|
||||||
{
|
{
|
||||||
int day = MWBase::Environment::get().getWorld()->getGlobalVariable ("dayspassed").mLong;
|
int day = MWBase::Environment::get().getWorld()->getGlobalInt ("dayspassed");
|
||||||
int month = MWBase::Environment::get().getWorld()->getGlobalVariable ("month").mLong;
|
int month = MWBase::Environment::get().getWorld()->getGlobalInt ("month");
|
||||||
int dayOfMonth = MWBase::Environment::get().getWorld()->getGlobalVariable ("day").mLong;
|
int dayOfMonth = MWBase::Environment::get().getWorld()->getGlobalInt ("day");
|
||||||
|
|
||||||
return StampedJournalEntry (topic, idFromIndex (topic, index), day, month, dayOfMonth);
|
return StampedJournalEntry (topic, idFromIndex (topic, index), day, month, dayOfMonth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,45 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace MWWorld
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct ESMStore;
|
struct JournalEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
/// \brief A quest or dialogue entry
|
/// \brief Basic quest/dialogue/topic entry
|
||||||
struct JournalEntry
|
struct Entry
|
||||||
|
{
|
||||||
|
std::string mInfoId;
|
||||||
|
std::string mText;
|
||||||
|
std::string mActorName; // optional
|
||||||
|
|
||||||
|
Entry();
|
||||||
|
|
||||||
|
Entry (const std::string& topic, const std::string& infoId);
|
||||||
|
|
||||||
|
Entry (const ESM::JournalEntry& record);
|
||||||
|
|
||||||
|
std::string getText() const;
|
||||||
|
|
||||||
|
void write (ESM::JournalEntry& entry) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A dialogue entry
|
||||||
|
///
|
||||||
|
/// Same as entry, but store TopicID
|
||||||
|
struct JournalEntry : public Entry
|
||||||
{
|
{
|
||||||
std::string mTopic;
|
std::string mTopic;
|
||||||
std::string mInfoId;
|
|
||||||
|
|
||||||
JournalEntry();
|
JournalEntry();
|
||||||
|
|
||||||
JournalEntry (const std::string& topic, const std::string& infoId);
|
JournalEntry (const std::string& topic, const std::string& infoId);
|
||||||
|
|
||||||
std::string getText (const MWWorld::ESMStore& store) const;
|
JournalEntry (const ESM::JournalEntry& record);
|
||||||
|
|
||||||
|
void write (ESM::JournalEntry& entry) const;
|
||||||
|
|
||||||
static JournalEntry makeFromQuest (const std::string& topic, int index);
|
static JournalEntry makeFromQuest (const std::string& topic, int index);
|
||||||
|
|
||||||
|
@ -39,6 +60,10 @@ namespace MWDialogue
|
||||||
StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
||||||
int day, int month, int dayOfMonth);
|
int day, int month, int dayOfMonth);
|
||||||
|
|
||||||
|
StampedJournalEntry (const ESM::JournalEntry& record);
|
||||||
|
|
||||||
|
void write (ESM::JournalEntry& entry) const;
|
||||||
|
|
||||||
static StampedJournalEntry makeFromQuest (const std::string& topic, int index);
|
static StampedJournalEntry makeFromQuest (const std::string& topic, int index);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
|
|
||||||
#include "journalimp.hpp"
|
#include "journalimp.hpp"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/queststate.hpp>
|
||||||
|
#include <components/esm/journalentry.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -26,6 +33,38 @@ namespace MWDialogue
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Topic& Journal::getTopic (const std::string& id)
|
||||||
|
{
|
||||||
|
TTopicContainer::iterator iter = mTopics.find (id);
|
||||||
|
|
||||||
|
if (iter==mTopics.end())
|
||||||
|
{
|
||||||
|
std::pair<TTopicContainer::iterator, bool> result
|
||||||
|
= mTopics.insert (std::make_pair (id, Topic (id)));
|
||||||
|
|
||||||
|
iter = result.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Journal::isThere (const std::string& topicId, const std::string& infoId) const
|
||||||
|
{
|
||||||
|
if (const ESM::Dialogue *dialogue =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().search (topicId))
|
||||||
|
{
|
||||||
|
if (infoId.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
||||||
|
iter!=dialogue->mInfo.end(); ++iter)
|
||||||
|
if (iter->mId == infoId)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Journal::Journal()
|
Journal::Journal()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -64,19 +103,13 @@ namespace MWDialogue
|
||||||
quest.setIndex (index);
|
quest.setIndex (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::addTopic (const std::string& topicId, const std::string& infoId)
|
void Journal::addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName)
|
||||||
{
|
{
|
||||||
TTopicContainer::iterator iter = mTopics.find (topicId);
|
Topic& topic = getTopic (topicId);
|
||||||
|
|
||||||
if (iter==mTopics.end())
|
JournalEntry entry(topicId, infoId);
|
||||||
{
|
entry.mActorName = actorName;
|
||||||
std::pair<TTopicContainer::iterator, bool> result
|
topic.addEntry (entry);
|
||||||
= mTopics.insert (std::make_pair (topicId, Topic (topicId)));
|
|
||||||
|
|
||||||
iter = result.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter->second.addEntry (JournalEntry (topicId, infoId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Journal::getJournalIndex (const std::string& id) const
|
int Journal::getJournalIndex (const std::string& id) const
|
||||||
|
@ -118,4 +151,106 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
return mTopics.end();
|
return mTopics.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Journal::countSavedGameRecords() const
|
||||||
|
{
|
||||||
|
int count = static_cast<int> (mQuests.size());
|
||||||
|
|
||||||
|
for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter)
|
||||||
|
count += std::distance (iter->second.begin(), iter->second.end());
|
||||||
|
|
||||||
|
count += std::distance (mJournal.begin(), mJournal.end());
|
||||||
|
|
||||||
|
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
|
||||||
|
count += std::distance (iter->second.begin(), iter->second.end());
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Journal::write (ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter)
|
||||||
|
{
|
||||||
|
const Quest& quest = iter->second;
|
||||||
|
|
||||||
|
ESM::QuestState state;
|
||||||
|
quest.write (state);
|
||||||
|
writer.startRecord (ESM::REC_QUES);
|
||||||
|
state.save (writer);
|
||||||
|
writer.endRecord (ESM::REC_QUES);
|
||||||
|
|
||||||
|
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
|
||||||
|
{
|
||||||
|
ESM::JournalEntry entry;
|
||||||
|
entry.mType = ESM::JournalEntry::Type_Quest;
|
||||||
|
entry.mTopic = quest.getTopic();
|
||||||
|
iter->write (entry);
|
||||||
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
|
entry.save (writer);
|
||||||
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TEntryIter iter (mJournal.begin()); iter!=mJournal.end(); ++iter)
|
||||||
|
{
|
||||||
|
ESM::JournalEntry entry;
|
||||||
|
entry.mType = ESM::JournalEntry::Type_Journal;
|
||||||
|
iter->write (entry);
|
||||||
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
|
entry.save (writer);
|
||||||
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
|
||||||
|
{
|
||||||
|
const Topic& topic = iter->second;
|
||||||
|
|
||||||
|
for (Topic::TEntryIter iter (topic.begin()); iter!=topic.end(); ++iter)
|
||||||
|
{
|
||||||
|
ESM::JournalEntry entry;
|
||||||
|
entry.mType = ESM::JournalEntry::Type_Topic;
|
||||||
|
entry.mTopic = topic.getTopic();
|
||||||
|
iter->write (entry);
|
||||||
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
|
entry.save (writer);
|
||||||
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Journal::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||||
|
{
|
||||||
|
if (type==ESM::REC_JOUR)
|
||||||
|
{
|
||||||
|
ESM::JournalEntry record;
|
||||||
|
record.load (reader);
|
||||||
|
|
||||||
|
if (isThere (record.mTopic, record.mInfo))
|
||||||
|
switch (record.mType)
|
||||||
|
{
|
||||||
|
case ESM::JournalEntry::Type_Quest:
|
||||||
|
|
||||||
|
getQuest (record.mTopic).insertEntry (record);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESM::JournalEntry::Type_Journal:
|
||||||
|
|
||||||
|
mJournal.push_back (record);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESM::JournalEntry::Type_Topic:
|
||||||
|
|
||||||
|
getTopic (record.mTopic).insertEntry (record);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type==ESM::REC_QUES)
|
||||||
|
{
|
||||||
|
ESM::QuestState record;
|
||||||
|
record.load (reader);
|
||||||
|
|
||||||
|
if (isThere (record.mTopic))
|
||||||
|
mQuests.insert (std::make_pair (record.mTopic, record));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,14 @@ namespace MWDialogue
|
||||||
TQuestContainer mQuests;
|
TQuestContainer mQuests;
|
||||||
TTopicContainer mTopics;
|
TTopicContainer mTopics;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
Quest& getQuest (const std::string& id);
|
Quest& getQuest (const std::string& id);
|
||||||
|
|
||||||
|
Topic& getTopic (const std::string& id);
|
||||||
|
|
||||||
|
bool isThere (const std::string& topicId, const std::string& infoId = "") const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Journal();
|
Journal();
|
||||||
|
@ -32,7 +38,7 @@ namespace MWDialogue
|
||||||
virtual int getJournalIndex (const std::string& id) const;
|
virtual int getJournalIndex (const std::string& id) const;
|
||||||
///< Get the journal index.
|
///< Get the journal index.
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topicId, const std::string& infoId);
|
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName);
|
||||||
|
|
||||||
virtual TEntryIter begin() const;
|
virtual TEntryIter begin() const;
|
||||||
///< Iterator pointing to the begin of the main journal.
|
///< Iterator pointing to the begin of the main journal.
|
||||||
|
@ -55,6 +61,12 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual TTopicIter topicEnd() const;
|
virtual TTopicIter topicEnd() const;
|
||||||
///< Iterator pointing past the last topic.
|
///< Iterator pointing past the last topic.
|
||||||
|
|
||||||
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
||||||
|
virtual void write (ESM::ESMWriter& writer) const;
|
||||||
|
|
||||||
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
#include "quest.hpp"
|
#include "quest.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/queststate.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -16,7 +18,11 @@ namespace MWDialogue
|
||||||
: Topic (topic), mIndex (0), mFinished (false)
|
: Topic (topic), mIndex (0), mFinished (false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const std::string Quest::getName() const
|
Quest::Quest (const ESM::QuestState& state)
|
||||||
|
: Topic (state.mTopic), mIndex (state.mState), mFinished (state.mFinished!=0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string Quest::getName() const
|
||||||
{
|
{
|
||||||
const ESM::Dialogue *dialogue =
|
const ESM::Dialogue *dialogue =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (mTopic);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (mTopic);
|
||||||
|
@ -39,20 +45,23 @@ namespace MWDialogue
|
||||||
const ESM::Dialogue *dialogue =
|
const ESM::Dialogue *dialogue =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (mTopic);
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (mTopic);
|
||||||
|
|
||||||
|
bool found=false;
|
||||||
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
for (std::vector<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
||||||
iter!=dialogue->mInfo.end(); ++iter)
|
iter!=dialogue->mInfo.end(); ++iter)
|
||||||
if (iter->mData.mDisposition==index && iter->mQuestStatus!=ESM::DialInfo::QS_Name)
|
if (iter->mData.mDisposition==index && iter->mQuestStatus!=ESM::DialInfo::QS_Name)
|
||||||
{
|
{
|
||||||
mIndex = index;
|
|
||||||
|
|
||||||
if (iter->mQuestStatus==ESM::DialInfo::QS_Finished)
|
if (iter->mQuestStatus==ESM::DialInfo::QS_Finished)
|
||||||
mFinished = true;
|
mFinished = true;
|
||||||
else if (iter->mQuestStatus==ESM::DialInfo::QS_Restart)
|
else if (iter->mQuestStatus==ESM::DialInfo::QS_Restart)
|
||||||
mFinished = false;
|
mFinished = false;
|
||||||
|
|
||||||
return;
|
found = true;
|
||||||
|
// Don't return here. Quest status may actually be in a different info record, since we don't merge these (yet?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
mIndex = index;
|
||||||
|
else
|
||||||
throw std::runtime_error ("unknown journal index for topic " + mTopic);
|
throw std::runtime_error ("unknown journal index for topic " + mTopic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,12 +88,20 @@ namespace MWDialogue
|
||||||
if (index==-1)
|
if (index==-1)
|
||||||
throw std::runtime_error ("unknown journal entry for topic " + mTopic);
|
throw std::runtime_error ("unknown journal entry for topic " + mTopic);
|
||||||
|
|
||||||
|
if (index > mIndex)
|
||||||
setIndex (index);
|
setIndex (index);
|
||||||
|
|
||||||
for (TEntryIter iter (mEntries.begin()); iter!=mEntries.end(); ++iter)
|
for (TEntryIter iter (mEntries.begin()); iter!=mEntries.end(); ++iter)
|
||||||
if (*iter==entry.mInfoId)
|
if (iter->mInfoId==entry.mInfoId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mEntries.push_back (entry.mInfoId);
|
mEntries.push_back (entry); // we want slicing here
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quest::write (ESM::QuestState& state) const
|
||||||
|
{
|
||||||
|
state.mTopic = getTopic();
|
||||||
|
state.mState = mIndex;
|
||||||
|
state.mFinished = mFinished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
|
|
||||||
#include "topic.hpp"
|
#include "topic.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct QuestState;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
/// \brief A quest in progress or a compelted quest
|
/// \brief A quest in progress or a completed quest
|
||||||
class Quest : public Topic
|
class Quest : public Topic
|
||||||
{
|
{
|
||||||
int mIndex;
|
int mIndex;
|
||||||
|
@ -17,13 +22,15 @@ namespace MWDialogue
|
||||||
|
|
||||||
Quest (const std::string& topic);
|
Quest (const std::string& topic);
|
||||||
|
|
||||||
const std::string getName() const;
|
Quest (const ESM::QuestState& state);
|
||||||
|
|
||||||
|
virtual std::string getName() const;
|
||||||
///< May be an empty string
|
///< May be an empty string
|
||||||
|
|
||||||
int getIndex() const;
|
int getIndex() const;
|
||||||
|
|
||||||
void setIndex (int index);
|
void setIndex (int index);
|
||||||
///< Calling this function with a non-existant index while throw an exception.
|
///< Calling this function with a non-existent index will throw an exception.
|
||||||
|
|
||||||
bool isFinished() const;
|
bool isFinished() const;
|
||||||
|
|
||||||
|
@ -31,6 +38,8 @@ namespace MWDialogue
|
||||||
///< Add entry and adjust index accordingly.
|
///< Add entry and adjust index accordingly.
|
||||||
///
|
///
|
||||||
/// \note Redundant entries are ignored, but the index is still adjusted.
|
/// \note Redundant entries are ignored, but the index is still adjusted.
|
||||||
|
|
||||||
|
void write (ESM::QuestState& state) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
|
||||||
#include "topic.hpp"
|
#include "topic.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
|
@ -9,7 +12,8 @@ namespace MWDialogue
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Topic::Topic (const std::string& topic)
|
Topic::Topic (const std::string& topic)
|
||||||
: mTopic (topic)
|
: mTopic (topic), mName (
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (topic)->mId)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Topic::~Topic()
|
Topic::~Topic()
|
||||||
|
@ -20,11 +24,29 @@ namespace MWDialogue
|
||||||
if (entry.mTopic!=mTopic)
|
if (entry.mTopic!=mTopic)
|
||||||
throw std::runtime_error ("topic does not match: " + mTopic);
|
throw std::runtime_error ("topic does not match: " + mTopic);
|
||||||
|
|
||||||
for (TEntryIter iter = begin(); iter!=end(); ++iter)
|
// bail out if we already have heard this
|
||||||
if (*iter==entry.mInfoId)
|
for (Topic::TEntryIter it = mEntries.begin(); it != mEntries.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mInfoId == entry.mInfoId)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mEntries.push_back (entry.mInfoId);
|
mEntries.push_back (entry); // we want slicing here
|
||||||
|
}
|
||||||
|
|
||||||
|
void Topic::insertEntry (const ESM::JournalEntry& entry)
|
||||||
|
{
|
||||||
|
mEntries.push_back (entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Topic::getTopic() const
|
||||||
|
{
|
||||||
|
return mTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Topic::getName() const
|
||||||
|
{
|
||||||
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
Topic::TEntryIter Topic::begin() const
|
Topic::TEntryIter Topic::begin() const
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include "journalentry.hpp"
|
#include "journalentry.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct JournalEntry;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
/// \brief Collection of seen responses for a topic
|
/// \brief Collection of seen responses for a topic
|
||||||
|
@ -13,13 +18,14 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector<std::string> TEntryContainer;
|
typedef std::vector<Entry> TEntryContainer;
|
||||||
typedef TEntryContainer::const_iterator TEntryIter;
|
typedef TEntryContainer::const_iterator TEntryIter;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::string mTopic;
|
std::string mTopic;
|
||||||
TEntryContainer mEntries; // info-IDs
|
std::string mName;
|
||||||
|
TEntryContainer mEntries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -34,7 +40,13 @@ namespace MWDialogue
|
||||||
///
|
///
|
||||||
/// \note Redundant entries are ignored.
|
/// \note Redundant entries are ignored.
|
||||||
|
|
||||||
std::string const & getName () const { return mTopic; }
|
void insertEntry (const ESM::JournalEntry& entry);
|
||||||
|
///< Add entry without checking for redundant entries or modifying the state of the
|
||||||
|
/// topic otherwise
|
||||||
|
|
||||||
|
std::string getTopic() const;
|
||||||
|
|
||||||
|
virtual std::string getName() const;
|
||||||
|
|
||||||
TEntryIter begin() const;
|
TEntryIter begin() const;
|
||||||
///< Iterator pointing to the begin of the journal for this topic.
|
///< Iterator pointing to the begin of the journal for this topic.
|
||||||
|
|
|
@ -33,8 +33,7 @@ namespace MWGui
|
||||||
|
|
||||||
getWidget(mBirthList, "BirthsignList");
|
getWidget(mBirthList, "BirthsignList");
|
||||||
mBirthList->setScrollVisible(true);
|
mBirthList->setScrollVisible(true);
|
||||||
mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onAccept);
|
||||||
mBirthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
|
||||||
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
|
||||||
|
|
||||||
MyGUI::Button* backButton;
|
MyGUI::Button* backButton;
|
||||||
|
@ -97,6 +96,14 @@ namespace MWGui
|
||||||
eventDone(this);
|
eventDone(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BirthDialog::onAccept(MyGUI::ListBox *_sender, size_t _index)
|
||||||
|
{
|
||||||
|
onSelectBirth(_sender, _index);
|
||||||
|
if(mBirthList->getIndexSelected() == MyGUI::ITEM_NONE)
|
||||||
|
return;
|
||||||
|
eventDone(this);
|
||||||
|
}
|
||||||
|
|
||||||
void BirthDialog::onBackClicked(MyGUI::Widget* _sender)
|
void BirthDialog::onBackClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
eventBack();
|
eventBack();
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace MWGui
|
||||||
protected:
|
protected:
|
||||||
void onSelectBirth(MyGUI::ListBox* _sender, size_t _index);
|
void onSelectBirth(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
|
||||||
|
void onAccept(MyGUI::ListBox* _sender, size_t index);
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/fallback.hpp"
|
#include "../mwworld/fallback.hpp"
|
||||||
|
|
||||||
|
@ -47,9 +47,8 @@ namespace
|
||||||
void updatePlayerHealth()
|
void updatePlayerHealth()
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats(player);
|
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
|
||||||
|
npcStats.updateHealth();
|
||||||
creatureStats.updateHealth();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,8 +82,7 @@ namespace MWGui
|
||||||
|
|
||||||
getWidget(mClassList, "ClassList");
|
getWidget(mClassList, "ClassList");
|
||||||
mClassList->setScrollVisible(true);
|
mClassList->setScrollVisible(true);
|
||||||
mClassList->eventListSelectAccept += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
mClassList->eventListSelectAccept += MyGUI::newDelegate(this, &PickClassDialog::onAccept);
|
||||||
mClassList->eventListMouseItemActivate += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
|
||||||
mClassList->eventListChangePosition += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
mClassList->eventListChangePosition += MyGUI::newDelegate(this, &PickClassDialog::onSelectClass);
|
||||||
|
|
||||||
getWidget(mClassImage, "ClassImage");
|
getWidget(mClassImage, "ClassImage");
|
||||||
|
@ -152,6 +151,14 @@ namespace MWGui
|
||||||
eventBack();
|
eventBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PickClassDialog::onAccept(MyGUI::ListBox* _sender, size_t _index)
|
||||||
|
{
|
||||||
|
onSelectClass(_sender, _index);
|
||||||
|
if(mClassList->getIndexSelected() == MyGUI::ITEM_NONE)
|
||||||
|
return;
|
||||||
|
eventDone(this);
|
||||||
|
}
|
||||||
|
|
||||||
void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
|
void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
|
|
|
@ -111,6 +111,7 @@ namespace MWGui
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectClass(MyGUI::ListBox* _sender, size_t _index);
|
void onSelectClass(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
void onAccept(MyGUI::ListBox* _sender, size_t _index);
|
||||||
|
|
||||||
void onOkClicked(MyGUI::Widget* _sender);
|
void onOkClicked(MyGUI::Widget* _sender);
|
||||||
void onBackClicked(MyGUI::Widget* _sender);
|
void onBackClicked(MyGUI::Widget* _sender);
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace MWGui
|
||||||
|
|
||||||
void CompanionItemModel::copyItem (const ItemStack& item, size_t count)
|
void CompanionItemModel::copyItem (const ItemStack& item, size_t count)
|
||||||
{
|
{
|
||||||
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||||
stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
||||||
|
@ -23,7 +23,7 @@ namespace MWGui
|
||||||
|
|
||||||
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
|
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
|
||||||
{
|
{
|
||||||
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||||
stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
||||||
|
|
|
@ -235,7 +235,7 @@ namespace MWGui
|
||||||
|
|
||||||
mItemView->setModel (mSortModel);
|
mItemView->setModel (mSortModel);
|
||||||
|
|
||||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
|
||||||
|
|
||||||
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
||||||
// or we end up using a possibly invalid model.
|
// or we end up using a possibly invalid model.
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
|
@ -296,6 +298,28 @@ namespace MWGui
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the player is attempting to use a soulstone or item that was stolen from this actor
|
||||||
|
if (mPtr != player)
|
||||||
|
{
|
||||||
|
for (int i=0; i<2; ++i)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
|
||||||
|
if (Misc::StringUtils::ciEqual(item.getCellRef().mOwner, mPtr.getCellRef().mRefID))
|
||||||
|
{
|
||||||
|
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
|
||||||
|
if (msg.find("%s") != std::string::npos)
|
||||||
|
msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->reportCrime(player, mPtr, MWBase::MechanicsManager::OT_Theft,
|
||||||
|
item.getClass().getValue(item));
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int result = mEnchanting.create();
|
int result = mEnchanting.create();
|
||||||
|
|
||||||
if(result==1)
|
if(result==1)
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <boost/range/algorithm/copy.hpp>
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
#include <OgreUTFString.h>
|
#include <OgreUTFString.h>
|
||||||
|
|
||||||
|
#include <OgreResourceGroupManager.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
int convertFromHex(std::string hex)
|
int convertFromHex(std::string hex)
|
||||||
|
@ -288,6 +290,16 @@ namespace MWGui
|
||||||
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox",
|
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox",
|
||||||
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top,
|
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top,
|
||||||
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
||||||
|
|
||||||
|
// Apparently a bug with some morrowind versions, they reference the image without the size suffix.
|
||||||
|
// So if the image isn't found, try appending the size.
|
||||||
|
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("bookart\\"+image))
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
str << image.substr(0, image.rfind(".")) << "_" << width << "_" << height << image.substr(image.rfind("."));
|
||||||
|
image = str.str();
|
||||||
|
}
|
||||||
|
|
||||||
box->setImageTexture("bookart\\" + image);
|
box->setImageTexture("bookart\\" + image);
|
||||||
box->setProperty("NeedMouse", "false");
|
box->setProperty("NeedMouse", "false");
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,9 +74,9 @@ void InventoryItemModel::update()
|
||||||
|
|
||||||
ItemStack newItem (item, this, item.getRefData().getCount());
|
ItemStack newItem (item, this, item.getRefData().getCount());
|
||||||
|
|
||||||
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
if (mActor.getClass().hasInventoryStore(mActor))
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& store = MWWorld::Class::get(mActor).getInventoryStore(mActor);
|
MWWorld::InventoryStore& store = mActor.getClass().getInventoryStore(mActor);
|
||||||
for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot)
|
for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot)
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStoreIterator equipped = store.getSlot(slot);
|
MWWorld::ContainerStoreIterator equipped = store.getSlot(slot);
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace MWGui
|
||||||
getWidget(mRightPane, "RightPane");
|
getWidget(mRightPane, "RightPane");
|
||||||
getWidget(mArmorRating, "ArmorRating");
|
getWidget(mArmorRating, "ArmorRating");
|
||||||
|
|
||||||
mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
mAvatarImage->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
||||||
|
|
||||||
getWidget(mItemView, "ItemView");
|
getWidget(mItemView, "ItemView");
|
||||||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
|
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
|
||||||
|
@ -76,11 +76,12 @@ namespace MWGui
|
||||||
|
|
||||||
void InventoryWindow::adjustPanes()
|
void InventoryWindow::adjustPanes()
|
||||||
{
|
{
|
||||||
const float aspect = 0.5; // fixed aspect ratio for the left pane
|
const float aspect = 0.5; // fixed aspect ratio for the avatar image
|
||||||
mLeftPane->setSize( (mMainWidget->getSize().height-44) * aspect, mMainWidget->getSize().height-44 );
|
float leftPaneWidth = (mMainWidget->getSize().height-44-mArmorRating->getHeight()) * aspect;
|
||||||
mRightPane->setCoord( mLeftPane->getPosition().left + (mMainWidget->getSize().height-44) * aspect + 4,
|
mLeftPane->setSize( leftPaneWidth, mMainWidget->getSize().height-44 );
|
||||||
|
mRightPane->setCoord( mLeftPane->getPosition().left + leftPaneWidth + 4,
|
||||||
mRightPane->getPosition().top,
|
mRightPane->getPosition().top,
|
||||||
mMainWidget->getSize().width - 12 - (mMainWidget->getSize().height-44) * aspect - 15,
|
mMainWidget->getSize().width - 12 - leftPaneWidth - 15,
|
||||||
mMainWidget->getSize().height-44 );
|
mMainWidget->getSize().height-44 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,9 +419,9 @@ namespace MWGui
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MyGUI::IntPoint mousePos = MyGUI::InputManager::getInstance ().getLastPressedPosition (MyGUI::MouseButton::Left);
|
MyGUI::IntPoint mousePos = MyGUI::InputManager::getInstance ().getLastPressedPosition (MyGUI::MouseButton::Left);
|
||||||
MyGUI::IntPoint relPos = mousePos - mAvatar->getAbsolutePosition ();
|
MyGUI::IntPoint relPos = mousePos - mAvatarImage->getAbsolutePosition ();
|
||||||
int realX = int(float(relPos.left) / float(mAvatar->getSize().width) * 512.f );
|
int realX = int(float(relPos.left) / float(mAvatarImage->getSize().width) * 512.f );
|
||||||
int realY = int(float(relPos.top) / float(mAvatar->getSize().height) * 1024.f );
|
int realY = int(float(relPos.top) / float(mAvatarImage->getSize().height) * 1024.f );
|
||||||
|
|
||||||
MWWorld::Ptr itemSelected = getAvatarSelectedItem (realX, realY);
|
MWWorld::Ptr itemSelected = getAvatarSelectedItem (realX, realY);
|
||||||
if (itemSelected.isEmpty ())
|
if (itemSelected.isEmpty ())
|
||||||
|
@ -487,11 +488,18 @@ namespace MWGui
|
||||||
if (mPreviewDirty)
|
if (mPreviewDirty)
|
||||||
{
|
{
|
||||||
mPreviewDirty = false;
|
mPreviewDirty = false;
|
||||||
MyGUI::IntSize size = mAvatar->getSize();
|
MyGUI::IntSize size = mAvatarImage->getSize();
|
||||||
|
|
||||||
mPreview.update (size.width, size.height);
|
mPreview.update (size.width, size.height);
|
||||||
mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024)));
|
|
||||||
mAvatarImage->setImageTexture("CharacterPreview");
|
mAvatarImage->setImageTexture("CharacterPreview");
|
||||||
|
mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height)));
|
||||||
|
mAvatarImage->setImageTile(MyGUI::IntSize(std::min(512, size.width), std::min(1024, size.height)));
|
||||||
|
|
||||||
|
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
|
||||||
|
+ boost::lexical_cast<std::string>(static_cast<int>(MWWorld::Class::get(mPtr).getArmorRating(mPtr))));
|
||||||
|
if (mArmorRating->getTextSize().width > mArmorRating->getSize().width)
|
||||||
|
mArmorRating->setCaptionWithReplacing (boost::lexical_cast<std::string>(static_cast<int>(MWWorld::Class::get(mPtr).getArmorRating(mPtr))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,9 +510,6 @@ namespace MWGui
|
||||||
MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells();
|
MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells();
|
||||||
|
|
||||||
mPreviewDirty = true;
|
mPreviewDirty = true;
|
||||||
|
|
||||||
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
|
|
||||||
+ boost::lexical_cast<std::string>(static_cast<int>(MWWorld::Class::get(mPtr).getArmorRating(mPtr))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
|
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
|
||||||
|
@ -551,9 +556,4 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntCoord InventoryWindow::getAvatarScreenCoord ()
|
|
||||||
{
|
|
||||||
return mAvatar->getAbsoluteCoord ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ namespace MWGui
|
||||||
|
|
||||||
void pickUpObject (MWWorld::Ptr object);
|
void pickUpObject (MWWorld::Ptr object);
|
||||||
|
|
||||||
MyGUI::IntCoord getAvatarScreenCoord();
|
|
||||||
|
|
||||||
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
|
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
|
||||||
|
|
||||||
void rebuildAvatar() {
|
void rebuildAvatar() {
|
||||||
|
|
|
@ -196,34 +196,6 @@ book JournalBooks::createEmptyJournalBook ()
|
||||||
typesetter->lineBreak ();
|
typesetter->lineBreak ();
|
||||||
typesetter->write (body, to_utf8_span ("You should have gone though the starting quest and got an initial quest."));
|
typesetter->write (body, to_utf8_span ("You should have gone though the starting quest and got an initial quest."));
|
||||||
|
|
||||||
BookTypesetter::Style* big = typesetter->createStyle ("", MyGUI::Colour::Black);
|
|
||||||
BookTypesetter::Style* test = typesetter->createStyle ("MonoFont", MyGUI::Colour::Blue);
|
|
||||||
|
|
||||||
typesetter->sectionBreak (20);
|
|
||||||
typesetter->write (body, to_utf8_span (
|
|
||||||
"The layout engine doesn't currently support aligning fonts to "
|
|
||||||
"their baseline within a single line so the following text looks "
|
|
||||||
"funny. In order to properly implement it, a stupidly simple "
|
|
||||||
"change is needed in MyGUI to report the where the baseline is for "
|
|
||||||
"a particular font"
|
|
||||||
));
|
|
||||||
|
|
||||||
typesetter->sectionBreak (20);
|
|
||||||
typesetter->write (big, to_utf8_span ("big text g"));
|
|
||||||
typesetter->write (body, to_utf8_span (" проверяем только в дебаге"));
|
|
||||||
typesetter->write (body, to_utf8_span (" normal g"));
|
|
||||||
typesetter->write (big, to_utf8_span (" done g"));
|
|
||||||
|
|
||||||
typesetter->sectionBreak (20);
|
|
||||||
typesetter->write (test, to_utf8_span (
|
|
||||||
"int main (int argc,\n"
|
|
||||||
" char ** argv)\n"
|
|
||||||
"{\n"
|
|
||||||
" print (\"hello world!\\n\");\n"
|
|
||||||
" return 0;\n"
|
|
||||||
"}\n"
|
|
||||||
));
|
|
||||||
|
|
||||||
return typesetter->complete ();
|
return typesetter->complete ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@ namespace MWGui {
|
||||||
|
|
||||||
struct JournalViewModelImpl;
|
struct JournalViewModelImpl;
|
||||||
|
|
||||||
static void injectMonthName (std::ostream & os, int month);
|
|
||||||
|
|
||||||
struct JournalViewModelImpl : JournalViewModel
|
struct JournalViewModelImpl : JournalViewModel
|
||||||
{
|
{
|
||||||
typedef KeywordSearch <std::string, intptr_t> KeywordSearchT;
|
typedef KeywordSearch <std::string, intptr_t> KeywordSearchT;
|
||||||
|
@ -206,10 +204,12 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
if (active_only && i->second.isFinished ())
|
if (active_only && i->second.isFinished ())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/// \todo quest.getName() is broken? returns empty string
|
const MWDialogue::Quest& quest = i->second;
|
||||||
//const MWDialogue::Quest& quest = i->second;
|
// Unfortunately Morrowind.esm has no quest names, since the quest book was added with tribunal.
|
||||||
|
if (quest.getName().empty())
|
||||||
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (i->first));
|
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (i->first));
|
||||||
|
else
|
||||||
|
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (quest.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,21 +235,21 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
|
|
||||||
std::string getText () const
|
std::string getText () const
|
||||||
{
|
{
|
||||||
return itr->getText(MWBase::Environment::get().getWorld()->getStore());
|
return itr->getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
Utf8Span timestamp () const
|
Utf8Span timestamp () const
|
||||||
{
|
{
|
||||||
if (timestamp_buffer.empty ())
|
if (timestamp_buffer.empty ())
|
||||||
{
|
{
|
||||||
|
std::string dayStr = MyGUI::LanguageManager::getInstance().replaceTags("#{sDay}");
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
|
||||||
os << itr->mDayOfMonth << ' ';
|
os
|
||||||
|
<< itr->mDayOfMonth << ' '
|
||||||
injectMonthName (os, itr->mMonth);
|
<< MWBase::Environment::get().getWorld()->getMonthName (itr->mMonth)
|
||||||
|
<< " (" << dayStr << " " << (itr->mDay + 1) << ')';
|
||||||
const std::string& dayStr = MyGUI::LanguageManager::getInstance().replaceTags("#{sDay}");
|
|
||||||
os << " (" << dayStr << " " << (itr->mDay + 1) << ')';
|
|
||||||
|
|
||||||
timestamp_buffer = os.str ();
|
timestamp_buffer = os.str ();
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
{
|
{
|
||||||
for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j)
|
for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j)
|
||||||
{
|
{
|
||||||
if (i->mInfoId == *j)
|
if (i->mInfoId == j->mInfoId)
|
||||||
visitor (JournalEntryImpl <MWBase::Journal::TEntryIter> (this, i));
|
visitor (JournalEntryImpl <MWBase::Journal::TEntryIter> (this, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,9 +290,7 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const
|
void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const
|
||||||
{
|
{
|
||||||
MWDialogue::Topic const & topic = * reinterpret_cast <MWDialogue::Topic const *> (topicId);
|
MWDialogue::Topic const & topic = * reinterpret_cast <MWDialogue::Topic const *> (topicId);
|
||||||
// This is to get the correct case for the topic
|
visitor (toUtf8Span (topic.getName()));
|
||||||
const std::string& name = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find(topic.getName())->mId;
|
|
||||||
visitor (toUtf8Span (name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const
|
void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const
|
||||||
|
@ -304,10 +302,7 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
if (i->first [0] != std::tolower (character, mLocale))
|
if (i->first [0] != std::tolower (character, mLocale))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// This is to get the correct case for the topic
|
visitor (TopicId (&i->second), toUtf8Span (i->second.getName()));
|
||||||
const std::string& name = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find(i->first)->mId;
|
|
||||||
|
|
||||||
visitor (TopicId (&i->second), toUtf8Span (name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -316,24 +311,18 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
{
|
{
|
||||||
MWDialogue::Topic const & mTopic;
|
MWDialogue::Topic const & mTopic;
|
||||||
|
|
||||||
mutable std::string source_buffer;
|
|
||||||
|
|
||||||
TopicEntryImpl (JournalViewModelImpl const * model, MWDialogue::Topic const & topic, iterator_t itr) :
|
TopicEntryImpl (JournalViewModelImpl const * model, MWDialogue::Topic const & topic, iterator_t itr) :
|
||||||
BaseEntry (model, itr), mTopic (topic)
|
BaseEntry (model, itr), mTopic (topic)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string getText () const
|
std::string getText () const
|
||||||
{
|
{
|
||||||
/// \todo defines are not replaced (%PCName etc). should probably be done elsewhere though since we need the actor
|
return itr->getText();
|
||||||
return mTopic.getEntry (*itr).getText(MWBase::Environment::get().getWorld()->getStore());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Utf8Span source () const
|
Utf8Span source () const
|
||||||
{
|
{
|
||||||
if (source_buffer.empty ())
|
return toUtf8Span (itr->mActorName);
|
||||||
source_buffer = "someone";
|
|
||||||
return toUtf8Span (source_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -349,38 +338,6 @@ struct JournalViewModelImpl : JournalViewModel
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void injectMonthName (std::ostream & os, int month)
|
|
||||||
{
|
|
||||||
MyGUI::LanguageManager& lm = MyGUI::LanguageManager::getInstance();
|
|
||||||
|
|
||||||
if (month == 0)
|
|
||||||
os << lm.replaceTags ("#{sMonthMorningstar}");
|
|
||||||
else if (month == 1)
|
|
||||||
os << lm.replaceTags ("#{sMonthSunsdawn}");
|
|
||||||
else if (month == 2)
|
|
||||||
os << lm.replaceTags ("#{sMonthFirstseed}");
|
|
||||||
else if (month == 3)
|
|
||||||
os << lm.replaceTags ("#{sMonthRainshand}");
|
|
||||||
else if (month == 4)
|
|
||||||
os << lm.replaceTags ("#{sMonthSecondseed}");
|
|
||||||
else if (month == 5)
|
|
||||||
os << lm.replaceTags ("#{sMonthMidyear}");
|
|
||||||
else if (month == 6)
|
|
||||||
os << lm.replaceTags ("#{sMonthSunsheight}");
|
|
||||||
else if (month == 7)
|
|
||||||
os << lm.replaceTags ("#{sMonthLastseed}");
|
|
||||||
else if (month == 8)
|
|
||||||
os << lm.replaceTags ("#{sMonthHeartfire}");
|
|
||||||
else if (month == 9)
|
|
||||||
os << lm.replaceTags ("#{sMonthFrostfall}");
|
|
||||||
else if (month == 10)
|
|
||||||
os << lm.replaceTags ("#{sMonthSunsdusk}");
|
|
||||||
else if (month == 11)
|
|
||||||
os << lm.replaceTags ("#{sMonthEveningstar}");
|
|
||||||
else
|
|
||||||
os << month;
|
|
||||||
}
|
|
||||||
|
|
||||||
JournalViewModel::Ptr JournalViewModel::create ()
|
JournalViewModel::Ptr JournalViewModel::create ()
|
||||||
{
|
{
|
||||||
return boost::make_shared <JournalViewModelImpl> ();
|
return boost::make_shared <JournalViewModelImpl> ();
|
||||||
|
|
|
@ -155,7 +155,6 @@ namespace MWGui
|
||||||
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
|
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
|
|
||||||
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
|
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
|
||||||
|
|
||||||
if (mSpentAttributes.size() < 3)
|
if (mSpentAttributes.size() < 3)
|
||||||
|
@ -165,15 +164,14 @@ namespace MWGui
|
||||||
// increase attributes
|
// increase attributes
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
MWMechanics::AttributeValue attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
MWMechanics::AttributeValue attribute = pcStats.getAttribute(mSpentAttributes[i]);
|
||||||
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
||||||
|
|
||||||
if (attribute.getBase() >= 100)
|
if (attribute.getBase() >= 100)
|
||||||
attribute.setBase(100);
|
attribute.setBase(100);
|
||||||
creatureStats.setAttribute(mSpentAttributes[i], attribute);
|
pcStats.setAttribute(mSpentAttributes[i], attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
creatureStats.levelUp();
|
|
||||||
pcStats.levelUp ();
|
pcStats.levelUp ();
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Levelup);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Levelup);
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#include "mainmenu.hpp"
|
#include "mainmenu.hpp"
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/journal.hpp"
|
#include "../mwbase/journal.hpp"
|
||||||
#include "../mwbase/dialoguemanager.hpp"
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwstate/character.hpp"
|
||||||
|
|
||||||
#include "savegamedialog.hpp"
|
#include "savegamedialog.hpp"
|
||||||
|
|
||||||
|
@ -16,90 +17,132 @@ namespace MWGui
|
||||||
|
|
||||||
MainMenu::MainMenu(int w, int h)
|
MainMenu::MainMenu(int w, int h)
|
||||||
: OEngine::GUI::Layout("openmw_mainmenu.layout")
|
: OEngine::GUI::Layout("openmw_mainmenu.layout")
|
||||||
, mButtonBox(0)
|
, mButtonBox(0), mWidth (w), mHeight (h)
|
||||||
|
, mSaveGameDialog(NULL)
|
||||||
{
|
{
|
||||||
onResChange(w,h);
|
updateMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainMenu::~MainMenu()
|
||||||
|
{
|
||||||
|
delete mSaveGameDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainMenu::onResChange(int w, int h)
|
void MainMenu::onResChange(int w, int h)
|
||||||
{
|
{
|
||||||
setCoord(0,0,w,h);
|
mWidth = w;
|
||||||
|
mHeight = h;
|
||||||
|
|
||||||
|
updateMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainMenu::setVisible (bool visible)
|
||||||
|
{
|
||||||
|
if (visible)
|
||||||
|
updateMenu();
|
||||||
|
|
||||||
|
OEngine::GUI::Layout::setVisible (visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainMenu::onButtonClicked(MyGUI::Widget *sender)
|
||||||
|
{
|
||||||
|
std::string name = *sender->getUserData<std::string>();
|
||||||
|
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
|
||||||
|
if (name == "return")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
|
||||||
|
MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu);
|
||||||
|
}
|
||||||
|
else if (name == "options")
|
||||||
|
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
|
||||||
|
else if (name == "exitgame")
|
||||||
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||||
|
else if (name == "newgame")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getStateManager()->newGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!mSaveGameDialog)
|
||||||
|
mSaveGameDialog = new SaveGameDialog();
|
||||||
|
if (name == "loadgame")
|
||||||
|
mSaveGameDialog->setLoadOrSave(true);
|
||||||
|
else if (name == "savegame")
|
||||||
|
mSaveGameDialog->setLoadOrSave(false);
|
||||||
|
mSaveGameDialog->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainMenu::updateMenu()
|
||||||
|
{
|
||||||
|
setCoord(0,0, mWidth, mHeight);
|
||||||
|
|
||||||
|
|
||||||
if (mButtonBox)
|
if (!mButtonBox)
|
||||||
MyGUI::Gui::getInstance ().destroyWidget(mButtonBox);
|
|
||||||
|
|
||||||
mButtonBox = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
|
mButtonBox = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
|
||||||
|
|
||||||
int curH = 0;
|
int curH = 0;
|
||||||
|
|
||||||
|
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
|
||||||
|
|
||||||
std::vector<std::string> buttons;
|
std::vector<std::string> buttons;
|
||||||
|
|
||||||
|
if (state==MWBase::StateManager::State_Running)
|
||||||
buttons.push_back("return");
|
buttons.push_back("return");
|
||||||
|
|
||||||
buttons.push_back("newgame");
|
buttons.push_back("newgame");
|
||||||
//buttons.push_back("loadgame");
|
|
||||||
//buttons.push_back("savegame");
|
if (MWBase::Environment::get().getStateManager()->characterBegin()!=
|
||||||
|
MWBase::Environment::get().getStateManager()->characterEnd())
|
||||||
|
buttons.push_back("loadgame");
|
||||||
|
|
||||||
|
if (state==MWBase::StateManager::State_Running &&
|
||||||
|
MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1)
|
||||||
|
buttons.push_back("savegame");
|
||||||
|
|
||||||
buttons.push_back("options");
|
buttons.push_back("options");
|
||||||
//buttons.push_back("credits");
|
//buttons.push_back("credits");
|
||||||
buttons.push_back("exitgame");
|
buttons.push_back("exitgame");
|
||||||
|
|
||||||
int maxwidth = 0;
|
// Create new buttons if needed
|
||||||
|
|
||||||
mButtons.clear();
|
|
||||||
for (std::vector<std::string>::iterator it = buttons.begin(); it != buttons.end(); ++it)
|
for (std::vector<std::string>::iterator it = buttons.begin(); it != buttons.end(); ++it)
|
||||||
|
{
|
||||||
|
if (mButtons.find(*it) == mButtons.end())
|
||||||
{
|
{
|
||||||
MWGui::ImageButton* button = mButtonBox->createWidget<MWGui::ImageButton>
|
MWGui::ImageButton* button = mButtonBox->createWidget<MWGui::ImageButton>
|
||||||
("ImageBox", MyGUI::IntCoord(0, curH, 0, 0), MyGUI::Align::Default);
|
("ImageBox", MyGUI::IntCoord(0, curH, 0, 0), MyGUI::Align::Default);
|
||||||
button->setProperty("ImageHighlighted", "textures\\menu_" + *it + "_over.dds");
|
button->setProperty("ImageHighlighted", "textures\\menu_" + *it + "_over.dds");
|
||||||
button->setProperty("ImageNormal", "textures\\menu_" + *it + ".dds");
|
button->setProperty("ImageNormal", "textures\\menu_" + *it + ".dds");
|
||||||
button->setProperty("ImagePushed", "textures\\menu_" + *it + "_pressed.dds");
|
button->setProperty("ImagePushed", "textures\\menu_" + *it + "_pressed.dds");
|
||||||
MyGUI::IntSize requested = button->getRequestedSize();
|
|
||||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::onButtonClicked);
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::onButtonClicked);
|
||||||
|
button->setUserData(std::string(*it));
|
||||||
mButtons[*it] = button;
|
mButtons[*it] = button;
|
||||||
curH += requested.height;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start by hiding all buttons
|
||||||
|
int maxwidth = 0;
|
||||||
|
for (std::map<std::string, MWGui::ImageButton*>::iterator it = mButtons.begin(); it != mButtons.end(); ++it)
|
||||||
|
{
|
||||||
|
it->second->setVisible(false);
|
||||||
|
MyGUI::IntSize requested = it->second->getRequestedSize();
|
||||||
if (requested.width > maxwidth)
|
if (requested.width > maxwidth)
|
||||||
maxwidth = requested.width;
|
maxwidth = requested.width;
|
||||||
}
|
}
|
||||||
for (std::map<std::string, MWGui::ImageButton*>::iterator it = mButtons.begin(); it != mButtons.end(); ++it)
|
|
||||||
|
// Now show and position the ones we want
|
||||||
|
for (std::vector<std::string>::iterator it = buttons.begin(); it != buttons.end(); ++it)
|
||||||
{
|
{
|
||||||
MyGUI::IntSize requested = it->second->getRequestedSize();
|
assert(mButtons.find(*it) != mButtons.end());
|
||||||
it->second->setCoord((maxwidth-requested.width) / 2, it->second->getTop(), requested.width, requested.height);
|
MWGui::ImageButton* button = mButtons[*it];
|
||||||
|
button->setVisible(true);
|
||||||
|
MyGUI::IntSize requested = button->getRequestedSize();
|
||||||
|
button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, requested.height);
|
||||||
|
curH += requested.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
mButtonBox->setCoord (w/2 - maxwidth/2, h/2 - curH/2, maxwidth, curH);
|
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH);
|
||||||
}
|
|
||||||
|
|
||||||
void MainMenu::onButtonClicked(MyGUI::Widget *sender)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
|
|
||||||
if (sender == mButtons["return"])
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
|
|
||||||
MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu);
|
|
||||||
}
|
|
||||||
else if (sender == mButtons["options"])
|
|
||||||
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
|
|
||||||
else if (sender == mButtons["exitgame"])
|
|
||||||
MWBase::Environment::get().setRequestExit();
|
|
||||||
else if (sender == mButtons["newgame"])
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->startNewGame();
|
|
||||||
MWBase::Environment::get().getWindowManager()->setNewGame(true);
|
|
||||||
MWBase::Environment::get().getDialogueManager()->clear();
|
|
||||||
MWBase::Environment::get().getJournal()->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (sender == mButtons["loadgame"])
|
|
||||||
{
|
|
||||||
MWGui::SaveGameDialog* dialog = new MWGui::SaveGameDialog();
|
|
||||||
dialog->setLoadOrSave(true);
|
|
||||||
dialog->setVisible(true);
|
|
||||||
}
|
|
||||||
else if (sender == mButtons["savegame"])
|
|
||||||
{
|
|
||||||
MWGui::SaveGameDialog* dialog = new MWGui::SaveGameDialog();
|
|
||||||
dialog->setLoadOrSave(false);
|
|
||||||
dialog->setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,19 +5,33 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class SaveGameDialog;
|
||||||
|
|
||||||
class MainMenu : public OEngine::GUI::Layout
|
class MainMenu : public OEngine::GUI::Layout
|
||||||
{
|
{
|
||||||
|
int mWidth;
|
||||||
|
int mHeight;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MainMenu(int w, int h);
|
MainMenu(int w, int h);
|
||||||
|
~MainMenu();
|
||||||
|
|
||||||
void onResChange(int w, int h);
|
void onResChange(int w, int h);
|
||||||
|
|
||||||
|
virtual void setVisible (bool visible);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MyGUI::Widget* mButtonBox;
|
MyGUI::Widget* mButtonBox;
|
||||||
|
|
||||||
std::map<std::string, MWGui::ImageButton*> mButtons;
|
std::map<std::string, MWGui::ImageButton*> mButtons;
|
||||||
|
|
||||||
void onButtonClicked (MyGUI::Widget* sender);
|
void onButtonClicked (MyGUI::Widget* sender);
|
||||||
|
|
||||||
|
void updateMenu();
|
||||||
|
|
||||||
|
SaveGameDialog* mSaveGameDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,8 +373,9 @@ namespace MWGui
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
MapWindow::MapWindow(const std::string& cacheDir)
|
MapWindow::MapWindow(DragAndDrop* drag, const std::string& cacheDir)
|
||||||
: MWGui::WindowPinnableBase("openmw_map_window.layout")
|
: WindowPinnableBase("openmw_map_window.layout")
|
||||||
|
, NoDrop(drag, mMainWidget)
|
||||||
, mGlobal(false)
|
, mGlobal(false)
|
||||||
, mGlobalMap(0)
|
, mGlobalMap(0)
|
||||||
, mGlobalMapRender(0)
|
, mGlobalMapRender(0)
|
||||||
|
@ -434,7 +435,7 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
static int _counter=0;
|
static int _counter=0;
|
||||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
|
||||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||||
markerWidget->setImageResource("DoorMarker");
|
markerWidget->setImageResource("DoorMarker");
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
|
@ -499,10 +500,11 @@ namespace MWGui
|
||||||
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||||
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
|
||||||
|
|
||||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
// force markers to foreground
|
||||||
|
for (unsigned int i=0; i<mGlobalMapOverlay->getChildCount (); ++i)
|
||||||
{
|
{
|
||||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
|
if (mGlobalMapOverlay->getChildAt (i)->getName().substr(0,4) == "Door")
|
||||||
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
mGlobalMapOverlay->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||||
}
|
}
|
||||||
|
|
||||||
globalMapUpdatePlayer();
|
globalMapUpdatePlayer();
|
||||||
|
@ -573,4 +575,31 @@ namespace MWGui
|
||||||
mGlobalMap->setViewOffset(viewoffs);
|
mGlobalMap->setViewOffset(viewoffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapWindow::clear()
|
||||||
|
{
|
||||||
|
mGlobalMapRender->clear();
|
||||||
|
|
||||||
|
while (mEventBoxGlobal->getChildCount())
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget(mEventBoxGlobal->getChildAt(0));
|
||||||
|
while (mGlobalMapOverlay->getChildCount())
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::write(ESM::ESMWriter &writer)
|
||||||
|
{
|
||||||
|
mGlobalMapRender->write(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<int, int> > exploredCells;
|
||||||
|
mGlobalMapRender->readRecord(reader, type, exploredCells);
|
||||||
|
|
||||||
|
for (std::vector<std::pair<int, int> >::iterator it = exploredCells.begin(); it != exploredCells.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
|
||||||
|
if (cell && !cell->mName.empty())
|
||||||
|
addVisitedLocation(cell->mName, it->first, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef MWGUI_MAPWINDOW_H
|
#ifndef MWGUI_MAPWINDOW_H
|
||||||
#define MWGUI_MAPWINDOW_H
|
#define MWGUI_MAPWINDOW_H
|
||||||
|
|
||||||
|
#include <libs/platform/stdint.h>
|
||||||
|
|
||||||
#include "windowpinnablebase.hpp"
|
#include "windowpinnablebase.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -8,6 +10,12 @@ namespace MWRender
|
||||||
class GlobalMap;
|
class GlobalMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
{
|
{
|
||||||
class Listener;
|
class Listener;
|
||||||
|
@ -75,10 +83,10 @@ namespace MWGui
|
||||||
float mLastDirectionY;
|
float mLastDirectionY;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase
|
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapWindow(const std::string& cacheDir);
|
MapWindow(DragAndDrop* drag, const std::string& cacheDir);
|
||||||
virtual ~MapWindow();
|
virtual ~MapWindow();
|
||||||
|
|
||||||
void setCellName(const std::string& cellName);
|
void setCellName(const std::string& cellName);
|
||||||
|
@ -92,6 +100,14 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void open();
|
virtual void open();
|
||||||
|
|
||||||
|
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
||||||
|
|
||||||
|
/// Clear all savegame-specific data
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void write (ESM::ESMWriter& writer);
|
||||||
|
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||||
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||||
|
|
|
@ -245,11 +245,11 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
MyGUI::IntPoint absPos;
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
mMainWidget->setPosition(absPos);
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
|
@ -287,24 +287,6 @@ namespace MWGui
|
||||||
else {
|
else {
|
||||||
mainWidgetSize.width = textSize.width + 3*textPadding;
|
mainWidgetSize.width = textSize.width + 3*textPadding;
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
|
|
||||||
|
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
|
||||||
|
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
|
||||||
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
|
||||||
messageWidgetCoord.top = textPadding;
|
|
||||||
mMessageWidget->setCoord(messageWidgetCoord);
|
|
||||||
|
|
||||||
mMessageWidget->setSize(textSize);
|
|
||||||
|
|
||||||
MyGUI::IntCoord buttonCord;
|
MyGUI::IntCoord buttonCord;
|
||||||
MyGUI::IntSize buttonSize(0, buttonHeight);
|
MyGUI::IntSize buttonSize(0, buttonHeight);
|
||||||
|
@ -326,6 +308,21 @@ namespace MWGui
|
||||||
top += buttonSize.height + 2*buttonTopPadding;
|
top += buttonSize.height + 2*buttonTopPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainWidgetSize.height = top + buttonMainPadding;
|
||||||
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
|
MyGUI::IntPoint absPos;
|
||||||
|
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
|
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
|
mMainWidget->setPosition(absPos);
|
||||||
|
|
||||||
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
|
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
||||||
|
messageWidgetCoord.top = textPadding;
|
||||||
|
messageWidgetCoord.width = textSize.width;
|
||||||
|
messageWidgetCoord.height = textSize.height;
|
||||||
|
mMessageWidget->setCoord(messageWidgetCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set key focus to "Ok" button
|
// Set key focus to "Ok" button
|
||||||
|
@ -335,7 +332,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok))
|
if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok))
|
||||||
{
|
{
|
||||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(*button);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(*button);
|
||||||
(*button)->eventKeyButtonPressed += MyGUI::newDelegate(this, &InteractiveMessageBox::onKeyPressed);
|
(*button)->eventKeyButtonPressed += MyGUI::newDelegate(this, &InteractiveMessageBox::onKeyPressed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,15 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/actionequip.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/spells.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "../mwgui/inventorywindow.hpp"
|
#include "../mwgui/inventorywindow.hpp"
|
||||||
#include "../mwgui/bookwindow.hpp"
|
#include "../mwgui/bookwindow.hpp"
|
||||||
#include "../mwgui/scrollwindow.hpp"
|
#include "../mwgui/scrollwindow.hpp"
|
||||||
|
@ -17,8 +24,8 @@ namespace
|
||||||
{
|
{
|
||||||
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
|
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
|
||||||
{
|
{
|
||||||
int cmp = MWWorld::Class::get(left).getName(left).compare(
|
int cmp = left.getClass().getName(left).compare(
|
||||||
MWWorld::Class::get(right).getName(right));
|
right.getClass().getName(right));
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,10 +341,7 @@ namespace MWGui
|
||||||
// equip, if it can be equipped
|
// equip, if it can be equipped
|
||||||
if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
||||||
{
|
{
|
||||||
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
|
||||||
|
|
||||||
MWWorld::ActionEquip action(item);
|
|
||||||
action.execute (MWBase::Environment::get().getWorld ()->getPlayerPtr());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
store.setSelectedEnchantItem(it);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue