1
0
Fork 1
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:
David Cernat 2016-10-24 09:18:21 +03:00
commit 47ebd24b4a
43 changed files with 477 additions and 159 deletions

View file

@ -1,7 +1,7 @@
os:
- linux
# - osx
#osx_image: xcode7.2
osx_image: xcode7.2
language: cpp
sudo: required
dist: trusty

View file

@ -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

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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

View file

@ -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);
}
}

View file

@ -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))
{

View file

@ -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())

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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();

View file

@ -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;

View file

@ -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;
}

View file

@ -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() };

View file

@ -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);

View file

@ -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());

View file

@ -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);

View file

@ -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:

View file

@ -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;
}

View file

@ -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;
};
}

View file

@ -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);

View file

@ -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
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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()

View file

@ -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()))
{

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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();

View file

@ -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);
}
}
}

View file

@ -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

View 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);
}

View 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

View file

@ -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,

View file

@ -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).

View file

@ -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;