mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:49:58 +00:00
Merge pull request #79 from OpenMW/master while resolving conflicts
# Conflicts: # .travis.yml # apps/openmw/mwinput/inputmanagerimp.cpp
This commit is contained in:
commit
47ebd24b4a
43 changed files with 477 additions and 159 deletions
|
@ -1,7 +1,7 @@
|
|||
os:
|
||||
- linux
|
||||
# - osx
|
||||
#osx_image: xcode7.2
|
||||
osx_image: xcode7.2
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
|
|
@ -271,23 +271,34 @@ private:
|
|||
class ConvertPCDT : public Converter
|
||||
{
|
||||
public:
|
||||
ConvertPCDT() : mFirstPersonCam(true) {}
|
||||
ConvertPCDT()
|
||||
: mFirstPersonCam(true),
|
||||
mTeleportingEnabled(true),
|
||||
mLevitationEnabled(true)
|
||||
{}
|
||||
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
PCDT pcdt;
|
||||
pcdt.load(esm);
|
||||
|
||||
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam);
|
||||
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam, mTeleportingEnabled, mLevitationEnabled, mContext->mControlsState);
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
esm.startRecord(ESM::REC_ENAB);
|
||||
esm.writeHNT("TELE", mTeleportingEnabled);
|
||||
esm.writeHNT("LEVT", mLevitationEnabled);
|
||||
esm.endRecord(ESM::REC_ENAB);
|
||||
|
||||
esm.startRecord(ESM::REC_CAM_);
|
||||
esm.writeHNT("FIRS", mFirstPersonCam);
|
||||
esm.endRecord(ESM::REC_CAM_);
|
||||
}
|
||||
private:
|
||||
bool mFirstPersonCam;
|
||||
bool mTeleportingEnabled;
|
||||
bool mLevitationEnabled;
|
||||
};
|
||||
|
||||
class ConvertCNTC : public Converter
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam)
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
|
||||
{
|
||||
out.mBirthsign = pcdt.mBirthsign;
|
||||
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||
|
@ -25,18 +25,28 @@ namespace ESSImport
|
|||
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||
if (pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_WeaponDrawn)
|
||||
out.mObject.mCreatureStats.mDrawState = 1;
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Spell)
|
||||
if (pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_SpellDrawn)
|
||||
out.mObject.mCreatureStats.mDrawState = 2;
|
||||
|
||||
firstPersonCam = !(pcdt.mPNAM.mCameraFlags & PCDT::CameraFlag_ThirdPerson);
|
||||
firstPersonCam = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ThirdPerson);
|
||||
teleportingEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_TeleportingDisabled);
|
||||
levitationEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_LevitationDisabled);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
|
||||
it != pcdt.mKnownDialogueTopics.end(); ++it)
|
||||
{
|
||||
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(*it));
|
||||
}
|
||||
|
||||
controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;
|
||||
controls.mControlsDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ControlsDisabled;
|
||||
controls.mJumpingDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_JumpingDisabled;
|
||||
controls.mLookingDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_LookingDisabled;
|
||||
controls.mVanityModeDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_VanityModeDisabled;
|
||||
controls.mWeaponDrawingDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_WeaponDrawingDisabled;
|
||||
controls.mSpellDrawingDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_SpellDrawingDisabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
#include "importplayer.hpp"
|
||||
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm/controlsstate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam);
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -422,6 +422,10 @@ namespace ESSImport
|
|||
writer.startRecord (ESM::REC_DIAS);
|
||||
context.mDialogueState.save(writer);
|
||||
writer.endRecord(ESM::REC_DIAS);
|
||||
|
||||
writer.startRecord(ESM::REC_INPU);
|
||||
context.mControlsState.save(writer);
|
||||
writer.endRecord(ESM::REC_INPU);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/esm/globalmap.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/controlsstate.hpp>
|
||||
|
||||
#include "importnpcc.hpp"
|
||||
#include "importcrec.hpp"
|
||||
|
@ -32,6 +33,8 @@ namespace ESSImport
|
|||
|
||||
ESM::DialogueState mDialogueState;
|
||||
|
||||
ESM::ControlsState mControlsState;
|
||||
|
||||
// cells which should show an explored overlay on the global map
|
||||
std::set<std::pair<int, int> > mExploredCells;
|
||||
|
||||
|
|
|
@ -38,14 +38,20 @@ struct PCDT
|
|||
|
||||
std::vector<std::string> mKnownDialogueTopics;
|
||||
|
||||
enum DrawState_
|
||||
enum PlayerFlags
|
||||
{
|
||||
DrawState_Weapon = 0x80,
|
||||
DrawState_Spell = 0x100
|
||||
};
|
||||
enum CameraFlags
|
||||
{
|
||||
CameraFlag_ThirdPerson = 0x2
|
||||
PlayerFlags_ViewSwitchDisabled = 0x1,
|
||||
PlayerFlags_ControlsDisabled = 0x4,
|
||||
PlayerFlags_WeaponDrawn = 0x80,
|
||||
PlayerFlags_SpellDrawn = 0x100,
|
||||
PlayerFlags_JumpingDisabled = 0x1000,
|
||||
PlayerFlags_LookingDisabled = 0x2000,
|
||||
PlayerFlags_VanityModeDisabled = 0x4000,
|
||||
PlayerFlags_WeaponDrawingDisabled = 0x8000,
|
||||
PlayerFlags_SpellDrawingDisabled = 0x10000,
|
||||
PlayerFlags_ThirdPerson = 0x20000,
|
||||
PlayerFlags_TeleportingDisabled = 0x40000,
|
||||
PlayerFlags_LevitationDisabled = 0x80000
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
|
@ -62,8 +68,7 @@ struct PCDT
|
|||
|
||||
struct PNAM
|
||||
{
|
||||
short mDrawState; // DrawState
|
||||
short mCameraFlags; // CameraFlags
|
||||
int mPlayerFlags; // controls, camera and draw state
|
||||
unsigned int mLevelProgress;
|
||||
float mSkillProgress[27]; // skill progress, non-uniform scaled
|
||||
unsigned char mSkillIncreases[8]; // number of skill increases for each attribute
|
||||
|
|
|
@ -73,11 +73,11 @@ void CSMDoc::Loader::load()
|
|||
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||
|
||||
{ // silence a g++ warning
|
||||
for (CSMDoc::Messages::Iterator iter (messages.begin());
|
||||
iter!=messages.end(); ++iter)
|
||||
for (CSMDoc::Messages::Iterator messageIter (messages.begin());
|
||||
messageIter!=messages.end(); ++messageIter)
|
||||
{
|
||||
document->getReport (log)->add (*iter);
|
||||
emit loadMessage (document, iter->mMessage);
|
||||
document->getReport (log)->add (*messageIter);
|
||||
emit loadMessage (document, messageIter->mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseNAry (const Token& ke
|
|||
|
||||
nodes.push_back (node);
|
||||
|
||||
Token token = getNextToken();
|
||||
token = getNextToken();
|
||||
|
||||
if (!token || (token.mType!=Token::Type_Close && token.mType!=Token::Type_Comma))
|
||||
{
|
||||
|
|
|
@ -19,8 +19,6 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
|
|||
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||
(base ? record2.mBase : record2.mModified) = record;
|
||||
|
||||
int index = -1;
|
||||
|
||||
std::string topic = Misc::StringUtils::lowerCase (record2.get().mTopicId);
|
||||
|
||||
if (!record2.get().mPrev.empty())
|
||||
|
|
|
@ -25,12 +25,12 @@ CSMWorld::Resources::Resources (const VFS::Manager* vfs, const std::string& base
|
|||
|
||||
if (extensions)
|
||||
{
|
||||
std::string::size_type index = filepath.find_last_of ('.');
|
||||
std::string::size_type extensionIndex = filepath.find_last_of ('.');
|
||||
|
||||
if (index==std::string::npos)
|
||||
if (extensionIndex==std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string extension = filepath.substr (index+1);
|
||||
std::string extension = filepath.substr (extensionIndex+1);
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
|
|||
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||
return;
|
||||
|
||||
std::vector<CSMWorld::UniversalId> data = mime->getData();
|
||||
std::vector<CSMWorld::UniversalId> universalIdData = mime->getData();
|
||||
|
||||
emit recordDropped(data, event->proposedAction());
|
||||
emit recordDropped(universalIdData, event->proposedAction());
|
||||
}
|
||||
|
||||
void CSVFilter::FilterBox::dragEnterEvent (QDragEnterEvent* event)
|
||||
|
|
|
@ -219,12 +219,12 @@ bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft,
|
|||
}
|
||||
|
||||
// add new objects
|
||||
for (std::map<std::string, bool>::iterator iter (ids.begin()); iter!=ids.end(); ++iter)
|
||||
for (std::map<std::string, bool>::iterator mapIter (ids.begin()); mapIter!=ids.end(); ++mapIter)
|
||||
{
|
||||
if (!iter->second)
|
||||
if (!mapIter->second)
|
||||
{
|
||||
mObjects.insert (std::make_pair (
|
||||
iter->first, new Object (mData, mCellNode, iter->first, false)));
|
||||
mapIter->first, new Object (mData, mCellNode, mapIter->first, false)));
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
|
|
@ -259,8 +259,8 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
|||
mDragMode = DragMode_Scale;
|
||||
|
||||
// Calculate scale factor
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
osg::Vec3f center = getScreenCoords(getSelectionCenter(selection));
|
||||
std::vector<osg::ref_ptr<TagBase> > editedSelection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection));
|
||||
|
||||
int widgetHeight = getWorldspaceWidget().height();
|
||||
|
||||
|
|
|
@ -558,18 +558,18 @@ std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (co
|
|||
}
|
||||
|
||||
bool CSVRender::PagedWorldspaceWidget::handleDrop (
|
||||
const std::vector< CSMWorld::UniversalId >& data, DropType type)
|
||||
const std::vector< CSMWorld::UniversalId >& universalIdData, DropType type)
|
||||
{
|
||||
if (WorldspaceWidget::handleDrop (data, type))
|
||||
if (WorldspaceWidget::handleDrop (universalIdData, type))
|
||||
return true;
|
||||
|
||||
if (type!=Type_CellsExterior)
|
||||
return false;
|
||||
|
||||
bool selectionChanged = false;
|
||||
for (unsigned i = 0; i < data.size(); ++i)
|
||||
for (unsigned i = 0; i < universalIdData.size(); ++i)
|
||||
{
|
||||
std::pair<int, int> coordinates(getCoordinatesFromId(data[i].getId()));
|
||||
std::pair<int, int> coordinates(getCoordinatesFromId(universalIdData[i].getId()));
|
||||
if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second)))
|
||||
{
|
||||
selectionChanged = true;
|
||||
|
|
|
@ -80,20 +80,20 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
|
|||
emit closeRequest();
|
||||
}
|
||||
|
||||
bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data, DropType type)
|
||||
bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& universalIdData, DropType type)
|
||||
{
|
||||
if (WorldspaceWidget::handleDrop (data, type))
|
||||
if (WorldspaceWidget::handleDrop (universalIdData, type))
|
||||
return true;
|
||||
|
||||
if (type!=Type_CellsInterior)
|
||||
return false;
|
||||
|
||||
mCellId = data.begin()->getId();
|
||||
mCellId = universalIdData.begin()->getId();
|
||||
|
||||
mCell.reset (new Cell (getDocument().getData(), mRootNode, mCellId));
|
||||
|
||||
update();
|
||||
emit cellChanged(*data.begin());
|
||||
emit cellChanged(*universalIdData.begin());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -303,15 +303,15 @@ CSVRender::WorldspaceWidget::dropRequirments
|
|||
return ignored;
|
||||
}
|
||||
|
||||
bool CSVRender::WorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data,
|
||||
bool CSVRender::WorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& universalIdData,
|
||||
DropType type)
|
||||
{
|
||||
if (type==Type_DebugProfile)
|
||||
{
|
||||
if (mRun)
|
||||
{
|
||||
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (data.begin());
|
||||
iter!=data.end(); ++iter)
|
||||
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (universalIdData.begin());
|
||||
iter!=universalIdData.end(); ++iter)
|
||||
mRun->addProfile (iter->getId());
|
||||
}
|
||||
|
||||
|
@ -402,9 +402,9 @@ CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick (const QPo
|
|||
continue;
|
||||
}
|
||||
|
||||
for (std::vector<osg::Node*>::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it)
|
||||
for (std::vector<osg::Node*>::iterator nodeIter = intersection.nodePath.begin(); nodeIter != intersection.nodePath.end(); ++nodeIter)
|
||||
{
|
||||
osg::Node* node = *it;
|
||||
osg::Node* node = *nodeIter;
|
||||
if (osg::ref_ptr<CSVRender::TagBase> tag = dynamic_cast<CSVRender::TagBase *>(node->getUserData()))
|
||||
{
|
||||
WorldspaceHitResult hit = { true, tag, 0, 0, 0, intersection.getWorldIntersectPoint() };
|
||||
|
|
|
@ -658,8 +658,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
int displayRole = tree->nestedHeaderData (i, col,
|
||||
Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt();
|
||||
|
||||
CSMWorld::ColumnBase::Display display =
|
||||
static_cast<CSMWorld::ColumnBase::Display> (displayRole);
|
||||
display = static_cast<CSMWorld::ColumnBase::Display> (displayRole);
|
||||
|
||||
mNestedTableDispatcher->makeDelegate (display);
|
||||
|
||||
|
|
|
@ -67,8 +67,8 @@ void CSVWorld::DragRecordTable::dropEvent(QDropEvent *event)
|
|||
CSMWorld::ColumnBase::Display display = getIndexDisplayType(index);
|
||||
if (CSVWorld::DragDropUtils::canAcceptData(*event, display))
|
||||
{
|
||||
const CSMWorld::TableMimeData *data = CSVWorld::DragDropUtils::getTableMimeData(*event);
|
||||
if (data->fromDocument(mDocument))
|
||||
const CSMWorld::TableMimeData *tableMimeData = CSVWorld::DragDropUtils::getTableMimeData(*event);
|
||||
if (tableMimeData->fromDocument(mDocument))
|
||||
{
|
||||
CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, display);
|
||||
QVariant newIndexData = QString::fromUtf8(id.getId().c_str());
|
||||
|
|
|
@ -26,10 +26,10 @@ CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUnd
|
|||
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
|
||||
iter!=types.end(); ++iter)
|
||||
{
|
||||
CSMWorld::UniversalId id (*iter, "");
|
||||
CSMWorld::UniversalId id2 (*iter, "");
|
||||
|
||||
mType->addItem (QIcon (id.getIcon().c_str()), id.getTypeName().c_str(),
|
||||
static_cast<int> (id.getType()));
|
||||
mType->addItem (QIcon (id2.getIcon().c_str()), id2.getTypeName().c_str(),
|
||||
static_cast<int> (id2.getType()));
|
||||
}
|
||||
|
||||
insertBeforeButtons (mType, false);
|
||||
|
|
|
@ -187,18 +187,18 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection
|
|||
emit updateTitle();
|
||||
}
|
||||
|
||||
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& universalIdData)
|
||||
{
|
||||
CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL;
|
||||
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
|
||||
CSVWidget::SceneToolbar* toolbar = NULL;
|
||||
|
||||
CSVRender::WorldspaceWidget::DropType type = CSVRender::WorldspaceWidget::getDropType (data);
|
||||
CSVRender::WorldspaceWidget::DropType type = CSVRender::WorldspaceWidget::getDropType (universalIdData);
|
||||
|
||||
switch (mScene->getDropRequirements (type))
|
||||
{
|
||||
case CSVRender::WorldspaceWidget::canHandle:
|
||||
mScene->handleDrop (data, type);
|
||||
mScene->handleDrop (universalIdData, type);
|
||||
break;
|
||||
|
||||
case CSVRender::WorldspaceWidget::needPaged:
|
||||
|
@ -206,15 +206,15 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI
|
|||
toolbar = makeToolbar(pagedNewWidget, widget_Paged);
|
||||
makeConnections(pagedNewWidget);
|
||||
replaceToolbarAndWorldspace(pagedNewWidget, toolbar);
|
||||
mScene->handleDrop (data, type);
|
||||
mScene->handleDrop (universalIdData, type);
|
||||
break;
|
||||
|
||||
case CSVRender::WorldspaceWidget::needUnpaged:
|
||||
unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this);
|
||||
unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(universalIdData.begin()->getId(), mDocument, this);
|
||||
toolbar = makeToolbar(unPagedNewWidget, widget_Unpaged);
|
||||
makeConnections(unPagedNewWidget);
|
||||
replaceToolbarAndWorldspace(unPagedNewWidget, toolbar);
|
||||
cellSelectionChanged(*(data.begin()));
|
||||
cellSelectionChanged(*(universalIdData.begin()));
|
||||
break;
|
||||
|
||||
case CSVRender::WorldspaceWidget::ignored:
|
||||
|
|
|
@ -148,14 +148,14 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
|
|||
{
|
||||
if (QDropEvent* drop = dynamic_cast<QDropEvent*>(event))
|
||||
{
|
||||
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
|
||||
if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||
const CSMWorld::TableMimeData* tableMimeData = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
|
||||
if (!tableMimeData) // May happen when non-records (e.g. plain text) are dragged and dropped
|
||||
return false;
|
||||
|
||||
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
|
||||
bool handled = tableMimeData->holdsType(CSMWorld::UniversalId::Type_Filter);
|
||||
if (handled)
|
||||
{
|
||||
mFilterBox->setRecordFilter(data->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
|
||||
mFilterBox->setRecordFilter(tableMimeData->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,19 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
/// \brief Interface for input manager (implemented in MWInput)
|
||||
|
@ -56,6 +69,10 @@ namespace MWBase
|
|||
/// Returns if the last used input device was a joystick or a keyboard
|
||||
/// @return true if joystick, false otherwise
|
||||
virtual bool joystickLastUsed() = 0;
|
||||
|
||||
virtual int countSavedGameRecords() const = 0;
|
||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -187,12 +187,12 @@ namespace MWDialogue
|
|||
state.save (writer);
|
||||
writer.endRecord (ESM::REC_QUES);
|
||||
|
||||
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
|
||||
for (Topic::TEntryIter entryIter (quest.begin()); entryIter!=quest.end(); ++entryIter)
|
||||
{
|
||||
ESM::JournalEntry entry;
|
||||
entry.mType = ESM::JournalEntry::Type_Quest;
|
||||
entry.mTopic = quest.getTopic();
|
||||
iter->write (entry);
|
||||
entryIter->write (entry);
|
||||
writer.startRecord (ESM::REC_JOUR);
|
||||
entry.save (writer);
|
||||
writer.endRecord (ESM::REC_JOUR);
|
||||
|
@ -213,12 +213,12 @@ namespace MWDialogue
|
|||
{
|
||||
const Topic& topic = iter->second;
|
||||
|
||||
for (Topic::TEntryIter iter (topic.begin()); iter!=topic.end(); ++iter)
|
||||
for (Topic::TEntryIter entryIter (topic.begin()); entryIter!=topic.end(); ++entryIter)
|
||||
{
|
||||
ESM::JournalEntry entry;
|
||||
entry.mType = ESM::JournalEntry::Type_Topic;
|
||||
entry.mTopic = topic.getTopic();
|
||||
iter->write (entry);
|
||||
entryIter->write (entry);
|
||||
writer.startRecord (ESM::REC_JOUR);
|
||||
entry.save (writer);
|
||||
writer.endRecord (ESM::REC_JOUR);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <LinearMath/btQuickprof.h>
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
|
||||
namespace
|
||||
{
|
||||
void bulletDumpRecursive(CProfileIterator* pit, int spacing, std::stringstream& os)
|
||||
|
@ -71,6 +73,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
#endif // BT_NO_PROFILE
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -92,10 +95,13 @@ namespace MWGui
|
|||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
mMainWidget->setSize(viewSize);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DebugWindow::onFrame(float dt)
|
||||
{
|
||||
#ifndef BT_NO_PROFILE
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
|
@ -115,6 +121,7 @@ namespace MWGui
|
|||
size_t previousPos = mBulletProfilerEdit->getVScrollPosition();
|
||||
mBulletProfilerEdit->setCaption(stream.str());
|
||||
mBulletProfilerEdit->setVScrollPosition(std::min(previousPos, mBulletProfilerEdit->getVScrollRange()-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,13 @@
|
|||
|
||||
#include <components/sdlutil/sdlinputwrapper.hpp>
|
||||
#include <components/sdlutil/sdlvideowrapper.hpp>
|
||||
|
||||
#include <apps/openmw/mwmp/Main.hpp>
|
||||
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/controlsstate.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
@ -1576,6 +1581,44 @@ namespace MWInput
|
|||
mInputBinder->removeJoystickButtonBinding (mFakeDeviceID, mInputBinder->getJoystickButtonBinding (control, mFakeDeviceID, ICS::Control::INCREASE));
|
||||
}
|
||||
|
||||
int InputManager::countSavedGameRecords() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InputManager::write(ESM::ESMWriter& writer, Loading::Listener& /*progress*/)
|
||||
{
|
||||
ESM::ControlsState controls;
|
||||
controls.mViewSwitchDisabled = !getControlSwitch("playerviewswitch");
|
||||
controls.mControlsDisabled = !getControlSwitch("playercontrols");
|
||||
controls.mJumpingDisabled = !getControlSwitch("playerjumping");
|
||||
controls.mLookingDisabled = !getControlSwitch("playerlooking");
|
||||
controls.mVanityModeDisabled = !getControlSwitch("vanitymode");
|
||||
controls.mWeaponDrawingDisabled = !getControlSwitch("playerfighting");
|
||||
controls.mSpellDrawingDisabled = !getControlSwitch("playermagic");
|
||||
|
||||
writer.startRecord (ESM::REC_INPU);
|
||||
controls.save(writer);
|
||||
writer.endRecord (ESM::REC_INPU);
|
||||
}
|
||||
|
||||
void InputManager::readRecord(ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type == ESM::REC_INPU)
|
||||
{
|
||||
ESM::ControlsState controls;
|
||||
controls.load(reader);
|
||||
|
||||
toggleControlSwitch("playerviewswitch", !controls.mViewSwitchDisabled);
|
||||
toggleControlSwitch("playercontrols", !controls.mControlsDisabled);
|
||||
toggleControlSwitch("playerjumping", !controls.mJumpingDisabled);
|
||||
toggleControlSwitch("playerlooking", !controls.mLookingDisabled);
|
||||
toggleControlSwitch("vanitymode", !controls.mVanityModeDisabled);
|
||||
toggleControlSwitch("playerfighting", !controls.mWeaponDrawingDisabled);
|
||||
toggleControlSwitch("playermagic", !controls.mSpellDrawingDisabled);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::resetToDefaultKeyBindings()
|
||||
{
|
||||
loadKeyDefaults(true);
|
||||
|
|
|
@ -149,6 +149,10 @@ namespace MWInput
|
|||
void clearAllKeyBindings (ICS::Control* control);
|
||||
void clearAllControllerBindings (ICS::Control* control);
|
||||
|
||||
virtual int countSavedGameRecords() const;
|
||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
private:
|
||||
SDL_Window* mWindow;
|
||||
bool mWindowVisible;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
|
||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
|
||||
|
||||
#include <LinearMath/btQuickprof.h>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
@ -1363,8 +1364,10 @@ namespace MWPhysics
|
|||
for (std::set<Object*>::iterator it = mAnimatedObjects.begin(); it != mAnimatedObjects.end(); ++it)
|
||||
(*it)->animateCollisionShapes(mCollisionWorld);
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
CProfileManager::Reset();
|
||||
CProfileManager::Increment_Frame_Counter();
|
||||
#endif
|
||||
}
|
||||
|
||||
void PhysicsSystem::debugDraw()
|
||||
|
|
|
@ -978,8 +978,8 @@ namespace MWRender
|
|||
{
|
||||
const NifOsg::TextKeyMap &keys = (*animiter)->getTextKeys();
|
||||
|
||||
const AnimSource::ControllerMap& ctrls = (*animiter)->mControllerMap[0];
|
||||
for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it)
|
||||
const AnimSource::ControllerMap& ctrls2 = (*animiter)->mControllerMap[0];
|
||||
for (AnimSource::ControllerMap::const_iterator it = ctrls2.begin(); it != ctrls2.end(); ++it)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->first, mAccumRoot->getName()))
|
||||
{
|
||||
|
|
|
@ -172,37 +172,37 @@ namespace MWRender
|
|||
|
||||
unsigned char r,g,b;
|
||||
|
||||
float y = 0;
|
||||
float y2 = 0;
|
||||
if (landData)
|
||||
y = (landData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
|
||||
y2 = (landData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
|
||||
else
|
||||
y = (SCHAR_MIN << 4) / 2048.f;
|
||||
if (y < 0)
|
||||
y2 = (SCHAR_MIN << 4) / 2048.f;
|
||||
if (y2 < 0)
|
||||
{
|
||||
r = static_cast<unsigned char>(14 * y + 38);
|
||||
g = static_cast<unsigned char>(20 * y + 56);
|
||||
b = static_cast<unsigned char>(18 * y + 51);
|
||||
r = static_cast<unsigned char>(14 * y2 + 38);
|
||||
g = static_cast<unsigned char>(20 * y2 + 56);
|
||||
b = static_cast<unsigned char>(18 * y2 + 51);
|
||||
}
|
||||
else if (y < 0.3f)
|
||||
else if (y2 < 0.3f)
|
||||
{
|
||||
if (y < 0.1f)
|
||||
y *= 8.f;
|
||||
if (y2 < 0.1f)
|
||||
y2 *= 8.f;
|
||||
else
|
||||
{
|
||||
y -= 0.1f;
|
||||
y += 0.8f;
|
||||
y2 -= 0.1f;
|
||||
y2 += 0.8f;
|
||||
}
|
||||
r = static_cast<unsigned char>(66 - 32 * y);
|
||||
g = static_cast<unsigned char>(48 - 23 * y);
|
||||
b = static_cast<unsigned char>(33 - 16 * y);
|
||||
r = static_cast<unsigned char>(66 - 32 * y2);
|
||||
g = static_cast<unsigned char>(48 - 23 * y2);
|
||||
b = static_cast<unsigned char>(33 - 16 * y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
y -= 0.3f;
|
||||
y *= 1.428f;
|
||||
r = static_cast<unsigned char>(34 - 29 * y);
|
||||
g = static_cast<unsigned char>(25 - 20 * y);
|
||||
b = static_cast<unsigned char>(17 - 12 * y);
|
||||
y2 -= 0.3f;
|
||||
y2 *= 1.428f;
|
||||
r = static_cast<unsigned char>(34 - 29 * y2);
|
||||
g = static_cast<unsigned char>(25 - 20 * y2);
|
||||
b = static_cast<unsigned char>(17 - 12 * y2);
|
||||
}
|
||||
|
||||
data[texelY * mWidth * 3 + texelX * 3] = r;
|
||||
|
|
|
@ -249,7 +249,8 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
|
||||
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getMechanicsManager()->countSavedGameRecords();
|
||||
+MWBase::Environment::get().getMechanicsManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getInputManager()->countSavedGameRecords();
|
||||
writer.setRecordCount (recordCount);
|
||||
|
||||
writer.save (stream);
|
||||
|
@ -271,6 +272,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
|
||||
MWBase::Environment::get().getWindowManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getMechanicsManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getInputManager()->write(writer, listener);
|
||||
|
||||
// Ensure we have written the number of records that was estimated
|
||||
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
|
||||
|
@ -462,6 +464,10 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
MWBase::Environment::get().getMechanicsManager()->readRecord(reader, n.intval);
|
||||
break;
|
||||
|
||||
case ESM::REC_INPU:
|
||||
MWBase::Environment::get().getInputManager()->readRecord(reader, n.intval);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
// ignore invalid records
|
||||
|
|
|
@ -230,6 +230,14 @@ namespace MWWorld
|
|||
return (ref.mRef.mRefnum == pRefnum);
|
||||
}
|
||||
|
||||
Ptr CellStore::getCurrentPtr(LiveCellRefBase *ref)
|
||||
{
|
||||
MovedRefTracker::iterator found = mMovedToAnotherCell.find(ref);
|
||||
if (found != mMovedToAnotherCell.end())
|
||||
return Ptr(ref, found->second);
|
||||
return Ptr(ref, this);
|
||||
}
|
||||
|
||||
void CellStore::moveFrom(const Ptr &object, CellStore *from)
|
||||
{
|
||||
if (mState != State_Loaded)
|
||||
|
@ -1023,26 +1031,26 @@ namespace MWWorld
|
|||
mLastRespawn = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
for (CellRefList<ESM::Container>::List::iterator it (mContainers.mList.begin()); it!=mContainers.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
Ptr ptr = getCurrentPtr(&*it);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (CellRefList<ESM::Creature>::List::iterator it (mCreatures.mList.begin()); it!=mCreatures.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
Ptr ptr = getCurrentPtr(&*it);
|
||||
clearCorpse(ptr);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::NPC>::List::iterator it (mNpcs.mList.begin()); it!=mNpcs.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
Ptr ptr = getCurrentPtr(&*it);
|
||||
clearCorpse(ptr);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::CreatureLevList>::List::iterator it (mCreatureLists.mList.begin()); it!=mCreatureLists.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
Ptr ptr = getCurrentPtr(&*it);
|
||||
// no need to clearCorpse, handled as part of mCreatures
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
|
|
|
@ -111,6 +111,9 @@ namespace MWWorld
|
|||
// Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from mMovedToAnotherCell
|
||||
std::vector<LiveCellRefBase*> mMergedRefs;
|
||||
|
||||
// Get the Ptr for the given ref which originated from this cell (possibly moved to another cell at this point).
|
||||
Ptr getCurrentPtr(MWWorld::LiveCellRefBase* ref);
|
||||
|
||||
/// Moves object from the given cell to this cell.
|
||||
void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from);
|
||||
|
||||
|
|
|
@ -450,10 +450,10 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|||
}
|
||||
else
|
||||
{
|
||||
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
||||
if (id.empty())
|
||||
std::string itemId = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
||||
if (itemId.empty())
|
||||
return;
|
||||
addInitialItem(id, owner, count, false, levItemList->mId);
|
||||
addInitialItem(itemId, owner, count, false, levItemList->mId);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <components/esm/loadench.hpp>
|
||||
#include <components/esm/inventorystate.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -214,79 +215,57 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot)
|
|||
return mSlots[slot];
|
||||
}
|
||||
|
||||
bool MWWorld::InventoryStore::canActorAutoEquip(const MWWorld::Ptr& actor, const MWWorld::Ptr& item)
|
||||
{
|
||||
if (!Settings::Manager::getBool("prevent merchant equipping", "Game"))
|
||||
return true;
|
||||
|
||||
// Only autoEquip if we are the original owner of the item.
|
||||
// This stops merchants from auto equipping anything you sell to them.
|
||||
// ...unless this is a companion, he should always equip items given to him.
|
||||
if (!Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), actor.getCellRef().getRefId()) &&
|
||||
(actor.getClass().getScript(actor).empty() ||
|
||||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))
|
||||
&& !actor.getClass().getCreatureStats(actor).isDead() // Corpses can be dressed up by the player as desired
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
||||
{
|
||||
if (!actor.getClass().isNpc())
|
||||
// autoEquip is no-op for creatures
|
||||
return;
|
||||
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
|
||||
MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor);
|
||||
|
||||
static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
|
||||
static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
|
||||
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
|
||||
|
||||
float unarmoredRating = static_cast<int>((fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill));
|
||||
|
||||
TSlots slots_;
|
||||
initSlots (slots_);
|
||||
|
||||
// Disable model update during auto-equip
|
||||
mUpdatesEnabled = false;
|
||||
|
||||
for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
||||
// Autoequip clothing, armor and weapons.
|
||||
// Equipping lights is handled in Actors::updateEquippedLight based on environment light.
|
||||
|
||||
for (ContainerStoreIterator iter (begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter!=end(); ++iter)
|
||||
{
|
||||
Ptr test = *iter;
|
||||
|
||||
// Don't autoEquip lights. Handled in Actors::updateEquippedLight based on environment light.
|
||||
if (test.getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
if (!canActorAutoEquip(actor, test))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only autoEquip if we are the original owner of the item.
|
||||
// This stops merchants from auto equipping anything you sell to them.
|
||||
// ...unless this is a companion, he should always equip items given to him.
|
||||
if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) &&
|
||||
(actor.getClass().getScript(actor).empty() ||
|
||||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))
|
||||
&& !actor.getClass().getCreatureStats(actor).isDead() // Corpses can be dressed up by the player as desired
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int testSkill = test.getClass().getEquipmentSkill (test);
|
||||
|
||||
std::pair<std::vector<int>, bool> itemsSlots =
|
||||
iter->getClass().getEquipmentSlots (*iter);
|
||||
|
||||
for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
|
||||
iter2!=itemsSlots.first.end(); ++iter2)
|
||||
{
|
||||
if (*iter2 == Slot_CarriedRight) // Items in right hand are situational use, so don't equip them.
|
||||
// Equipping weapons is handled by AiCombat. Anything else (lockpicks, probes) can't be used by NPCs anyway (yet)
|
||||
continue;
|
||||
|
||||
if (iter.getType() == MWWorld::ContainerStore::Type_Weapon)
|
||||
continue;
|
||||
|
||||
if (slots_.at (*iter2)!=end())
|
||||
{
|
||||
Ptr old = *slots_.at (*iter2);
|
||||
|
||||
// check skill
|
||||
int oldSkill = old.getClass().getEquipmentSkill (old);
|
||||
|
||||
bool use = false;
|
||||
if (testSkill!=-1 && oldSkill==-1)
|
||||
use = true;
|
||||
else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill)
|
||||
{
|
||||
if (actor.getClass().getSkill(actor, oldSkill) > actor.getClass().getSkill (actor, testSkill))
|
||||
continue; // rejected, because old item better matched the NPC's skills.
|
||||
|
||||
if (actor.getClass().getSkill(actor, oldSkill) < actor.getClass().getSkill (actor, testSkill))
|
||||
use = true;
|
||||
}
|
||||
|
||||
if (!use)
|
||||
{
|
||||
// check value
|
||||
if (old.getClass().getValue (old)>=
|
||||
test.getClass().getValue (test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(test.getClass().canBeEquipped (test, actor).first)
|
||||
{
|
||||
|
@ -296,6 +275,47 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
break;
|
||||
}
|
||||
|
||||
if (iter.getType() == ContainerStore::Type_Armor &&
|
||||
test.getClass().getEffectiveArmorRating(test, actor) <= std::max(unarmoredRating, 0.f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::pair<std::vector<int>, bool> itemsSlots =
|
||||
iter->getClass().getEquipmentSlots (*iter);
|
||||
|
||||
for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
|
||||
iter2!=itemsSlots.first.end(); ++iter2)
|
||||
{
|
||||
if (slots_.at (*iter2)!=end())
|
||||
{
|
||||
Ptr old = *slots_.at (*iter2);
|
||||
|
||||
if (iter.getType() == ContainerStore::Type_Armor)
|
||||
{
|
||||
if (old.getTypeName() == typeid(ESM::Armor).name())
|
||||
{
|
||||
if (old.getClass().getEffectiveArmorRating(old, actor) >= test.getClass().getEffectiveArmorRating(test, actor))
|
||||
// old armor had better armor rating
|
||||
continue;
|
||||
}
|
||||
// suitable armor should replace already equipped clothing
|
||||
}
|
||||
else if (iter.getType() == ContainerStore::Type_Clothing)
|
||||
{
|
||||
if (old.getTypeName() == typeid(ESM::Clothing).name())
|
||||
{
|
||||
// check value
|
||||
if (old.getClass().getValue (old) > test.getClass().getValue (test))
|
||||
// old clothing was more valuable
|
||||
continue;
|
||||
}
|
||||
else
|
||||
// suitable clothing should NOT replace already equipped armor
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped
|
||||
{
|
||||
// unstack item pointed to by iterator if required
|
||||
|
@ -310,6 +330,99 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
}
|
||||
}
|
||||
|
||||
static const ESM::Skill::SkillEnum weaponSkills[] =
|
||||
{
|
||||
ESM::Skill::LongBlade,
|
||||
ESM::Skill::Axe,
|
||||
ESM::Skill::Spear,
|
||||
ESM::Skill::ShortBlade,
|
||||
ESM::Skill::Marksman,
|
||||
ESM::Skill::BluntWeapon
|
||||
};
|
||||
const size_t weaponSkillsLength = sizeof(weaponSkills) / sizeof(weaponSkills[0]);
|
||||
|
||||
bool weaponSkillVisited[weaponSkillsLength] = { false };
|
||||
|
||||
for (int i = 0; i < static_cast<int>(weaponSkillsLength); ++i)
|
||||
{
|
||||
int max = 0;
|
||||
int maxWeaponSkill = -1;
|
||||
|
||||
for (int j = 0; j < static_cast<int>(weaponSkillsLength); ++j)
|
||||
{
|
||||
int skillValue = stats.getSkill(static_cast<int>(weaponSkills[j])).getModified();
|
||||
|
||||
if (skillValue > max && !weaponSkillVisited[j])
|
||||
{
|
||||
max = skillValue;
|
||||
maxWeaponSkill = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxWeaponSkill == -1)
|
||||
break;
|
||||
|
||||
max = 0;
|
||||
ContainerStoreIterator weapon(end());
|
||||
|
||||
for (ContainerStoreIterator iter(begin(ContainerStore::Type_Weapon)); iter!=end(); ++iter)
|
||||
{
|
||||
if (!canActorAutoEquip(actor, *iter))
|
||||
continue;
|
||||
|
||||
const ESM::Weapon* esmWeapon = iter->get<ESM::Weapon>()->mBase;
|
||||
|
||||
if (esmWeapon->mData.mType == ESM::Weapon::Arrow || esmWeapon->mData.mType == ESM::Weapon::Bolt)
|
||||
continue;
|
||||
|
||||
if (iter->getClass().getEquipmentSkill(*iter) == weaponSkills[maxWeaponSkill])
|
||||
{
|
||||
if (esmWeapon->mData.mChop[1] >= max)
|
||||
{
|
||||
max = esmWeapon->mData.mChop[1];
|
||||
weapon = iter;
|
||||
}
|
||||
|
||||
if (esmWeapon->mData.mSlash[1] >= max)
|
||||
{
|
||||
max = esmWeapon->mData.mSlash[1];
|
||||
weapon = iter;
|
||||
}
|
||||
|
||||
if (esmWeapon->mData.mThrust[1] >= max)
|
||||
{
|
||||
max = esmWeapon->mData.mThrust[1];
|
||||
weapon = iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (weapon != end() && weapon->getClass().canBeEquipped(*weapon, actor).first)
|
||||
{
|
||||
std::pair<std::vector<int>, bool> itemsSlots =
|
||||
weapon->getClass().getEquipmentSlots (*weapon);
|
||||
|
||||
for (std::vector<int>::const_iterator slot (itemsSlots.first.begin());
|
||||
slot!=itemsSlots.first.end(); ++slot)
|
||||
{
|
||||
if (!itemsSlots.second)
|
||||
{
|
||||
if (weapon->getRefData().getCount() > 1)
|
||||
{
|
||||
unstack(*weapon, actor);
|
||||
}
|
||||
}
|
||||
|
||||
slots_[*slot] = weapon;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
weaponSkillVisited[maxWeaponSkill] = true;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (std::size_t i=0; i<slots_.size(); ++i)
|
||||
|
|
|
@ -115,6 +115,8 @@ namespace MWWorld
|
|||
virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const;
|
||||
virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory);
|
||||
|
||||
bool canActorAutoEquip(const MWWorld::Ptr& actor, const MWWorld::Ptr& item);
|
||||
|
||||
public:
|
||||
|
||||
InventoryStore();
|
||||
|
|
|
@ -832,17 +832,14 @@ bool WeatherManager::readRecord(ESM::ESMReader& reader, uint32_t type)
|
|||
mQueuedWeather = state.mQueuedWeather;
|
||||
|
||||
mRegions.clear();
|
||||
std::map<std::string, ESM::RegionWeatherState>::iterator it = state.mRegions.begin();
|
||||
if(it == state.mRegions.end())
|
||||
{
|
||||
// When loading an imported save, the region modifiers aren't currently being set, so just reset them.
|
||||
importRegions();
|
||||
}
|
||||
else
|
||||
|
||||
for(std::map<std::string, ESM::RegionWeatherState>::iterator it = state.mRegions.begin(); it != state.mRegions.end(); ++it)
|
||||
{
|
||||
for(; it != state.mRegions.end(); ++it)
|
||||
std::map<std::string, RegionWeather>::iterator found = mRegions.find(it->first);
|
||||
if (found != mRegions.end())
|
||||
{
|
||||
mRegions.insert(std::make_pair(it->first, RegionWeather(it->second)));
|
||||
found->second = RegionWeather(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ add_component_dir (esm
|
|||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||
aisequence magiceffects util custommarkerstate stolenitems transport animationstate
|
||||
aisequence magiceffects util custommarkerstate stolenitems transport animationstate controlsstate
|
||||
)
|
||||
|
||||
add_component_dir (esmterrain
|
||||
|
|
43
components/esm/controlsstate.cpp
Normal file
43
components/esm/controlsstate.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "controlsstate.hpp"
|
||||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
|
||||
ESM::ControlsState::ControlsState()
|
||||
: mViewSwitchDisabled(false),
|
||||
mControlsDisabled(false),
|
||||
mJumpingDisabled(false),
|
||||
mLookingDisabled(false),
|
||||
mVanityModeDisabled(false),
|
||||
mWeaponDrawingDisabled(false),
|
||||
mSpellDrawingDisabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ESM::ControlsState::load(ESM::ESMReader& esm)
|
||||
{
|
||||
int flags;
|
||||
esm.getHNT(flags, "CFLG");
|
||||
|
||||
mViewSwitchDisabled = flags & ViewSwitchDisabled;
|
||||
mControlsDisabled = flags & ControlsDisabled;
|
||||
mJumpingDisabled = flags & JumpingDisabled;
|
||||
mLookingDisabled = flags & LookingDisabled;
|
||||
mVanityModeDisabled = flags & VanityModeDisabled;
|
||||
mWeaponDrawingDisabled = flags & WeaponDrawingDisabled;
|
||||
mSpellDrawingDisabled = flags & SpellDrawingDisabled;
|
||||
}
|
||||
|
||||
void ESM::ControlsState::save(ESM::ESMWriter& esm) const
|
||||
{
|
||||
int flags = 0;
|
||||
if (mViewSwitchDisabled) flags |= ViewSwitchDisabled;
|
||||
if (mControlsDisabled) flags |= ControlsDisabled;
|
||||
if (mJumpingDisabled) flags |= JumpingDisabled;
|
||||
if (mLookingDisabled) flags |= LookingDisabled;
|
||||
if (mVanityModeDisabled) flags |= VanityModeDisabled;
|
||||
if (mWeaponDrawingDisabled) flags |= WeaponDrawingDisabled;
|
||||
if (mSpellDrawingDisabled) flags |= SpellDrawingDisabled;
|
||||
|
||||
esm.writeHNT("CFLG", flags);
|
||||
}
|
39
components/esm/controlsstate.hpp
Normal file
39
components/esm/controlsstate.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef OPENMW_ESM_CONTROLSSTATE_H
|
||||
#define OPENMW_ESM_CONTROLSSTATE_H
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
// format 0, saved games only
|
||||
|
||||
struct ControlsState
|
||||
{
|
||||
ControlsState();
|
||||
|
||||
enum Flags
|
||||
{
|
||||
ViewSwitchDisabled = 0x1,
|
||||
ControlsDisabled = 0x4,
|
||||
JumpingDisabled = 0x1000,
|
||||
LookingDisabled = 0x2000,
|
||||
VanityModeDisabled = 0x4000,
|
||||
WeaponDrawingDisabled = 0x8000,
|
||||
SpellDrawingDisabled = 0x10000
|
||||
};
|
||||
|
||||
bool mViewSwitchDisabled;
|
||||
bool mControlsDisabled;
|
||||
bool mJumpingDisabled;
|
||||
bool mLookingDisabled;
|
||||
bool mVanityModeDisabled;
|
||||
bool mWeaponDrawingDisabled;
|
||||
bool mSpellDrawingDisabled;
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -127,6 +127,7 @@ enum RecNameInts
|
|||
REC_ENAB = FourCC<'E','N','A','B'>::value,
|
||||
REC_CAM_ = FourCC<'C','A','M','_'>::value,
|
||||
REC_STLN = FourCC<'S','T','L','N'>::value,
|
||||
REC_INPU = FourCC<'I','N','P','U'>::value,
|
||||
|
||||
// format 1
|
||||
REC_FILT = FourCC<'F','I','L','T'>::value,
|
||||
|
|
|
@ -145,6 +145,9 @@ difficulty = 0
|
|||
# Show duration of magic effect and lights in the spells window.
|
||||
show effect duration = false
|
||||
|
||||
# Prevents merchants from equipping items that are sold to them.
|
||||
prevent merchant equipping = false
|
||||
|
||||
[General]
|
||||
|
||||
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
||||
|
|
|
@ -20,9 +20,7 @@ vec4 doLighting(vec3 viewPos, vec3 viewNormal, vec4 vertexColor)
|
|||
d = length(lightDir);
|
||||
lightDir = normalize(lightDir);
|
||||
|
||||
lightResult.xyz += ambient * gl_LightSource[i].ambient.xyz;
|
||||
lightResult.xyz += diffuse.xyz * gl_LightSource[i].diffuse.xyz * clamp(1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d), 0.0, 1.0)
|
||||
* max(dot(viewNormal.xyz, lightDir), 0.0);
|
||||
lightResult.xyz += (ambient * gl_LightSource[i].ambient.xyz + diffuse.xyz * gl_LightSource[i].diffuse.xyz * max(dot(viewNormal.xyz, lightDir), 0.0)) * clamp(1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d), 0.0, 1.0);
|
||||
}
|
||||
|
||||
lightResult.xyz += gl_LightModel.ambient.xyz * ambient;
|
||||
|
|
Loading…
Reference in a new issue