From 4e7ee970504334321c15654ce2ecceddcebfe783 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Mon, 14 Apr 2014 17:18:29 +0400 Subject: [PATCH 001/545] fix for windows builds --- apps/openmw/mwgui/savegamedialog.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index caa082646e..3ff583264e 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -259,7 +259,11 @@ namespace MWGui timeinfo = localtime(&time); // Use system/environment locale settings for datetime formatting +#if defined(_WIN32) || defined(__WINDOWS__) + setlocale(LC_TIME, ""); +#else std::setlocale(LC_TIME, ""); +#endif const int size=1024; char buffer[size]; From f811abb752efdd8306c081df67d92edd57d86728 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 20 Apr 2014 20:35:07 +0400 Subject: [PATCH 002/545] pathgrid shortcutting extended --- apps/openmw/mwbase/world.hpp | 2 + apps/openmw/mwmechanics/aicombat.cpp | 204 ++++++++++++++++-------- apps/openmw/mwmechanics/aicombat.hpp | 5 +- apps/openmw/mwmechanics/pathfinding.cpp | 11 +- apps/openmw/mwmechanics/pathfinding.hpp | 13 +- apps/openmw/mwmechanics/steering.cpp | 3 +- apps/openmw/mwmechanics/steering.hpp | 3 + apps/openmw/mwworld/worldimp.cpp | 15 +- apps/openmw/mwworld/worldimp.hpp | 2 + 9 files changed, 181 insertions(+), 77 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index f03a9197d9..98ec9cfced 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -407,6 +407,8 @@ namespace MWBase virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0; ///< get Line of Sight (morrowind stupid implementation) + virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0; + virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0; virtual int canRest() = 0; diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index fd2fa61ba0..84798ca028 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -31,6 +31,40 @@ namespace //chooses an attack depending on probability to avoid uniformity void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement); + + float getZAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) + { + float len = (dirLen >= 0.0f)? dirLen : dir.length(); + return Ogre::Radian( Ogre::Math::ACos(dir.y / len) * sgn(Ogre::Math::ASin(dir.x / len)) ).valueDegrees(); + } + + const float PATHFIND_Z_REACH = 50.0f; + // distance at which actor pays more attention to decide whether to shortcut or stick to pathgrid + const float PATHFIND_CAUTION_DIST = 500.0f; + // distance after which actor (failed previously to shortcut) will try again + const float PATHFIND_SHORTCUT_RETRY_DIST = 300.0f; + + // cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target; + // magnitude of pits/obstacles is defined by PATHFIND_Z_REACH + bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offset) + { + if((to - from).length() >= PATHFIND_CAUTION_DIST || abs(from.z - to.z) <= PATHFIND_Z_REACH) + { + Ogre::Vector3 dir = to - from; + dir.z = 0; + dir.normalise(); + float verticalOffset = 200; // instead of '200' here we want the height of the actor + Ogre::Vector3 _from = from + dir*offset + Ogre::Vector3::UNIT_Z * verticalOffset; + + // cast up-down ray and find height in world space of hit + float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1); + + if(abs(from.z - h) <= PATHFIND_Z_REACH) + return true; + } + + return false; + } } namespace MWMechanics @@ -44,9 +78,10 @@ namespace MWMechanics mReadyToAttack(false), mStrike(false), mCombatMove(false), - mRotate(false), mMovement(), - mTargetAngle(0) + mTargetAngle(0), + mForceNoShortcut(false), + mShortcutFailPos() { } @@ -71,13 +106,12 @@ namespace MWMechanics mCombatMove = false; } } - + actor.getClass().getMovementSettings(actor) = mMovement; - if (mRotate) + if(actor.getRefData().getPosition().rot[2] != mTargetAngle) { - if (zTurn(actor, Ogre::Degree(mTargetAngle))) - mRotate = false; + zTurn(actor, Ogre::Degree(mTargetAngle)); } @@ -92,7 +126,7 @@ namespace MWMechanics } //Update with period = tReaction - + mTimerReact = 0; //actual attacking logic @@ -136,6 +170,7 @@ namespace MWMechanics actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); + // Get weapon characteristics if (actor.getClass().hasInventoryStore(actor)) { MWMechanics::DrawState_ state = actor.getClass().getCreatureStats(actor).getDrawState(); @@ -166,15 +201,13 @@ namespace MWMechanics weapRange = 150; //TODO: use true attack range (the same problem in Creature::hit) } - ESM::Position pos = actor.getRefData().getPosition(); - float rangeMelee; float rangeCloseUp; bool distantCombat = false; if (weaptype==WeapType_BowAndArrow || weaptype==WeapType_Crossbow || weaptype==WeapType_Thrown) { rangeMelee = 1000; // TODO: should depend on archer skill - rangeCloseUp = 0; //doesn't needed when attacking from distance + rangeCloseUp = 0; // not needed in ranged combat distantCombat = true; } else @@ -182,23 +215,27 @@ namespace MWMechanics rangeMelee = weapRange; rangeCloseUp = 300; } + + ESM::Position pos = actor.getRefData().getPosition(); + Ogre::Vector3 vActorPos(pos.pos); + Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; + float distToTarget = vDirToTarget.length(); - Ogre::Vector3 vStart(pos.pos[0], pos.pos[1], pos.pos[2]); - ESM::Position targetPos = mTarget.getRefData().getPosition(); - Ogre::Vector3 vDest(targetPos.pos[0], targetPos.pos[1], targetPos.pos[2]); - Ogre::Vector3 vDir = vDest - vStart; - float distBetween = vDir.length(); + bool isStuck = false; + float speed = 0.0f; + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = cls.getSpeed(actor)) / 10.0f) + isStuck = true; - if(distBetween < rangeMelee || (distBetween <= rangeCloseUp && mFollowTarget) ) + mLastPos = pos; + + if(distToTarget < rangeMelee || (distToTarget <= rangeCloseUp && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - vDir.z = 0; - float dirLen = vDir.length(); - mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / dirLen) * sgn(Ogre::Math::ASin(vDir.x / dirLen)) ).valueDegrees(); - mRotate = true; + vDirToTarget.z = 0; + mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); - //bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); - if (mFollowTarget && distBetween > rangeMelee) + if (mFollowTarget && distToTarget > rangeMelee) { //Close-up combat: just run up on target mMovement.mPosition[1] = 1; @@ -228,7 +265,7 @@ namespace MWMechanics } } - if(distantCombat && distBetween < rangeMelee/4) + if(distantCombat && distToTarget < rangeMelee/4) { mMovement.mPosition[1] = -1; } @@ -238,32 +275,80 @@ namespace MWMechanics mFollowTarget = true; } } - else + else // remote pathfinding { - //target is at far distance: build path to target OR follow target (if previously actor had reached it once) - mFollowTarget = false; + bool preferShortcut = false; + bool inLOS; - buildNewPath(actor); //may fail to build a path, check before use - - //delete visited path node - mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); - - //if no new path leave mTargetAngle unchanged - if(!mPathFinder.getPath().empty()) + if(mReadyToAttack) isStuck = false; + + // check if shortcut is available + if(!isStuck + && (!mForceNoShortcut + || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) + && (inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))) { - //try shortcut - if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget)) - mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees(); - else - mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - mRotate = true; + if(speed == 0.0f) speed = cls.getSpeed(actor); + // maximum dist before pit/obstacle for actor to avoid them depending on his speed + float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; + //if(actor.getRefData().getPosition().rot[2] != mTargetAngle) + preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); + } + + if(preferShortcut) + { + mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + mForceNoShortcut = false; + mShortcutFailPos.pos[0] = mShortcutFailPos.pos[1] = mShortcutFailPos.pos[2] = 0; + if(mPathFinder.isPathConstructed()) + mPathFinder.clearPath(); + } + else // if shortcut failed stick to path grid + { + if(!isStuck && mShortcutFailPos.pos[0] == 0.0f && mShortcutFailPos.pos[1] == 0.0f && mShortcutFailPos.pos[2] == 0.0f) + { + mForceNoShortcut = true; + mShortcutFailPos = pos; + } + + mFollowTarget = false; + + buildNewPath(actor); //may fail to build a path, check before use + + //delete visited path node + mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]); + + // This works on the borders between the path grid and areas with no waypoints. + if(inLOS && mPathFinder.getPath().size() > 1) + { + // get point just before target + std::list::iterator pntIter = --mPathFinder.getPath().end(); + --pntIter; + Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ); + + // if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target + if(distToTarget <= (vTargetPos - vBeforeTarget).length()) + { + mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + preferShortcut = true; + } + } + + // if there is no new path, then go straight on target + if(!preferShortcut) + { + if(!mPathFinder.getPath().empty()) + mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + else + mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + } } mMovement.mPosition[1] = 1; mReadyToAttack = false; } - if(distBetween > rangeMelee) + if(distToTarget > rangeMelee) { //special run attack; it shouldn't affect melee combat tactics if(actor.getClass().getMovementSettings(actor).mPosition[1] == 1) @@ -277,7 +362,7 @@ namespace MWMechanics && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) speed2 = 0; - float s1 = distBetween - weapRange; + float s1 = distToTarget - weapRange; float t = s1/speed1; float s2 = speed2 * t; float t_swing = 0.17f/weapSpeed;//instead of 0.17 should be the time of playing weapon anim from 'start' to 'hit' tags @@ -300,31 +385,23 @@ namespace MWMechanics void AiCombat::buildNewPath(const MWWorld::Ptr& actor) { - //Construct path to target - ESM::Pathgrid::Point dest; - dest.mX = mTarget.getRefData().getPosition().pos[0]; - dest.mY = mTarget.getRefData().getPosition().pos[1]; - dest.mZ = mTarget.getRefData().getPosition().pos[2]; - Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ); + Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); - float dist = -1; //hack to indicate first time, to construct a new path + float dist; + if(!mPathFinder.getPath().empty()) { ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ); - dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length()); + dist = (newPathTarget - currPathTarget).length(); } + else dist = 1e+38F; // necessarily construct a new path - float targetPosThreshold; - bool isOutside = actor.getCell()->getCell()->isExterior(); - if (isOutside) - targetPosThreshold = 300; - else - targetPosThreshold = 100; + float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300 : 100; - if((dist < 0) || (dist > targetPosThreshold)) + //construct new path only if target has moved away more than on [targetPosThreshold] + if(dist > targetPosThreshold) { - //construct new path only if target has moved away more than on ESM::Position pos = actor.getRefData().getPosition(); ESM::Pathgrid::Point start; @@ -332,17 +409,18 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; + ESM::Pathgrid::Point dest; + dest.mX = newPathTarget.x; + dest.mY = newPathTarget.y; + dest.mZ = newPathTarget.z; + if(!mPathFinder.isPathConstructed()) - mPathFinder.buildPath(start, dest, actor.getCell(), isOutside); + mPathFinder.buildPath(start, dest, actor.getCell(), false); else { PathFinder newPathFinder; - newPathFinder.buildPath(start, dest, actor.getCell(), isOutside); + newPathFinder.buildPath(start, dest, actor.getCell(), false); - //TO EXPLORE: - //maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path, - //not the actual path length. Here we should know if the new path is actually more effective. - //if(pathFinder2.getPathSize() < mPathFinder.getPathSize()) if(!mPathFinder.getPath().empty()) { newPathFinder.syncStart(mPathFinder.getPath()); diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 767a362924..b71dd9cf0e 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -43,8 +43,11 @@ namespace MWMechanics bool mReadyToAttack, mStrike; bool mFollowTarget; bool mCombatMove; - bool mRotate; + bool mForceNoShortcut; + ESM::Position mShortcutFailPos; + + ESM::Position mLastPos; MWMechanics::Movement mMovement; MWWorld::Ptr mTarget; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 3ecd407431..4aee6f6e4b 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -384,22 +384,21 @@ namespace MWMechanics return false; } - void PathFinder::syncStart(const std::list &path) + bool PathFinder::syncStart(const std::list &path) { if (mPath.size() < 2) - return; //nothing to pop + return false; //nothing to pop std::list::const_iterator oldStart = path.begin(); std::list::iterator iter = ++mPath.begin(); if( (*iter).mX == oldStart->mX && (*iter).mY == oldStart->mY - && (*iter).mZ == oldStart->mZ - && (*iter).mAutogenerated == oldStart->mAutogenerated - && (*iter).mConnectionNum == oldStart->mConnectionNum ) + && (*iter).mZ == oldStart->mZ) { mPath.pop_front(); + return true; } - + return false; } } diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index ecaaef568f..86fa3b6bc5 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -64,10 +64,15 @@ namespace MWMechanics return mPath; } - //When first point of newly created path is the nearest to actor point, then - //the cituation can occure when this point is undesirable (if the 2nd point of new path == the 1st point of old path) - //This functions deletes that point. - void syncStart(const std::list &path); + /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times + @note + If the first point is chosen as the nearest one + the cituation can occure when the 1st point of the new path is undesirable + (i.e. the 2nd point of new path == the 1st point of old path). + @param path - old path + @return true if such point was found and deleted + */ + bool syncStart(const std::list &path); void addPointToPath(ESM::Pathgrid::Point &point) { diff --git a/apps/openmw/mwmechanics/steering.cpp b/apps/openmw/mwmechanics/steering.cpp index d911fd81b8..7646e832da 100644 --- a/apps/openmw/mwmechanics/steering.cpp +++ b/apps/openmw/mwmechanics/steering.cpp @@ -31,8 +31,7 @@ bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle) if (absDiff < epsilon) return true; - // Max. speed of 10 radian per sec - Ogre::Radian limit = Ogre::Radian(10) * MWBase::Environment::get().getFrameDuration(); + Ogre::Radian limit = MAX_VEL_ANGULAR * MWBase::Environment::get().getFrameDuration(); if (absDiff > limit) diff = Ogre::Math::Sign(diff) * limit; diff --git a/apps/openmw/mwmechanics/steering.hpp b/apps/openmw/mwmechanics/steering.hpp index 504dc3ac33..9bdf7d4a3b 100644 --- a/apps/openmw/mwmechanics/steering.hpp +++ b/apps/openmw/mwmechanics/steering.hpp @@ -10,6 +10,9 @@ class Ptr; namespace MWMechanics { +// Max rotating speed, radian/sec +const Ogre::Radian MAX_VEL_ANGULAR(10); + /// configure rotation settings for an actor to reach this target angle (eventually) /// @return have we reached the target angle? bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 594a9f7f4e..47536ab6c2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1875,7 +1875,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) @@ -1893,6 +1893,19 @@ namespace MWWorld return false; } + float World::getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) + { + btVector3 btFrom(from.x, from.y, from.z); + btVector3 btTo = btVector3(dir.x, dir.y, dir.z); + btTo.normalize(); + btTo = btFrom + btTo * maxDist; + + std::pair result = mPhysEngine->rayTest(btFrom, btTo, false); + + if(result.second == -1) return maxDist; + else return result.second*(btTo-btFrom).length(); + } + void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable) { OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f1e89bf6bc..0eea3c6a0f 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -510,6 +510,8 @@ namespace MWWorld virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc); ///< get Line of Sight (morrowind stupid implementation) + virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist); + virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable); virtual int canRest(); From e3244501184f2c0b6e422f6d566f8853fd6d27f1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Apr 2014 09:02:58 +0200 Subject: [PATCH 003/545] replaced return value of DocumentManager::addDocument with a signal --- apps/opencs/CMakeLists.txt | 4 ++-- apps/opencs/editor.cpp | 18 +++++++++------- apps/opencs/editor.hpp | 2 ++ apps/opencs/model/doc/documentmanager.cpp | 4 ++-- apps/opencs/model/doc/documentmanager.hpp | 25 +++++++++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cbe90b1d3e..1db922afab 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,11 +5,11 @@ opencs_units (. editor) set (CMAKE_BUILD_TYPE DEBUG) opencs_units (model/doc - document operation saving + document operation saving documentmanager ) opencs_units_noqt (model/doc - documentmanager stage savingstate savingstages + stage savingstate savingstages ) opencs_hdrs_noqt (model/doc diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 87660a60bc..de68098395 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -37,6 +37,9 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) mNewGame.setLocalData (mLocal); mFileDialog.setLocalData (mLocal); + connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)), + this, SLOT (documentAdded (CSMDoc::Document *))); + connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ())); connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ())); connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ())); @@ -150,9 +153,8 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath) foreach (const QString &path, mFileDialog.selectedFilePaths()) files.push_back(path.toUtf8().constData()); - CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false); + mDocumentManager.addDocument (files, savePath, false); - mViewManager.addView (document); mFileDialog.hide(); } @@ -166,9 +168,8 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath) files.push_back(mFileDialog.filename().toUtf8().constData()); - CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true); + mDocumentManager.addDocument (files, savePath, true); - mViewManager.addView (document); mFileDialog.hide(); } @@ -178,9 +179,7 @@ void CS::Editor::createNewGame (const boost::filesystem::path& file) files.push_back (file); - CSMDoc::Document *document = mDocumentManager.addDocument (files, file, true); - - mViewManager.addView (document); + mDocumentManager.addDocument (files, file, true); mNewGame.hide(); } @@ -287,3 +286,8 @@ std::auto_ptr CS::Editor::setupGraphics() return factory; } + +void CS::Editor::documentAdded (CSMDoc::Document *document) +{ + mViewManager.addView (document); +} \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 164398fb73..53afee0484 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -85,6 +85,8 @@ namespace CS void showSettings(); + void documentAdded (CSMDoc::Document *document); + private: QString mIpcServerName; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 3ff75c9c15..3f19269e7b 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,14 +27,14 @@ CSMDoc::DocumentManager::~DocumentManager() delete *iter; } -CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, +void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { Document *document = new Document (mConfiguration, files, savePath, mResDir, new_); mDocuments.push_back (document); - return document; + emit documentAdded (document); } bool CSMDoc::DocumentManager::removeDocument (Document *document) diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index b969862e99..e41c490298 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -6,6 +6,8 @@ #include +#include + namespace Files { class ConfigurationManager; @@ -15,8 +17,10 @@ namespace CSMDoc { class Document; - class DocumentManager + class DocumentManager : public QObject { + Q_OBJECT + std::vector mDocuments; const Files::ConfigurationManager& mConfiguration; @@ -29,20 +33,23 @@ namespace CSMDoc ~DocumentManager(); - Document *addDocument (const std::vector< boost::filesystem::path >& files, - const boost::filesystem::path& savePath, - bool new_); - ///< The ownership of the returned document is not transferred to the caller. - /// - /// \param new_ Do not load the last content file in \a files and instead create in an + void addDocument (const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, bool new_); + ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. bool removeDocument (Document *document); ///< \return last document removed? + void setResourceDir (const boost::filesystem::path& parResDir); - - private: + + private: + boost::filesystem::path mResDir; + + signals: + + void documentAdded (CSMDoc::Document *document); }; } From 9998c2783eb4813137c61451085615f7ba8f70bc Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 Apr 2014 17:37:06 +0200 Subject: [PATCH 004/545] Fix travis Why again do we need a unit test for something that was never used? --- .../components/misc/test_slicearray.cpp | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 apps/openmw_test_suite/components/misc/test_slicearray.cpp diff --git a/apps/openmw_test_suite/components/misc/test_slicearray.cpp b/apps/openmw_test_suite/components/misc/test_slicearray.cpp deleted file mode 100644 index ab63e56c4f..0000000000 --- a/apps/openmw_test_suite/components/misc/test_slicearray.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include "components/misc/slice_array.hpp" - -struct SliceArrayTest : public ::testing::Test -{ - protected: - virtual void SetUp() - { - } - - virtual void TearDown() - { - } -}; - -TEST_F(SliceArrayTest, hello_string) -{ - Misc::SString s("hello"); - ASSERT_EQ(sizeof("hello") - 1, s.length); - ASSERT_FALSE(s=="hel"); - ASSERT_FALSE(s=="hell"); - ASSERT_TRUE(s=="hello"); -} - -TEST_F(SliceArrayTest, othello_string_with_offset_2_and_size_4) -{ - Misc::SString s("othello" + 2, 4); - ASSERT_EQ(sizeof("hell") - 1, s.length); - ASSERT_FALSE(s=="hel"); - ASSERT_TRUE(s=="hell"); - ASSERT_FALSE(s=="hello"); -} - From 1ab51306c3dfafdc5007dc8f15a96d9daf103118 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Apr 2014 17:47:20 +0200 Subject: [PATCH 005/545] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index eb427a22b7..499c55eebd 100644 --- a/credits.txt +++ b/credits.txt @@ -70,6 +70,7 @@ Sebastian Wick (swick) Sergey Shambir sir_herrbatka Sylvain Thesnieres (Garvek) +Thomas Luppi (Digmaster) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) From fbd0ffe86ff00da9bac3ae24670d1cbca32c1860 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Tue, 22 Apr 2014 22:59:39 +0400 Subject: [PATCH 006/545] enable z-moving for flying/water combatants --- apps/openmw/mwmechanics/aicombat.cpp | 32 +++++++++++++++++++-------- apps/openmw/mwmechanics/character.cpp | 10 +++++---- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 84798ca028..807e08c1db 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -38,7 +38,7 @@ namespace return Ogre::Radian( Ogre::Math::ACos(dir.y / len) * sgn(Ogre::Math::ASin(dir.x / len)) ).valueDegrees(); } - const float PATHFIND_Z_REACH = 50.0f; + const float PATHFIND_Z_REACH = 50.0f; // distance at which actor pays more attention to decide whether to shortcut or stick to pathgrid const float PATHFIND_CAUTION_DIST = 500.0f; // distance after which actor (failed previously to shortcut) will try again @@ -115,6 +115,7 @@ namespace MWMechanics } + mTimerAttack -= duration; actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike); @@ -229,6 +230,17 @@ namespace MWMechanics mLastPos = pos; + // check if can move along z-axis + bool canMoveByZ; + if(canMoveByZ = ((actor.getClass().isNpc() || actor.getClass().canSwim(actor)) && MWBase::Environment::get().getWorld()->isSwimming(actor)) + || (actor.getClass().canFly(actor) && MWBase::Environment::get().getWorld()->isFlying(actor))) + { + float zToTarget = vTargetPos.z - pos.pos[2]; + + mMovement.mPosition[1] = sqrt(distToTarget*distToTarget - zToTarget*zToTarget); // XY-plane vec length + mMovement.mPosition[2] = zToTarget; + } + if(distToTarget < rangeMelee || (distToTarget <= rangeCloseUp && mFollowTarget && !isStuck) ) { //Melee and Close-up combat @@ -238,12 +250,13 @@ namespace MWMechanics if (mFollowTarget && distToTarget > rangeMelee) { //Close-up combat: just run up on target - mMovement.mPosition[1] = 1; + if(!canMoveByZ) mMovement.mPosition[1] = 1; } else { //Melee: stop running and attack mMovement.mPosition[1] = 0; + if(canMoveByZ) mMovement.mPosition[2] = 0; // When attacking with a weapon, choose between slash, thrust or chop if (actor.getClass().hasInventoryStore(actor)) @@ -295,15 +308,16 @@ namespace MWMechanics preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); } - if(preferShortcut) - { + if(canMoveByZ) preferShortcut = true; + + if(preferShortcut) + { mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); mForceNoShortcut = false; mShortcutFailPos.pos[0] = mShortcutFailPos.pos[1] = mShortcutFailPos.pos[2] = 0; - if(mPathFinder.isPathConstructed()) - mPathFinder.clearPath(); - } - else // if shortcut failed stick to path grid + mPathFinder.clearPath(); + } + else // if shortcut failed stick to path grid { if(!isStuck && mShortcutFailPos.pos[0] == 0.0f && mShortcutFailPos.pos[1] == 0.0f && mShortcutFailPos.pos[2] == 0.0f) { @@ -344,7 +358,7 @@ namespace MWMechanics } } - mMovement.mPosition[1] = 1; + if(!canMoveByZ) mMovement.mPosition[1] = 1; mReadyToAttack = false; } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 93c789af1a..2c63d5a142 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1018,6 +1018,7 @@ void CharacterController::update(float duration) vec.x *= mMovementSpeed; vec.y *= mMovementSpeed; + if(inwater || flying) vec.z *= mMovementSpeed; CharacterState movestate = CharState_None; CharacterState idlestate = CharState_SpecialIdle; @@ -1084,7 +1085,8 @@ void CharacterController::update(float duration) fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss, fatigue.getCurrent() < 0); cls.getCreatureStats(mPtr).setFatigue(fatigue); - if(sneak || inwater || flying) + // kind of hack, reason - creatures can move along z when in water/flying + if(sneak || ((inwater || flying) && mPtr.getRefData().getHandle() == "player")) vec.z = 0.0f; if (inwater || flying) @@ -1119,7 +1121,7 @@ void CharacterController::update(float duration) vec.y *= mult; vec.z = 0.0f; } - else if(vec.z > 0.0f && mJumpState == JumpState_None) + else if(!inwater && !flying && vec.z > 0.0f && mJumpState == JumpState_None) { // Started a jump. float z = cls.getJump(mPtr); @@ -1179,9 +1181,9 @@ void CharacterController::update(float duration) } else { - if(!(vec.z > 0.0f)) + if(!(vec.z > 0.0f)) mJumpState = JumpState_None; - vec.z = 0.0f; + if(!inwater && !flying) vec.z = 0.0f; if(std::abs(vec.x/2.0f) > std::abs(vec.y)) { From d3148555fad4ed85bb9e592003804e4f185f9b14 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 22 Apr 2014 22:16:14 -0500 Subject: [PATCH 007/545] Delete old framework files --- .../model/settings/settingcontainer.cpp | 82 ------- .../model/settings/settingcontainer.hpp | 47 ---- apps/opencs/model/settings/settingsitem.cpp | 104 --------- apps/opencs/model/settings/settingsitem.hpp | 67 ------ apps/opencs/view/settings/abstractblock.cpp | 112 --------- apps/opencs/view/settings/abstractblock.hpp | 82 ------- apps/opencs/view/settings/abstractpage.cpp | 44 ---- apps/opencs/view/settings/abstractpage.hpp | 70 ------ apps/opencs/view/settings/abstractwidget.cpp | 78 ------- apps/opencs/view/settings/abstractwidget.hpp | 69 ------ apps/opencs/view/settings/blankpage.cpp | 50 ---- apps/opencs/view/settings/blankpage.hpp | 28 --- apps/opencs/view/settings/customblock.cpp | 121 ---------- apps/opencs/view/settings/customblock.hpp | 47 ---- .../view/settings/datadisplayformatpage.cpp | 57 ----- .../view/settings/datadisplayformatpage.hpp | 33 --- apps/opencs/view/settings/editorpage.cpp | 53 ----- apps/opencs/view/settings/editorpage.hpp | 33 --- apps/opencs/view/settings/groupblock.cpp | 108 --------- apps/opencs/view/settings/groupblock.hpp | 43 ---- apps/opencs/view/settings/groupbox.cpp | 56 ----- apps/opencs/view/settings/groupbox.hpp | 28 --- apps/opencs/view/settings/itemblock.cpp | 115 ---------- apps/opencs/view/settings/itemblock.hpp | 48 ---- apps/opencs/view/settings/proxyblock.cpp | 152 ------------- apps/opencs/view/settings/proxyblock.hpp | 52 ----- apps/opencs/view/settings/settingwidget.cpp | 1 - apps/opencs/view/settings/settingwidget.hpp | 214 ------------------ apps/opencs/view/settings/toggleblock.cpp | 80 ------- apps/opencs/view/settings/toggleblock.hpp | 29 --- .../view/settings/usersettingsdialog.cpp | 119 ---------- .../view/settings/usersettingsdialog.hpp | 71 ------ apps/opencs/view/settings/windowpage.cpp | 144 ------------ apps/opencs/view/settings/windowpage.hpp | 34 --- 34 files changed, 2471 deletions(-) delete mode 100644 apps/opencs/model/settings/settingcontainer.cpp delete mode 100644 apps/opencs/model/settings/settingcontainer.hpp delete mode 100644 apps/opencs/model/settings/settingsitem.cpp delete mode 100644 apps/opencs/model/settings/settingsitem.hpp delete mode 100644 apps/opencs/view/settings/abstractblock.cpp delete mode 100644 apps/opencs/view/settings/abstractblock.hpp delete mode 100644 apps/opencs/view/settings/abstractpage.cpp delete mode 100644 apps/opencs/view/settings/abstractpage.hpp delete mode 100644 apps/opencs/view/settings/abstractwidget.cpp delete mode 100644 apps/opencs/view/settings/abstractwidget.hpp delete mode 100644 apps/opencs/view/settings/blankpage.cpp delete mode 100644 apps/opencs/view/settings/blankpage.hpp delete mode 100644 apps/opencs/view/settings/customblock.cpp delete mode 100644 apps/opencs/view/settings/customblock.hpp delete mode 100755 apps/opencs/view/settings/datadisplayformatpage.cpp delete mode 100755 apps/opencs/view/settings/datadisplayformatpage.hpp delete mode 100644 apps/opencs/view/settings/editorpage.cpp delete mode 100644 apps/opencs/view/settings/editorpage.hpp delete mode 100644 apps/opencs/view/settings/groupblock.cpp delete mode 100644 apps/opencs/view/settings/groupblock.hpp delete mode 100644 apps/opencs/view/settings/groupbox.cpp delete mode 100644 apps/opencs/view/settings/groupbox.hpp delete mode 100644 apps/opencs/view/settings/itemblock.cpp delete mode 100644 apps/opencs/view/settings/itemblock.hpp delete mode 100644 apps/opencs/view/settings/proxyblock.cpp delete mode 100644 apps/opencs/view/settings/proxyblock.hpp delete mode 100644 apps/opencs/view/settings/settingwidget.cpp delete mode 100644 apps/opencs/view/settings/settingwidget.hpp delete mode 100644 apps/opencs/view/settings/toggleblock.cpp delete mode 100644 apps/opencs/view/settings/toggleblock.hpp delete mode 100644 apps/opencs/view/settings/usersettingsdialog.cpp delete mode 100644 apps/opencs/view/settings/usersettingsdialog.hpp delete mode 100644 apps/opencs/view/settings/windowpage.cpp delete mode 100644 apps/opencs/view/settings/windowpage.hpp diff --git a/apps/opencs/model/settings/settingcontainer.cpp b/apps/opencs/model/settings/settingcontainer.cpp deleted file mode 100644 index a75a84ec55..0000000000 --- a/apps/opencs/model/settings/settingcontainer.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "settingcontainer.hpp" - -#include - -CSMSettings::SettingContainer::SettingContainer(QObject *parent) : - QObject(parent), mValue (0), mValues (0) -{ -} - -CSMSettings::SettingContainer::SettingContainer(const QString &value, QObject *parent) : - QObject(parent), mValue (new QString (value)), mValues (0) -{ -} - -void CSMSettings::SettingContainer::insert (const QString &value) -{ - if (mValue) - { - mValues = new QStringList; - mValues->push_back (*mValue); - mValues->push_back (value); - - delete mValue; - mValue = 0; - } - else - { - delete mValue; - mValue = new QString (value); - } - -} - -void CSMSettings::SettingContainer::update (const QString &value, int index) -{ - if (isEmpty()) - mValue = new QString(value); - - else if (mValue) - *mValue = value; - - else if (mValues) - mValues->replace(index, value); -} - -QString CSMSettings::SettingContainer::getValue (int index) const -{ - QString retVal(""); - - //if mValue is valid, it's a single-value property. - //ignore the index and return the value - if (mValue) - retVal = *mValue; - - //otherwise, if it's a multivalued property - //return the appropriate value at the index - else if (mValues) - { - if (index == -1) - retVal = mValues->at(0); - - else if (index < mValues->size()) - retVal = mValues->at(index); - } - - return retVal; -} - -int CSMSettings::SettingContainer::count () const -{ - int retVal = 0; - - if (!isEmpty()) - { - if (mValues) - retVal = mValues->size(); - else - retVal = 1; - } - - return retVal; -} diff --git a/apps/opencs/model/settings/settingcontainer.hpp b/apps/opencs/model/settings/settingcontainer.hpp deleted file mode 100644 index 5af298a57a..0000000000 --- a/apps/opencs/model/settings/settingcontainer.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SETTINGCONTAINER_HPP -#define SETTINGCONTAINER_HPP - -#include - -class QStringList; - -namespace CSMSettings -{ - class SettingContainer : public QObject - { - Q_OBJECT - - QString *mValue; - QStringList *mValues; - - public: - - explicit SettingContainer (QObject *parent = 0); - explicit SettingContainer (const QString &value, QObject *parent = 0); - - /// add a value to the container - /// multiple values supported - void insert (const QString &value); - - /// update an existing value - /// index specifies multiple values - void update (const QString &value, int index = 0); - - /// return value at specified index - QString getValue (int index = -1) const; - - /// retrieve list of all values - inline QStringList *getValues() const { return mValues; } - - /// return size of list - int count() const; - - /// test for empty container - /// useful for default-constructed containers returned by QMap when invalid key is passed - inline bool isEmpty() const { return (!mValue && !mValues); } - - inline bool isMultiValue() const { return (mValues); } - }; -} - -#endif // SETTINGCONTAINER_HPP diff --git a/apps/opencs/model/settings/settingsitem.cpp b/apps/opencs/model/settings/settingsitem.cpp deleted file mode 100644 index 5d897448ac..0000000000 --- a/apps/opencs/model/settings/settingsitem.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "settingsitem.hpp" - -#include - -bool CSMSettings::SettingsItem::updateItem (const QStringList *values) -{ - QStringList::ConstIterator it = values->begin(); - - //if the item is not multivalued, - //save the last value passed in the container - if (!mIsMultiValue) - { - it = values->end(); - it--; - } - - bool isValid = true; - QString value (""); - - for (; it != values->end(); ++it) - { - value = *it; - isValid = validate(value); - - //skip only the invalid values - if (!isValid) - continue; - - insert(value); - } - - return isValid; -} - -bool CSMSettings::SettingsItem::updateItem (const QString &value) -{ - //takes a value or a SettingsContainer and updates itself accordingly - //after validating the data against it's own definition - - QString newValue = value; - - if (!validate (newValue)) - newValue = mDefaultValue; - - bool success = (getValue() != newValue); - - if (success) - { - if (mIsMultiValue) - insert (newValue); - else - update (newValue); - } - return success; -} - -bool CSMSettings::SettingsItem::updateItem(int valueListIndex) -{ - bool success = false; - - if (mValueList) - { - if (mValueList->size() > valueListIndex) - success = updateItem (mValueList->at(valueListIndex)); - } - return success; -} - -bool CSMSettings::SettingsItem::validate (const QString &value) -{ - //if there is no value list or value pair, there is no validation to do - bool isValid = !(!mValueList->isEmpty() || mValuePair); - - if (!isValid && !mValueList->isEmpty()) - { - for (QStringList::Iterator it = mValueList->begin(); it != mValueList->end(); ++it) - // foreach (QString listItem, *mValueList) - { - isValid = (value == *it); - - if (isValid) - break; - } - } - else if (!isValid && mValuePair) - { - int numVal = value.toInt(); - - isValid = (numVal > mValuePair->left.toInt() && numVal < mValuePair->right.toInt()); - } - - return isValid; -} - -void CSMSettings::SettingsItem::setDefaultValue (const QString &value) -{ - mDefaultValue = value; - update (value); -} - -QString CSMSettings::SettingsItem::getDefaultValue() const -{ - return mDefaultValue; -} diff --git a/apps/opencs/model/settings/settingsitem.hpp b/apps/opencs/model/settings/settingsitem.hpp deleted file mode 100644 index 87a85e8e4e..0000000000 --- a/apps/opencs/model/settings/settingsitem.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef SETTINGSITEM_HPP -#define SETTINGSITEM_HPP - -#include -#include "support.hpp" -#include "settingcontainer.hpp" - -namespace CSMSettings -{ - /// Represents a setting including metadata - /// (valid values, ranges, defaults, and multivalue status - class SettingsItem : public SettingContainer - { - QStringPair *mValuePair; - QStringList *mValueList; - bool mIsMultiValue; - QString mDefaultValue; - - public: - explicit SettingsItem(QString name, bool isMultiValue, - const QString& defaultValue, QObject *parent = 0) - : SettingContainer(defaultValue, parent), - mIsMultiValue (isMultiValue), mValueList (0), - mValuePair (0), mDefaultValue (defaultValue) - { - QObject::setObjectName(name); - } - - /// updateItem overloads for updating setting value - /// provided a list of values (multi-valued), - /// a specific value - /// or an index value corresponding to the mValueList - bool updateItem (const QStringList *values); - bool updateItem (const QString &value); - bool updateItem (int valueListIndex); - - /// retrieve list of valid values for setting - inline QStringList *getValueList() { return mValueList; } - - /// write list of valid values for setting - inline void setValueList (QStringList *valueList) { mValueList = valueList; } - - /// valuePair used for spin boxes (max / min) - inline QStringPair *getValuePair() { return mValuePair; } - - /// set value range (spinbox / integer use) - inline void setValuePair (QStringPair valuePair) - { - delete mValuePair; - mValuePair = new QStringPair(valuePair); - } - - inline bool isMultivalue () { return mIsMultiValue; } - - void setDefaultValue (const QString &value); - QString getDefaultValue () const; - - private: - - /// Verifies that the supplied value is one of the following: - /// 1. Within the limits of the value pair (min / max) - /// 2. One of the values indicated in the value list - bool validate (const QString &value); - }; -} -#endif // SETTINGSITEM_HPP - diff --git a/apps/opencs/view/settings/abstractblock.cpp b/apps/opencs/view/settings/abstractblock.cpp deleted file mode 100644 index 65825ce8be..0000000000 --- a/apps/opencs/view/settings/abstractblock.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "abstractblock.hpp" - -CSVSettings::AbstractBlock::AbstractBlock(QWidget* parent) - : QObject (parent), mBox ( new GroupBox (parent) ), mWidgetParent (parent) -{} - -CSVSettings::AbstractBlock::AbstractBlock(bool isVisible, QWidget* parent) - : QObject (parent), mBox ( new GroupBox (isVisible, parent)), mWidgetParent (parent) -{} - -QLayout *CSVSettings::AbstractBlock::createLayout (Orientation direction, - bool isZeroMargin, QWidget* parent) -{ - QLayout *layout = 0; - - if (direction == Orient_Vertical) - layout = new QVBoxLayout (parent); - else - layout = new QHBoxLayout (parent); - - if (isZeroMargin) - layout->setContentsMargins(0, 0, 0, 0); - - return layout; -} - -QGroupBox *CSVSettings::AbstractBlock::getGroupBox() -{ - return mBox; -} - -CSVSettings::AbstractWidget *CSVSettings::AbstractBlock::buildWidget (const QString& widgetName, WidgetDef &def, - QLayout *layout, bool isConnected) const -{ - AbstractWidget *widg = 0; - - switch (def.type) - { - - case Widget_RadioButton: - widg = new SettingWidget (def, layout, mBox); - break; - - case Widget_SpinBox: - widg = new SettingWidget (def, layout, mBox); - break; - - case Widget_CheckBox: - widg = new SettingWidget (def, layout, mBox); - break; - - case Widget_LineEdit: - widg = new SettingWidget (def, layout, mBox); - break; - - case Widget_ListBox: - widg = new SettingWidget (def, layout, mBox); - break; - - case Widget_ComboBox: - widg = new SettingWidget (def, layout, mBox); - break; - - default: - break; - }; - - if (!mBox->layout()) - mBox->setLayout(widg->getLayout()); - - widg->widget()->setObjectName(widgetName); - - if (isConnected) - connect (widg, SIGNAL (signalUpdateItem (const QString &)), this, SLOT (slotUpdate (const QString &))); - connect (this, SIGNAL (signalUpdateWidget (const QString &)), widg, SLOT (slotUpdateWidget (const QString &) )); - - return widg; -} - -void CSVSettings::AbstractBlock::setVisible (bool isVisible) -{ - mBox->setBorderVisibility (isVisible); -} - -bool CSVSettings::AbstractBlock::isVisible () const -{ - return mBox->borderVisibile(); -} - -QWidget *CSVSettings::AbstractBlock::getParent() const -{ - return mWidgetParent; -} - -void CSVSettings::AbstractBlock::slotUpdate (const QString &value) -{ - slotUpdateSetting (objectName(), value); -} - -void CSVSettings::AbstractBlock::slotSetEnabled(bool value) -{ - mBox->setEnabled(value); -} - -void CSVSettings::AbstractBlock::slotUpdateSetting (const QString &settingName, const QString &settingValue) -{ - bool doEmit = true; - updateBySignal (settingName, settingValue, doEmit); - - if (doEmit) - emit signalUpdateSetting (settingName, settingValue); -} diff --git a/apps/opencs/view/settings/abstractblock.hpp b/apps/opencs/view/settings/abstractblock.hpp deleted file mode 100644 index 361339fe25..0000000000 --- a/apps/opencs/view/settings/abstractblock.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef ABSTRACTBLOCK_HPP -#define ABSTRACTBLOCK_HPP - -#include -#include - -#include "settingwidget.hpp" -#include "../../model/settings/settingsitem.hpp" -#include "groupbox.hpp" - -namespace CSVSettings -{ - - /// Abstract base class for all blocks - class AbstractBlock : public QObject - { - Q_OBJECT - - protected: - - typedef QMap SettingsItemMap; - GroupBox *mBox; - QWidget *mWidgetParent; - - public: - - explicit AbstractBlock (QWidget *parent = 0); - explicit AbstractBlock (bool isVisible, QWidget *parent = 0); - - QGroupBox *getGroupBox(); - void setVisible (bool isVisible); - bool isVisible() const; - - virtual CSMSettings::SettingList *getSettings() = 0; - - /// update settings found in the passed map and are encapsulated by the block - virtual bool updateSettings (const CSMSettings::SettingMap &settings) = 0; - - /// update callback function called from update slot - /// used for updating application-level settings in the editor - virtual bool updateBySignal (const QString &name, const QString &value, bool &doEmit) - { return false; } - - protected: - - /// Creates the layout for the block's QGroupBox - QLayout *createLayout (Orientation direction, bool isZeroMargin, QWidget* parent = 0); - - /// Creates widgets that exist as direct children of the block - AbstractWidget *buildWidget (const QString &widgetName, WidgetDef &wDef, - QLayout *layout = 0, bool isConnected = true) const; - - QWidget *getParent() const; - - public slots: - - /// enables / disables block-level widgets based on signals from other widgets - /// used in ToggleBlock - void slotSetEnabled (bool value); - - /// receives updates to applicaion-level settings in the Editor - void slotUpdateSetting (const QString &settingName, const QString &settingValue); - - private slots: - - /// receives updates to a setting in the block pushed from the application level - void slotUpdate (const QString &value); - - signals: - - /// signal to UserSettings instance - void signalUpdateSetting (const QString &propertyName, const QString &propertyValue); - - /// signal to widget for updating widget value - void signalUpdateWidget (const QString & value); - - /// ProxyBlock use only. - /// Name and value correspond to settings for which the block is a proxy. - void signalUpdateProxySetting (const QString &propertyName, const QString &propertyValue); - }; -} -#endif // ABSTRACTBLOCK_HPP diff --git a/apps/opencs/view/settings/abstractpage.cpp b/apps/opencs/view/settings/abstractpage.cpp deleted file mode 100644 index e6c605275d..0000000000 --- a/apps/opencs/view/settings/abstractpage.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "abstractpage.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CSVSettings::AbstractPage::AbstractPage(QWidget *parent): - QWidget(parent) -{ - QGridLayout *pageLayout = new QGridLayout(this); - setLayout (pageLayout); -} - -CSVSettings::AbstractPage::AbstractPage(const QString &pageName, QWidget *parent): - QWidget(parent) -{ - QWidget::setObjectName (pageName); - - QGridLayout *pageLayout = new QGridLayout(this); - setLayout (pageLayout); -} - -CSVSettings::AbstractPage::~AbstractPage() -{ -} - -CSMSettings::SettingList *CSVSettings::AbstractPage::getSettings() -{ - CSMSettings::SettingList *settings = new CSMSettings::SettingList(); - - foreach (AbstractBlock *block, mAbstractBlocks) - { - CSMSettings::SettingList *groupSettings = block->getSettings(); - settings->append (*groupSettings); - } - - return settings; -} diff --git a/apps/opencs/view/settings/abstractpage.hpp b/apps/opencs/view/settings/abstractpage.hpp deleted file mode 100644 index 77ef4524f0..0000000000 --- a/apps/opencs/view/settings/abstractpage.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef ABSTRACTPAGE_HPP -#define ABSTRACTPAGE_HPP - -#include -#include -#include - -#include "abstractblock.hpp" - -class SettingMap; -class SettingList; - -namespace CSVSettings { - - typedef QList AbstractBlockList; - - /// Abstract base class for all setting pages in the dialog - - /// \todo Scripted implementation of settings should eliminate the need - /// \todo derive page classes. - /// \todo AbstractPage should be replaced with a general page construction class. - class AbstractPage: public QWidget - { - - protected: - - AbstractBlockList mAbstractBlocks; - - public: - - AbstractPage(QWidget *parent = 0); - AbstractPage (const QString &pageName, QWidget* parent = 0); - - ~AbstractPage(); - - virtual void setupUi() = 0; - - /// triggers widgiet initialization at the page level. All widgets updated to - /// current setting values - virtual void initializeWidgets (const CSMSettings::SettingMap &settings) = 0; - - /// retrieve the list of settings local to the page. - CSMSettings::SettingList *getSettings(); - - void setObjectName(); - - protected: - - /// Create a block for the page. - /// Block is constructed using passed definition struct - /// Page level-layout is created and assigned - template - AbstractBlock *buildBlock (T *def) - { - S *block = new S (this); - int ret = block->build (def); - - if (ret < 0) - return 0; - - QGroupBox *box = block->getGroupBox(); - QWidget::layout()->addWidget (box); - - return block; - } - - }; -} - -#endif // ABSTRACTPAGE_HPP diff --git a/apps/opencs/view/settings/abstractwidget.cpp b/apps/opencs/view/settings/abstractwidget.cpp deleted file mode 100644 index f268d3b279..0000000000 --- a/apps/opencs/view/settings/abstractwidget.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "abstractwidget.hpp" - -#include -#include - -void CSVSettings::AbstractWidget::build(QWidget *widget, WidgetDef &def, bool noLabel) -{ - if (!mLayout) - createLayout(def.orientation, true); - - buildLabelAndWidget (widget, def, noLabel); - -} - -void CSVSettings::AbstractWidget::buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel) -{ - if (def.widgetWidth > -1) - widget->setFixedWidth (def.widgetWidth); - - if (!(def.caption.isEmpty() || noLabel) ) - { - QLabel *label = new QLabel (def.caption, &dynamic_cast( *parent())); - label->setBuddy (widget); - mLayout->addWidget (label); - - if (def.labelWidth > -1) - label->setFixedWidth(def.labelWidth); - } - - mLayout->addWidget (widget); - mLayout->setAlignment (widget, getAlignment (def.widgetAlignment)); -} - -void CSVSettings::AbstractWidget::createLayout - (Orientation direction, bool isZeroMargin) -{ - if (direction == Orient_Vertical) - mLayout = new QVBoxLayout (); - else - mLayout = new QHBoxLayout (); - - if (isZeroMargin) - mLayout->setContentsMargins(0, 0, 0, 0); -} - -QFlags CSVSettings::AbstractWidget::getAlignment (CSVSettings::Alignment flag) -{ - return QFlags(static_cast(flag)); -} - -QLayout *CSVSettings::AbstractWidget::getLayout() -{ - return mLayout; -} - -void CSVSettings::AbstractWidget::slotUpdateWidget (const QString &value) -{ - updateWidget (value); -} - -void CSVSettings::AbstractWidget::slotUpdateItem(const QString &value) -{ - emit signalUpdateItem (value); -} - -void CSVSettings::AbstractWidget::slotUpdateItem(bool value) -{ - if (value) - emit signalUpdateItem (widget()->objectName()); -} - -void CSVSettings::AbstractWidget::slotUpdateItem(int value) -{ - emit signalUpdateItem (QString::number(value)); -} - -void CSVSettings::AbstractWidget::slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous) -{} diff --git a/apps/opencs/view/settings/abstractwidget.hpp b/apps/opencs/view/settings/abstractwidget.hpp deleted file mode 100644 index 325de2bd23..0000000000 --- a/apps/opencs/view/settings/abstractwidget.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef ABSTRACTWIDGET_HPP -#define ABSTRACTWIDGET_HPP - -#include -#include "support.hpp" - -class QLayout; - -namespace CSVSettings -{ - /// Abstract base class for widgets which are used in user preferences dialog - class AbstractWidget : public QObject - { - Q_OBJECT - - QLayout *mLayout; - - public: - - /// Passed layout is assigned the constructed widget. - /// if no layout is passed, one is created. - explicit AbstractWidget (QLayout *layout = 0, QWidget* parent = 0) - : QObject (parent), mLayout (layout) - {} - - /// retrieve layout for insertion into itemblock - QLayout *getLayout(); - - /// create the derived widget instance - void build (QWidget* widget, WidgetDef &def, bool noLabel = false); - - /// reference to the derived widget instance - virtual QWidget *widget() = 0; - - protected: - - /// Callback called by receiving slot for widget udpates - virtual void updateWidget (const QString &value) = 0; - - /// Converts user-defined enum to Qt equivalents - QFlags getAlignment (Alignment flag); - - private: - - /// Creates layout and assigns label and widget as appropriate - void createLayout (Orientation direction, bool isZeroMargin); - - /// Creates label and widget according to passed definition - void buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel); - - - signals: - - /// outbound update signal - void signalUpdateItem (const QString &value); - - public slots: - - /// receives inbound updates - void slotUpdateWidget (const QString &value); - - /// Overloads for outbound updates from derived widget signal - void slotUpdateItem (const QString &value); - void slotUpdateItem (bool value); - void slotUpdateItem (int value); - void slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous); - }; -} -#endif // ABSTRACTWIDGET_HPP diff --git a/apps/opencs/view/settings/blankpage.cpp b/apps/opencs/view/settings/blankpage.cpp deleted file mode 100644 index 837a31bee1..0000000000 --- a/apps/opencs/view/settings/blankpage.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "blankpage.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_MAC -#include -#endif - -#include "../../model/settings/usersettings.hpp" -#include "groupblock.hpp" -#include "toggleblock.hpp" - -CSVSettings::BlankPage::BlankPage(QWidget *parent): - AbstractPage("Blank", parent) -{ - -} - -CSVSettings::BlankPage::BlankPage(const QString &title, QWidget *parent): - AbstractPage(title, parent) -{ - // Hacks to get the stylesheet look properly -#ifdef Q_OS_MAC - QPlastiqueStyle *style = new QPlastiqueStyle; - //profilesComboBox->setStyle(style); -#endif - - setupUi(); -} - -void CSVSettings::BlankPage::setupUi() -{ - QGroupBox *pageBox = new QGroupBox(this); - layout()->addWidget(pageBox); -} - -void CSVSettings::BlankPage::initializeWidgets (const CSMSettings::SettingMap &settings) -{ - //iterate each item in each blocks in this section - //validate the corresponding setting against the defined valuelist if any. - foreach (AbstractBlock *block, mAbstractBlocks) - block->updateSettings (settings); -} diff --git a/apps/opencs/view/settings/blankpage.hpp b/apps/opencs/view/settings/blankpage.hpp deleted file mode 100644 index 07049fb71f..0000000000 --- a/apps/opencs/view/settings/blankpage.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef BLANKPAGE_HPP -#define BLANKPAGE_HPP - -#include "abstractpage.hpp" - -class QGroupBox; - -namespace CSVSettings { - - class UserSettings; - class AbstractBlock; - - /// Derived page with no widgets - /// Reference use only. - class BlankPage : public AbstractPage - { - - public: - - BlankPage (QWidget *parent = 0); - BlankPage (const QString &title, QWidget *parent); - - void setupUi(); - void initializeWidgets (const CSMSettings::SettingMap &settings); - }; -} - -#endif // BLANKPAGE_HPP diff --git a/apps/opencs/view/settings/customblock.cpp b/apps/opencs/view/settings/customblock.cpp deleted file mode 100644 index bbceafabe9..0000000000 --- a/apps/opencs/view/settings/customblock.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "customblock.hpp" -#include "groupblock.hpp" -#include "itemblock.hpp" -#include "proxyblock.hpp" - -CSVSettings::CustomBlock::CustomBlock (QWidget *parent) : AbstractBlock (parent) -{ -} - -int CSVSettings::CustomBlock::build(GroupBlockDefList &defList, GroupBlockDefList::iterator *it) -{ - int retVal = 0; - - GroupBlockDefList::iterator defaultIt; - GroupBlockDefList::iterator listIt = defList.begin(); - GroupBlockDefList::iterator proxyIt = defaultIt; - - if (it) - listIt = *it; - - ProxyBlock *proxyBlock = new ProxyBlock(getParent()); - - for (; listIt != defList.end(); ++listIt) - { - if (!(*listIt)->isProxy) - retVal = buildGroupBlock (*listIt); - else - { - mGroupList << proxyBlock; - proxyIt = listIt; - } - } - - if (proxyIt != defaultIt) - retVal = buildProxyBlock (*proxyIt, proxyBlock); - - return retVal; -} - -CSVSettings::GroupBox *CSVSettings::CustomBlock::buildGroupBox (Orientation orientation) -{ - GroupBox *box = new GroupBox (false, mBox); - createLayout (orientation, true, box); - - return box; -} - -int CSVSettings::CustomBlock::buildGroupBlock(GroupBlockDef *def) -{ - GroupBlock *block = new GroupBlock (getParent()); - - mGroupList << block; - - connect (block, SIGNAL (signalUpdateSetting(const QString &, const QString &)), - this, SLOT (slotUpdateSetting (const QString &, const QString &))); - - return block->build(def); -} - -int CSVSettings::CustomBlock::buildProxyBlock(GroupBlockDef *def, ProxyBlock *block) -{ - if (def->settingItems.size() != 1) - return -1; - - int retVal = block->build(def); - - if (retVal != 0) - return retVal; - - // The first settingItem is the proxy setting, containing the list of settings bound to it. - foreach (QStringList *list, *(def->settingItems.at(0)->proxyList)) - { - QString proxiedBlockName = list->at(0); - - //iterate each group in the custom block, matching it to each proxied setting - //and connecting it appropriately - foreach (GroupBlock *groupBlock, mGroupList) - { - ItemBlock *proxiedBlock = groupBlock->getItemBlock (proxiedBlockName); - - if (proxiedBlock) - { - block->addSetting(proxiedBlock, list); - - //connect the proxy block's update signal to the custom block's slot - connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)), - this, SLOT (slotUpdateSetting (const QString &, const QString &))); - } - } - } - - return 0; -} - -CSMSettings::SettingList *CSVSettings::CustomBlock::getSettings() -{ - CSMSettings::SettingList *settings = new CSMSettings::SettingList(); - - foreach (GroupBlock *block, mGroupList) - { - CSMSettings::SettingList *groupSettings = block->getSettings(); - - if (groupSettings) - settings->append(*groupSettings); - } - - return settings; -} - -bool CSVSettings::CustomBlock::updateSettings (const CSMSettings::SettingMap &settings) -{ - bool success = true; - - foreach (GroupBlock *block, mGroupList) - { - bool success2 = block->updateSettings (settings); - success = success && success2; - } - - return success; -} diff --git a/apps/opencs/view/settings/customblock.hpp b/apps/opencs/view/settings/customblock.hpp deleted file mode 100644 index 54c50f395f..0000000000 --- a/apps/opencs/view/settings/customblock.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef CUSTOMBLOCK_HPP -#define CUSTOMBLOCK_HPP - -#include "abstractblock.hpp" - -namespace CSVSettings -{ - - class ProxyBlock; - - /// Base class for customized user preference setting blocks - /// Special block classes should be derived from CustomBlock - class CustomBlock : public AbstractBlock - { - - protected: - - GroupBlockList mGroupList; - - public: - - explicit CustomBlock (QWidget *parent = 0); - - /// Update settings local to the block - bool updateSettings (const CSMSettings::SettingMap &settings); - - /// Retrieve settings local to the block - CSMSettings::SettingList *getSettings(); - - /// construct the block using the passed definition - int build (GroupBlockDefList &defList, GroupBlockDefList::Iterator *it = 0); - - protected: - - /// construct the block groupbox - GroupBox *buildGroupBox (Orientation orientation); - - private: - - /// Construction function for creating a standard GroupBlock child - int buildGroupBlock(GroupBlockDef *def); - - /// Construction function for creating a standard ProxyBlock child - int buildProxyBlock(GroupBlockDef *def, ProxyBlock *block); - }; -} -#endif // CUSTOMBLOCK_HPP diff --git a/apps/opencs/view/settings/datadisplayformatpage.cpp b/apps/opencs/view/settings/datadisplayformatpage.cpp deleted file mode 100755 index 332b68f5c4..0000000000 --- a/apps/opencs/view/settings/datadisplayformatpage.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "datadisplayformatpage.hpp" -#include "groupblock.hpp" -#include "../../model/settings/usersettings.hpp" - -CSVSettings::DataDisplayFormatPage::DataDisplayFormatPage(QWidget* parent) : - AbstractPage("Display Format", parent) -{ - setupUi(); -} - -CSVSettings::GroupBlockDef *CSVSettings::DataDisplayFormatPage::setupDataDisplay( const QString &title) -{ - GroupBlockDef *statusBlock = new GroupBlockDef(QString(title)); - - SettingsItemDef *statusItem = new SettingsItemDef (statusBlock->title, "Icon Only"); - *(statusItem->valueList) << QString("Icon and Text") << QString("Icon Only") << QString("Text Only"); - - WidgetDef statusWidget (Widget_RadioButton); - statusWidget.valueList = statusItem->valueList; - - statusItem->widget = statusWidget; - - statusBlock->settingItems << statusItem; - - statusBlock->isZeroMargin = false; - - return statusBlock; -} - - -void CSVSettings::DataDisplayFormatPage::setupUi() -{ - - mAbstractBlocks << buildBlock (setupDataDisplay ("Record Status Display")); - mAbstractBlocks << buildBlock (setupDataDisplay ("Referenceable ID Type Display")); - - foreach (AbstractBlock *block, mAbstractBlocks) - { - connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)), - this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) ); - } - - connect ( this, - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)), - &(CSMSettings::UserSettings::instance()), - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &))); - -} - -void CSVSettings::DataDisplayFormatPage::initializeWidgets (const CSMSettings::SettingMap &settings) -{ - //iterate each item in each blocks in this section - //validate the corresponding setting against the defined valuelist if any. - for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin(); - it_block != mAbstractBlocks.end(); ++it_block) - (*it_block)->updateSettings (settings); -} diff --git a/apps/opencs/view/settings/datadisplayformatpage.hpp b/apps/opencs/view/settings/datadisplayformatpage.hpp deleted file mode 100755 index b785bbd238..0000000000 --- a/apps/opencs/view/settings/datadisplayformatpage.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef EDITORPAGE_HPP -#define EDITORPAGE_HPP - -#include "support.hpp" -#include "abstractpage.hpp" - -namespace CSVSettings -{ - class DataDisplayFormatPage : public AbstractPage - { - Q_OBJECT - - public: - explicit DataDisplayFormatPage(QWidget *parent = 0); - - void initializeWidgets (const CSMSettings::SettingMap &settings); - void setupUi(); - - private: - - /// User preference view of the record status delegate's icon / text setting - GroupBlockDef *setupDataDisplay(const QString &); - - signals: - - /// Signals up for changes to editor application-level settings - void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue); - - public slots: - }; -} - -#endif // EDITORPAGE_HPP diff --git a/apps/opencs/view/settings/editorpage.cpp b/apps/opencs/view/settings/editorpage.cpp deleted file mode 100644 index 153ac1551d..0000000000 --- a/apps/opencs/view/settings/editorpage.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "editorpage.hpp" -#include "groupblock.hpp" -#include "../../model/settings/usersettings.hpp" - -CSVSettings::EditorPage::EditorPage(QWidget* parent) : - AbstractPage("Display Format", parent) -{ - setupUi(); -} - -CSVSettings::GroupBlockDef *CSVSettings::EditorPage::setupRecordStatusDisplay() -{ - GroupBlockDef *statusBlock = new GroupBlockDef(QString("Record Status Display")); - - SettingsItemDef *statusItem = new SettingsItemDef (statusBlock->title, "Icon and Text"); - *(statusItem->valueList) << QString("Icon and Text") << QString("Icon Only") << QString("Text Only"); - - WidgetDef statusWidget (Widget_RadioButton); - statusWidget.valueList = statusItem->valueList; - - statusItem->widget = statusWidget; - - statusBlock->settingItems << statusItem; - - return statusBlock; -} - -void CSVSettings::EditorPage::setupUi() -{ - - mAbstractBlocks << buildBlock(setupRecordStatusDisplay()); - - foreach (AbstractBlock *block, mAbstractBlocks) - { - connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)), - this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) ); - } - - connect ( this, - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)), - &(CSMSettings::UserSettings::instance()), - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &))); - -} - -void CSVSettings::EditorPage::initializeWidgets (const CSMSettings::SettingMap &settings) -{ - //iterate each item in each blocks in this section - //validate the corresponding setting against the defined valuelist if any. - for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin(); - it_block != mAbstractBlocks.end(); ++it_block) - (*it_block)->updateSettings (settings); -} diff --git a/apps/opencs/view/settings/editorpage.hpp b/apps/opencs/view/settings/editorpage.hpp deleted file mode 100644 index 85215edabf..0000000000 --- a/apps/opencs/view/settings/editorpage.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef EDITORPAGE_HPP -#define EDITORPAGE_HPP - -#include "support.hpp" -#include "abstractpage.hpp" - -namespace CSVSettings -{ - class EditorPage : public AbstractPage - { - Q_OBJECT - - public: - explicit EditorPage(QWidget *parent = 0); - - void initializeWidgets (const CSMSettings::SettingMap &settings); - void setupUi(); - - private: - - /// User preference view of the record status delegate's icon / text setting - GroupBlockDef *setupRecordStatusDisplay(); - - signals: - - /// Signals up for changes to editor application-level settings - void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue); - - public slots: - }; -} - -#endif // EDITORPAGE_HPP diff --git a/apps/opencs/view/settings/groupblock.cpp b/apps/opencs/view/settings/groupblock.cpp deleted file mode 100644 index e31e526c03..0000000000 --- a/apps/opencs/view/settings/groupblock.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "groupblock.hpp" -#include "itemblock.hpp" - -CSVSettings::GroupBlock::GroupBlock (QWidget* parent) - : AbstractBlock (parent) -{} - -CSVSettings::GroupBlock::GroupBlock (bool isVisible, QWidget *parent) - : AbstractBlock (isVisible, parent) -{} - -int CSVSettings::GroupBlock::build (GroupBlockDef *def) -{ - - if (def->settingItems.size() == 0) - return -1; - - int retVal = 0; - - setVisible (def->isVisible); - - mBox->setLayout(createLayout (def->widgetOrientation, def->isZeroMargin)); - - setObjectName (def->title); - mBox->setTitle (def->title); - - foreach (SettingsItemDef *itemDef, def->settingItems) - { - ItemBlock *block = new ItemBlock (mBox); - - if (block->build (*itemDef) < 0) - { - retVal = -2; - break; - } - - mItemBlockList << block; - mBox->layout()->addWidget (block->getGroupBox()); - - connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)), - this, SLOT (slotUpdateSetting (const QString &, const QString &) )); - } - - return retVal; -} - -CSMSettings::SettingList *CSVSettings::GroupBlock::getSettings() -{ - CSMSettings::SettingList *settings = 0; - - foreach (ItemBlock *block, mItemBlockList) - { - if (!settings) - settings = new CSMSettings::SettingList(); - - settings->append(*(block->getSettings ())); - } - - return settings; -} - -CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (const QString &name, ItemBlockList *blockList) -{ - ItemBlock *retBlock = 0; - - if (!blockList) - blockList = &mItemBlockList; - - foreach (ItemBlock *block, *blockList) - { - if (block->objectName() == name) - { - retBlock = block; - break; - } - } - - return retBlock; -} - -CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (int index) -{ - ItemBlock *retBlock = 0; - - if (mItemBlockList.size() > index) - retBlock = mItemBlockList.at(index); - - return retBlock; -} - -bool CSVSettings::GroupBlock::updateSettings (const CSMSettings::SettingMap &settings) -{ - bool success = true; - - //update all non-proxy settings - foreach (ItemBlock *block, mItemBlockList) - { - CSMSettings::SettingContainer *setting = settings[block->objectName()]; - - if (setting) - { - bool success2 = block->update (setting->getValue()); - success = success && success2; - } - } - - return success; -} diff --git a/apps/opencs/view/settings/groupblock.hpp b/apps/opencs/view/settings/groupblock.hpp deleted file mode 100644 index 5c0754193c..0000000000 --- a/apps/opencs/view/settings/groupblock.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef GROUPBLOCK_HPP -#define GROUPBLOCK_HPP - -#include -#include "abstractblock.hpp" - -namespace CSVSettings -{ - class ItemBlock; - - /// Base class for group blocks. - /// Derived block classes should use CustomBlock - class GroupBlock : public AbstractBlock - { - ItemBlockList mItemBlockList; - - public: - GroupBlock (QWidget* parent = 0); - GroupBlock (bool isVisible, QWidget *parent = 0); - - /// build the gorup block based on passed definition - int build (GroupBlockDef *def); - - /// update settings local to the group block - bool updateSettings (const CSMSettings::SettingMap &settings); - - /// retrieve setting list local to the group block - CSMSettings::SettingList *getSettings(); - - /// retrieve item block by name from the passed list or local list - ItemBlock *getItemBlock (const QString &name, ItemBlockList *blockList = 0); - - /// retrieve the item block by index from the local list - ItemBlock *getItemBlock (int index); - - protected: - - /// create block layout based on passed definition - int buildLayout (GroupBlockDef &def); - - }; -} -#endif // GROUPBLOCK_HPP diff --git a/apps/opencs/view/settings/groupbox.cpp b/apps/opencs/view/settings/groupbox.cpp deleted file mode 100644 index da2cc25711..0000000000 --- a/apps/opencs/view/settings/groupbox.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "groupbox.hpp" - -const QString CSVSettings::GroupBox::INVISIBLE_BOX_STYLE = - QString::fromUtf8("QGroupBox { border: 0px; padding 0px; margin: 0px;}"); - -CSVSettings::GroupBox::GroupBox(QWidget *parent) : - QGroupBox (parent) -{ - initBox(); -} - -CSVSettings::GroupBox::GroupBox (bool isVisible, QWidget *parent) : - QGroupBox (parent) -{ - initBox(isVisible); -} - -void CSVSettings::GroupBox::initBox(bool isVisible) -{ - setFlat (true); - VISIBLE_BOX_STYLE = styleSheet(); - - if (!isVisible) - setStyleSheet (INVISIBLE_BOX_STYLE); -} - -bool CSVSettings::GroupBox::borderVisibile() const -{ - return (styleSheet() != INVISIBLE_BOX_STYLE); -} - -void CSVSettings::GroupBox::setTitle (const QString &title) -{ - if (borderVisibile() ) - { - QGroupBox::setTitle (title); - setMinimumWidth(); - } -} - -void CSVSettings::GroupBox::setBorderVisibility (bool value) -{ - if (value) - setStyleSheet(VISIBLE_BOX_STYLE); - else - setStyleSheet(INVISIBLE_BOX_STYLE); -} - -void CSVSettings::GroupBox::setMinimumWidth() -{ - //set minimum width to accommodate title, if needed - //1.5 multiplier to account for bold title. - QFontMetrics fm (font()); - int minWidth = fm.width(title()); - QGroupBox::setMinimumWidth (minWidth * 1.5); -} diff --git a/apps/opencs/view/settings/groupbox.hpp b/apps/opencs/view/settings/groupbox.hpp deleted file mode 100644 index 9d3a019363..0000000000 --- a/apps/opencs/view/settings/groupbox.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef GROUPBOX_HPP -#define GROUPBOX_HPP - -#include - -namespace CSVSettings -{ - /// Custom implementation of QGroupBox to be used with block classes - class GroupBox : public QGroupBox - { - static const QString INVISIBLE_BOX_STYLE; - QString VISIBLE_BOX_STYLE; //not a const... - - public: - explicit GroupBox (QWidget *parent = 0); - explicit GroupBox (bool isVisible, QWidget *parent = 0); - - void setTitle (const QString &title); - void setBorderVisibility (bool value); - bool borderVisibile() const; - - private: - void setMinimumWidth(); - void initBox(bool isVisible = true); - }; -} - -#endif // GROUPBOX_HPP diff --git a/apps/opencs/view/settings/itemblock.cpp b/apps/opencs/view/settings/itemblock.cpp deleted file mode 100644 index 9cb0ae1a1a..0000000000 --- a/apps/opencs/view/settings/itemblock.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "itemblock.hpp" - -#include - -CSVSettings::ItemBlock::ItemBlock (QWidget* parent) - : mSetting (0), AbstractBlock (false, parent) -{ -} - -int CSVSettings::ItemBlock::build(SettingsItemDef &iDef) -{ - buildItemBlock (iDef); - buildItemBlockWidgets (iDef); - - return 0; -} - -void CSVSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef) -{ - WidgetDef wDef = iDef.widget; - QLayout *blockLayout = 0; - QString defaultValue = iDef.defaultValue; - - switch (wDef.type) - { - - case Widget_CheckBox: - case Widget_RadioButton: - - foreach (QString item, *(iDef.valueList)) - { - wDef.caption = item; - wDef.isDefault = (item == defaultValue); - - blockLayout = buildWidget (item, wDef, blockLayout)->getLayout(); - } - - break; - - case Widget_ComboBox: - case Widget_ListBox: - - //assign the item's value list to the widget's value list. - //pass through to default to finish widget construction. - if (!wDef.valueList) - wDef.valueList = iDef.valueList; - - default: - //only one instance of this non-list widget type. - //Set it's value to the default value for the item and build the widget. - - if (wDef.value.isEmpty()) - wDef.value = iDef.defaultValue; - - buildWidget (iDef.name, wDef); - } -} - -void CSVSettings::ItemBlock::buildItemBlock (SettingsItemDef &iDef) -{ - QString defaultValue = iDef.defaultValue; - - setObjectName(iDef.name); - - mSetting = new CSMSettings::SettingsItem (objectName(), - iDef.hasMultipleValues, iDef.defaultValue, - parent()); - - if (iDef.valueList) - mSetting->setValueList(iDef.valueList); - - if (!iDef.minMax.isEmpty()) - mSetting->setValuePair(iDef.minMax); -} - - -bool CSVSettings::ItemBlock::update (const QString &value) -{ - bool success = updateItem (value); - - if (success) - signalUpdateWidget (value); - - return success; -} - - -bool CSVSettings::ItemBlock::updateItem (const QString &value) -{ - return mSetting->updateItem(value); -} - - -bool CSVSettings::ItemBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit) -{ - bool success = (mSetting->getValue() != value); - - if (success) - success = updateItem(value); - - return success; -} - -CSMSettings::SettingList *CSVSettings::ItemBlock::getSettings () -{ - CSMSettings::SettingList *list = new CSMSettings::SettingList(); - list->push_back(mSetting); - - return list; -} - -QString CSVSettings::ItemBlock::getValue() const -{ - return mSetting->getValue(); -} diff --git a/apps/opencs/view/settings/itemblock.hpp b/apps/opencs/view/settings/itemblock.hpp deleted file mode 100644 index 2d1d45d418..0000000000 --- a/apps/opencs/view/settings/itemblock.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef ITEMBLOCK_HPP -#define ITEMBLOCK_HPP - -#include "abstractblock.hpp" - -namespace CSVSettings -{ - - class ItemBlock : public AbstractBlock - { - CSMSettings::SettingsItem *mSetting; - WidgetList mWidgetList; - - public: - - ItemBlock (QWidget* parent = 0); - - /// pure virtual function not implemented - bool updateSettings (const CSMSettings::SettingMap &settings) { return false; } - - CSMSettings::SettingList *getSettings (); - - QString getValue () const; - - /// item blocks encapsulate only one setting - int getSettingCount(); - - /// update setting value and corresponding widget - bool update (const QString &value); - - /// virtual construction function - int build(SettingsItemDef &iDef); - - private: - - /// custom construction function - void buildItemBlock (SettingsItemDef& iDef); - void buildItemBlockWidgets (SettingsItemDef& iDef); - - /// update the setting value - bool updateItem (const QString &); - - /// callback function triggered when update to application level is signalled - bool updateBySignal (const QString &name, const QString &value, bool &doEmit); - }; -} - -#endif // ITEMBLOCK_HPP diff --git a/apps/opencs/view/settings/proxyblock.cpp b/apps/opencs/view/settings/proxyblock.cpp deleted file mode 100644 index 81cc54fca5..0000000000 --- a/apps/opencs/view/settings/proxyblock.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "proxyblock.hpp" -#include "itemblock.hpp" - -CSVSettings::ProxyBlock::ProxyBlock (QWidget *parent) - : GroupBlock (parent) -{ -} -int CSVSettings::ProxyBlock::build (GroupBlockDef *proxyDef) -{ - //get the list of pre-defined values for the proxy - mValueList = proxyDef->settingItems.at(0)->valueList; - - bool success = GroupBlock::build(proxyDef); - - //connect the item block of the proxy setting to the proxy-update slot - connect (getItemBlock(0), SIGNAL (signalUpdateSetting(const QString &, const QString &)), - this, SLOT (slotUpdateProxySetting (const QString &, const QString &))); - - return success; -} - -void CSVSettings::ProxyBlock::addSetting (ItemBlock *settingBlock, QStringList *proxyList) -{ - //connect the item block of the proxied seting to the generic update slot - connect (settingBlock, SIGNAL (signalUpdateSetting(const QString &, const QString &)), - this, SLOT (slotUpdateProxySetting(const QString &, const QString &))); - - mProxiedItemBlockList << settingBlock; - mProxyList << proxyList; -} - -bool CSVSettings::ProxyBlock::updateSettings (const CSMSettings::SettingMap &settings) -{ - return updateByProxiedSettings(&settings); -} - -bool CSVSettings::ProxyBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit) -{ - doEmit = false; - return updateProxiedSettings(); -} - -void CSVSettings::ProxyBlock::slotUpdateProxySetting (const QString &name, const QString &value) -{ - updateByProxiedSettings(); -} - -bool CSVSettings::ProxyBlock::updateProxiedSettings() -{ - foreach (ItemBlock *block, mProxiedItemBlockList) - { - QString value = getItemBlock(0)->getValue(); - - bool success = false; - int i = 0; - - //find the value index of the selected value in the proxy setting - for (; i < mValueList->size(); ++i) - { - success = (value == mValueList->at(i)); - - if (success) - break; - } - - if (!success) - return false; - - // update the containing the proxied item's name - foreach (QStringList *list, mProxyList) - { - if ( list->at(0) == block->objectName()) - block->update (list->at(++i)); - } - } - - return true; -} - -bool CSVSettings::ProxyBlock::updateByProxiedSettings(const CSMSettings::SettingMap *settings) -{ - bool success = false; - int commonIndex = -1; - - //update all proxy settings based on values from non-proxies - foreach (QStringList *list, mProxyList) - { - //Iterate each proxy item's proxied setting list, getting the current values - //Compare those value indices. - //If indices match, they correlate to one of the proxy's values in it's value list - - //first value is always the name of the setting the proxy setting manages - QStringList::Iterator itProxyValue = list->begin(); - QString proxiedSettingName = (*itProxyValue); - QString proxiedSettingValue = ""; - itProxyValue++; - - if (!settings) - { - //get the actual setting value - ItemBlock *block = getProxiedItemBlock (proxiedSettingName); - - if (block) - proxiedSettingValue = block->getValue(); - } - else - proxiedSettingValue = (*settings)[proxiedSettingName]->getValue(); - - int j = 0; - - //iterate each value in the proxy string list - for (; itProxyValue != (list)->end(); ++itProxyValue) - { - success = ((*itProxyValue) == proxiedSettingValue); - - if (success) - break; - - j++; - } - - //break if no match was found - if ( !success ) - break; - - if (commonIndex != -1) - success = (commonIndex == j); - else - commonIndex = j; - - //break if indices were found, but mismatch - if (!success) - break; - } - - //if successful, the proxied setting values match a pre-defined value in the - //proxy's value list. Set the proxy to that value index - if (success) - { - ItemBlock *block = getItemBlock(0); - - if (block) - block->update (mValueList->at(commonIndex)); - } - - return success; -} - -CSVSettings::ItemBlock *CSVSettings::ProxyBlock::getProxiedItemBlock (const QString &name) -{ - return getItemBlock (name, &mProxiedItemBlockList); -} diff --git a/apps/opencs/view/settings/proxyblock.hpp b/apps/opencs/view/settings/proxyblock.hpp deleted file mode 100644 index 90fb9bc97e..0000000000 --- a/apps/opencs/view/settings/proxyblock.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef PROXYBLOCK_HPP -#define PROXYBLOCK_HPP - -#include "groupblock.hpp" - -namespace CSVSettings -{ - class ProxyBlock : public GroupBlock - { - Q_OBJECT - - /// TODO: Combine mProxyItemBlockList and mProxyList. - ItemBlockList mProxiedItemBlockList; - ProxyList mProxyList; - QStringList *mValueList; - - public: - - explicit ProxyBlock (QWidget *parent = 0); - explicit ProxyBlock (ItemBlock *proxyItemBlock, QWidget *parent = 0); - - /// Add a block that contains a proxied setting to the proxy block. - void addSetting (ItemBlock* settingBlock, QStringList *proxyList); - - int build (GroupBlockDef *def); - - CSMSettings::SettingList *getSettings() { return 0; } - - /// Update settings local to the proxy block pushed from application level - bool updateSettings (const CSMSettings::SettingMap &settings); - - /// callback function triggered when update to the application level is signaled. - bool updateBySignal (const QString &name, const QString &value, bool &doEmit); - - private: - - /// return the item block of a proxied setting - ItemBlock *getProxiedItemBlock (const QString &name); - - /// update the proxy setting with data from the proxied settings - bool updateByProxiedSettings(const CSMSettings::SettingMap *settings = 0); - - /// update proxied settings with data from the proxy setting - bool updateProxiedSettings(); - - private slots: - - void slotUpdateProxySetting (const QString &name, const QString &value); - - }; -} -#endif // PROXYBLOCK_HPP diff --git a/apps/opencs/view/settings/settingwidget.cpp b/apps/opencs/view/settings/settingwidget.cpp deleted file mode 100644 index 2c93986e75..0000000000 --- a/apps/opencs/view/settings/settingwidget.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "settingwidget.hpp" diff --git a/apps/opencs/view/settings/settingwidget.hpp b/apps/opencs/view/settings/settingwidget.hpp deleted file mode 100644 index 9f45136716..0000000000 --- a/apps/opencs/view/settings/settingwidget.hpp +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef SETTINGWIDGET_HPP -#define SETTINGWIDGET_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "abstractwidget.hpp" - -namespace CSVSettings -{ - - /// Generic template for radiobuttons / checkboxes - template - class SettingWidget : public AbstractWidget - { - - T1 *mWidget; - - public: - - explicit SettingWidget (WidgetDef &def, QLayout *layout, QWidget* parent = 0) - : AbstractWidget (layout, parent), mWidget (new T1 (parent)) - { - mWidget->setText(def.caption); - build (mWidget, def, true); - mWidget->setChecked(def.isDefault); - - connect (mWidget, SIGNAL (toggled (bool)), - this, SLOT (slotUpdateItem (bool))); - } - - QWidget *widget() { return mWidget; } - - private: - - void updateWidget (const QString &value) - { - if ( value == mWidget->objectName() && !mWidget->isChecked() ) - mWidget->setChecked (true); - } - }; - - /// spin box template - template <> - class SettingWidget : public AbstractWidget - { - - QSpinBox *mWidget; - - public: - - SettingWidget (WidgetDef &def, QLayout *layout, QWidget *parent = 0) - : AbstractWidget (layout, parent), mWidget (new QSpinBox (parent)) - { - def.caption += tr(" (%1 to %2)").arg(def.minMax->left).arg(def.minMax->right); - - mWidget->setMaximum (def.minMax->right.toInt()); - mWidget->setMinimum (def.minMax->left.toInt()); - mWidget->setValue (def.value.toInt()); - - build (mWidget, def); - - connect (mWidget, SIGNAL (valueChanged (int)), - this, SLOT (slotUpdateItem (int))); - - mWidget->setAlignment (getAlignment(def.valueAlignment)); - - - } - - QWidget *widget() { return mWidget; } - - private: - - void updateWidget (const QString &value) - { - int intVal = value.toInt(); - - if (intVal >= mWidget->minimum() && intVal <= mWidget->maximum() && intVal != mWidget->value()) - mWidget->setValue (intVal); - } - - signals: - - }; - - /// combo box template - template <> - class SettingWidget : public CSVSettings::AbstractWidget - { - - QComboBox *mWidget; - - - public: - - explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0) - : AbstractWidget (layout, parent), mWidget (new QComboBox (parent)) - { - int i = 0; - - foreach (QString item, *(def.valueList)) - { - mWidget->addItem (item); - - if (item == def.value) - mWidget->setCurrentIndex(i); - - i++; - } - - build (mWidget, def); - - connect (mWidget, SIGNAL (currentIndexChanged (const QString &)), - this, SLOT (slotUpdateItem (const QString &))); - - //center the combo box items - mWidget->setEditable (true); - mWidget->lineEdit()->setReadOnly (true); - mWidget->lineEdit()->setAlignment (getAlignment(def.valueAlignment)); - - QFlags alignment = mWidget->lineEdit()->alignment(); - - for (int j = 0; j < mWidget->count(); j++) - mWidget->setItemData (j, QVariant(alignment), Qt::TextAlignmentRole); - } - - QWidget *widget() { return mWidget; } - - private: - - void updateWidget (const QString &value) - { - if (mWidget->currentText() != value) - mWidget->setCurrentIndex(mWidget->findText(value)); - } - - }; - - /// line edit template - template <> - class SettingWidget : public CSVSettings::AbstractWidget - { - - QLineEdit *mWidget; - - public: - - explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0) - : AbstractWidget (layout, parent), mWidget (new QLineEdit (parent)) - { - if (!def.inputMask.isEmpty()) - mWidget->setInputMask (def.inputMask); - - mWidget->setText (def.value); - - build (mWidget, def); - - connect (mWidget, SIGNAL (textChanged (const QString &)), - this, SLOT (slotUpdateItem (const QString &))); - - mWidget->setAlignment (getAlignment(def.valueAlignment)); - } - - QWidget *widget() { return mWidget; } - - void updateWidget (const QString &value) - { - if (mWidget->text() != value) - mWidget->setText(value); - } - }; - - /// list widget template - /// \todo Not fully implemented. Only widget supporting multi-valued settings - template <> - class SettingWidget : public CSVSettings::AbstractWidget - { - - QListWidget *mWidget; - - public: - - explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0 ) - : AbstractWidget (layout, parent), mWidget (new QListWidget (parent)) - { - int i = 0; - - foreach (QString item, *(def.valueList)) - { - mWidget->addItem (item); - - if (item == def.value) {} - i++; - } - build (mWidget, def); - } - - QWidget *widget() { return mWidget; } - - private: - void updateWidget (const QString &value) {} - }; - -} -#endif // SETTINGWIDGET_HPP diff --git a/apps/opencs/view/settings/toggleblock.cpp b/apps/opencs/view/settings/toggleblock.cpp deleted file mode 100644 index 3406a62c4d..0000000000 --- a/apps/opencs/view/settings/toggleblock.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "toggleblock.hpp" -#include "groupblock.hpp" -#include "groupbox.hpp" -#include "itemblock.hpp" - -CSVSettings::ToggleBlock::ToggleBlock(QWidget *parent) : - CustomBlock(parent) -{} - -int CSVSettings::ToggleBlock::build(CustomBlockDef *def) -{ - if (def->blockDefList.size()==0) - return -1; - - QList::Iterator it = def->blockDefList.begin(); - - //first def in the list is the def for the toggle block - GroupBlockDef *toggleDef = *it++; - - if (toggleDef->captions.size() != def->blockDefList.size()-1 ) - return -2; - - if (toggleDef->widgets.size() == 0) - return -3; - - //create the toogle block UI structure - QLayout *blockLayout = createLayout (def->blockOrientation, true); - GroupBox *propertyBox = buildGroupBox (toggleDef->widgetOrientation); - - mBox->setLayout(blockLayout); - mBox->setTitle (toggleDef->title); - - //build the blocks contained in the def list - //this manages proxy block construction. - //Any settings managed by the proxy setting - //must be included in the blocks defined in the list. - CustomBlock::build (def->blockDefList, &it); - - for (GroupBlockList::iterator it = mGroupList.begin(); it != mGroupList.end(); ++it) - propertyBox->layout()->addWidget ((*it)->getGroupBox()); - - //build togle widgets, linking them to the settings - GroupBox *toggleBox = buildToggleWidgets (toggleDef, def->defaultValue); - - blockLayout->addWidget(toggleBox); - blockLayout->addWidget(propertyBox); - blockLayout->setAlignment (propertyBox, Qt::AlignRight); - - return 0; -} - -CSVSettings::GroupBox *CSVSettings::ToggleBlock::buildToggleWidgets (GroupBlockDef *def, QString &defaultToggle) -{ - GroupBox *box = new GroupBox (false, getParent()); - - QLayout *layout = createLayout (def->widgetOrientation, true, static_cast(box)); - - for (int i = 0; i < def->widgets.size(); ++i) - { - QString caption = def->captions.at(i); - WidgetDef *wDef = def->widgets.at(i); - - wDef->caption = caption; - wDef->widgetAlignment = Align_Left; - - AbstractWidget *widg = buildWidget (caption, *wDef, layout, false); - - GroupBlock *block = mGroupList.at(i); - - //connect widget's update to the property block's enabled status - connect (widg->widget(), SIGNAL (toggled (bool)), block, SLOT (slotSetEnabled(bool))); - - //enable the default toggle option - block->getGroupBox()->setEnabled( caption == defaultToggle ); - - layout = widg->getLayout(); - } - - return box; -} diff --git a/apps/opencs/view/settings/toggleblock.hpp b/apps/opencs/view/settings/toggleblock.hpp deleted file mode 100644 index 4b6e8e344d..0000000000 --- a/apps/opencs/view/settings/toggleblock.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef TOGGLEBLOCK_HPP -#define TOGGLEBLOCK_HPP - -#include - -#include "customblock.hpp" - -namespace CSVSettings -{ - class GroupBlock; - class GroupBox; - class ToggleWidget; - class ItemBlock; - - class ToggleBlock : public CustomBlock - { - - public: - explicit ToggleBlock(QWidget *parent = 0); - - int build (CustomBlockDef *def); - - private: - /// Constructor for toggle widgets that are specific to toggle block - /// Widgets are not a part of the user preference settings - GroupBox *buildToggleWidgets (GroupBlockDef *def, QString &defaultToggle); - }; -} -#endif // TOGGLEBLOCK_HPP diff --git a/apps/opencs/view/settings/usersettingsdialog.cpp b/apps/opencs/view/settings/usersettingsdialog.cpp deleted file mode 100644 index e73e24dcb4..0000000000 --- a/apps/opencs/view/settings/usersettingsdialog.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "usersettingsdialog.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../model/settings/support.hpp" - -#include "datadisplayformatpage.hpp" -#include "windowpage.hpp" -#include "settingwidget.hpp" - -CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) : - QMainWindow (parent), mStackedWidget (0) -{ - setWindowTitle(QString::fromUtf8 ("User Settings")); - buildPages(); - setWidgetStates (); - - connect (mListWidget, - SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)), - this, - SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*))); - - QRect scr = QApplication::desktop()->screenGeometry(); - QRect rect = geometry(); - move (scr.center().x() - rect.center().x(), scr.center().y() - rect.center().y()); -} - -CSVSettings::UserSettingsDialog::~UserSettingsDialog() -{ -} - -void CSVSettings::UserSettingsDialog::closeEvent (QCloseEvent *event) -{ - writeSettings(); -} - -void CSVSettings::UserSettingsDialog::setWidgetStates () -{ - CSMSettings::UserSettings::instance().loadSettings("opencs.cfg"); - - //iterate the tabWidget's pages (sections) - for (int i = 0; i < mStackedWidget->count(); i++) - { - //get the settings defined for the entire section - //and update widget - QString pageName = mStackedWidget->widget(i)->objectName(); - - const CSMSettings::SettingMap *settings = CSMSettings::UserSettings::instance().getSettings(pageName); - AbstractPage &page = getAbstractPage (i); - page.initializeWidgets(*settings); - } -} - -void CSVSettings::UserSettingsDialog::buildPages() -{ - //craete central widget with it's layout and immediate children - QWidget *centralWidget = new QWidget (this); - - mListWidget = new QListWidget (centralWidget); - mStackedWidget = new QStackedWidget (centralWidget); - - QGridLayout* dialogLayout = new QGridLayout(); - - mListWidget->setMinimumWidth(0); - mListWidget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Expanding); - - mStackedWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); - - dialogLayout->addWidget (mListWidget,0,0); - dialogLayout->addWidget (mStackedWidget,0,1, Qt::AlignTop); - - centralWidget->setLayout (dialogLayout); - - setCentralWidget (centralWidget); - setDockOptions (QMainWindow::AllowNestedDocks); - - createPage(); - createPage(); - -} - -void CSVSettings::UserSettingsDialog::writeSettings() -{ - QMap settings; - - for (int i = 0; i < mStackedWidget->count(); ++i) - { - AbstractPage &page = getAbstractPage (i); - settings [page.objectName()] = page.getSettings(); - } - CSMSettings::UserSettings::instance().writeSettings(settings); -} - -CSVSettings::AbstractPage &CSVSettings::UserSettingsDialog::getAbstractPage (int index) -{ - return dynamic_cast (*(mStackedWidget->widget (index))); -} - -void CSVSettings::UserSettingsDialog::slotChangePage(QListWidgetItem *current, QListWidgetItem *previous) -{ - if (!current) - current = previous; - - if (!(current == previous)) - mStackedWidget->setCurrentIndex (mListWidget->row(current)); -} diff --git a/apps/opencs/view/settings/usersettingsdialog.hpp b/apps/opencs/view/settings/usersettingsdialog.hpp deleted file mode 100644 index 3b3fa5b79e..0000000000 --- a/apps/opencs/view/settings/usersettingsdialog.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef USERSETTINGSDIALOG_H -#define USERSETTINGSDIALOG_H - -#include -#include -#include -#include - -#include "../../model/settings/usersettings.hpp" -#include "../../model/settings/support.hpp" - -class QHBoxLayout; -class AbstractWidget; -class QStackedWidget; -class QListWidget; - -namespace CSVSettings { - - class AbstractPage; - - class UserSettingsDialog : public QMainWindow - { - Q_OBJECT - - QListWidget *mListWidget; - QStackedWidget *mStackedWidget; - - public: - UserSettingsDialog(QMainWindow *parent = 0); - ~UserSettingsDialog(); - - private: - - /// Settings are written on close - void closeEvent (QCloseEvent *event); - - /// return the setting page by name - /// performs dynamic cast to AbstractPage * - AbstractPage &getAbstractPage (int index); - void setWidgetStates (); - void buildPages(); - void writeSettings(); - - /// Templated function to create a custom user preference page - template - void createPage () - { - T *page = new T(mStackedWidget); - - mStackedWidget->addWidget (&dynamic_cast(*page)); - - new QListWidgetItem (page->objectName(), mListWidget); - - //finishing touches - QFontMetrics fm (QApplication::font()); - int textWidth = fm.width(page->objectName()); - - if ((textWidth + 50) > mListWidget->minimumWidth()) - mListWidget->setMinimumWidth(textWidth + 50); - - resize (mStackedWidget->sizeHint()); - } - - public slots: - - /// Called when a different page is selected in the left-hand list widget - void slotChangePage (QListWidgetItem*, QListWidgetItem*); - }; - -} -#endif // USERSETTINGSDIALOG_H diff --git a/apps/opencs/view/settings/windowpage.cpp b/apps/opencs/view/settings/windowpage.cpp deleted file mode 100644 index ae42623b78..0000000000 --- a/apps/opencs/view/settings/windowpage.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "windowpage.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_MAC -#include -#endif - -#include "../../model/settings/usersettings.hpp" -#include "groupblock.hpp" -#include "toggleblock.hpp" -#include "../../view/settings/abstractblock.hpp" - -CSVSettings::WindowPage::WindowPage(QWidget *parent): - AbstractPage("Window Size", parent) -{ - // Hacks to get the stylesheet look properly -#ifdef Q_OS_MAC - QPlastiqueStyle *style = new QPlastiqueStyle; - //profilesComboBox->setStyle(style); -#endif - - setupUi(); -} - -CSVSettings::GroupBlockDef * CSVSettings::WindowPage::buildDefinedWindowSize() -{ - GroupBlockDef *block = new GroupBlockDef ( "Defined Size"); - - SettingsItemDef *widthByHeightItem = new SettingsItemDef ("Window Size", "640x480"); - WidgetDef widthByHeightWidget = WidgetDef (Widget_ComboBox); - widthByHeightWidget.widgetWidth = 90; - *(widthByHeightItem->valueList) << "640x480" << "800x600" << "1024x768" << "1440x900"; - - QStringList *widthProxy = new QStringList; - QStringList *heightProxy = new QStringList; - - (*widthProxy) << "Width" << "640" << "800" << "1024" << "1440"; - (*heightProxy) << "Height" << "480" << "600" << "768" << "900"; - - *(widthByHeightItem->proxyList) << widthProxy << heightProxy; - - widthByHeightItem->widget = widthByHeightWidget; - - block->settingItems << widthByHeightItem; - block->isProxy = true; - block->isVisible = false; - - return block; -} - -CSVSettings::GroupBlockDef *CSVSettings::WindowPage::buildCustomWindowSize() -{ - GroupBlockDef *block = new GroupBlockDef ("Custom Size"); - - //custom width - SettingsItemDef *widthItem = new SettingsItemDef ("Width", "640"); - widthItem->widget = WidgetDef (Widget_LineEdit); - widthItem->widget.widgetWidth = 45; - widthItem->widget.inputMask = "9999"; - - //custom height - SettingsItemDef *heightItem = new SettingsItemDef ("Height", "480"); - heightItem->widget = WidgetDef (Widget_LineEdit); - heightItem->widget.widgetWidth = 45; - heightItem->widget.caption = "x"; - heightItem->widget.inputMask = "9999"; - - block->settingItems << widthItem << heightItem; - block->widgetOrientation = Orient_Horizontal; - block->isVisible = false; - - return block; -} - -CSVSettings::GroupBlockDef *CSVSettings::WindowPage::buildWindowSizeToggle() -{ - GroupBlockDef *block = new GroupBlockDef (objectName()); - - // window size toggle - block->captions << "Pre-Defined" << "Custom"; - block->widgetOrientation = Orient_Vertical; - block->isVisible = false; - - //define a widget for each group in the toggle - for (int i = 0; i < 2; i++) - block->widgets << new WidgetDef (Widget_RadioButton); - - block->widgets.at(0)->isDefault = false; - - return block; -} - -CSVSettings::CustomBlockDef *CSVSettings::WindowPage::buildWindowSize(GroupBlockDef *toggle_def, - GroupBlockDef *defined_def, - GroupBlockDef *custom_def) -{ - CustomBlockDef *block = new CustomBlockDef(QString ("Window Size")); - - block->blockDefList << toggle_def << defined_def << custom_def; - block->defaultValue = "Custom"; - - return block; - -} - -void CSVSettings::WindowPage::setupUi() -{ - CustomBlockDef *windowSize = buildWindowSize(buildWindowSizeToggle(), - buildDefinedWindowSize(), - buildCustomWindowSize() - ); - - mAbstractBlocks << buildBlock (windowSize); - - foreach (AbstractBlock *block, mAbstractBlocks) - { - connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)), - this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) ); - } - - connect ( this, - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)), - &(CSMSettings::UserSettings::instance()), - SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &))); - -} - - -void CSVSettings::WindowPage::initializeWidgets (const CSMSettings::SettingMap &settings) -{ - //iterate each item in each blocks in this section - //validate the corresponding setting against the defined valuelist if any. - for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin(); - it_block != mAbstractBlocks.end(); ++it_block) - (*it_block)->updateSettings (settings); -} diff --git a/apps/opencs/view/settings/windowpage.hpp b/apps/opencs/view/settings/windowpage.hpp deleted file mode 100644 index 2f28306256..0000000000 --- a/apps/opencs/view/settings/windowpage.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef WINDOWPAGE_H -#define WINDOWPAGE_H - -#include "abstractpage.hpp" - -class QGroupBox; - -namespace CSVSettings { - - class UserSettings; - class AbstractBlock; - - class WindowPage : public AbstractPage - { - Q_OBJECT - - public: - - WindowPage(QWidget *parent = 0); - - void setupUi(); - void initializeWidgets (const CSMSettings::SettingMap &settings); - - /// - GroupBlockDef *buildCustomWindowSize(); - GroupBlockDef *buildDefinedWindowSize(); - GroupBlockDef *buildWindowSizeToggle(); - CustomBlockDef *buildWindowSize (GroupBlockDef *, GroupBlockDef *, GroupBlockDef *); - - signals: - void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue); - }; -} -#endif //WINDOWPAGE_H From 331df17b48fb66f9305aea041a094f919df5707c Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 22 Apr 2014 22:17:19 -0500 Subject: [PATCH 008/545] Added new framework files --- apps/opencs/model/settings/connector.cpp | 127 +++++++ apps/opencs/model/settings/connector.hpp | 55 +++ apps/opencs/model/settings/setting.cpp | 281 +++++++++++++++ apps/opencs/model/settings/setting.hpp | 119 +++++++ apps/opencs/model/settings/settingmanager.cpp | 330 ++++++++++++++++++ apps/opencs/model/settings/settingmanager.hpp | 82 +++++ apps/opencs/view/settings/booleanview.cpp | 91 +++++ apps/opencs/view/settings/booleanview.hpp | 44 +++ apps/opencs/view/settings/dialog.cpp | 132 +++++++ apps/opencs/view/settings/dialog.hpp | 55 +++ apps/opencs/view/settings/frame.cpp | 103 ++++++ apps/opencs/view/settings/frame.hpp | 58 +++ apps/opencs/view/settings/listview.cpp | 106 ++++++ apps/opencs/view/settings/listview.hpp | 63 ++++ apps/opencs/view/settings/page.cpp | 88 +++++ apps/opencs/view/settings/page.hpp | 54 +++ .../view/settings/resizeablestackedwidget.cpp | 40 +++ .../view/settings/resizeablestackedwidget.hpp | 23 ++ apps/opencs/view/settings/settingwindow.cpp | 114 ++++++ apps/opencs/view/settings/settingwindow.hpp | 49 +++ apps/opencs/view/settings/textview.cpp | 73 ++++ apps/opencs/view/settings/textview.hpp | 56 +++ apps/opencs/view/settings/view.cpp | 218 ++++++++++++ apps/opencs/view/settings/view.hpp | 163 +++++++++ 24 files changed, 2524 insertions(+) create mode 100644 apps/opencs/model/settings/connector.cpp create mode 100644 apps/opencs/model/settings/connector.hpp create mode 100644 apps/opencs/model/settings/setting.cpp create mode 100644 apps/opencs/model/settings/setting.hpp create mode 100644 apps/opencs/model/settings/settingmanager.cpp create mode 100644 apps/opencs/model/settings/settingmanager.hpp create mode 100644 apps/opencs/view/settings/booleanview.cpp create mode 100644 apps/opencs/view/settings/booleanview.hpp create mode 100644 apps/opencs/view/settings/dialog.cpp create mode 100644 apps/opencs/view/settings/dialog.hpp create mode 100644 apps/opencs/view/settings/frame.cpp create mode 100644 apps/opencs/view/settings/frame.hpp create mode 100644 apps/opencs/view/settings/listview.cpp create mode 100644 apps/opencs/view/settings/listview.hpp create mode 100644 apps/opencs/view/settings/page.cpp create mode 100644 apps/opencs/view/settings/page.hpp create mode 100644 apps/opencs/view/settings/resizeablestackedwidget.cpp create mode 100644 apps/opencs/view/settings/resizeablestackedwidget.hpp create mode 100644 apps/opencs/view/settings/settingwindow.cpp create mode 100644 apps/opencs/view/settings/settingwindow.hpp create mode 100644 apps/opencs/view/settings/textview.cpp create mode 100644 apps/opencs/view/settings/textview.hpp create mode 100644 apps/opencs/view/settings/view.cpp create mode 100644 apps/opencs/view/settings/view.hpp diff --git a/apps/opencs/model/settings/connector.cpp b/apps/opencs/model/settings/connector.cpp new file mode 100644 index 0000000000..05a9ba8f96 --- /dev/null +++ b/apps/opencs/model/settings/connector.cpp @@ -0,0 +1,127 @@ +#include "connector.hpp" +#include "../../view/settings/view.hpp" +#include "../../view/settings/page.hpp" + +CSMSettings::Connector::Connector(CSVSettings::View *master, + QObject *parent) + : mMasterView (master), QObject(parent) +{} + +void CSMSettings::Connector::addSlaveView (CSVSettings::View *view, + QList &masterProxyValues) +{ + mSlaveViews.append (view); + + mProxyListMap[view->viewKey()].append (masterProxyValues); +} + +QList CSMSettings::Connector::getSlaveViewValues() const +{ + QList list; + + foreach (const CSVSettings::View *view, mSlaveViews) + list.append (view->selectedValues()); + + return list; +} + +bool CSMSettings::Connector::proxyListsMatch ( + const QList &list1, + const QList &list2) const +{ + bool success = true; + + for (int i = 0; i < list1.size(); i++) + { + success = stringListsMatch (list1.at(i), list2.at(i)); + + if (!success) + break; + } + return success; +} + +void CSMSettings::Connector::slotUpdateMaster() const +{ + //list of the current values for each slave. + QList slaveValueList = getSlaveViewValues(); + + int masterColumn = -1; + + /* + * A row in the master view is one of the values in the + * master view's data model. This corresponds directly to the number of + * values in a proxy list contained in the ProxyListMap member. + * Thus, we iterate each "column" in the master proxy list + * (one for each vlaue in the master. Each column represents + * one master value's corresponding list of slave values. We examine + * each master value's list, comparing it to the current slave value list, + * stopping when we find a match using proxyListsMatch(). + * + * If no match is found, clear the master view's value + */ + + for (int i = 0; i < mMasterView->rowCount(); i++) + { + QList proxyValueList; + + foreach (const QString &settingKey, mProxyListMap.keys()) + { + // append the proxy value list stored in the i'th column + // for each setting key. A setting key is the id of the setting + // in page.name format. + proxyValueList.append (mProxyListMap.value(settingKey).at(i)); + } + + if (proxyListsMatch (slaveValueList, proxyValueList)) + { + masterColumn = i; + break; + } + } + + QString masterValue = mMasterView->value (masterColumn); + mMasterView->setSelectedValue (masterValue); +} + +void CSMSettings::Connector::slotUpdateSlaves() const +{ + int row = mMasterView->currentIndex(); + + if (row == -1) + return; + + //iterate the proxy lists for the chosen master index + //and pass the list to each slave for updating + for (int i = 0; i < mSlaveViews.size(); i++) + { + QList proxyList = + mProxyListMap.value(mSlaveViews.at(i)->viewKey()); + + mSlaveViews.at(i)->setSelectedValues (proxyList.at(row)); + } +} + +bool CSMSettings::Connector::stringListsMatch ( + const QStringList &list1, + const QStringList &list2) const +{ + //returns a "sloppy" match, verifying that each list contains all the same + //items, though not necessarily in the same order. + + if (list1.size() != list2.size()) + return false; + + QStringList tempList(list2); + + //iterate each value in the list, removing one occurrence of the value in + //the other list. If no corresponding value is found, test fails + foreach (const QString &value, list1) + { + if (!tempList.contains(value)) + return false; + + tempList.removeOne(value); + } + return true; +} diff --git a/apps/opencs/model/settings/connector.hpp b/apps/opencs/model/settings/connector.hpp new file mode 100644 index 0000000000..da4c36d44c --- /dev/null +++ b/apps/opencs/model/settings/connector.hpp @@ -0,0 +1,55 @@ +#ifndef CSMSETTINGS_CONNECTOR_HPP +#define CSMSETTINGS_CONNECTOR_HPP + +#include +#include +#include +#include + +#include "support.hpp" + +namespace CSVSettings { + class View; +} + +namespace CSMSettings { + + class Connector : public QObject + { + Q_OBJECT + + CSVSettings::View *mMasterView; + + //map using the view pointer as a key to it's index value + QList mSlaveViews; + + //list of proxy values for each master value. + //value list order is indexed to the master value index. + QMap < QString, QList > mProxyListMap; + + public: + explicit Connector(CSVSettings::View *master, + QObject *parent = 0); + + void setMasterView (CSVSettings::View *view); + void addSlaveView (CSVSettings::View *view, + QList &masterProxyValues); + + private: + + bool proxyListsMatch (const QList &list1, + const QList &list2) const; + + bool stringListsMatch (const QStringList &list1, + const QStringList &list2) const; + + QList getSlaveViewValues() const; + + public slots: + + void slotUpdateSlaves() const; + void slotUpdateMaster() const; + }; +} + +#endif // CSMSETTINGS_CONNECTOR_HPP diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp new file mode 100644 index 0000000000..6c7e780879 --- /dev/null +++ b/apps/opencs/model/settings/setting.cpp @@ -0,0 +1,281 @@ +#include "setting.hpp" +#include "support.hpp" + +CSMSettings::Setting::Setting() +{ + buildDefaultSetting(); +} + +CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, + const QString &pageName, const QStringList &values) + : mIsEditorSetting (false) +{ + buildDefaultSetting(); + + int vType = static_cast (typ); + + if ((vType % 2) == 0) + setProperty (Property_IsMultiValue, + QVariant(true).toString()); + else + vType--; + + setProperty (Property_ViewType, QVariant (vType / 2).toString()); + setProperty (Property_Page, pageName); + setProperty (Property_Name, settingName); + setProperty (Property_DeclaredValues, values); +} + +void CSMSettings::Setting::buildDefaultSetting() +{ + int arrLen = sizeof(sPropertyDefaults) / sizeof (*sPropertyDefaults); + + for (int i = 0; i < arrLen; i++) + { + QStringList propertyList; + + if (i list; + + foreach (const QString &val, vals) + list << (QStringList() << val); + + mProxies [setting->page() + '.' + setting->name()] = list; +} + +void CSMSettings::Setting::addProxy (const Setting *setting, + const QList &list) +{ + if (serializable()) + setProperty (Property_Serializable, false); + + mProxies [setting->page() + '.' + setting->name()] = list; +} + +void CSMSettings::Setting::setColumnSpan (int value) +{ + setProperty (Property_ColumnSpan, value); +} + +int CSMSettings::Setting::columnSpan() const +{ + return property (Property_ColumnSpan).at(0).toInt(); +} + +QStringList CSMSettings::Setting::declaredValues() const +{ + return property (Property_DeclaredValues); +} + +void CSMSettings::Setting::setDefinedValues (QStringList list) +{ + setProperty (Property_DefinedValues, list); +} + +QStringList CSMSettings::Setting::definedValues() const +{ + return property (Property_DefinedValues); +} + +QStringList CSMSettings::Setting::property (SettingProperty prop) const +{ + if (prop >= mProperties.size()) + return QStringList(); + + return mProperties.at(prop); +} + +void CSMSettings::Setting::setDefaultValue (const QString &value) +{ + setDefaultValues (QStringList() << value); +} + +void CSMSettings::Setting::setDefaultValues (const QStringList &values) +{ + setProperty (Property_DefaultValues, values); +} + +QStringList CSMSettings::Setting::defaultValues() const +{ + return property (Property_DefaultValues); +} + +void CSMSettings::Setting::setDelimiter (const QString &value) +{ + setProperty (Property_Delimiter, value); +} + +QString CSMSettings::Setting::delimiter() const +{ + return property (Property_Delimiter).at(0); +} + +void CSMSettings::Setting::setEditorSetting(bool state) +{ + mIsEditorSetting = true; +} + +bool CSMSettings::Setting::isEditorSetting() const +{ + return mIsEditorSetting; +} +void CSMSettings::Setting::setIsMultiLine (bool state) +{ + setProperty (Property_IsMultiLine, state); +} + +bool CSMSettings::Setting::isMultiLine() const +{ + return (property (Property_IsMultiLine).at(0) == "true"); +} + +void CSMSettings::Setting::setIsMultiValue (bool state) +{ + setProperty (Property_IsMultiValue, state); +} + +bool CSMSettings::Setting::isMultiValue() const +{ + return (property (Property_IsMultiValue).at(0) == "true"); +} + +const CSMSettings::ProxyValueMap &CSMSettings::Setting::proxyLists() const +{ + return mProxies; +} + +void CSMSettings::Setting::setSerializable (bool state) +{ + setProperty (Property_Serializable, state); +} + +bool CSMSettings::Setting::serializable() const +{ + return (property (Property_Serializable).at(0) == "true"); +} + +void CSMSettings::Setting::setName (const QString &value) +{ + setProperty (Property_Name, value); +} + +QString CSMSettings::Setting::name() const +{ + return property (Property_Name).at(0); +} + +void CSMSettings::Setting::setPage (const QString &value) +{ + setProperty (Property_Page, value); +} + +QString CSMSettings::Setting::page() const +{ + return property (Property_Page).at(0); +} + +void CSMSettings::Setting::setRowSpan (const int value) +{ + setProperty (Property_RowSpan, value); +} + +int CSMSettings::Setting::rowSpan () const +{ + return property (Property_RowSpan).at(0).toInt(); +} + +void CSMSettings::Setting::setViewType (int vType) +{ + setProperty (Property_ViewType, vType); +} + +CSVSettings::ViewType CSMSettings::Setting::viewType() const +{ + return static_cast + (property(Property_ViewType).at(0).toInt()); +} + +void CSMSettings::Setting::setViewColumn (int value) +{ + setProperty (Property_ViewColumn, value); +} + +int CSMSettings::Setting::viewColumn() const +{ + return property (Property_ViewColumn).at(0).toInt(); +} + +void CSMSettings::Setting::setViewLocation (int row, int column) +{ + setViewRow (row); + setViewColumn (column); +} + +void CSMSettings::Setting::setViewRow (int value) +{ + setProperty (Property_ViewRow, value); +} + +int CSMSettings::Setting::viewRow() const +{ + return property (Property_ViewRow).at(0).toInt(); +} + +void CSMSettings::Setting::setWidgetWidth (int value) +{ + setProperty (Property_WidgetWidth, value); +} + +int CSMSettings::Setting::widgetWidth() const +{ + return property (Property_WidgetWidth).at(0).toInt(); +} +void CSMSettings::Setting::setProperty (SettingProperty prop, bool value) +{ + setProperty (prop, QStringList() << QVariant (value).toString()); +} + +void CSMSettings::Setting::setProperty (SettingProperty prop, int value) +{ + setProperty (prop, QStringList() << QVariant (value).toString()); +} + +void CSMSettings::Setting::setProperty (SettingProperty prop, + const QString &value) +{ + setProperty (prop, QStringList() << value); +} + +void CSMSettings::Setting::setProperty (SettingProperty prop, + const QStringList &value) +{ + if (prop < mProperties.size()) + mProperties.replace (prop, value); +} + +QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting) +{ + stream << setting.properties(); + + stream << setting.proxies(); + return stream; +} + +QDataStream &operator >>(QDataStream& stream, CSMSettings::Setting& setting) +{ + // stream >> setting.properties(); + // stream >> setting.proxies(); + return stream; +} diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp new file mode 100644 index 0000000000..1463e4d7d2 --- /dev/null +++ b/apps/opencs/model/settings/setting.hpp @@ -0,0 +1,119 @@ +#ifndef CSMSETTINGS_SETTING_HPP +#define CSMSETTINGS_SETTING_HPP + +#include +#include +#include "support.hpp" + +namespace CSMSettings +{ + //Maps setting id ("page.name") to a list of corresponding proxy values. + //Order of proxy value stringlists corresponds to order of master proxy's + //values in it's declared value list + typedef QMap > ProxyValueMap; + + class Setting + { + QList mProperties; + QStringList mDefaults; + + bool mIsEditorSetting; + + //QString is the setting id in the form of "page.name" + //QList is a list of stringlists of proxy values. + //Order is important! Proxy stringlists are matched against + //master values by their position in the QList. + ProxyValueMap mProxies; + + public: + + + explicit Setting(); + + explicit Setting(SettingType typ, const QString &settingName, + const QString &pageName, + const QStringList &values = QStringList()); + + void addProxy (const Setting *setting, const QStringList &vals); + void addProxy (const Setting *setting, const QList &list); + + const QList &properties() const { return mProperties; } + const ProxyValueMap &proxies() const { return mProxies; } + + void setColumnSpan (int value); + int columnSpan() const; + + void setDeclaredValues (QStringList list); + QStringList declaredValues() const; + + void setDefinedValues (QStringList list); + QStringList definedValues() const; + + void setDefaultValue (const QString &value); + + void setDefaultValues (const QStringList &values); + QStringList defaultValues() const; + + void setDelimiter (const QString &value); + QString delimiter() const; + + void setEditorSetting (bool state); + bool isEditorSetting() const; + + void setIsMultiLine (bool state); + bool isMultiLine() const; + + void setIsMultiValue (bool state); + bool isMultiValue() const; + + void setName (const QString &value); + QString name() const; + + void setPage (const QString &value); + QString page() const; + + void setRowSpan (const int value); + int rowSpan() const; + + const ProxyValueMap &proxyLists() const; + + void setSerializable (bool state); + bool serializable() const; + + void setViewColumn (int value); + int viewColumn() const; + + void setViewLocation (int row = -1, int column = -1); + + void setViewRow (int value); + int viewRow() const; + + void setViewType (int vType); + CSVSettings::ViewType viewType() const; + + void setWidgetWidth (int value); + int widgetWidth() const; + + ///returns the specified property value + QStringList property (SettingProperty prop) const; + + ///boilerplate code to convert setting values of common types + void setProperty (SettingProperty prop, bool value); + void setProperty (SettingProperty prop, int value); + void setProperty (SettingProperty prop, const QString &value); + void setProperty (SettingProperty prop, const QStringList &value); + + void addProxy (Setting* setting, + QMap &proxyMap); + + protected: + void buildDefaultSetting(); + }; +} + +Q_DECLARE_METATYPE(CSMSettings::Setting) + +QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting); +QDataStream &operator >>(QDataStream &stream, CSMSettings::Setting& setting); + +#endif // CSMSETTINGS_SETTING_HPP diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp new file mode 100644 index 0000000000..70b91ee40a --- /dev/null +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include + +#include "setting.hpp" +#include "settingmanager.hpp" + +CSMSettings::SettingManager::SettingManager(QObject *parent) : + QObject(parent) +{ + mReadWriteMessage = QObject::tr("
Could not open or create file for \ + writing

Please make sure you have the right\ + permissions and try again.
"); + + mReadOnlyMessage = QObject::tr("
Could not open file for \ + reading

Please make sure you have the \ + right permissions and try again.
"); + +} + +void CSMSettings::SettingManager::dumpModel() +{ + foreach (Setting *setting, mSettings) + { + if (setting->proxyLists().isEmpty()) + continue; + } +} + +CSMSettings::Setting *CSMSettings::SettingManager::createSetting + (CSMSettings::SettingType typ, const QString &page, const QString &name, + const QStringList &values) +{ + //get list of all settings for the current setting name + if (findSetting (page, name)) + { + qWarning() << "Duplicate declaration encountered: " + << (name + '.' + page); + return 0; + } + + Setting *setting = new Setting (typ, name, page, values); + + //add declaration to the model + mSettings.append (setting); + + return setting; +} + +CSMSettings::DefinitionPageMap + CSMSettings::SettingManager::readFilestream (QTextStream *stream) +{ + //regEx's for page names and keys / values + QRegExp pageRegEx ("^\\[([^]]+)\\]"); + QRegExp keyRegEx ("^([^=]+)\\s*=\\s*(.+)$"); + + QString currPage = "Unassigned"; + + DefinitionPageMap pageMap; + + if (!stream) + { + displayFileErrorMessage(mReadWriteMessage, false); + return pageMap; + } + + if (stream->atEnd()) + return pageMap; + + DefinitionMap *settingMap = new DefinitionMap(); + pageMap[currPage] = settingMap; + + while (!stream->atEnd()) + { + QString line = stream->readLine().simplified(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + //page name found + if (pageRegEx.exactMatch(line)) + { + currPage = pageRegEx.cap(1).simplified().trimmed(); + settingMap = new DefinitionMap(); + pageMap[currPage] = settingMap; + continue; + } + + //setting definition found + if ( (keyRegEx.indexIn(line) != -1)) + { + QString settingName = keyRegEx.cap(1).simplified(); + QString settingValue = keyRegEx.cap(2).simplified(); + + if (!settingMap->contains (settingName)) + settingMap->insert (settingName, new QStringList()); + + settingMap->value(settingName)->append(settingValue); + } + } + + //return empty map if no settings were ever added to + if (pageMap.size() == 1) + { + QString pageKey = pageMap.keys().at(0); + if (pageMap[pageKey]->size() == 0) + pageMap.clear(); + } + + return pageMap; +} + +bool CSMSettings::SettingManager::writeFilestream(QTextStream *stream, + const QMap &settingListMap) +{ + if (!stream) + { + displayFileErrorMessage(mReadWriteMessage, false); + return false; + } + //disabled after rolling selector class into view. Need to + //iterate views to get setting definitions before writing to file + + QStringList sectionKeys; + + foreach (const QString &key, settingListMap.keys()) + { + QStringList names = key.split('.'); + QString section = names.at(0); + + if (!sectionKeys.contains(section)) + if (!settingListMap.value(key).isEmpty()) + sectionKeys.append (section); + } + + foreach (const QString §ion, sectionKeys) + { + *stream << '[' << section << "]\n"; + foreach (const QString &key, settingListMap.keys()) + { + QStringList names = key.split('.'); + + if (names.at(0) != section) + continue; + + QStringList list = settingListMap.value(key); + + if (list.isEmpty()) + continue; + + QString name = names.at(1); + + foreach (const QString value, list) + { + if (value.isEmpty()) + continue; + + *stream << name << " = " << value << '\n'; + } + } + } + + destroyStream (stream); + return true; +} + +void CSMSettings::SettingManager::mergeSettings(DefinitionPageMap &destMap, DefinitionPageMap &srcMap) +{ + if (srcMap.isEmpty()) + return; + + foreach (const QString &pageKey, srcMap.keys()) + { + DefinitionMap *srcSetting = srcMap.value(pageKey); + //Unique Page: + //insertfrom the source map + if (!destMap.keys().contains (pageKey)) + { + destMap.insert (pageKey, srcSetting); + continue; + } + + DefinitionMap *destSetting = destMap.value(pageKey); + + //Duplicate Page: + //iterate the settings in the source and check for duplicates in the + //destination + foreach (const QString &srcKey, srcSetting->keys()) + { + //insert into destination if unique + if (!destSetting->keys().contains (srcKey)) + destSetting->insert(srcKey, srcSetting->value (srcKey)); + } + } +} + +QTextStream *CSMSettings::SettingManager::openFilestream (const QString &filePath, + bool isReadOnly) const +{ + QIODevice::OpenMode openFlags = QIODevice::Text; + + if (isReadOnly) + openFlags = QIODevice::ReadOnly | openFlags; + else + openFlags = QIODevice::ReadWrite | QIODevice::Truncate | openFlags; + + QFile *file = new QFile(filePath); + QTextStream *stream = 0; + + if (file->open(openFlags)) + stream = new QTextStream(file); + + if (stream) + stream->setCodec(QTextCodec::codecForName("UTF-8")); + + return stream; +} + +void CSMSettings::SettingManager::destroyStream(QTextStream *stream) const +{ + stream->device()->close(); + + delete stream; +} + +void CSMSettings::SettingManager::displayFileErrorMessage(const QString &message, + bool isReadOnly) const +{ + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + + if (!isReadOnly) + msgBox.setText (mReadWriteMessage + message); + else + msgBox.setText (message); + + msgBox.exec(); +} + +void CSMSettings::SettingManager::addDefinitions (DefinitionPageMap &pageMap) +{ + foreach (QString pageName, pageMap.keys()) + { + DefinitionMap *settingMap = pageMap.value (pageName); + + foreach (QString settingName, (*settingMap).keys()) + { + QStringList *values = settingMap->value (settingName); + Setting *setting = findSetting (pageName, settingName); + + if (!setting) + { + qWarning() << "Found definitions for undeclared setting " + << pageName << "." << settingName; + continue; + } + + if (values->size() == 0) + values->append (setting->defaultValues()); + + setting->setDefinedValues (*values); + } + } +} + +QList CSMSettings::SettingManager::findSettings + (const QStringList &list) +{ + QList settings; + + foreach (const QString &value, list) + { + QStringList names = value.split(".", QString::SkipEmptyParts); + + if (names.size() != 2) + continue; + + Setting *setting = findSetting (names.at(0), names.at(1)); + + if (!setting) + continue; + + settings.append (setting); + } + + return settings; +} + + +CSMSettings::Setting *CSMSettings::SettingManager::findSetting + (const QString &pageName, const QString &settingName) +{ + foreach (Setting *setting, mSettings) + { + if (setting->name() == settingName) + { + if (setting->page() == pageName) + return setting; + } + } + return 0; +} + +QList CSMSettings::SettingManager::findSettings + (const QString &pageName) +{ + QList settings; + + foreach (Setting *setting, mSettings) + { + if (setting->page() == pageName) + settings.append (setting); + } + return settings; +} + +CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const +{ + SettingPageMap pageMap; + + foreach (Setting *setting, mSettings) + pageMap[setting->page()].append (setting); + + return pageMap; +} diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp new file mode 100644 index 0000000000..8819096adf --- /dev/null +++ b/apps/opencs/model/settings/settingmanager.hpp @@ -0,0 +1,82 @@ +#ifndef CSMSETTINGS_SETTINGMANAGER_HPP +#define CSMSETTINGS_SETTINGMANAGER_HPP + +#include +#include +#include +#include + +#include "support.hpp" +#include "setting.hpp" + +namespace CSMSettings +{ + + typedef QMap DefinitionMap; + typedef QMap DefinitionPageMap; + + typedef QMap > SettingPageMap; + + class SettingManager : public QObject + { + Q_OBJECT + + QString mReadOnlyMessage; + QString mReadWriteMessage; + QList mSettings; + + public: + explicit SettingManager(QObject *parent = 0); + + ///retrieve a setting object from a given page and setting name + Setting *findSetting + (const QString &pageName, const QString &settingName); + + ///retrieve all settings for a specified page + QList findSettings (const QString &pageName); + + ///retrieve all settings named in the attached list. + ///Setting names are specified in "PageName.SettingName" format. + QList findSettings (const QStringList &list); + + ///Retreive a map of the settings, keyed by page name + SettingPageMap settingPageMap() const; + + protected: + + ///add a new setting to the model and return it + Setting *createSetting (CSMSettings::SettingType typ, + const QString &page, const QString &name, + const QStringList &values = QStringList()); + + ///add definitions to the settings specified in the page map + void addDefinitions (DefinitionPageMap &pageMap); + + ///read setting definitions from file + DefinitionPageMap readFilestream(QTextStream *stream); + + ///write setting definitions to file + bool writeFilestream (QTextStream *stream, + const QMap &settingMap); + + ///merge PageMaps of settings when loading from multiple files + void mergeSettings (DefinitionPageMap &destMap, DefinitionPageMap &srcMap); + + QTextStream *openFilestream (const QString &filePath, + bool isReadOnly) const; + + void destroyStream(QTextStream *stream) const; + + void displayFileErrorMessage(const QString &message, + bool isReadOnly) const; + + QList settings() const { return mSettings; } + void dumpModel(); + + signals: + + public slots: + + }; +} +#endif // CSMSETTINGS_SETTINGMANAGER_HPP diff --git a/apps/opencs/view/settings/booleanview.cpp b/apps/opencs/view/settings/booleanview.cpp new file mode 100644 index 0000000000..1c48199d1d --- /dev/null +++ b/apps/opencs/view/settings/booleanview.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include +#include +#include + +#include + +#include "booleanview.hpp" +#include "../../model/settings/setting.hpp" + +CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, + Page *parent) + : View (setting, parent) +{ + foreach (const QString &value, setting->declaredValues()) + { + QAbstractButton *button = 0; + + if (isMultiValue()) + button = new QCheckBox (value, this); + else + button = new QRadioButton (value, this); + + connect (button, SIGNAL (clicked (bool)), + this, SLOT (slotToggled (bool))); + + button->setObjectName (value); + + addWidget (button); + + mButtons[value] = button; + } +} + +void CSVSettings::BooleanView::slotToggled (bool state) +{ + //test only for true to avoid multiple selection updates with radiobuttons + if (!isMultiValue() && !state) + return; + + QStringList values; + + foreach (QString key, mButtons.keys()) + { + if (mButtons.value(key)->isChecked()) + values.append (key); + } + setSelectedValues (values, false); + + View::updateView(); +} + +void CSVSettings::BooleanView::updateView (bool signalUpdate) const +{ + + QStringList values = selectedValues(); + + foreach (const QString &buttonName, mButtons.keys()) + { + QAbstractButton *button = mButtons[buttonName]; + + //if the value is not found in the list, the widget is checked false + bool buttonValue = values.contains(buttonName); + + //skip if the butotn value will not change + if (button->isChecked() == buttonValue) + continue; + + //disable autoexclusive if it's enabled and we're setting + //the button value to false + bool switchExclusive = (!buttonValue && button->autoExclusive()); + + if (switchExclusive) + button->setAutoExclusive (false); + + button->setChecked (buttonValue); + + if (switchExclusive) + button->setAutoExclusive(true); + } + View::updateView (signalUpdate); +} + +CSVSettings::BooleanView *CSVSettings::BooleanViewFactory::createView + (CSMSettings::Setting *setting, + Page *parent) +{ + return new BooleanView (setting, parent); +} diff --git a/apps/opencs/view/settings/booleanview.hpp b/apps/opencs/view/settings/booleanview.hpp new file mode 100644 index 0000000000..52f9e05f1f --- /dev/null +++ b/apps/opencs/view/settings/booleanview.hpp @@ -0,0 +1,44 @@ +#ifndef CSVSETTINGS_BOOLEANVIEW_HPP +#define CSVSETTINGS_BOOELANVIEW_HPP + +#include +#include + +#include "view.hpp" +#include "../../model/settings/support.hpp" + +class QStringListModel; + +namespace CSVSettings +{ + class BooleanView : public View + { + Q_OBJECT + + QMap mButtons; + + public: + explicit BooleanView (CSMSettings::Setting *setting, + Page *parent); + + protected: + void updateView (bool signalUpdate = true) const; + + private slots: + void slotToggled (bool state); + }; + + class BooleanViewFactory : public QObject, public IViewFactory + { + Q_OBJECT + + public: + explicit BooleanViewFactory (QWidget *parent = 0) + : QObject (parent) + {} + + BooleanView *createView (CSMSettings::Setting *setting, + Page *parent); + }; +} +#endif // CSVSETTINGS_BOOLEANVIEW_HPP diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp new file mode 100644 index 0000000000..d9d5830d98 --- /dev/null +++ b/apps/opencs/view/settings/dialog.cpp @@ -0,0 +1,132 @@ +#include "dialog.hpp" + +#include +#include +#include +#include +#include + +#include "../../model/settings/usersettings.hpp" + +#include "page.hpp" + +#include + +#include + +#include +#include +#include + +#include +#include + +CSVSettings::Dialog::Dialog(QMainWindow *parent) + : mStackedWidget (0), mDebugMode (false), SettingWindow (parent) +{ + setWindowTitle(QString::fromUtf8 ("User Settings")); + + setupDialog(); + + connect (mPageListWidget, + SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, + SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*))); +} + +void CSVSettings::Dialog::slotChangePage + (QListWidgetItem *cur, QListWidgetItem *prev) +{ + mStackedWidget->changePage + (mPageListWidget->row (cur), mPageListWidget->row (prev)); + + layout()->activate(); + setFixedSize(minimumSizeHint()); +} + +void CSVSettings::Dialog::setupDialog() +{ + //create central widget with it's layout and immediate children + QWidget *centralWidget = new QGroupBox (this); + + centralWidget->setLayout (new QHBoxLayout()); + centralWidget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred); + setCentralWidget (centralWidget); + setDockOptions (QMainWindow::AllowNestedDocks); + + buildPageListWidget (centralWidget); + buildStackedWidget (centralWidget); +} + +void CSVSettings::Dialog::buildPages() +{ + SettingWindow::createPages (); + + QFontMetrics fm (QApplication::font()); + + foreach (Page *page, SettingWindow::pages()) + { + QString pageName = page->objectName(); + + int textWidth = fm.width(pageName); + + new QListWidgetItem (pageName, mPageListWidget); + mPageListWidget->setFixedWidth (textWidth + 50); + + mStackedWidget->addWidget (&dynamic_cast(*(page))); + } + + addDebugPage(); + + resize (mStackedWidget->sizeHint()); +} + +void CSVSettings::Dialog::addDebugPage() +{ + /* + QTreeView *tree = new QTreeView(); + + //tree->setModel( &CSMSettings::UserSettings::instance().model() ); + + mStackedWidget->addWidget(tree); + new QListWidgetItem ("Standard Item Model", mPageListWidget);*/ +} + +void CSVSettings::Dialog::buildPageListWidget (QWidget *centralWidget) +{ + mPageListWidget = new QListWidget (centralWidget); + mPageListWidget->setMinimumWidth(50); + mPageListWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Expanding); + + mPageListWidget->setSelectionBehavior (QAbstractItemView::SelectItems); + + centralWidget->layout()->addWidget(mPageListWidget); +} + +void CSVSettings::Dialog::buildStackedWidget (QWidget *centralWidget) +{ + mStackedWidget = new ResizeableStackedWidget (centralWidget); + + centralWidget->layout()->addWidget (mStackedWidget); +} + +void CSVSettings::Dialog::closeEvent (QCloseEvent *event) +{ + //SettingWindow::closeEvent() must be called first to ensure + //model is updated + SettingWindow::closeEvent (event); + + saveSettings(); +} + +void CSVSettings::Dialog::show() +{ + if (pages().isEmpty()) + buildPages(); + + QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); + + move (screenCenter - geometry().center()); + + QWidget::show(); +} diff --git a/apps/opencs/view/settings/dialog.hpp b/apps/opencs/view/settings/dialog.hpp new file mode 100644 index 0000000000..0cfd415acd --- /dev/null +++ b/apps/opencs/view/settings/dialog.hpp @@ -0,0 +1,55 @@ +#ifndef CSVSETTINGS_DIALOG_H +#define CSVSETTINGS_DIALOG_H + +#include "settingwindow.hpp" +#include "resizeablestackedwidget.hpp" +#include + +class QStackedWidget; +class QListWidget; +class QListWidgetItem; + +namespace CSVSettings { + + class Page; + + class Dialog : public SettingWindow + { + Q_OBJECT + + QListWidget *mPageListWidget; + ResizeableStackedWidget *mStackedWidget; + bool mDebugMode; + + public: + + explicit Dialog (QMainWindow *parent = 0); + + ///Enables setting debug mode. When the dialog opens, a page is created + ///which displays the SettingModel's contents in a Tree view. + void enableDebugMode (bool state, QStandardItemModel *model = 0); + + protected: + + /// Settings are written on close + void closeEvent (QCloseEvent *event); + + void setupDialog(); + + private: + + void buildPages(); + void buildPageListWidget (QWidget *centralWidget); + void buildStackedWidget (QWidget *centralWidget); + void addDebugPage(); + + public slots: + + void show(); + + private slots: + + void slotChangePage (QListWidgetItem *, QListWidgetItem *); + }; +} +#endif // CSVSETTINGS_DIALOG_H diff --git a/apps/opencs/view/settings/frame.cpp b/apps/opencs/view/settings/frame.cpp new file mode 100644 index 0000000000..db5091999a --- /dev/null +++ b/apps/opencs/view/settings/frame.cpp @@ -0,0 +1,103 @@ +#include "frame.hpp" + +#include + +const QString CSVSettings::Frame::sInvisibleBoxStyle = + QString::fromUtf8("Frame { border:2px; padding 2px; margin: 2px;}"); + +CSVSettings::Frame::Frame (bool isVisible, const QString &title, + QWidget *parent) + : mIsHorizontal (true), mLayout (new SettingLayout()), + QGroupBox (title, parent) +{ + setFlat (true); + mVisibleBoxStyle = styleSheet(); + + if (!isVisible) + setStyleSheet (sInvisibleBoxStyle); + + setLayout (mLayout); +} + +void CSVSettings::Frame::hideWidgets() +{ + for (int i = 0; i < children().size(); i++) + { + QObject *obj = children().at(i); + + Frame *widgFrame = dynamic_cast (obj); + + if (widgFrame) + { + widgFrame->hideWidgets(); + continue; + } + + QWidget *widg = static_cast (obj); + if (widg->property("sizePolicy").isValid()) + widg->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored); + } + + layout()->activate(); + setFixedSize(minimumSizeHint()); + +} + +void CSVSettings::Frame::showWidgets() +{ + for (int i = 0; i < children().size(); i++) + { + QObject *obj = children().at(i); + + Frame *widgFrame = dynamic_cast (obj); + + if (widgFrame) + { + widgFrame->showWidgets(); + continue; + } + + QWidget *widg = static_cast (obj); + + if (widg->property("sizePolicy").isValid()) + widg->setSizePolicy + (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + } + layout()->activate(); + setFixedSize(minimumSizeHint()); +} + +void CSVSettings::Frame::addWidget (QWidget *widget, int row, int column, + int rowSpan, int columnSpan) +{ + if (row == -1) + row = getNextRow(); + + if (column == -1) + column = getNextColumn(); + + mLayout->addWidget (widget, row, column, rowSpan, columnSpan); + //, Qt::AlignLeft | Qt::AlignTop); + + widget->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored); +} + +int CSVSettings::Frame::getNextRow () const +{ + int row = mLayout->rowCount(); + + if (mIsHorizontal && row > 0) + row--; + + return row; +} + +int CSVSettings::Frame::getNextColumn () const +{ + int column = 0; + + if (mIsHorizontal) + column = mLayout->columnCount(); + + return column; +} diff --git a/apps/opencs/view/settings/frame.hpp b/apps/opencs/view/settings/frame.hpp new file mode 100644 index 0000000000..2b52dfd1f4 --- /dev/null +++ b/apps/opencs/view/settings/frame.hpp @@ -0,0 +1,58 @@ +#ifndef CSVSETTINGS_FRAME_HPP +#define CSVSETTINGS_FRAME_HPP + +#include +#include +#include +#include "../../model/settings/support.hpp" + +namespace CSVSettings +{ + class SettingLayout : public QGridLayout + { + public: + explicit SettingLayout (QWidget *parent = 0) + : QGridLayout (parent) + { + setContentsMargins(0,0,0,0); + setAlignment(Qt::AlignLeft | Qt::AlignTop); + } + }; + + /// Custom implementation of QGroupBox to act as a base for view classes + class Frame : public QGroupBox + { + static const QString sInvisibleBoxStyle; + + QString mVisibleBoxStyle; + + bool mIsHorizontal; + + SettingLayout *mLayout; + + public: + explicit Frame (bool isVisible, const QString &title = "", + QWidget *parent = 0); + + ///Adds a widget to the grid layout, setting the position + ///relative to the last added widgets, or absolutely for positive + ///row / column values + void addWidget (QWidget *widget, int row = -1, int column = -1, + int rowSpan = 1, int columnSpan = 1); + + ///Force the grid to lay out in horizontal or vertical alignments + void setHLayout() { mIsHorizontal = true; } + void setVLayout() { mIsHorizontal = false; } + + void showWidgets(); + void hideWidgets(); + + private: + + int getNextColumn() const; + int getNextRow() const; + + }; +} + +#endif // CSVSETTINGS_FRAME_HPP diff --git a/apps/opencs/view/settings/listview.cpp b/apps/opencs/view/settings/listview.cpp new file mode 100644 index 0000000000..b2a47903ff --- /dev/null +++ b/apps/opencs/view/settings/listview.cpp @@ -0,0 +1,106 @@ +#include "listview.hpp" +#include "../../model/settings/setting.hpp" + +#include +#include +#include + +CSVSettings::ListView::ListView(CSMSettings::Setting *setting, + Page *parent) + : mComboBox (0), mAbstractItemView (0), View(setting, parent) +{ + QWidget *widget = + buildWidget(setting->isMultiLine(), setting->widgetWidth()); + + addWidget (widget, setting->viewRow(), setting->viewColumn()); + + if (mComboBox) + buildComboBoxModel(); + + else if (mAbstractItemView) + buildAbstractItemViewModel(); +} + +void CSVSettings::ListView::buildComboBoxModel() +{ + mComboBox->setModel (dataModel()); + mComboBox->setModelColumn (0); + mComboBox->view()->setSelectionModel (selectionModel()); + + int curIdx = -1; + + if (!selectionModel()->selection().isEmpty()) + curIdx = selectionModel()->selectedIndexes().at(0).row(); + + mComboBox->setCurrentIndex (curIdx); + + connect (mComboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(emitItemViewUpdate(int))); +} + +void CSVSettings::ListView::buildAbstractItemViewModel() +{ + mAbstractItemView->setModel (dataModel()); + mAbstractItemView->setSelectionModel (selectionModel()); + + //connection needs to go here for list view update to signal to + //the outside +} + +void CSVSettings::ListView::emitItemViewUpdate (int idx) +{ + emit viewUpdated (objectName(), selectedValues()); +} + +QWidget *CSVSettings::ListView::buildWidget(bool isMultiLine, int width) +{ + QWidget *widget = 0; + + if (isMultiLine) + { + mAbstractItemView = new QListView (this); + widget = mAbstractItemView; + + if (width > 0) + widget->setFixedWidth (widgetWidth (width)); + } + else + { + mComboBox = new QComboBox (this); + widget = mComboBox; + + if (width > 0) + mComboBox->setMinimumContentsLength (width); + } + + return widget; +} + +void CSVSettings::ListView::showEvent ( QShowEvent * event ) +{ + View::showEvent (event); +} + +void CSVSettings::ListView::updateView (bool signalUpdate) const +{ + QStringList values = selectedValues(); + + if (mComboBox) + { + int idx = -1; + + if (values.size() > 0) + idx = (mComboBox->findText(values.at(0))); + + mComboBox->setCurrentIndex (idx); + } + + View::updateView (signalUpdate); +} + +CSVSettings::ListView *CSVSettings::ListViewFactory::createView + (CSMSettings::Setting *setting, + Page *parent) +{ + return new ListView(setting, parent); +} diff --git a/apps/opencs/view/settings/listview.hpp b/apps/opencs/view/settings/listview.hpp new file mode 100644 index 0000000000..c2860d769a --- /dev/null +++ b/apps/opencs/view/settings/listview.hpp @@ -0,0 +1,63 @@ +#ifndef CSVSETTINGS_LISTVIEW_HPP +#define CSVSETTINGS_LISTVIEW_HPP + +#include "view.hpp" + + +class QStringListModel; +class QComboBox; +class QAbstractItemView; + +namespace CSVSettings +{ + class ListView : public View + { + Q_OBJECT + + QAbstractItemView *mAbstractItemView; + QComboBox *mComboBox; + + public: + explicit ListView (CSMSettings::Setting *setting, + Page *parent); + + protected: + + void updateView (bool signalUpdate = true) const; + void showEvent ( QShowEvent * event ); + + ///Receives signal from widget and signals viwUpdated() + void slotTextEdited (QString value); + + private: + + ///Helper function to construct a model for an AbstractItemView + void buildAbstractItemViewModel(); + + ///Helper function to construct a model for a combobox + void buildComboBoxModel(); + + ///Helper function to build the view widget + QWidget *buildWidget (bool isMultiLine, int width); + + private slots: + + ///Receives updates from single-select widgets (like combobox) and + ///signals viewUpdated with the selected values. + void emitItemViewUpdate (int idx); + }; + + class ListViewFactory : public QObject, public IViewFactory + { + Q_OBJECT + + public: + explicit ListViewFactory (QWidget *parent = 0) + : QObject (parent) + {} + + ListView *createView (CSMSettings::Setting *setting, + Page *parent); + }; +} +#endif // CSVSETTINGS_LISTVIEW_HPP diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp new file mode 100644 index 0000000000..665326c2c0 --- /dev/null +++ b/apps/opencs/view/settings/page.cpp @@ -0,0 +1,88 @@ +#include "page.hpp" +#include "view.hpp" +#include "booleanview.hpp" +#include "textview.hpp" +#include "listview.hpp" + +#include "../../model/settings/usersettings.hpp" +#include "../../model/settings/connector.hpp" +#include "settingwindow.hpp" + +QMap + CSVSettings::Page::mViewFactories; + +CSVSettings::Page::Page(const QString &pageName, + QList settingList, + SettingWindow *parent) : + mParent(parent), mIsEditorPage (false), Frame(false, "", parent) +{ + setObjectName (pageName); + + if (mViewFactories.size() == 0) + buildFactories(); + + setVLayout(); + setupViews (settingList); +} + +void CSVSettings::Page::setupViews + (QList &settingList) +{ + foreach (CSMSettings::Setting *setting, settingList) + addView (setting); +} + +void CSVSettings::Page::addView (CSMSettings::Setting *setting) +{ + if (setting->viewType() == ViewType_Undefined) + return; + + View *view = mViewFactories[setting->viewType()]->createView(setting, this); + + if (!view) + return; + + mViews.append (view); + + addWidget (view, setting->viewRow(), setting->viewColumn(), + setting->rowSpan(), setting->columnSpan() ); + + //if this page is an editor page, connect each of it's views up to the + //UserSettings singleton for signaling back to OpenCS + if (setting->isEditorSetting()) { + connect (view, SIGNAL (viewUpdated(const QString&, const QStringList&)), + &CSMSettings::UserSettings::instance(), + SIGNAL (userSettingUpdated (const QString &, const QStringList &))); + } +} + +CSVSettings::View *CSVSettings::Page::findView (const QString &page, + const QString &setting) const +{ + + //if this is not the page we're looking for, + //appeal to the parent setting window to find the appropriate view + if (page != objectName()) + return mParent->findView (page, setting); + + //otherwise, return the matching view + for (int i = 0; i < mViews.size(); i++) + { + View *view = mViews.at(i); + + if (view->parentPage()->objectName() != page) + continue; + + if (view->objectName() == setting) + return view; + } + + return 0; +} + +void CSVSettings::Page::buildFactories() +{ + mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this); + mViewFactories[ViewType_Text] = new TextViewFactory (this); + mViewFactories[ViewType_List] = new ListViewFactory (this); +} diff --git a/apps/opencs/view/settings/page.hpp b/apps/opencs/view/settings/page.hpp new file mode 100644 index 0000000000..7f24f6a625 --- /dev/null +++ b/apps/opencs/view/settings/page.hpp @@ -0,0 +1,54 @@ +#ifndef CSVSETTINGS_PAGE_HPP +#define CSVSETTINGS_PAGE_HPP + +#include +#include +#include +#include + +#include "frame.hpp" + +#include "../../model/settings/support.hpp" + +namespace CSMSettings { class Setting; } + +namespace CSVSettings +{ + class View; + class IViewFactory; + class SettingWindow; + + class Page : public Frame + { + Q_OBJECT + + QList mViews; + SettingWindow *mParent; + static QMap mViewFactories; + bool mIsEditorPage; + + public: + explicit Page(const QString &pageName, + QList settingList, + SettingWindow *parent); + + ///Creates a new view based on the passed setting and adds it to + ///the page. + void addView (CSMSettings::Setting *setting); + + ///Iterates the views created for this page based on the passed setting + ///and returns it. + View *findView (const QString &page, const QString &setting) const; + + const QList &views () const { return mViews; } + + private: + + ///Creates views based on the passed setting list + void setupViews (QList &settingList); + + ///Creates factory objects for view construction + void buildFactories(); + }; +} +#endif // CSVSETTINGS_PAGE_HPP diff --git a/apps/opencs/view/settings/resizeablestackedwidget.cpp b/apps/opencs/view/settings/resizeablestackedwidget.cpp new file mode 100644 index 0000000000..cb127cb761 --- /dev/null +++ b/apps/opencs/view/settings/resizeablestackedwidget.cpp @@ -0,0 +1,40 @@ +#include "resizeablestackedwidget.hpp" +#include "page.hpp" + +#include + +CSVSettings::ResizeableStackedWidget::ResizeableStackedWidget(QWidget *parent) : + QStackedWidget(parent) +{} + +void CSVSettings::ResizeableStackedWidget::addWidget(QWidget* pWidget) +{ + QStackedWidget::addWidget(pWidget); +} + +void CSVSettings::ResizeableStackedWidget::changePage + (int current, int previous) +{ + if (current == previous) + return; + + Page *prevPage = 0; + Page *curPage = 0; + + if (previous > -1) + prevPage = static_cast (widget (previous)); + + if (current > -1) + curPage = static_cast (widget (current)); + + if (prevPage) + prevPage->hideWidgets(); + + if (curPage) + curPage->showWidgets(); + + layout()->activate(); + setFixedSize(minimumSizeHint()); + + setCurrentIndex (current); +} diff --git a/apps/opencs/view/settings/resizeablestackedwidget.hpp b/apps/opencs/view/settings/resizeablestackedwidget.hpp new file mode 100644 index 0000000000..5e894d8dfd --- /dev/null +++ b/apps/opencs/view/settings/resizeablestackedwidget.hpp @@ -0,0 +1,23 @@ +#ifndef CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP +#define CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP + +#include + +class QListWidgetItem; + +namespace CSVSettings +{ + class ResizeableStackedWidget : public QStackedWidget + { + Q_OBJECT + + public: + explicit ResizeableStackedWidget(QWidget *parent = 0); + + void addWidget(QWidget* pWidget); + + void changePage (int, int); + }; +} + +#endif // CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp new file mode 100644 index 0000000000..9283bbf51b --- /dev/null +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -0,0 +1,114 @@ +#include +#include + +#include "../../model/settings/setting.hpp" +#include "../../model/settings/connector.hpp" +#include "../../model/settings/usersettings.hpp" +#include "settingwindow.hpp" +#include "page.hpp" +#include "view.hpp" + +CSVSettings::SettingWindow::SettingWindow(QWidget *parent) + : QMainWindow(parent) +{} + +void CSVSettings::SettingWindow::createPages() +{ + CSMSettings::SettingPageMap pageMap = mModel->settingPageMap(); + + QList connectedSettings; + + foreach (const QString &pageName, pageMap.keys()) + { + QList pageSettings = pageMap.value (pageName); + + mPages.append (new Page (pageName, pageSettings, this)); + + for (int i = 0; i < pageSettings.size(); i++) + { + CSMSettings::Setting *setting = pageSettings.at(i); + + if (!setting->proxyLists().isEmpty()) + connectedSettings.append (setting); + } + } + + if (!connectedSettings.isEmpty()) + createConnections(connectedSettings); +} + +void CSVSettings::SettingWindow::createConnections + (const QList &list) +{ + foreach (const CSMSettings::Setting *setting, list) + { + View *masterView = findView (setting->page(), setting->name()); + + CSMSettings::Connector *connector = + new CSMSettings::Connector (masterView, this); + + connect (masterView, + SIGNAL (viewUpdated(const QString &, const QStringList &)), + connector, + SLOT (slotUpdateSlaves()) + ); + + const CSMSettings::ProxyValueMap &proxyMap = setting->proxyLists(); + + foreach (const QString &key, proxyMap.keys()) + { + QStringList keyPair = key.split('.'); + + if (keyPair.size() != 2) + continue; + + View *slaveView = findView (keyPair.at(0), keyPair.at(1)); + + if (!slaveView) + { + qWarning () << "Unable to create connection for view " + << key; + continue; + } + + QList proxyList = proxyMap.value (key); + connector->addSlaveView (slaveView, proxyList); + + connect (slaveView, + SIGNAL (viewUpdated(const QString &, const QStringList &)), + connector, + SLOT (slotUpdateMaster())); + } + } +} + +CSVSettings::View *CSVSettings::SettingWindow::findView + (const QString &pageName, const QString &setting) +{ + foreach (const Page *page, mPages) + { + if (page->objectName() == pageName) + return page->findView (pageName, setting); + } + return 0; +} + +void CSVSettings::SettingWindow::saveSettings() +{ + QMap settingMap; + + foreach (const Page *page, mPages) + { + foreach (const View *view, page->views()) + { + if (view->serializable()) + settingMap[view->viewKey()] = view->selectedValues(); + } + } + CSMSettings::UserSettings::instance().saveSettings (settingMap); +} + +void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event) +{ + QApplication::focusWidget()->clearFocus(); +} diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp new file mode 100644 index 0000000000..35ae4c068c --- /dev/null +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -0,0 +1,49 @@ +#ifndef CSVSETTINGS_SETTINGWINDOW_HPP +#define CSVSETTINGS_SETTINGWINDOW_HPP + +#include +#include + +#include "../../model/settings/support.hpp" + +namespace CSMSettings { + class Setting; + class SettingManager; +} + +namespace CSVSettings { + + class Page; + class View; + + typedef QList PageList; + + class SettingWindow : public QMainWindow + { + Q_OBJECT + + PageList mPages; + CSMSettings::SettingManager *mModel; + + public: + explicit SettingWindow(QWidget *parent = 0); + + View *findView (const QString &pageName, const QString &setting); + void setModel (CSMSettings::SettingManager &model) { mModel = &model; } + + protected: + + virtual void closeEvent (QCloseEvent *event); + + void createPages(); + + const PageList &pages() const { return mPages; } + + void saveSettings(); + + private: + void createConnections (const QList &list); + }; +} + +#endif // CSVSETTINGS_SETTINGWINDOW_HPP diff --git a/apps/opencs/view/settings/textview.cpp b/apps/opencs/view/settings/textview.cpp new file mode 100644 index 0000000000..5e10c346f7 --- /dev/null +++ b/apps/opencs/view/settings/textview.cpp @@ -0,0 +1,73 @@ +#include +#include + +#include "textview.hpp" +#include "../../model/settings/setting.hpp" + +CSVSettings::TextView::TextView(CSMSettings::Setting *setting, Page *parent) + : mDelimiter (setting->delimiter()), View (setting, parent) + +{ + if (setting->isMultiLine()) + mTextWidget = new QTextEdit ("", this); + else + mTextWidget = new QLineEdit ("", this); + + if (setting->widgetWidth() > 0) + mTextWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); + + connect (mTextWidget, SIGNAL (textEdited (QString)), + this, SLOT (slotTextEdited (QString))); + + addWidget (mTextWidget, setting->viewRow(), setting->viewColumn()); +} + +bool CSVSettings::TextView::isEquivalent + (const QString &lhs, const QString &rhs) const +{ + return (lhs.trimmed() == rhs.trimmed()); +} + +void CSVSettings::TextView::setWidgetText (const QString &value) const +{ + mTextWidget->setProperty ("text", value); +} + +void CSVSettings::TextView::slotTextEdited (QString value) +{ + QStringList values = value.split (mDelimiter, QString::SkipEmptyParts); + + QStringList returnValues; + + foreach (const QString &splitValue, values) + returnValues.append (splitValue.trimmed()); + + setSelectedValues (returnValues, false); + + View::updateView(); +} + +void CSVSettings::TextView::updateView(bool signalUpdate) const +{ + QString values = selectedValues().join (mDelimiter); + + if (isEquivalent (widgetText(), values)) + return; + + setWidgetText (values); + + View::updateView (signalUpdate); +} + +QString CSVSettings::TextView::widgetText() const +{ + return mTextWidget->property("text").toString(); +} + +CSVSettings::TextView *CSVSettings::TextViewFactory::createView + (CSMSettings::Setting *setting, + Page *parent) +{ + return new TextView (setting, parent); +} + diff --git a/apps/opencs/view/settings/textview.hpp b/apps/opencs/view/settings/textview.hpp new file mode 100644 index 0000000000..6d718aad87 --- /dev/null +++ b/apps/opencs/view/settings/textview.hpp @@ -0,0 +1,56 @@ +#ifndef CSVSETTINGS_TEXTVIEW_HPP +#define CSVSETTINGS_TEXTVIEW_HPP + +#include "view.hpp" +#include "../../model/settings/setting.hpp" + +namespace CSVSettings +{ + class TextView : public View + { + Q_OBJECT + + QWidget *mTextWidget; + + QString mDelimiter; + + public: + explicit TextView (CSMSettings::Setting *setting, + Page *parent = 0); + + protected: + + void updateView (bool signalUpdate = true) const; + + protected slots: + + ///Receives updates to the widget for signalling + void slotTextEdited (QString value); + + private: + + ///Comparison function that returns true if the trimmed() strings + ///are equal + bool isEquivalent (const QString &lhs, const QString &rhs) const; + + ///Convenience function to return the text of the widget + QString widgetText() const; + + ///Convenience function to set the text of the widget + void setWidgetText (const QString &value) const; + }; + + class TextViewFactory : public QObject, public IViewFactory + { + Q_OBJECT + + public: + explicit TextViewFactory (QWidget *parent = 0) + : QObject (parent) + {} + + TextView *createView (CSMSettings::Setting *setting, + Page *parent); + }; +} +#endif // CSVSETTINGS_TEXTVIEW_HPP diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp new file mode 100644 index 0000000000..259dd518b6 --- /dev/null +++ b/apps/opencs/view/settings/view.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include + +#include "view.hpp" +#include "../../model/settings/support.hpp" +#include "../../model/settings/setting.hpp" +#include "page.hpp" + +CSVSettings::View::View(CSMSettings::Setting *setting, + Page *parent) + + : mDataModel(0), mParentPage (parent), + mHasFixedValues (!setting->declaredValues().isEmpty()), + mIsMultiValue (setting->isMultiValue()), + mViewKey (setting->page() + '.' + setting->name()), + mSerializable (setting->serializable()), + Frame(true, setting->name(), parent) +{ + setObjectName (setting->name()); + buildView(); + buildModel (setting); +} + +void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) +{ + QStringList values = setting->definedValues(); + + if (values.isEmpty()) + values.append (setting->defaultValues()); + + if (mHasFixedValues) + buildFixedValueModel (setting->declaredValues()); + else + buildUpdatableValueModel (values); + + mSelectionModel = new QItemSelectionModel (mDataModel, this); + + setSelectedValues (values, false); +} + +void CSVSettings::View::buildFixedValueModel (const QStringList &values) +{ + mDataModel = new QStringListModel (values, this); +} + +void CSVSettings::View::buildUpdatableValueModel (const QStringList &values) +{ + QList itemList; + + foreach (const QString &value, values) + itemList.append (new QStandardItem(value)); + +// QSortFilterProxyModel *filter = new QSortFilterProxyModel (this); + QStandardItemModel *model = new QStandardItemModel (this); + model->appendColumn (itemList); + +// filter->setSourceModel (model); + /* filter->setFilterRegExp ("*"); + filter->setFilterKeyColumn (0); + filter->setFilterRole (Qt::DisplayRole);*/ + mDataModel = model; +} + +void CSVSettings::View::buildView() +{ + setFlat (true); + setHLayout(); +} + +int CSVSettings::View::currentIndex () const +{ + if (selectedValues().isEmpty()) + return -1; + + QString currentValue = selectedValues().at(0); + + for (int i = 0; i < mDataModel->rowCount(); i++) + if (value(i) == currentValue) + return i; + + return -1; +} + +void CSVSettings::View::refresh() const +{ + select (mSelectionModel->selection()); + updateView(); +} + +int CSVSettings::View::rowCount() const +{ + return mDataModel->rowCount(); +} + +void CSVSettings::View::select (const QItemSelection &selection) const +{ + mSelectionModel->clear(); + mSelectionModel->select(selection, QItemSelectionModel::Select); +} + +QStringList CSVSettings::View::selectedValues() const +{ + QStringList selValues; + + foreach (const QModelIndex &idx, mSelectionModel->selectedIndexes()) + selValues.append (value(idx.row())); + + return selValues; +} + +void CSVSettings::View::setSelectedValue (const QString &value, + bool doViewUpdate, bool signalUpdate) +{ + setSelectedValues (QStringList() << value, doViewUpdate, signalUpdate); +} + +void CSVSettings::View::setSelectedValues (const QStringList &list, + bool doViewUpdate, bool signalUpdate) +{ + QItemSelection selection; + + if (stringListsMatch (list, selectedValues())) + return; + + if (!mHasFixedValues) + { + QStandardItemModel *model = + static_cast (mDataModel); + + model->clear(); + model->appendColumn (toStandardItemList (list)); + + for (int i = 0; i < model->rowCount(); i++) + { + QModelIndex idx = model->index(i, 0); + selection.append (QItemSelectionRange (idx, idx)); + } + } + else + { + for (int i = 0; i < mDataModel->rowCount(); i++) + { + if (list.contains(value(i))) + { + QModelIndex idx = mDataModel->index(i, 0); + selection.append(QItemSelectionRange (idx, idx)); + } + } + } + select (selection); + + if (doViewUpdate) + updateView (signalUpdate); +} + +void CSVSettings::View::showEvent ( QShowEvent * event ) +{ + refresh(); +} + +bool CSVSettings::View::stringListsMatch ( + const QStringList &list1, + const QStringList &list2) const +{ + //returns a "sloppy" match, verifying that each list contains all the same + //items, though not necessarily in the same order. + + if (list1.size() != list2.size()) + return false; + + QStringList tempList(list2); + + //iterate each value in the list, removing one occurrence of the value in + //the other list. If no corresponding value is found, test fails + foreach (const QString &value, list1) + { + if (!tempList.contains(value)) + return false; + + tempList.removeOne(value); + } + return true; +} + +QList CSVSettings::View::toStandardItemList + (const QStringList &list) const +{ + QList itemList; + + foreach (const QString &value, list) + itemList.append (new QStandardItem (value)); + + return itemList; +} + +void CSVSettings::View::updateView (bool signalUpdate) const +{ + if (signalUpdate) + emit viewUpdated(objectName(), selectedValues()); +} + +QString CSVSettings::View::value (int row) const +{ + if (row > -1 && row < mDataModel->rowCount()) + return mDataModel->data (mDataModel->index(row, 0)).toString(); + + return ""; +} + +int CSVSettings::View::widgetWidth(int characterCount) const +{ + QString widthToken = QString().fill ('P', characterCount); + QFontMetrics fm (QApplication::font()); + + return (fm.width (widthToken)); +} diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp new file mode 100644 index 0000000000..c998797622 --- /dev/null +++ b/apps/opencs/view/settings/view.hpp @@ -0,0 +1,163 @@ +#ifndef CSVSETTINGS_VIEW_HPP +#define CSVSETTINGS_VIEW_HPP + +#include +#include + +#include "frame.hpp" +#include "../../model/settings/support.hpp" + +class QGroupBox; +class QStringList; +class QStandardItem; +class QItemSelection; +class QStringListModel; +class QStandardItemModel; +class QAbstractItemModel; +class QItemSelectionModel; + +namespace CSMSettings { class Setting; } + +namespace CSVSettings +{ + class Page; + + class View : public Frame + { + Q_OBJECT + + ///Pointer to the owning Page instance + Page *mParentPage; + + ///Pointer to the selection model for the view + QItemSelectionModel *mSelectionModel; + + ///Pointer to the data model for the view's selection model + QAbstractItemModel *mDataModel; + + ///State indicating whether or not the setting has a pre-defined list + ///of values, limiting possible definitions + bool mHasFixedValues; + + ///State indicating whether the view will allow multiple values + bool mIsMultiValue; + + QString mViewKey; + + bool mSerializable; + + public: + + explicit View (CSMSettings::Setting *setting, Page *parent); + + ///Physical frame in which the view UI is contained + void addViewWidget (QWidget *widget, int row = -1, int col = -1) const; + + ///Returns the index / row of the passed value, -1 if not found. + int currentIndex () const; + + ///Returns the number of rows in the view's data model + int rowCount() const; + + ///Returns bool indicating the data in this view should / should not + ///be serialized to a config file + bool serializable() const { return mSerializable; } + + ///Returns a pointer to the view's owning parent page + const Page *parentPage() const { return mParentPage; } + + ///Returns the selected items in the selection model as a QStringList + QStringList selectedValues() const; + + ///Sets the selected items in the selection model based on passed list. + ///Bools allow opt-out of updating the view + ///or signaling the view was updatedto avoid viscious cylcing. + void setSelectedValues (const QStringList &values, + bool updateView = true, + bool signalUpdate = true); + + void setSelectedValue (const QString &value, + bool updateView = true, + bool signalUpdate = true); + + + ///Returns the value of the data model at the specified row + QString value (int row) const; + + QString viewKey() const { return mViewKey; } + + protected: + + /// Returns the model which provides data for the selection model + QAbstractItemModel *dataModel() { return mDataModel; } + + ///Accessor function for subclasses + bool isMultiValue() { return mIsMultiValue; } + + ///Returns the view selection model + QItemSelectionModel *selectionModel() { return mSelectionModel;} + + ///Global callback for basic view initialization + void showEvent ( QShowEvent * event ); + + ///Virtual for updating a specific View subclass + ///bool indicates whether a signal is emitted that the view was updated + virtual void updateView (bool signalUpdate = true) const; + + ///Returns the pixel width corresponding to the specified number of + ///characters. + int widgetWidth(int characterCount) const; + + private: + + ///Constructs the view layout + void buildView(); + + ///Constructs the data and selection models + void buildModel (const CSMSettings::Setting *setting); + + ///In cases where the view has a pre-defined list of possible values, + ///a QStringListModel is created using those values. + ///View changes operate on the selection model only. + void buildFixedValueModel (const QStringList &definitions); + + ///In cases where the view does not have a pre-defined list of possible + ///values, a QStandardItemModel is created, containing the actual + ///setting definitions. View changes first update the data in the + ///model to match the data in the view. The selection model always + ///selects all values. + void buildUpdatableValueModel (const QStringList &definitions); + + ///Refreshes the view + void refresh() const; + + ///Convenince function for selection model's select() method. Also + ///clears out the model beforehand to ensure complete selection. + void select (const QItemSelection &selection) const; + + ///Compares two string lists "loosely", ensuring that all values in + ///one list are contained entirely in the other, and that neither list + ///has more values than the other. List order is not considered. + bool stringListsMatch (const QStringList &list1, + const QStringList &list2) const; + + ///Converts a string list to a list of QStandardItem pointers. + QList toStandardItemList(const QStringList &) const; + + signals: + + ///Signals that the view has been changed. + void viewUpdated(const QString &, const QStringList &) const; + + }; + + class IViewFactory + { + public: + + ///Creation interface for view factories + virtual View *createView (CSMSettings::Setting *setting, + Page *parent) = 0; + }; +} +#endif // CSVSETTINGS_VIEW_HPP From e3384e399913e2dc4a56f599fea0f1e8b4ab65b9 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 22 Apr 2014 22:17:52 -0500 Subject: [PATCH 009/545] relocate support.hpp / remove support.cpp --- apps/opencs/CMakeLists.txt | 31 ++-- apps/opencs/model/settings/support.cpp | 1 - apps/opencs/model/settings/support.hpp | 139 +++++++++++++---- apps/opencs/view/settings/support.cpp | 1 - apps/opencs/view/settings/support.hpp | 206 ------------------------- 5 files changed, 126 insertions(+), 252 deletions(-) delete mode 100644 apps/opencs/model/settings/support.cpp delete mode 100644 apps/opencs/view/settings/support.cpp delete mode 100644 apps/opencs/view/settings/support.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cbe90b1d3e..8ab44243dc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -88,34 +88,29 @@ opencs_units_noqt (view/tools ) opencs_units (view/settings - abstractblock - proxyblock - abstractwidget - usersettingsdialog - datadisplayformatpage - windowpage + settingwindow + dialog + page + view + booleanview + textview + listview + resizeablestackedwidget ) opencs_units_noqt (view/settings - abstractpage - blankpage - groupblock - customblock - groupbox - itemblock - settingwidget - toggleblock - support + frame ) opencs_units (model/settings usersettings - settingcontainer + settingmanager + setting + connector ) -opencs_units_noqt (model/settings +opencs_hdrs_noqt (model/settings support - settingsitem ) opencs_units_noqt (model/filter diff --git a/apps/opencs/model/settings/support.cpp b/apps/opencs/model/settings/support.cpp deleted file mode 100644 index d79edfdb33..0000000000 --- a/apps/opencs/model/settings/support.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "support.hpp" diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index 4ffd01b73c..abc86a0cb6 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -1,39 +1,126 @@ -#ifndef MODEL_SUPPORT_HPP -#define MODEL_SUPPORT_HPP +#ifndef SETTING_SUPPORT_HPP +#define SETTING_SUPPORT_HPP -#include +#include +#include +#include +#include #include -class QLayout; -class QWidget; -class QListWidgetItem; - +//Typedefs namespace CSMSettings { - class SettingContainer; + // Definition / Declaration model typedefs + // "Pair" = Setting name and specific data + // "ListItem" = Page name and associated setting pair - typedef QList SettingList; - typedef QMap SettingMap; - typedef QMap SectionMap; + typedef QPair StringPair; + typedef QPair StringListPair; + typedef QList StringListPairs; - struct QStringPair +} + +//Enums +namespace CSMSettings +{ + enum SettingProperty { - QStringPair(): left (""), right ("") - {} + Property_Name = 0, + Property_Page = 1, + Property_ViewType = 2, + Property_IsMultiValue = 3, + Property_IsMultiLine = 4, + Property_WidgetWidth = 5, + Property_ViewRow = 6, + Property_ViewColumn = 7, + Property_Delimiter = 8, + Property_Serializable = 9, + Property_ColumnSpan = 10, + Property_RowSpan = 11, - QStringPair (const QString &leftValue, const QString &rightValue) - : left (leftValue), right(rightValue) - {} + //Stringlists should always be the last items + Property_DefaultValues = 12, + Property_DeclaredValues = 13, + Property_DefinedValues = 14, + Property_Proxies = 15 + }; - QStringPair (const QStringPair &pair) - : left (pair.left), right (pair.right) - {} + enum SettingType + { + Type_MultiBool = 0, + Type_SingleBool = 1, + Type_MultiList = 2, + Type_SingleList = 3, + Type_MultiRange = 4, + Type_SingleRange = 5, + Type_MultiText = 6, + Type_SingleText = 7 + }; - QString left; - QString right; - - bool isEmpty() const - { return (left.isEmpty() && right.isEmpty()); } + enum MergeMethod + { + Merge_Accept, + Merge_Ignore, + Merge_Overwrite }; } -#endif // MODEL_SUPPORT_HPP + +namespace CSVSettings +{ + enum ViewType + { + ViewType_Boolean = 0, + ViewType_List = 1, + ViewType_Range = 2, + ViewType_Text = 3, + ViewType_Undefined = 4 + }; + + enum Alignment + { + Align_Left = Qt::AlignLeft, + Align_Center = Qt::AlignHCenter, + Align_Right = Qt::AlignRight + }; +} + +// +namespace CSMSettings +{ + struct PropertyDefaultValues + { + int id; + QString name; + QVariant value; + }; + + const QString sPropertyNames[] = + { + "name", "page", "view_type", "is_multi_value", + "is_multi_line", "widget_width", "view_row", "view_column", "delimiter", + "is_serializable","column_span", "row_span", + "defaults", "declarations", "definitions", "proxies" + }; + + const QString sPropertyDefaults[] = + { + "", //name + "", //page + "0", //view type + "false", //multivalue + "false", //multiline + "0", //widget width + "-1", //view row + "-1", //view column + ",", //delimiter + "true", //serialized + "1", //column span + "1", //row span + "", //default values + "", //declared values + "", //defined values + "" //proxy values + }; +} + +#endif // VIEW_SUPPORT_HPP diff --git a/apps/opencs/view/settings/support.cpp b/apps/opencs/view/settings/support.cpp deleted file mode 100644 index d79edfdb33..0000000000 --- a/apps/opencs/view/settings/support.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "support.hpp" diff --git a/apps/opencs/view/settings/support.hpp b/apps/opencs/view/settings/support.hpp deleted file mode 100644 index 5d954505c4..0000000000 --- a/apps/opencs/view/settings/support.hpp +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef VIEW_SUPPORT_HPP -#define VIEW_SUPPORT_HPP - -#include -#include - -#include "../../model/settings/support.hpp" - -namespace CSVSettings -{ - struct WidgetDef; - class ItemBlock; - class GroupBlock; - struct GroupBlockDef; - - typedef QList GroupBlockDefList; - typedef QList GroupBlockList; - typedef QList ItemBlockList; - typedef QList ProxyList; - typedef QList WidgetList; - typedef QMap ItemBlockMap; - - enum Orientation - { - Orient_Horizontal, - Orient_Vertical - }; - - enum WidgetType - { - Widget_CheckBox, - Widget_ComboBox, - Widget_LineEdit, - Widget_ListBox, - Widget_RadioButton, - Widget_SpinBox, - Widget_Undefined - }; - - enum Alignment - { - Align_Left = Qt::AlignLeft, - Align_Center = Qt::AlignHCenter, - Align_Right = Qt::AlignRight - }; - - /// definition struct for widgets - struct WidgetDef - { - /// type of widget providing input - WidgetType type; - - /// width of caption label - int labelWidth; - - /// width of input widget - int widgetWidth; - - /// label / widget orientation (horizontal / vertical) - Orientation orientation; - - /// input mask (line edit only) - QString inputMask; - - /// label caption. Leave empty for multiple items. See BlockDef::captionList - QString caption; - - /// widget value. Leave empty for multiple items. See BlockDef::valueList - QString value; - - /// Min/Max QString value pair. If empty, assigned to property item value pair. - CSMSettings::QStringPair *minMax; - - /// value list for list widgets. If left empty, is assigned to property item value list during block build(). - QStringList *valueList; - - /// determined at runtime - bool isDefault; - - /// left / center / right-justify text in widget - Alignment valueAlignment; - - /// left / center / right-justify widget in group box - Alignment widgetAlignment; - - - WidgetDef() : labelWidth (-1), widgetWidth (-1), - orientation (Orient_Horizontal), - isDefault (true), valueAlignment (Align_Center), - widgetAlignment (Align_Right), - inputMask (""), value (""), - caption (""), valueList (0) - {} - - WidgetDef (WidgetType widgType) - : type (widgType), orientation (Orient_Horizontal), - caption (""), value (""), valueAlignment (Align_Center), - widgetAlignment (Align_Right), - labelWidth (-1), widgetWidth (-1), - valueList (0), isDefault (true) - {} - - }; - - /// Defines the attributes of the setting as it is represented in the config file - /// as well as the UI elements (group box and widget) that serve it. - /// Only one widget may serve as the input widget for the setting. - struct SettingsItemDef - { - /// setting name - QString name; - - /// list of valid values for the setting - QStringList *valueList; - - /// Used to populate option widget captions or list widget item lists (see WidgetDef::caption / value) - QString defaultValue; - - /// flag indicating multi-valued setting - bool hasMultipleValues; - - /// minimum / maximum value pair - CSMSettings::QStringPair minMax; - - /// definition of the input widget for this setting - WidgetDef widget; - - /// general orientation of the widget / label for this setting - Orientation orientation; - - /// list of settings and corresponding default values for proxy widget - ProxyList *proxyList; - - SettingsItemDef() : name (""), defaultValue (""), orientation (Orient_Vertical), hasMultipleValues (false) - {} - - SettingsItemDef (QString propName, QString propDefault, Orientation propOrient = Orient_Vertical) - : name (propName), defaultValue (propDefault), orientation (propOrient), - hasMultipleValues(false), valueList (new QStringList), proxyList ( new ProxyList) - {} - }; - - - /// Generic container block - struct GroupBlockDef - { - /// block title - QString title; - - /// list of captions for widgets at the block level (not associated with any particular setting) - QStringList captions; - - /// list of widgets at the block level (not associated with any particular setting) - WidgetList widgets; - - /// list of the settings which are subordinate to the setting block. - QList settingItems; - - /// general orientation of widgets in group block - Orientation widgetOrientation; - - /// determines whether or not box border/title are visible - bool isVisible; - - /// indicates whether or not this block defines a proxy block - bool isProxy; - - /// generic default value attribute - QString defaultValue; - - /// shows / hides margins - bool isZeroMargin; - - GroupBlockDef (): title(""), widgetOrientation (Orient_Vertical), isVisible (true), isProxy (false), defaultValue (""), isZeroMargin (true) - {} - - GroupBlockDef (QString blockTitle) - : title (blockTitle), widgetOrientation (Orient_Vertical), isProxy (false), isVisible (true), defaultValue (""), isZeroMargin (true) - {} - }; - - /// used to create unique, complex blocks - struct CustomBlockDef - { - /// block title - QString title; - - /// default value for widgets unique to the custom block - QString defaultValue; - - /// list of settings groups that comprise the settings within the custom block - GroupBlockDefList blockDefList; - - /// orientation of the widgets within the block - Orientation blockOrientation; - - CustomBlockDef (): title (""), defaultValue (""), blockOrientation (Orient_Horizontal) - {} - - CustomBlockDef (const QString &blockTitle) - : title (blockTitle), defaultValue (""), blockOrientation (Orient_Horizontal) - {} - }; -} - -#endif // VIEW_SUPPORT_HPP From 4b607d658f5e8f2008d06395f270b2f902ef4d3f Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 22 Apr 2014 22:19:53 -0500 Subject: [PATCH 010/545] Re-link user settings to editor main application --- apps/opencs/editor.cpp | 13 + apps/opencs/editor.hpp | 4 +- apps/opencs/model/settings/usersettings.cpp | 477 +++++++++----------- apps/opencs/model/settings/usersettings.hpp | 45 +- apps/opencs/view/doc/subview.cpp | 9 +- apps/opencs/view/doc/subview.hpp | 4 +- apps/opencs/view/doc/view.cpp | 39 +- apps/opencs/view/doc/view.hpp | 2 + apps/opencs/view/doc/viewmanager.cpp | 17 +- apps/opencs/view/doc/viewmanager.hpp | 3 - apps/opencs/view/tools/reportsubview.cpp | 7 +- apps/opencs/view/tools/reportsubview.hpp | 5 +- apps/opencs/view/world/table.cpp | 14 +- apps/opencs/view/world/table.hpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 7 +- apps/opencs/view/world/tablesubview.hpp | 3 +- apps/opencs/view/world/util.cpp | 6 +- apps/opencs/view/world/util.hpp | 4 +- 18 files changed, 290 insertions(+), 371 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 87660a60bc..2dfdb1de66 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -28,6 +28,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) setupDataFiles (config.first); CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); + mSettings.setModel (CSMSettings::UserSettings::instance()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); @@ -117,6 +118,18 @@ std::pair > CS::Editor::readConfi dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); + //iterate the data directories and add them to the file dialog for loading + for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) + { + QString path = QString::fromStdString(iter->string()); + mFileDialog.addFiles(path); + } +/* + //load the settings into the userSettings instance. + const QString settingFileName = "opencs.cfg"; + CSMSettings::UserSettings::instance().loadSettings(settingFileName); +*/ + return std::make_pair (dataDirs, variables["fallback-archive"].as >()); } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 164398fb73..4c02b462e6 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -24,7 +24,7 @@ #include "view/doc/filedialog.hpp" #include "view/doc/newgame.hpp" -#include "view/settings/usersettingsdialog.hpp" +#include "view/settings/dialog.hpp" namespace OgreInit { @@ -43,7 +43,7 @@ namespace CS CSVDoc::ViewManager mViewManager; CSVDoc::StartupDialogue mStartup; CSVDoc::NewGameDialogue mNewGame; - CSVSettings::UserSettingsDialog mSettings; + CSVSettings::Dialog mSettings; CSVDoc::FileDialog mFileDialog; boost::filesystem::path mLocal; boost::filesystem::path mResources; diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 94cee8a43b..db31f42552 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -9,11 +9,16 @@ #include #include +#include + +#include #include -#include "settingcontainer.hpp" #include +#include "setting.hpp" +#include "support.hpp" + /** * Workaround for problems with whitespaces in paths in older versions of Boost library */ @@ -37,38 +42,151 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; - mReadWriteMessage = QObject::tr("
Could not open or create file for writing

\ - Please make sure you have the right permissions and try again.
"); - - mReadOnlyMessage = QObject::tr("
Could not open file for reading

\ - Please make sure you have the right permissions and try again.
"); - - buildEditorSettingDefaults(); + buildSettingModelDefaults(); } -void CSMSettings::UserSettings::buildEditorSettingDefaults() +void CSMSettings::UserSettings::buildSettingModelDefaults() { - SettingContainer *windowHeight = new SettingContainer("768", this); - SettingContainer *windowWidth = new SettingContainer("1024", this); - SettingContainer *rsDelegate = new SettingContainer("Icon and Text", this); - SettingContainer *refIdTypeDelegate = new SettingContainer("Icon and Text", this); + QString section = "Window Size"; + { + Setting *width = createSetting (Type_SingleText, section, "Width"); + Setting *height = createSetting (Type_SingleText, section, "Height"); - windowHeight->setObjectName ("Height"); - windowWidth->setObjectName ("Width"); - rsDelegate->setObjectName ("Record Status Display"); - refIdTypeDelegate->setObjectName ("Referenceable ID Type Display"); + width->setWidgetWidth (5); + height->setWidgetWidth (5); - SettingMap *displayFormatMap = new SettingMap; - SettingMap *windowSizeMap = new SettingMap; + width->setDefaultValues (QStringList() << "1024"); + height->setDefaultValues (QStringList() << "768"); - displayFormatMap->insert (rsDelegate->objectName(), rsDelegate ); - displayFormatMap->insert (refIdTypeDelegate->objectName(), refIdTypeDelegate); + width->setEditorSetting (true); + height->setEditorSetting (true); - windowSizeMap->insert (windowWidth->objectName(), windowWidth ); - windowSizeMap->insert (windowHeight->objectName(), windowHeight ); + height->setViewLocation (2,2); + width->setViewLocation (2,1); - mEditorSettingDefaults.insert ("Display Format", displayFormatMap); - mEditorSettingDefaults.insert ("Window Size", windowSizeMap); + /* + *Create the proxy setting for predefined values + */ + Setting *preDefined = createSetting (Type_SingleList, section, + "Pre-Defined", + QStringList() + << "640 x 480" + << "800 x 600" + << "1024 x 768" + << "1440 x 900" + ); + + preDefined->setViewLocation (1, 1); + preDefined->setWidgetWidth (10); + preDefined->setColumnSpan (2); + + preDefined->addProxy (width, + QStringList() << "640" << "800" << "1024" << "1440" + ); + + preDefined->addProxy (height, + QStringList() << "480" << "600" << "768" << "900" + ); + } + + section = "Display Format"; + { + QString defaultValue = "Icon and Text"; + + QStringList values = QStringList() + << defaultValue << "Icon Only" << "Text Only"; + + Setting *rsd = createSetting (Type_SingleBool, + section, "Record Status Display", + values); + + Setting *ritd = createSetting (Type_SingleBool, + section, "Referenceable ID Type Display", + values); + + rsd->setEditorSetting (true); + ritd->setEditorSetting (true); + } + + section = "Proxy Selection Test"; + { + //create three setting objects, specifying the basic widget type, + //the setting view name, the page name, and the default value + Setting *masterBoolean = createSetting (Type_SingleBool, section, + "Master Proxy", + QStringList() + << "Profile One" << "Profile Two" + << "Profile Three" << "Profile Four" + ); + + Setting *slaveBoolean = createSetting (Type_MultiBool, section, + "Proxy Checkboxes", + QStringList() << "One" << "Two" + << "Three" << "Four" << "Five" + ); + + Setting *slaveSingleText = createSetting (Type_SingleText, section, + "Proxy TextBox 1" + ); + + Setting *slaveMultiText = createSetting (Type_SingleText, section, + "ProxyTextBox 2" + ); + + // There are three types of values: + // + // Declared values - Pre-determined values, typically for + // combobox drop downs and boolean (radiobutton / checkbox) labels. + // These values represent the total possible list of values that may + // define a setting. No other values are allowed. + // + // Defined values - Values which represent the atual, current value of + // a setting. For settings with declared values, this must be one or + // several declared values, as appropriate. + // + // Proxy values - values the proxy master updates the proxy slave when + // it's own definition is set / changed. These are definitions for + // proxy slave settings, but must match any declared values the proxy + // slave has, if any. + + masterBoolean->addProxy (slaveBoolean, QList () + << (QStringList() << "One" << "Three") + << (QStringList() << "One" << "Three") + << (QStringList() << "One" << "Three" << "Five") + << (QStringList() << "Two" << "Four") + ); + + masterBoolean->addProxy (slaveSingleText, QList () + << (QStringList() << "Text A") + << (QStringList() << "Text B") + << (QStringList() << "Text A") + << (QStringList() << "Text C") + ); + + masterBoolean->addProxy (slaveMultiText, QList () + << (QStringList() << "One" << "Three") + << (QStringList() << "One" << "Three") + << (QStringList() << "One" << "Three" << "Five") + << (QStringList() << "Two" << "Four") + ); + + //settings with proxies are not serialized by default + //other settings non-serialized for demo purposes + slaveBoolean->setSerializable (false); + slaveSingleText->setSerializable (false); + slaveMultiText->setSerializable (false); + + slaveBoolean->setDefaultValues (QStringList() + << "One" << "Three" << "Five"); + + slaveSingleText->setDefaultValue ("Text A"); + + slaveMultiText->setDefaultValues (QStringList() + << "One" << "Three" << "Five"); + + slaveSingleText->setWidgetWidth (24); + slaveMultiText->setWidgetWidth (24); + } } CSMSettings::UserSettings::~UserSettings() @@ -76,230 +194,83 @@ CSMSettings::UserSettings::~UserSettings() mUserSettingsInstance = 0; } -QTextStream *CSMSettings::UserSettings::openFileStream (const QString &filePath, bool isReadOnly) const -{ - QIODevice::OpenMode openFlags = QIODevice::Text; - - if (isReadOnly) - openFlags = QIODevice::ReadOnly | openFlags; - else - openFlags = QIODevice::ReadWrite | QIODevice::Truncate | openFlags; - - QFile *file = new QFile(filePath); - QTextStream *stream = 0; - - if (file->open(openFlags)) - { - stream = new QTextStream(file); - stream->setCodec(QTextCodec::codecForName("UTF-8")); - } - - return stream; - -} - -bool CSMSettings::UserSettings::writeSettings(QMap &settings) -{ - QTextStream *stream = openFileStream(mUserFilePath); - - bool success = (stream); - - if (success) - { - QList keyList = settings.keys(); - - foreach (QString key, keyList) - { - SettingList *sectionSettings = settings[key]; - - *stream << "[" << key << "]" << '\n'; - - foreach (SettingContainer *item, *sectionSettings) - *stream << item->objectName() << " = " << item->getValue() << '\n'; - } - - stream->device()->close(); - delete stream; - stream = 0; - } - else - { - displayFileErrorMessage(mReadWriteMessage, false); - } - - return (success); -} - - -const CSMSettings::SectionMap &CSMSettings::UserSettings::getSectionMap() const -{ - return mSectionSettings; -} - -const CSMSettings::SettingMap *CSMSettings::UserSettings::getSettings(const QString §ionName) const -{ - return getValidSettings(sectionName); -} - -bool CSMSettings::UserSettings::loadFromFile(const QString &filePath) -{ - if (filePath.isEmpty()) - return false; - - SectionMap loadedSettings; - - QTextStream *stream = openFileStream (filePath, true); - - bool success = (stream); - - if (success) - { - //looks for a square bracket, "'\\[" - //that has one or more "not nothing" in it, "([^]]+)" - //and is closed with a square bracket, "\\]" - - QRegExp sectionRe("^\\[([^]]+)\\]"); - - //Find any character(s) that is/are not equal sign(s), "[^=]+" - //followed by an optional whitespace, an equal sign, and another optional whitespace, "\\s*=\\s*" - //and one or more periods, "(.+)" - - QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); - - CSMSettings::SettingMap *settings = 0; - QString section = "none"; - - while (!stream->atEnd()) - { - QString line = stream->readLine().simplified(); - - if (line.isEmpty() || line.startsWith("#")) - continue; - - //if a section is found, push it onto a new QStringList - //and push the QStringList onto - if (sectionRe.exactMatch(line)) - { - //add the previous section's settings to the member map - if (settings) - loadedSettings.insert(section, settings); - - //save new section and create a new list - section = sectionRe.cap(1); - settings = new SettingMap; - continue; - } - - if (keyRe.indexIn(line) != -1) - { - SettingContainer *sc = new SettingContainer (keyRe.cap(2).simplified()); - sc->setObjectName(keyRe.cap(1).simplified()); - (*settings)[keyRe.cap(1).simplified()] = sc; - } - - } - - loadedSettings.insert(section, settings); - - stream->device()->close(); - delete stream; - stream = 0; - } - - mergeMap (loadedSettings); - - return success; -} - -void CSMSettings::UserSettings::mergeMap (const CSMSettings::SectionMap §ionSettings) -{ - foreach (QString key, sectionSettings.uniqueKeys()) - { - // insert entire section if it does not already exist in the loaded files - if (mSectionSettings.find(key) == mSectionSettings.end()) - mSectionSettings.insert(key, sectionSettings.value(key)); - else - { - SettingMap *passedSettings = sectionSettings.value(key); - SettingMap *settings = mSectionSettings.value(key); - - foreach (QString key2, passedSettings->uniqueKeys()) - { - //insert section settings individially if they do not already exist - if (settings->find(key2) == settings->end()) - settings->insert(key2, passedSettings->value(key2)); - else - { - settings->value(key2)->update(passedSettings->value(key2)->getValue()); - } - } - } - } -} - void CSMSettings::UserSettings::loadSettings (const QString &fileName) { - mSectionSettings.clear(); + mUserFilePath = QString::fromUtf8 + (mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8(); - //global - QString globalFilePath = QString::fromStdString(mCfgMgr.getGlobalPath().string()) + fileName; - bool globalOk = loadFromFile(globalFilePath); + QString global = QString::fromUtf8 + (mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8(); + QString local = QString::fromUtf8 + (mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8(); - //local - QString localFilePath = QString::fromStdString(mCfgMgr.getLocalPath().string()) + fileName; - bool localOk = loadFromFile(localFilePath); + //open user and global streams + QTextStream *userStream = openFilestream (mUserFilePath, true); + QTextStream *otherStream = openFilestream (global, true); - //user - mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName; - loadFromFile(mUserFilePath); + //failed stream, try for local + if (!otherStream) + otherStream = openFilestream (local, true); - if (!(localOk || globalOk)) + //error condition - notify and return + if (!otherStream || !userStream) { - QString message = QObject::tr("
Could not open user settings files for reading

\ - Global and local settings files could not be read.\ - You may have incorrect file permissions or the OpenCS installation may be corrupted.
"); + QString message = QObject::tr("
An error was encountered loading \ + user settings files.

One or several files could not \ + be read. This may be caused by a missing configuration file, \ + incorrect file permissions or a corrupted installation of \ + OpenCS.
"); - message += QObject::tr("
Global filepath: ") + globalFilePath; - message += QObject::tr("
Local filepath: ") + localFilePath; + message += QObject::tr("
Global filepath: ") + global; + message += QObject::tr("
Local filepath: ") + local; + message += QObject::tr("
User filepath: ") + mUserFilePath; displayFileErrorMessage ( message, true); - } -} - -void CSMSettings::UserSettings::updateSettings (const QString §ionName, const QString &settingName) -{ - - SettingMap *settings = getValidSettings(sectionName); - - if (!settings) return; + } - if (settingName.isEmpty()) - { - foreach (const SettingContainer *setting, *settings) - emit signalUpdateEditorSetting (setting->objectName(), setting->getValue()); - } - else - { - if (settings->find(settingName) != settings->end()) - { - const SettingContainer *setting = settings->value(settingName); - emit signalUpdateEditorSetting (setting->objectName(), setting->getValue()); - } - } + //success condition - merge the two streams into a single map and save + DefinitionPageMap totalMap = readFilestream (userStream); + DefinitionPageMap otherMap = readFilestream(otherStream); + + //merging other settings file in and ignore duplicate settings to + //avoid overwriting user-level settings + mergeSettings (totalMap, otherMap); + + if (!totalMap.isEmpty()) + addDefinitions (totalMap); } -QString CSMSettings::UserSettings::getSetting (const QString §ion, const QString &setting) const +void CSMSettings::UserSettings::saveSettings + (const QMap &settingMap) { - SettingMap *settings = getValidSettings(section); + for (int i = 0; i < settings().size(); i++) + { + Setting* setting = settings().at(i); - QString retVal = ""; + QString key = setting->page() + '.' + setting->name(); - if (settings->find(setting) != settings->end()) - retVal = settings->value(setting)->getValue(); + if (!settingMap.keys().contains(key)) + continue; - return retVal; + setting->setDefinedValues (settingMap.value(key)); + } + + writeFilestream (openFilestream (mUserFilePath, false), settingMap); +} + +QString CSMSettings::UserSettings::settingValue (const QString §ion, + const QString &name) +{ + Setting *setting = findSetting(section, name); + + if (setting) + { + if (!setting->definedValues().isEmpty()) + return setting->definedValues().at(0); + } + return ""; } CSMSettings::UserSettings& CSMSettings::UserSettings::instance() @@ -307,49 +278,3 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance() assert(mUserSettingsInstance); return *mUserSettingsInstance; } - -void CSMSettings::UserSettings::displayFileErrorMessage(const QString &message, bool isReadOnly) -{ - // File cannot be opened or created - QMessageBox msgBox; - msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - - if (!isReadOnly) - msgBox.setText (mReadWriteMessage + message); - else - msgBox.setText (message); - - msgBox.exec(); -} - -CSMSettings::SettingMap * -CSMSettings::UserSettings::getValidSettings (const QString §ionName) const -{ - SettingMap *settings = 0; - - //copy the default values for the entire section if it's not found - if (mSectionSettings.find(sectionName) == mSectionSettings.end()) - { - if (mEditorSettingDefaults.find(sectionName) != mEditorSettingDefaults.end()) - settings = mEditorSettingDefaults.value (sectionName); - } - //otherwise, iterate the section's settings, looking for missing values and replacing them with defaults. - else - { - SettingMap *loadedSettings = mSectionSettings[sectionName]; - SettingMap *defaultSettings = mEditorSettingDefaults[sectionName]; - - foreach (QString key, defaultSettings->uniqueKeys()) - { - //write the default value to the loaded settings - if (loadedSettings->find((key))==loadedSettings->end()) - loadedSettings->insert(key, defaultSettings->value(key)); - } - - settings = mSectionSettings.value (sectionName); - } - - return settings; -} diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 63e78bd612..75a3a0797a 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -8,7 +8,7 @@ #include -#include "support.hpp" +#include "settingmanager.hpp" #ifndef Q_MOC_RUN #include @@ -21,17 +21,15 @@ class QFile; namespace CSMSettings { - struct UserSettings: public QObject + class UserSettings: public SettingManager { Q_OBJECT - SectionMap mSectionSettings; - SectionMap mEditorSettingDefaults; - static UserSettings *mUserSettingsInstance; QString mUserFilePath; Files::ConfigurationManager mCfgMgr; + QString mReadOnlyMessage; QString mReadWriteMessage; @@ -47,48 +45,23 @@ namespace CSMSettings { void operator= (UserSettings const &); //not implemented /// Writes settings to the last loaded settings file - bool writeSettings(QMap §ions); - - /// Called from editor to trigger signal to update the specified setting. - /// If no setting name is specified, all settings found in the specified section are updated. - void updateSettings (const QString §ionName, const QString &settingName = ""); + bool writeSettings(); /// Retrieves the settings file at all three levels (global, local and user). - - /// \todo Multi-valued settings are not fully implemented. Setting values - /// \todo loaded in later files will always overwrite previously loaded values. void loadSettings (const QString &fileName); - /// Returns the entire map of settings across all sections - const SectionMap &getSectionMap () const; + /// Writes settings to the user's config file path + void saveSettings (const QMap &settingMap); - const SettingMap *getSettings (const QString §ionName) const; - - /// Retrieves the value as a QString of the specified setting in the specified section - QString getSetting(const QString §ion, const QString &setting) const; + QString settingValue (const QString §ion, const QString &name); private: - - /// Opens a QTextStream from the provided path as read-only or read-write. - QTextStream *openFileStream (const QString &filePath, bool isReadOnly = false) const; - - /// Parses a setting file specified in filePath from the provided text stream. - bool loadFromFile (const QString &filePath = ""); - - /// merge the passed map into mSectionSettings - void mergeMap (const SectionMap &); - - void displayFileErrorMessage(const QString &message, bool isReadOnly); - - void buildEditorSettingDefaults(); - - SettingMap *getValidSettings (const QString §ionName) const; + void buildSettingModelDefaults(); signals: - void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue); - + void userSettingUpdated(const QString &, const QStringList &); }; } #endif // USERSETTINGS_HPP diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 7fd0057173..a80d21cb2d 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -12,16 +12,15 @@ CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const return mUniversalId; } -void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QString &settingValue) -{ -} - void CSVDoc::SubView::setStatusBar (bool show) {} void CSVDoc::SubView::useHint (const std::string& hint) {} +void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &) +{} + void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) { mUniversalId = id; setWindowTitle (mUniversalId.toString().c_str()); -} \ No newline at end of file +} diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 85274a18db..52e42cc0ef 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -37,7 +37,9 @@ namespace CSVDoc CSMWorld::UniversalId getUniversalId() const; virtual void setEditLock (bool locked) = 0; - virtual void updateEditorSetting (const QString &, const QString &); + + virtual void updateUserSetting + (const QString &, const QStringList &); virtual void setStatusBar (bool show); ///< Default implementation: ignored diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index bc34c6118e..47e1a80de3 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -12,7 +12,7 @@ #include "../../model/doc/document.hpp" #include "../world/subviews.hpp" #include "../tools/subviews.hpp" -#include "../settings/usersettingsdialog.hpp" +#include "../../model/settings/usersettings.hpp" #include "viewmanager.hpp" #include "operations.hpp" #include "subview.hpp" @@ -235,8 +235,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { - QString width = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Width")); - QString height = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Height")); + QString width = CSMSettings::UserSettings::instance().settingValue + (QString("Window Size"), QString("Width")); + + QString height = CSMSettings::UserSettings::instance().settingValue + (QString("Window Size"), QString("Height")); resize (width.toInt(), height.toInt()); @@ -336,7 +339,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this, SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&))); - CSMSettings::UserSettings::instance().updateSettings("Display Format"); + connect (&CSMSettings::UserSettings::instance(), + SIGNAL (userSettingUpdated (const QString &, const QStringList &)), + view, + SLOT (updateUserSetting (const QString &, const QStringList &))); view->show(); } @@ -484,24 +490,19 @@ void CSVDoc::View::resizeViewHeight (int height) resize (geometry().width(), height); } -void CSVDoc::View::updateEditorSetting (const QString &settingName, const QString &settingValue) +void CSVDoc::View::updateUserSetting + (const QString &name, const QStringList &list) { - if ( (settingName == "Record Status Display") || (settingName == "Referenceable ID Type Display") ) - { - foreach (QObject *view, mSubViewWindow.children()) - { - // not all mSubviewWindow children are CSVDoc::Subview objects - CSVDoc::SubView *subview = dynamic_cast(view); + if (list.isEmpty()) + return; - if (subview) - subview->updateEditorSetting (settingName, settingValue); - } - } - else if (settingName == "Width") - resizeViewWidth (settingValue.toInt()); + int value = list.at(0).toInt(); - else if (settingName == "Height") - resizeViewHeight (settingValue.toInt()); + if (name == "Width") + resizeViewWidth (value); + + else if (name == "Height") + resizeViewHeight (value); } void CSVDoc::View::toggleShowStatusBar (bool show) diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index ee7380e2b1..5e6c9abc4d 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -126,6 +126,8 @@ namespace CSVDoc void abortOperation (int type); + void updateUserSetting (const QString &, const QStringList &); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 4a4dbc1244..2297af0ba0 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -15,7 +15,8 @@ #include "../world/vartypedelegate.hpp" #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" -#include "../settings/usersettingsdialog.hpp" + +#include "../../model/settings/usersettings.hpp" #include "view.hpp" @@ -83,9 +84,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) for (std::size_t i=0; iadd (sMapping[i].mDisplay, new CSVWorld::EnumDelegateFactory ( CSMWorld::Columns::getEnums (sMapping[i].mColumnId), sMapping[i].mAllowNone)); - - connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), - this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); } CSVDoc::ViewManager::~ViewManager() @@ -119,6 +117,11 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest())); connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest())); + connect (&CSMSettings::UserSettings::instance(), + SIGNAL (userSettingUpdated(const QString &, const QStringList &)), + view, + SLOT (updateUserSetting (const QString &, const QStringList &))); + updateIndices(); return view; @@ -313,9 +316,3 @@ void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view) if (notifySaveOnClose (view)) QApplication::instance()->exit(); } - -void CSVDoc::ViewManager::slotUpdateEditorSetting (const QString &settingName, const QString &settingValue) -{ - foreach (CSVDoc::View *view, mViews) - view->updateEditorSetting (settingName, settingValue); -} diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 01f4951864..00e33916d0 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -76,9 +76,6 @@ namespace CSVDoc void progress (int current, int max, int type, int threads, CSMDoc::Document *document); void onExitWarningHandler(int state, CSMDoc::Document* document); - - /// connected to update signal in UserSettings - void slotUpdateEditorSetting (const QString &, const QString &); }; } diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index d59f0c2349..e84f5cf4ba 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -33,12 +33,13 @@ void CSVTools::ReportSubView::setEditLock (bool locked) // ignored. We don't change document state anyway. } -void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QString& value) +void CSVTools::ReportSubView::updateUserSetting + (const QString &name, const QStringList &list) { - mIdTypeDelegate->updateEditorSetting (key, value); + mIdTypeDelegate->updateUserSetting (name, list); } void CSVTools::ReportSubView::show (const QModelIndex& index) { focusId (mModel->getUniversalId (index.row()), ""); -} \ No newline at end of file +} diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index 6503ebd278..9f6a4c1da3 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -39,7 +39,8 @@ namespace CSVTools virtual void setEditLock (bool locked); - virtual void updateEditorSetting (const QString&, const QString&); + virtual void updateUserSetting + (const QString &, const QStringList &); private slots: @@ -47,4 +48,4 @@ namespace CSVTools }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 712b8f5569..995de21fc1 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -449,15 +449,19 @@ void CSVWorld::Table::previewRecord() } } -void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue) +void CSVWorld::Table::updateUserSetting + (const QString &name, const QStringList &list) { int columns = mModel->columnCount(); for (int i=0; i (*delegate). - updateEditorSetting (settingName, settingValue)) - emit dataChanged (mModel->index (0, i), mModel->index (mModel->rowCount()-1, i)); + if (dynamic_cast + (*delegate).updateUserSetting (name, list)) + { + emit dataChanged (mModel->index (0, i), + mModel->index (mModel->rowCount()-1, i)); + } } void CSVWorld::Table::tableSizeUpdate() @@ -598,4 +602,4 @@ std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column } } return titles; -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 4231a4a432..dfc74b3eb8 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -78,7 +78,7 @@ namespace CSVWorld CSMWorld::UniversalId getUniversalId (int row) const; - void updateEditorSetting (const QString &settingName, const QString &settingValue); + void updateUserSetting (const QString &name, const QStringList &list); std::vector getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a5a7e8252e..c193ed32ba 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -82,9 +82,10 @@ void CSVWorld::TableSubView::editRequest (const CSMWorld::UniversalId& id, const focusId (id, hint); } -void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, const QString &settingValue) +void CSVWorld::TableSubView::updateUserSetting + (const QString &name, const QStringList &list) { - mTable->updateEditorSetting(settingName, settingValue); + mTable->updateUserSetting(name, list); } void CSVWorld::TableSubView::setStatusBar (bool show) @@ -134,4 +135,4 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event) return handled; } return false; -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index b344ba1ad2..9d86c32e40 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -43,7 +43,8 @@ namespace CSVWorld virtual void setEditLock (bool locked); - virtual void updateEditorSetting (const QString& key, const QString& value); + virtual void updateUserSetting + (const QString& name, const QStringList &list); virtual void setStatusBar (bool show); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index b2a32b551c..16310c8a97 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -196,8 +196,8 @@ bool CSVWorld::CommandDelegate::isEditLocked() const return mEditLock; } -bool CSVWorld::CommandDelegate::updateEditorSetting (const QString &settingName, - const QString &settingValue) +bool CSVWorld::CommandDelegate::updateUserSetting (const QString &name, + const QStringList &list) { return false; } @@ -263,4 +263,4 @@ void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event) const CSMWorld::TableMimeData* data(dynamic_cast(event->mimeData())); emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); //WIP -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 7664f3eae2..50e2cf858e 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -136,7 +136,9 @@ namespace CSVWorld bool isEditLocked() const; - virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue); + virtual bool updateUserSetting + (const QString &name, const QStringList &list); + ///< \return Does column require update? virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const; From e71a119c23ac5992ed016f0d3a2e4298494b309c Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 02:57:48 -0400 Subject: [PATCH 011/545] Made aifollowers run when long distances (800 or 10000, depending) from what they're following. --- apps/openmw/mwmechanics/aifollow.cpp | 60 ++++++++++++++++++---------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index c3b36516ce..161c9700f1 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -4,6 +4,7 @@ #include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" #include "../mwworld/cellstore.hpp" +#include "creaturestats.hpp" #include "movement.hpp" #include @@ -26,69 +27,77 @@ MWMechanics::AiFollow::AiFollow(const std::string &actorId) bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); - - if(target == MWWorld::Ptr()) return true; + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); //The target to follow - mTimer = mTimer + duration; - mStuckTimer = mStuckTimer + duration; - mTotalTime = mTotalTime + duration; + if(target == MWWorld::Ptr()) return true; //Target doesn't exist - ESM::Position pos = actor.getRefData().getPosition(); + mTimer = mTimer + duration; //Update timer + mStuckTimer = mStuckTimer + duration; //Update stuck timer + mTotalTime = mTotalTime + duration; //Update total time following - if(!mAlwaysFollow) + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + + if(!mAlwaysFollow) //Update if you only follow for a bit { - if(mTotalTime > mDuration && mDuration != 0) + if(mTotalTime > mDuration && mDuration != 0) //Check if we've run out of time return true; if((pos.pos[0]-mX)*(pos.pos[0]-mX) + (pos.pos[1]-mY)*(pos.pos[1]-mY) + - (pos.pos[2]-mZ)*(pos.pos[2]-mZ) < 100*100) + (pos.pos[2]-mZ)*(pos.pos[2]-mZ) < 100*100) //Close-ish to final position { - if(actor.getCell()->isExterior()) + if(actor.getCell()->isExterior()) //Outside? { - if(mCellId == "") + if(mCellId == "") //No cell to travel to return true; } else { - if(mCellId == actor.getCell()->getCell()->mName) + if(mCellId == actor.getCell()->getCell()->mName) //Cell to travel to return true; } } } + //Set the target desition from the actor ESM::Pathgrid::Point dest; dest.mX = target.getRefData().getPosition().pos[0]; dest.mY = target.getRefData().getPosition().pos[1]; dest.mZ = target.getRefData().getPosition().pos[2]; + //Current position, for pathfilding stuff ESM::Pathgrid::Point start; start.mX = pos.pos[0]; start.mY = pos.pos[1]; start.mZ = pos.pos[2]; + //Build the path to get to the destination if(mPathFinder.getPath().empty()) mPathFinder.buildPath(start, dest, actor.getCell(), true); - + //*********************** + // Checks if you can't get to the end position at all + //*********************** if(mTimer > 0.25) { - if(!mPathFinder.getPath().empty()) + if(!mPathFinder.getPath().empty()) //Path has points in it { - ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); + ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path - if((dest.mX - lastPos.mX)*(dest.mX - lastPos.mX) + if((dest.mX - lastPos.mX)*(dest.mX - lastPos.mX) +(dest.mY - lastPos.mY)*(dest.mY - lastPos.mY) +(dest.mZ - lastPos.mZ)*(dest.mZ - lastPos.mZ) - > 100*100) - mPathFinder.addPointToPath(dest); + > 100*100) //End of the path is far from the destination + mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go } mTimer = 0; } - if(mStuckTimer>0.5) + //************************ + // Checks if you aren't moving; you're stuck + //************************ + if(mStuckTimer>0.5) //Checks every half of a second { if((mStuckPos.pos[0] - pos.pos[0])*(mStuckPos.pos[0] - pos.pos[0]) +(mStuckPos.pos[1] - pos.pos[1])*(mStuckPos.pos[1] - pos.pos[1]) @@ -99,6 +108,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) mStuckPos = pos; } + //Checks if the path isn't over, turn tomards the direction that you're going if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) { zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); @@ -110,6 +120,16 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) else actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + //Check if you're far away + if((dest.mX - start.mX)*(dest.mX - start.mX) + +(dest.mY - start.mY)*(dest.mY - start.mY) + +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) > 1000*1000) + actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run + else if((dest.mX - start.mX)*(dest.mX - start.mX) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold + +(dest.mY - start.mY)*(dest.mY - start.mY) + +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < 800*800) + actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk + return false; } From cac8e52154a99b310368ceabe3b61dcf2f63d44c Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 05:12:07 -0400 Subject: [PATCH 012/545] Seperated locked and lock level, to allow for relocking doors to previous lock level. The data is stored in the esm as -lockLevel if unlocked; lockLevel if locked. While not tested, it should not present any problems. --- apps/openmw/mwclass/container.cpp | 23 +++++++++++++++-------- apps/openmw/mwclass/container.hpp | 5 ++++- apps/openmw/mwclass/door.cpp | 15 +++++++++++---- apps/openmw/mwclass/door.hpp | 6 +++++- apps/openmw/mwmechanics/security.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 5 +++-- apps/openmw/mwscript/miscextensions.cpp | 6 +++--- apps/openmw/mwworld/class.cpp | 7 ++++++- apps/openmw/mwworld/class.hpp | 2 ++ apps/openmw/mwworld/manualref.hpp | 1 + 10 files changed, 51 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 604b51990a..ee6dba9824 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -111,7 +111,7 @@ namespace MWClass MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player); - bool needKey = ptr.getCellRef().mLockLevel>0; + bool needKey = ptr.getCellRef().mLocked; bool hasKey = false; std::string keyName; @@ -132,7 +132,7 @@ namespace MWClass if (needKey && hasKey) { MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); - ptr.getCellRef().mLockLevel = 0; + unlock(ptr); // using a key disarms the trap ptr.getCellRef().mTrap = ""; } @@ -209,7 +209,7 @@ namespace MWClass info.caption = ref->mBase->mName; std::string text; - if (ref->mRef.mLockLevel > 0) + if (ref->mRef.mLocked) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; @@ -240,15 +240,22 @@ namespace MWClass void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - if (lockLevel<0) - lockLevel = 0; - - ptr.getCellRef().mLockLevel = lockLevel; + ptr.getCellRef().mLocked = true; + if(lockLevel>=0) //Lock level setting left as most of the code relies on this + ptr.getCellRef().mLockLevel = lockLevel; } void Container::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLockLevel = 0; + ptr.getCellRef().mLocked= false; + } + + void Container::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) { + if (lockLevel<0) + lockLevel = 0; + + ptr.getCellRef().mLockLevel = lockLevel; + if(doLock) lock(ptr); } MWWorld::Ptr diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index c97867d35a..6945ae4414 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -48,12 +48,15 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = -999) const; ///< Lock object virtual void unlock (const MWWorld::Ptr& ptr) const; ///< Unlock object + ///Changes the lock level of the object + virtual void changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool lock=true); + virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const; ///< Read additional state from \a state into \a ptr. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 3cd8237e70..2662e1c537 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -76,7 +76,7 @@ namespace MWClass MWWorld::ContainerStore &invStore = get(actor).getContainerStore(actor); - bool needKey = ptr.getCellRef().mLockLevel>0; + bool needKey = ptr.getCellRef().mLocked; bool hasKey = false; std::string keyName; @@ -98,7 +98,7 @@ namespace MWClass { if(actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}"); - ptr.getCellRef().mLockLevel = 0; + unlock(ptr); //Call the function here. because that makes sense. // using a key disarms the trap ptr.getCellRef().mTrap = ""; } @@ -158,15 +158,22 @@ namespace MWClass void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const { + ptr.getCellRef().mLocked = true; + if(lockLevel>=0) //Lock level setting left as most of the code relies on this + ptr.getCellRef().mLockLevel = lockLevel; + } + + void Door::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) const{ if (lockLevel<0) lockLevel = 0; ptr.getCellRef().mLockLevel = lockLevel; + if(doLock) lock(ptr); //A change in lock level almost always nesesitates a lock } void Door::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLockLevel = 0; + ptr.getCellRef().mLocked = false; } std::string Door::getScript (const MWWorld::Ptr& ptr) const @@ -208,7 +215,7 @@ namespace MWClass text += "\n" + getDestination(*ref); } - if (ref->mRef.mLockLevel > 0) + if (ref->mRef.mLocked == true) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 2ac342a61e..e053136d5d 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -36,18 +36,22 @@ namespace MWClass static std::string getDestination (const MWWorld::LiveCellRef& door); ///< @return destination cell name or token - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = -999) const; ///< Lock object virtual void unlock (const MWWorld::Ptr& ptr) const; ///< Unlock object + ///Change the lock level + virtual void changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool lock=true) const; + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; + private: }; } diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index edec45e15f..ba2a32727d 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -29,7 +29,7 @@ namespace MWMechanics void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick, std::string& resultMessage, std::string& resultSound) { - if (lock.getCellRef().mLockLevel <= 0) + if (!lock.getCellRef().mLocked) return; int lockStrength = lock.getCellRef().mLockLevel; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 6ea3f54729..d861e2032b 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -420,6 +420,7 @@ namespace MWMechanics { if (effectId == ESM::MagicEffect::Lock) { + target.getCellRef().mLocked = true; if (target.getCellRef().mLockLevel < magnitude) target.getCellRef().mLockLevel = magnitude; } @@ -427,12 +428,12 @@ namespace MWMechanics { if (target.getCellRef().mLockLevel <= magnitude) { - if (target.getCellRef().mLockLevel > 0) + if (target.getCellRef().mLocked) { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } - target.getCellRef().mLockLevel = 0; + target.getCellRef().mLocked=false; } else MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 968d3bbd74..f10d1df965 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -131,7 +131,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer lockLevel = 100; + Interpreter::Type_Integer lockLevel = ptr.getCellRef().mLockLevel; if (arg0==1) { @@ -283,7 +283,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { // We are ignoring the DontSaveObject statement for now. Probably not worth - /// bothering with. The incompatibility we are creating should be marginal at most. + // bothering with. The incompatibility we are creating should be marginal at most. } }; @@ -320,7 +320,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (ptr.getCellRef ().mLockLevel > 0); + runtime.push (ptr.getCellRef().mLocked); } }; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 99dbcc66c5..4b3d40ab78 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -137,6 +137,11 @@ namespace MWWorld throw std::runtime_error ("class does not support locking"); } + void Class::setLockLevel (const Ptr& ptr, int lockLevel) const + { + throw std::runtime_error ("class does not support setting lock level"); + } + void Class::unlock (const Ptr& ptr) const { throw std::runtime_error ("class does not support unlocking"); @@ -397,7 +402,7 @@ namespace MWWorld void Class::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const {} - int Class::getBaseGold(const MWWorld::Ptr& ptr) const + int Class::getBaseGold(const MWWorld::Ptr& ptr) const { throw std::runtime_error("class does not support base gold"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 27b8423484..dc06bf6c96 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -165,6 +165,8 @@ namespace MWWorld virtual void lock (const Ptr& ptr, int lockLevel) const; ///< Lock object (default implementation: throw an exception) + virtual void setLockLevel(const Ptr& ptr, int lockLevel) const; + virtual void unlock (const Ptr& ptr) const; ///< Unlock object (default implementation: throw an exception) diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 0e21c55acd..174e344232 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -76,6 +76,7 @@ namespace MWWorld cellRef.mEnchantmentCharge = -1; cellRef.mTeleport = false; cellRef.mLockLevel = 0; + cellRef.mLocked = false; cellRef.mReferenceBlocked = 0; mPtr.getRefData().setCount(count); } From 420163d35f6aac7a233bc57fb5bee334b4fd6fbd Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 05:19:34 -0400 Subject: [PATCH 013/545] Small changes to lock command (If no valid lockLevel exists, defaults to 100) --- apps/openmw/mwscript/miscextensions.cpp | 4 ++++ components/esm/cellref.cpp | 18 +++++++++++++++--- components/esm/cellref.hpp | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index f10d1df965..686fa94a74 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -132,6 +132,10 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer lockLevel = ptr.getCellRef().mLockLevel; + if(lockLevel<0) { //no lock level was ever set, set to 100 as default + ptr.getCellRef().mLockLevel = 100; + lockLevel = 100; + } if (arg0==1) { diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 00b15f4a30..c46d83c1bb 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -54,8 +54,15 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) else mTeleport = false; - mLockLevel = -1; + mLockLevel = -999; //Set to impossible value to indicate no lock + mLocked = false; esm.getHNOT (mLockLevel, "FLTV"); + if(mLockLevel < 0 && mLockLevel != -999) //Unlocked lock, save lock level properly + mLockLevel*=-1; + else if(mLockLevel != -999){ + mLocked = true; + } + mKey = esm.getHNOString ("KNAM"); mTrap = esm.getHNOString ("TNAM"); @@ -113,8 +120,12 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons esm.writeHNOCString("DNAM", mDestCell); } - if (mLockLevel != -1 && !inInventory) - esm.writeHNT("FLTV", mLockLevel); + if (mLockLevel != -999 && !inInventory) { + if(mLocked) + esm.writeHNT("FLTV", mLockLevel); + else //If it's not locked we simply flip the locklevel to indicate it's locked + esm.writeHNT("FLTV", -mLockLevel); + } if (!inInventory) esm.writeHNOCString ("KNAM", mKey); @@ -151,6 +162,7 @@ void ESM::CellRef::blank() mGoldValue = 0; mDestCell.clear(); mLockLevel = 0; + mLocked = false; mKey.clear(); mTrap.clear(); mReferenceBlocked = 0; diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 16f6603a28..75122eacb0 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -71,6 +71,7 @@ namespace ESM // Lock level for doors and containers int mLockLevel; + bool mLocked; //Door locked/unlocked std::string mKey, mTrap; // Key and trap ID names, if any // This corresponds to the "Reference Blocked" checkbox in the construction set, From 6022ffbd1ff25d56934760fd330e1c6de797bee8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 05:54:18 -0400 Subject: [PATCH 014/545] Evidence chest now locks when new evidence is added to it --- apps/openmw/mwworld/worldimp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e3c6325126..5b4c2570ae 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2724,6 +2724,7 @@ namespace MWWorld } } } + closestChest.getCellRef().mLocked = true; } void World::goToJail() @@ -2791,7 +2792,7 @@ namespace MWWorld message += "\n" + skillMsg; } - // TODO: Sleep the player + // TODO: Sleep the player std::vector buttons; buttons.push_back("#{sOk}"); From 61341d420678e6e5e9cae019d342d0dde2f531ad Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 10:00:18 -0400 Subject: [PATCH 015/545] Removed mLocked, kept it as "Negative lock level means unlocked" --- apps/openmw/mwclass/container.cpp | 8 ++++---- apps/openmw/mwclass/door.cpp | 10 +++++----- apps/openmw/mwmechanics/security.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- apps/openmw/mwscript/miscextensions.cpp | 5 ++--- apps/openmw/mwworld/manualref.hpp | 1 - apps/openmw/mwworld/worldimp.cpp | 2 +- components/esm/cellref.cpp | 10 ---------- components/esm/cellref.hpp | 1 - 9 files changed, 16 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index ee6dba9824..1847fbd44d 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -111,7 +111,7 @@ namespace MWClass MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player); - bool needKey = ptr.getCellRef().mLocked; + bool needKey = ptr.getCellRef().mLockLevel > 0; bool hasKey = false; std::string keyName; @@ -209,7 +209,7 @@ namespace MWClass info.caption = ref->mBase->mName; std::string text; - if (ref->mRef.mLocked) + if (ref->mRef.mLockLevel > 0) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; @@ -240,14 +240,14 @@ namespace MWClass void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - ptr.getCellRef().mLocked = true; + ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive if(lockLevel>=0) //Lock level setting left as most of the code relies on this ptr.getCellRef().mLockLevel = lockLevel; } void Container::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLocked= false; + ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel negative } void Container::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) { diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 2662e1c537..e9f3845720 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -76,7 +76,7 @@ namespace MWClass MWWorld::ContainerStore &invStore = get(actor).getContainerStore(actor); - bool needKey = ptr.getCellRef().mLocked; + bool needKey = ptr.getCellRef().mLockLevel > 0; bool hasKey = false; std::string keyName; @@ -158,9 +158,9 @@ namespace MWClass void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - ptr.getCellRef().mLocked = true; + ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive; if(lockLevel>=0) //Lock level setting left as most of the code relies on this - ptr.getCellRef().mLockLevel = lockLevel; + ptr.getCellRef().mLockLevel = abs(lockLevel); } void Door::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) const{ @@ -173,7 +173,7 @@ namespace MWClass void Door::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLocked = false; + ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive } std::string Door::getScript (const MWWorld::Ptr& ptr) const @@ -215,7 +215,7 @@ namespace MWClass text += "\n" + getDestination(*ref); } - if (ref->mRef.mLocked == true) + if (ref->mRef.mLockLevel > 0) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index ba2a32727d..3751e58285 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -29,7 +29,7 @@ namespace MWMechanics void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick, std::string& resultMessage, std::string& resultSound) { - if (!lock.getCellRef().mLocked) + if (!(lock.getCellRef().mLockLevel > 0)) //If it's unlocked back out immediately return; int lockStrength = lock.getCellRef().mLockLevel; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index d861e2032b..db8daff15d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -420,7 +420,7 @@ namespace MWMechanics { if (effectId == ESM::MagicEffect::Lock) { - target.getCellRef().mLocked = true; + target.getCellRef().mLockLevel = abs(target.getCellRef().mLockLevel); //Makes lockLevel positive if (target.getCellRef().mLockLevel < magnitude) target.getCellRef().mLockLevel = magnitude; } @@ -428,12 +428,12 @@ namespace MWMechanics { if (target.getCellRef().mLockLevel <= magnitude) { - if (target.getCellRef().mLocked) + if (target.getCellRef().mLockLevel > 0) { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } - target.getCellRef().mLocked=false; + target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); } else MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 686fa94a74..bc71cc4941 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -132,8 +132,7 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer lockLevel = ptr.getCellRef().mLockLevel; - if(lockLevel<0) { //no lock level was ever set, set to 100 as default - ptr.getCellRef().mLockLevel = 100; + if(lockLevel==-999) { //no lock level was ever set, set to 100 as default lockLevel = 100; } @@ -324,7 +323,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (ptr.getCellRef().mLocked); + runtime.push (ptr.getCellRef().mLockLevel > 0); } }; diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 174e344232..0e21c55acd 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -76,7 +76,6 @@ namespace MWWorld cellRef.mEnchantmentCharge = -1; cellRef.mTeleport = false; cellRef.mLockLevel = 0; - cellRef.mLocked = false; cellRef.mReferenceBlocked = 0; mPtr.getRefData().setCount(count); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5b4c2570ae..5c9b25d28e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2724,7 +2724,7 @@ namespace MWWorld } } } - closestChest.getCellRef().mLocked = true; + closestChest.getCellRef().mLockLevel = abs(closestChest.getCellRef().mLockLevel); } void World::goToJail() diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index c46d83c1bb..699d326ee6 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -55,13 +55,7 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) mTeleport = false; mLockLevel = -999; //Set to impossible value to indicate no lock - mLocked = false; esm.getHNOT (mLockLevel, "FLTV"); - if(mLockLevel < 0 && mLockLevel != -999) //Unlocked lock, save lock level properly - mLockLevel*=-1; - else if(mLockLevel != -999){ - mLocked = true; - } mKey = esm.getHNOString ("KNAM"); mTrap = esm.getHNOString ("TNAM"); @@ -121,10 +115,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons } if (mLockLevel != -999 && !inInventory) { - if(mLocked) esm.writeHNT("FLTV", mLockLevel); - else //If it's not locked we simply flip the locklevel to indicate it's locked - esm.writeHNT("FLTV", -mLockLevel); } if (!inInventory) @@ -162,7 +153,6 @@ void ESM::CellRef::blank() mGoldValue = 0; mDestCell.clear(); mLockLevel = 0; - mLocked = false; mKey.clear(); mTrap.clear(); mReferenceBlocked = 0; diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 75122eacb0..16f6603a28 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -71,7 +71,6 @@ namespace ESM // Lock level for doors and containers int mLockLevel; - bool mLocked; //Door locked/unlocked std::string mKey, mTrap; // Key and trap ID names, if any // This corresponds to the "Reference Blocked" checkbox in the construction set, From f6deca7c80c489488412cd85959c09e8ee68f5b9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 13:02:51 -0400 Subject: [PATCH 016/545] Fixed various issues caused by late-night coding. Also added "unlock" message to unlocked doors --- apps/openmw/mwclass/container.cpp | 16 ++++++---------- apps/openmw/mwclass/container.hpp | 5 +---- apps/openmw/mwclass/door.cpp | 19 +++++++------------ apps/openmw/mwclass/door.hpp | 5 +---- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- apps/openmw/mwscript/miscextensions.cpp | 2 +- apps/openmw/mwworld/class.cpp | 5 ----- apps/openmw/mwworld/class.hpp | 2 -- components/esm/cellref.cpp | 4 ++-- 9 files changed, 21 insertions(+), 43 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 1847fbd44d..be76bd0b41 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -211,6 +211,8 @@ namespace MWClass std::string text; if (ref->mRef.mLockLevel > 0) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); + else if (ref->mRef.mLockLevel < 0) + text += "\n#{sUnlocked}"; if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; @@ -240,9 +242,10 @@ namespace MWClass void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive - if(lockLevel>=0) //Lock level setting left as most of the code relies on this - ptr.getCellRef().mLockLevel = lockLevel; + if(lockLevel!=0) + ptr.getCellRef().mLockLevel = abs(lockLevel); //Changes lock to locklevel, in positive + else + ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //No locklevel given, just flip the oriional one } void Container::unlock (const MWWorld::Ptr& ptr) const @@ -250,13 +253,6 @@ namespace MWClass ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel negative } - void Container::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) { - if (lockLevel<0) - lockLevel = 0; - - ptr.getCellRef().mLockLevel = lockLevel; - if(doLock) lock(ptr); - } MWWorld::Ptr Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 6945ae4414..f012d675c8 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -48,15 +48,12 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = -999) const; + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = 0) const; ///< Lock object virtual void unlock (const MWWorld::Ptr& ptr) const; ///< Unlock object - ///Changes the lock level of the object - virtual void changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool lock=true); - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const; ///< Read additional state from \a state into \a ptr. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index e9f3845720..984e21e72b 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -158,22 +158,15 @@ namespace MWClass void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const { - ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive; - if(lockLevel>=0) //Lock level setting left as most of the code relies on this - ptr.getCellRef().mLockLevel = abs(lockLevel); - } - - void Door::changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool doLock) const{ - if (lockLevel<0) - lockLevel = 0; - - ptr.getCellRef().mLockLevel = lockLevel; - if(doLock) lock(ptr); //A change in lock level almost always nesesitates a lock + if(lockLevel!=0) + ptr.getCellRef().mLockLevel = abs(lockLevel); //Changes lock to locklevel, in positive + else + ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //No locklevel given, just flip the origional one } void Door::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel positive + ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel negative } std::string Door::getScript (const MWWorld::Ptr& ptr) const @@ -217,6 +210,8 @@ namespace MWClass if (ref->mRef.mLockLevel > 0) text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); + else if (ref->mRef.mLockLevel < 0) + text += "\n#{sUnlocked}"; if (ref->mRef.mTrap != "") text += "\n#{sTrapped}"; diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index e053136d5d..bddc46728d 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -36,15 +36,12 @@ namespace MWClass static std::string getDestination (const MWWorld::LiveCellRef& door); ///< @return destination cell name or token - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = -999) const; + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = 0) const; ///< Lock object virtual void unlock (const MWWorld::Ptr& ptr) const; ///< Unlock object - ///Change the lock level - virtual void changeLockLevel(const MWWorld::Ptr& ptr, int lockLevel, bool lock=true) const; - virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index db8daff15d..9a6cd6b896 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -420,20 +420,20 @@ namespace MWMechanics { if (effectId == ESM::MagicEffect::Lock) { - target.getCellRef().mLockLevel = abs(target.getCellRef().mLockLevel); //Makes lockLevel positive - if (target.getCellRef().mLockLevel < magnitude) + if (target.getCellRef().mLockLevel < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude target.getCellRef().mLockLevel = magnitude; } else if (effectId == ESM::MagicEffect::Open) { if (target.getCellRef().mLockLevel <= magnitude) { + //Door not already unlocked if (target.getCellRef().mLockLevel > 0) { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } - target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); + target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); //unlocks the door } else MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index bc71cc4941..20013493f2 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -132,7 +132,7 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer lockLevel = ptr.getCellRef().mLockLevel; - if(lockLevel==-999) { //no lock level was ever set, set to 100 as default + if(lockLevel==0) { //no lock level was ever set, set to 100 as default lockLevel = 100; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 4b3d40ab78..f20c5f6d27 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -137,11 +137,6 @@ namespace MWWorld throw std::runtime_error ("class does not support locking"); } - void Class::setLockLevel (const Ptr& ptr, int lockLevel) const - { - throw std::runtime_error ("class does not support setting lock level"); - } - void Class::unlock (const Ptr& ptr) const { throw std::runtime_error ("class does not support unlocking"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index dc06bf6c96..27b8423484 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -165,8 +165,6 @@ namespace MWWorld virtual void lock (const Ptr& ptr, int lockLevel) const; ///< Lock object (default implementation: throw an exception) - virtual void setLockLevel(const Ptr& ptr, int lockLevel) const; - virtual void unlock (const Ptr& ptr) const; ///< Unlock object (default implementation: throw an exception) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 699d326ee6..f04e819c88 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -54,7 +54,7 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) else mTeleport = false; - mLockLevel = -999; //Set to impossible value to indicate no lock + mLockLevel = 0; //Set to 0 to indicate no lock esm.getHNOT (mLockLevel, "FLTV"); mKey = esm.getHNOString ("KNAM"); @@ -114,7 +114,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons esm.writeHNOCString("DNAM", mDestCell); } - if (mLockLevel != -999 && !inInventory) { + if (mLockLevel != 0 && !inInventory) { esm.writeHNT("FLTV", mLockLevel); } From ee581f593b29f2656160b04cd1f5ea1a32b7f776 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 13:20:43 -0400 Subject: [PATCH 017/545] Fixed issue which may occur if there's no evidence chest nearby --- apps/openmw/mwworld/worldimp.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5c9b25d28e..87bdd2f9d2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2695,6 +2695,7 @@ namespace MWWorld MWWorld::Ptr closestChest; float closestDistance = FLT_MAX; + //Find closest stolen_goods chest std::vector chests; mCells.getInteriorPtrs("stolen_goods", chests); @@ -2712,19 +2713,19 @@ namespace MWWorld } } - if (!closestChest.isEmpty()) + if (!closestChest.isEmpty()) //Found a close chest { ContainerStore& store = ptr.getClass().getContainerStore(ptr); - for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) + for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest { - if (!it->getCellRef().mOwner.empty() && it->getCellRef().mOwner != "player") + if (!it->getCellRef().mOwner.empty() && it->getCellRef().mOwner != "player") //Not owned by no one/player? { closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest); store.remove(*it, it->getRefData().getCount(), ptr); } } + closestChest.getCellRef().mLockLevel = abs(closestChest.getCellRef().mLockLevel); } - closestChest.getCellRef().mLockLevel = abs(closestChest.getCellRef().mLockLevel); } void World::goToJail() From ce566693397b6fd23f71221abf07181325678e2e Mon Sep 17 00:00:00 2001 From: graffy76 Date: Wed, 23 Apr 2014 17:02:37 -0500 Subject: [PATCH 018/545] Fixed failed signal/slot connection between UserSettings and CSVWorld::SubView --- apps/opencs/view/doc/subview.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 52e42cc0ef..733a75bb0d 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -38,9 +38,6 @@ namespace CSVDoc virtual void setEditLock (bool locked) = 0; - virtual void updateUserSetting - (const QString &, const QStringList &); - virtual void setStatusBar (bool show); ///< Default implementation: ignored @@ -50,6 +47,10 @@ namespace CSVDoc signals: void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint); + + public slots: + virtual void updateUserSetting + (const QString &, const QStringList &); }; } From f90810223abeac58b05c807476a77d9cf338a7ab Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 21:02:09 -0400 Subject: [PATCH 019/545] Added quicksave and quickload --- apps/openmw/mwinput/inputmanagerimp.cpp | 43 +++++++++++++++++++++++++ apps/openmw/mwinput/inputmanagerimp.hpp | 2 ++ 2 files changed, 45 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1346b9e958..4bd2a1e653 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -26,6 +26,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwstate/character.hpp" using namespace ICS; @@ -252,6 +253,12 @@ namespace MWInput case A_ToggleHUD: MWBase::Environment::get().getWindowManager()->toggleHud(); break; + case A_QuickSave: + quickSave(); + break; + case A_QuickLoad: + quickLoad(); + break; } } } @@ -638,6 +645,36 @@ namespace MWInput } } + void InputManager::quickLoad() { + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character + if(mCurrentCharacter) { //Ensure a current character exists + const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save + if(slot) //Don't even try loading it if there's no prior save. + MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! + } + } + + void InputManager::quickSave() { + const MWState::Slot* slot = NULL; + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character + if (mCurrentCharacter) //Ensure one exists, otherwise do nothing + { + //Find quicksave slot + for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + { + if (it->mProfile.mDescription == "Quicksave") + slot = &*it; + } + //If no quicksave works create a new slot with Signature + if(slot == NULL) { + slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); + if(slot==NULL) + std::cout << "Couldn't work out" << std::endl; + } + //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? + MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); + } + } void InputManager::toggleSpell() { if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; @@ -842,6 +879,8 @@ namespace MWInput defaultKeyBindings[A_Screenshot] = SDL_GetKeyFromScancode(SDL_SCANCODE_F12); defaultKeyBindings[A_ToggleHUD] = SDL_GetKeyFromScancode(SDL_SCANCODE_F11); defaultKeyBindings[A_AlwaysRun] = SDL_GetKeyFromScancode(SDL_SCANCODE_Y); + defaultKeyBindings[A_QuickSave] = SDL_GetKeyFromScancode(SDL_SCANCODE_F5); + defaultKeyBindings[A_QuickLoad] = SDL_GetKeyFromScancode(SDL_SCANCODE_F9); std::map defaultMouseButtonBindings; defaultMouseButtonBindings[A_Inventory] = SDL_BUTTON_RIGHT; @@ -918,6 +957,8 @@ namespace MWInput descriptions[A_QuickKey9] = "sQuick9Cmd"; descriptions[A_QuickKey10] = "sQuick10Cmd"; descriptions[A_AlwaysRun] = "sAlways_Run"; + descriptions[A_QuickSave] = "sQuickSaveCmd"; + descriptions[A_QuickLoad] = "sQuickLoadCmd"; if (descriptions[action] == "") return ""; // not configurable @@ -961,6 +1002,8 @@ namespace MWInput ret.push_back(A_Journal); ret.push_back(A_Rest); ret.push_back(A_Console); + ret.push_back(A_QuickSave); + ret.push_back(A_QuickLoad); ret.push_back(A_Screenshot); ret.push_back(A_QuickKeysMenu); ret.push_back(A_QuickKey1); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 87fbda25cd..5eb355566b 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -183,6 +183,8 @@ namespace MWInput void toggleWalking(); void toggleAutoMove(); void rest(); + void quickLoad(); + void quickSave(); void quickKey (int index); void showQuickKeysMenu(); From e873135da7f1065c1168cff1ab6f18b8d5c04b8f Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 21:04:52 -0400 Subject: [PATCH 020/545] Missed a debug message --- apps/openmw/mwinput/inputmanagerimp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 4bd2a1e653..7fc8671864 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -668,8 +668,6 @@ namespace MWInput //If no quicksave works create a new slot with Signature if(slot == NULL) { slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); - if(slot==NULL) - std::cout << "Couldn't work out" << std::endl; } //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); From 49620968b93caf88d4b49f94d0da7649aaf90a24 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 21:21:11 -0400 Subject: [PATCH 021/545] Disallowed quicksave/load in character creation --- apps/openmw/mwinput/inputmanagerimp.cpp | 42 ++++++++++++++----------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 7fc8671864..3d5d2f4a85 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -646,31 +646,35 @@ namespace MWInput } void InputManager::quickLoad() { - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character - if(mCurrentCharacter) { //Ensure a current character exists - const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save - if(slot) //Don't even try loading it if there's no prior save. - MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! + if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character + if(mCurrentCharacter) { //Ensure a current character exists + const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save + if(slot) //Don't even try loading it if there's no prior save. + MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! + } } } void InputManager::quickSave() { - const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character - if (mCurrentCharacter) //Ensure one exists, otherwise do nothing - { - //Find quicksave slot - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation + const MWState::Slot* slot = NULL; + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character + if (mCurrentCharacter) //Ensure one exists { - if (it->mProfile.mDescription == "Quicksave") - slot = &*it; + //Find quicksave slot + for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + { + if (it->mProfile.mDescription == "Quicksave") + slot = &*it; + } + //If no quicksave works create a new slot with Signature + if(slot == NULL) { + slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); + } + //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? + MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); } - //If no quicksave works create a new slot with Signature - if(slot == NULL) { - slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); - } - //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? - MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); } } void InputManager::toggleSpell() From 682c39548869593b02873a11f819a019056145fc Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 21:39:25 -0400 Subject: [PATCH 022/545] Apparently a normal save must exist for some reason, calling for a character to be made doesn't cause the signature to be created, and I don't know how to force create the signature (It's kinda driving me nuts) --- apps/openmw/mwinput/inputmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 3d5d2f4a85..db030c940c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -659,7 +659,7 @@ namespace MWInput void InputManager::quickSave() { if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character if (mCurrentCharacter) //Ensure one exists { //Find quicksave slot From a598060071bd6c3224f5f8c959ed1ab38fd16beb Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 23:12:30 -0400 Subject: [PATCH 023/545] Added autosave on rest, as well as an option in the settings menu --- apps/openmw/mwgui/waitdialog.cpp | 21 +++++++++++++++++++++ apps/openmw/mwgui/waitdialog.hpp | 1 + apps/openmw/mwinput/inputmanagerimp.cpp | 6 +----- files/mygui/openmw_settings_window.layout | 18 +++++++++++++++--- files/settings-default.cfg | 2 ++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 9417d2a4b6..7e4522de60 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -8,6 +8,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/statemanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/cellstore.hpp" @@ -15,6 +16,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwstate/charactermanager.hpp" namespace MWGui { @@ -236,6 +238,25 @@ namespace MWGui { MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup); } + if(Settings::Manager::getBool("autosave","Saves")) + autosave(); + } + + void WaitDialog::autosave() { + if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation + const MWState::Slot* slot = NULL; + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character + if (mCurrentCharacter) //Ensure one exists + { + //Find quicksave slot + for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + { + if (it->mProfile.mDescription == "Autosave") + slot = &*it; + } + MWBase::Environment::get().getStateManager()->saveGame("Autosave", slot); + } + } } void WaitDialog::wakeUp () diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index d96649af6f..5a66c3370e 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -34,6 +34,7 @@ namespace MWGui bool getSleeping() { return mWaiting && mSleeping; } void wakeUp(); + void autosave(); protected: MyGUI::TextBox* mDateTimeText; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index db030c940c..c3f5ff7aa6 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -659,7 +659,7 @@ namespace MWInput void InputManager::quickSave() { if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character if (mCurrentCharacter) //Ensure one exists { //Find quicksave slot @@ -668,10 +668,6 @@ namespace MWInput if (it->mProfile.mDescription == "Quicksave") slot = &*it; } - //If no quicksave works create a new slot with Signature - if(slot == NULL) { - slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); - } //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); } diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index adf9f1557f..e348323be5 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -3,10 +3,10 @@ - - + + - + @@ -95,6 +95,18 @@ + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 6361476e34..f24636d151 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -174,6 +174,8 @@ best attack = false [Saves] character = +# Save when resting +autosave = true [Windows] inventory x = 0 From 6a8bf71c4c173f4c05489eb028b4c679859de476 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 23 Apr 2014 23:33:57 -0400 Subject: [PATCH 024/545] Moved autosave to before you rest, not after it. --- apps/openmw/mwgui/waitdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 7e4522de60..b4dae090f2 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -121,6 +121,8 @@ namespace MWGui MWBase::World* world = MWBase::Environment::get().getWorld(); world->getFader ()->fadeOut(0.2); setVisible(false); + if(Settings::Manager::getBool("autosave","Saves")) //autosaves + autosave(); mProgressBar.setVisible (true); mWaiting = true; @@ -238,8 +240,6 @@ namespace MWGui { MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup); } - if(Settings::Manager::getBool("autosave","Saves")) - autosave(); } void WaitDialog::autosave() { From 05b21c92afde503ec2c524e66c1233f5772d1b21 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 24 Apr 2014 03:06:36 -0400 Subject: [PATCH 025/545] Moved quick save into statemanager class. Kept loader as is as it's rather specalized. --- apps/openmw/mwbase/statemanager.hpp | 4 ++++ apps/openmw/mwgui/waitdialog.cpp | 18 +----------------- apps/openmw/mwinput/inputmanagerimp.cpp | 16 +--------------- apps/openmw/mwstate/statemanagerimp.cpp | 21 +++++++++++++++++++-- apps/openmw/mwstate/statemanagerimp.hpp | 4 ++++ 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwbase/statemanager.hpp b/apps/openmw/mwbase/statemanager.hpp index cd907408a5..b9cf6aa7f0 100644 --- a/apps/openmw/mwbase/statemanager.hpp +++ b/apps/openmw/mwbase/statemanager.hpp @@ -65,6 +65,10 @@ namespace MWBase /// /// \note \a slot must belong to \a character. + ///Simple saver, writes over the file if already existing + /** Used for quick save and autosave **/ + virtual void quickSave(std::string = "Quicksave")=0; + virtual MWState::Character *getCurrentCharacter (bool create = true) = 0; ///< \param create Create a new character, if there is no current character. diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index b4dae090f2..023e01b064 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -122,7 +122,7 @@ namespace MWGui world->getFader ()->fadeOut(0.2); setVisible(false); if(Settings::Manager::getBool("autosave","Saves")) //autosaves - autosave(); + MWBase::Environment::get().getStateManager()->quickSave("Autosave"); mProgressBar.setVisible (true); mWaiting = true; @@ -242,22 +242,6 @@ namespace MWGui } } - void WaitDialog::autosave() { - if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation - const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character - if (mCurrentCharacter) //Ensure one exists - { - //Find quicksave slot - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) - { - if (it->mProfile.mDescription == "Autosave") - slot = &*it; - } - MWBase::Environment::get().getStateManager()->saveGame("Autosave", slot); - } - } - } void WaitDialog::wakeUp () { diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index c3f5ff7aa6..bc1aaf8f61 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -657,21 +657,7 @@ namespace MWInput } void InputManager::quickSave() { - if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation - const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character - if (mCurrentCharacter) //Ensure one exists - { - //Find quicksave slot - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) - { - if (it->mProfile.mDescription == "Quicksave") - slot = &*it; - } - //MWBase::Environment::get().getWindowManager()->messageBox("#{sQuick_save}"); //No message on quicksave? - MWBase::Environment::get().getStateManager()->saveGame("Quicksave", slot); - } - } + MWBase::Environment::get().getStateManager()->quickSave(); } void InputManager::toggleSpell() { diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 6b0871012c..19b6ca1f33 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -223,6 +223,23 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot slot->mPath.parent_path().filename().string()); } +void MWState::StateManager::quickSave(std::string name) { + if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation + const MWState::Slot* slot = NULL; + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character + if (mCurrentCharacter) //Ensure one exists + { + //Find quicksave slot + for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + { + if (it->mProfile.mDescription == name) + slot = &*it; + } + MWBase::Environment::get().getStateManager()->saveGame(name, slot); + } + } +} + void MWState::StateManager::loadGame (const Character *character, const Slot *slot) { try @@ -309,11 +326,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl MWBase::Environment::get().getMechanicsManager()->playerLoaded(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - + //Update the weapon icon in the hud with whatever the player is currently holding. MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr); MWWorld::ContainerStoreIterator item = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - + if (item != invStore.end()) MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*item); diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index 46ade236b6..8082a2c785 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -49,6 +49,10 @@ namespace MWState /// /// \note Slot must belong to the current character. + ///Saves a file, using supplied filename, overwritting if needed + /** This is mostly used for quicksaving and autosaving, for they use the same name over and over again **/ + virtual void quickSave(std::string name = "Quicksave"); + virtual void loadGame (const Character *character, const Slot *slot); ///< Load a saved game file from \a slot. /// From 5b681e2199689120274e52e86585d803320552c4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 24 Apr 2014 03:14:47 -0400 Subject: [PATCH 026/545] Moved quickload to statemanager for consistency's sake, as well as make autosave only occur on sleep, not wait. --- apps/openmw/mwbase/statemanager.hpp | 4 ++++ apps/openmw/mwgui/waitdialog.cpp | 2 +- apps/openmw/mwinput/inputmanagerimp.cpp | 9 +-------- apps/openmw/mwstate/statemanagerimp.cpp | 11 +++++++++++ apps/openmw/mwstate/statemanagerimp.hpp | 7 ++++++- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwbase/statemanager.hpp b/apps/openmw/mwbase/statemanager.hpp index b9cf6aa7f0..fc4a2d806e 100644 --- a/apps/openmw/mwbase/statemanager.hpp +++ b/apps/openmw/mwbase/statemanager.hpp @@ -69,6 +69,10 @@ namespace MWBase /** Used for quick save and autosave **/ virtual void quickSave(std::string = "Quicksave")=0; + ///Simple loader, loads the last saved file + /** Used for quickload **/ + virtual void quickLoad()=0; + virtual MWState::Character *getCurrentCharacter (bool create = true) = 0; ///< \param create Create a new character, if there is no current character. diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 023e01b064..ed1b9e0a90 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -121,7 +121,7 @@ namespace MWGui MWBase::World* world = MWBase::Environment::get().getWorld(); world->getFader ()->fadeOut(0.2); setVisible(false); - if(Settings::Manager::getBool("autosave","Saves")) //autosaves + if(Settings::Manager::getBool("autosave","Saves") && mSleeping) //autosaves when enabled and sleeping (Not resting, apparently) MWBase::Environment::get().getStateManager()->quickSave("Autosave"); mProgressBar.setVisible (true); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index bc1aaf8f61..51c0a1621e 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -646,14 +646,7 @@ namespace MWInput } void InputManager::quickLoad() { - if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character - if(mCurrentCharacter) { //Ensure a current character exists - const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save - if(slot) //Don't even try loading it if there's no prior save. - MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! - } - } + MWBase::Environment::get().getStateManager()->quickLoad(); } void InputManager::quickSave() { diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 19b6ca1f33..a0971b9427 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -345,6 +345,17 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl } } +void MWState::StateManager::quickLoad() { + if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { + MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character + if(mCurrentCharacter) { //Ensure a current character exists + const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save + if(slot) //Don't even try loading it if there's no prior save. + MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! + } + } +} + MWState::Character *MWState::StateManager::getCurrentCharacter (bool create) { return mCharacterManager.getCurrentCharacter (create); diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index 8082a2c785..2d3ca21fbc 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -50,9 +50,14 @@ namespace MWState /// \note Slot must belong to the current character. ///Saves a file, using supplied filename, overwritting if needed - /** This is mostly used for quicksaving and autosaving, for they use the same name over and over again **/ + /** This is mostly used for quicksaving and autosaving, for they use the same name over and over again + \param name Name of save, defaults to "Quicksave"**/ virtual void quickSave(std::string name = "Quicksave"); + ///Loads the last saved file + /** Used for quickload **/ + virtual void quickLoad(); + virtual void loadGame (const Character *character, const Slot *slot); ///< Load a saved game file from \a slot. /// From 42b3233bdad827479a75a070b9edfa18a888d643 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Apr 2014 09:54:47 +0200 Subject: [PATCH 027/545] removed a redundant check --- apps/openmw/mwstate/statemanagerimp.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index a0971b9427..56f562e04e 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -227,16 +227,14 @@ void MWState::StateManager::quickSave(std::string name) { if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation const MWState::Slot* slot = NULL; MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character - if (mCurrentCharacter) //Ensure one exists + + //Find quicksave slot + for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) { - //Find quicksave slot - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) - { - if (it->mProfile.mDescription == name) - slot = &*it; - } - MWBase::Environment::get().getStateManager()->saveGame(name, slot); + if (it->mProfile.mDescription == name) + slot = &*it; } + MWBase::Environment::get().getStateManager()->saveGame(name, slot); } } From 760c8c721426f4a02711faad9ef94211f6254581 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Apr 2014 09:56:51 +0200 Subject: [PATCH 028/545] removed a redundant include --- apps/openmw/mwinput/inputmanagerimp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 51c0a1621e..b378139153 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -26,7 +26,6 @@ #include "../mwworld/esmstore.hpp" #include "../mwmechanics/creaturestats.hpp" -#include "../mwstate/character.hpp" using namespace ICS; From 9db9ad410d52387a5cd4c96660fda44206eef5e3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Apr 2014 10:14:17 +0200 Subject: [PATCH 029/545] fixed checks for allowing load/save and some general cleanup --- apps/openmw/mwstate/statemanagerimp.cpp | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 56f562e04e..e32aad5053 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -223,19 +223,23 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot slot->mPath.parent_path().filename().string()); } -void MWState::StateManager::quickSave(std::string name) { - if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { //ensure you're not in character creation - const MWState::Slot* slot = NULL; - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(true); //Get current character +void MWState::StateManager::quickSave (std::string name) +{ + if (mState!=State_Running || + MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")!=-1) // char gen + return; - //Find quicksave slot - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) - { - if (it->mProfile.mDescription == name) - slot = &*it; - } - MWBase::Environment::get().getStateManager()->saveGame(name, slot); + const Slot* slot = NULL; + Character* mCurrentCharacter = getCurrentCharacter(true); //Get current character + + //Find quicksave slot + for (Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it) + { + if (it->mProfile.mDescription == name) + slot = &*it; } + + saveGame(name, slot); } void MWState::StateManager::loadGame (const Character *character, const Slot *slot) @@ -343,15 +347,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl } } -void MWState::StateManager::quickLoad() { - if(MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) { - MWState::Character* mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter(false); //Get current character - if(mCurrentCharacter) { //Ensure a current character exists - const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save - if(slot) //Don't even try loading it if there's no prior save. - MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! - } - } +void MWState::StateManager::quickLoad() +{ + if (Character* mCurrentCharacter = getCurrentCharacter (false)) + if (const MWState::Slot* slot = &*mCurrentCharacter->begin()) //Get newest save + loadGame (mCurrentCharacter, slot); } MWState::Character *MWState::StateManager::getCurrentCharacter (bool create) From dbb192f084c53be4ebb475ae63692b5a73a7128f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Apr 2014 15:09:25 +0200 Subject: [PATCH 030/545] moved loading to a separate thread --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 86 ++++++++++------------- apps/opencs/model/doc/document.hpp | 7 +- apps/opencs/model/doc/documentmanager.cpp | 32 ++++++++- apps/opencs/model/doc/documentmanager.hpp | 16 +++++ apps/opencs/model/doc/loader.cpp | 66 +++++++++++++++++ apps/opencs/model/doc/loader.hpp | 55 +++++++++++++++ 7 files changed, 210 insertions(+), 54 deletions(-) create mode 100644 apps/opencs/model/doc/loader.cpp create mode 100644 apps/opencs/model/doc/loader.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 1db922afab..f1d50467bd 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ opencs_units (. editor) set (CMAKE_BUILD_TYPE DEBUG) opencs_units (model/doc - document operation saving documentmanager + document operation saving documentmanager loader ) opencs_units_noqt (model/doc diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3ef14ee7e5..20a355d483 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2219,68 +2219,32 @@ void CSMDoc::Document::createBase() } } -CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_) - : mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir), - mProjectPath ((configuration.getUserDataPath() / "projects") / - (savePath.filename().string() + ".project")), - mSaving (*this, mProjectPath) +CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, + const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir) +: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir), + mProjectPath ((configuration.getUserDataPath() / "projects") / + (savePath.filename().string() + ".project")), + mSaving (*this, mProjectPath) { - if (files.empty()) + if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); - if (new_ && files.size()==1) - createBase(); - else - { - std::vector::const_iterator end = files.end(); - - if (new_) - --end; - - load (files.begin(), end, !new_); - } - - if (new_) - { - mData.setDescription (""); - mData.setAuthor (""); - } - - bool filtersFound = false; - - if (boost::filesystem::exists (mProjectPath)) - { - filtersFound = true; - } - else + if (!boost::filesystem::exists (mProjectPath)) { boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath()); locCustomFiltersPath /= "defaultfilters"; - if (boost::filesystem::exists(locCustomFiltersPath)) + if (boost::filesystem::exists (locCustomFiltersPath)) { boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath); - filtersFound = true; } else { - boost::filesystem::path filters(mResDir); - filters /= "defaultfilters"; - - if (boost::filesystem::exists(filters)) - { - boost::filesystem::copy_file(filters, mProjectPath); - filtersFound = true; - } + boost::filesystem::copy_file (mResDir / "defaultfilters", mProjectPath); } } - if (filtersFound) - getData().loadFile (mProjectPath, false, true); - - addOptionalGmsts(); - addOptionalGlobals(); - connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); @@ -2289,13 +2253,39 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int))); connect (&mSaving, SIGNAL (reportMessage (const QString&, int)), - this, SLOT (reportMessage (const QString&, int))); + this, SLOT (reportMessage (const QString&, int))); } CSMDoc::Document::~Document() { } +void CSMDoc::Document::setupData (bool new_) +{ + if (new_ && mContentFiles.size()==1) + createBase(); + else + { + std::vector::const_iterator end = mContentFiles.end(); + + if (new_) + --end; + + load (mContentFiles.begin(), end, !new_); + } + + if (new_) + { + mData.setDescription (""); + mData.setAuthor (""); + } + + getData().loadFile (mProjectPath, false, true); + + addOptionalGmsts(); + addOptionalGlobals(); +} + QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 201fb4342a..c7d87e16a0 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -72,12 +72,13 @@ namespace CSMDoc public: Document (const Files::ConfigurationManager& configuration, - const std::vector< boost::filesystem::path >& files, - const boost::filesystem::path& savePath, - const boost::filesystem::path& resDir, bool new_); + const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir); ~Document(); + void setupData (bool new_); + QUndoStack& getUndoStack(); int getState() const; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 3f19269e7b..51774e4ffa 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -19,10 +19,24 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con if (!boost::filesystem::is_directory (projectPath)) boost::filesystem::create_directories (projectPath); + + mLoader.moveToThread (&mLoaderThread); + mLoaderThread.start(); + + connect (&mLoader, SIGNAL (documentLoaded (Document *)), + this, SLOT (documentLoaded (Document *))); + connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)), + this, SLOT (documentNotLoaded (Document *, const std::string&))); + connect (this, SIGNAL (loadRequest (Document *, bool)), + &mLoader, SLOT (loadDocument (Document *, bool))); } CSMDoc::DocumentManager::~DocumentManager() { + mLoaderThread.quit(); + mLoader.hasThingsToDo().wakeAll(); + mLoaderThread.wait(); + for (std::vector::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter) delete *iter; } @@ -30,11 +44,13 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, savePath, mResDir, new_); + Document *document = new Document (mConfiguration, files, savePath, mResDir); mDocuments.push_back (document); - emit documentAdded (document); + emit loadRequest (document, new_); + + mLoader.hasThingsToDo().wakeAll(); } bool CSMDoc::DocumentManager::removeDocument (Document *document) @@ -54,3 +70,15 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par { mResDir = boost::filesystem::system_complete(parResDir); } + +void CSMDoc::DocumentManager::documentLoaded (Document *document) +{ + emit documentAdded (document); +} + +void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error) +{ + removeDocument (document); + /// \todo report error + /// \todo handle removeDocument returning true +} \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index e41c490298..c30c83c066 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -7,6 +7,9 @@ #include #include +#include + +#include "loader.hpp" namespace Files { @@ -23,6 +26,8 @@ namespace CSMDoc std::vector mDocuments; const Files::ConfigurationManager& mConfiguration; + QThread mLoaderThread; + Loader mLoader; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -47,9 +52,20 @@ namespace CSMDoc boost::filesystem::path mResDir; + private slots: + + void documentLoaded (Document *document); + ///< The ownership of \a document is not transferred. + + void documentNotLoaded (Document *document, const std::string& error); + ///< Document load has been interrupted either because of a call to abortLoading + /// or a problem during loading). In the former case error will be an empty string. + signals: void documentAdded (CSMDoc::Document *document); + + void loadRequest (Document *document, bool _new); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp new file mode 100644 index 0000000000..722e903641 --- /dev/null +++ b/apps/opencs/model/doc/loader.cpp @@ -0,0 +1,66 @@ + +#include "loader.hpp" + +#include + +#include "document.hpp" + +CSMDoc::Loader::Loader() +{ + QTimer *timer = new QTimer (this); + + connect (timer, SIGNAL (timeout()), this, SLOT (load())); + timer->start (1000); +} + +QWaitCondition& CSMDoc::Loader::hasThingsToDo() +{ + return mThingsToDo; +} + +void CSMDoc::Loader::load() +{ + if (mDocuments.empty()) + { + mMutex.lock(); + mThingsToDo.wait (&mMutex); + mMutex.unlock(); + return; + } + + std::vector >::iterator iter = mDocuments.begin(); + + Document *document = iter->first; + bool new_ = iter->second; + + mDocuments.erase (iter); + + try + { + document->setupData (new_); + emit documentLoaded (document); + } + catch (const std::exception& e) + { + emit documentNotLoaded (document, e.what()); + } +} + +void CSMDoc::Loader::loadDocument (Document *document, bool new_) +{ + mDocuments.push_back (std::make_pair (document, new_)); +} + +void CSMDoc::Loader::abortLoading (Document *document) +{ + for (std::vector >::iterator iter = mDocuments.begin(); + iter!=mDocuments.end(); ++iter) + { + if (iter->first==document) + { + mDocuments.erase (iter); + emit documentNotLoaded (document, ""); + break; + } + } +} \ No newline at end of file diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp new file mode 100644 index 0000000000..eae0c8001a --- /dev/null +++ b/apps/opencs/model/doc/loader.hpp @@ -0,0 +1,55 @@ +#ifndef CSM_DOC_LOADER_H +#define CSM_DOC_LOADER_H + +#include + +#include +#include +#include + +namespace CSMDoc +{ + class Document; + + class Loader : public QObject + { + Q_OBJECT + + QMutex mMutex; + QWaitCondition mThingsToDo; + std::vector > mDocuments; + + public: + + Loader(); + + QWaitCondition& hasThingsToDo(); + + private slots: + + void load(); + + public slots: + + void loadDocument (Document *document, bool new_); + ///< The ownership of \a document is not transferred. + /// \param new_ Do not load the last content file in the files list specified in + /// \a document and instead create it in an appropriate way. + + void abortLoading (Document *document); + ///< Abort loading \a docuemnt (ignored if \a document has already finished being + /// loaded). Will result in a documentNotLoaded signal, once the Loader has finished + /// cleaning up. + + signals: + + void documentLoaded (Document *document); + ///< The ownership of \a document is not transferred. + + void documentNotLoaded (Document *document, const std::string& error); + ///< Document load has been interrupted either because of a call to abortLoading + /// or a problem during loading). In the former case error will be an empty string. + }; +} + +#endif From 3f2ae950f5b51aa3c6a86d92b9756c3b7827e866 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Thu, 24 Apr 2014 12:50:10 -0500 Subject: [PATCH 031/545] Disabled view resize for open views when user setting changes. Fixed new view size issue to match existing user settings. --- apps/opencs/model/settings/settingmanager.cpp | 12 ++++++++++++ apps/opencs/model/settings/settingmanager.hpp | 3 +++ apps/opencs/model/settings/usersettings.hpp | 4 ---- apps/opencs/view/doc/view.cpp | 13 +------------ apps/opencs/view/settings/listview.cpp | 2 +- apps/opencs/view/settings/page.cpp | 2 +- apps/opencs/view/settings/view.cpp | 7 ++++++- apps/opencs/view/world/table.cpp | 6 ++++-- apps/opencs/view/world/table.hpp | 4 ++-- apps/opencs/view/world/util.cpp | 6 ------ apps/opencs/view/world/util.hpp | 8 +++----- 11 files changed, 33 insertions(+), 34 deletions(-) diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index 70b91ee40a..450252cd90 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -328,3 +328,15 @@ CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const return pageMap; } + +void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, + const QStringList &list) +{ + QStringList names = settingKey.split('.'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + setting->setDefinedValues (list); + + emit userSettingUpdated (names.at(1), list); +} diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp index 8819096adf..ca8a2cc7b9 100644 --- a/apps/opencs/model/settings/settingmanager.hpp +++ b/apps/opencs/model/settings/settingmanager.hpp @@ -75,8 +75,11 @@ namespace CSMSettings signals: + void userSettingUpdated (const QString &, const QStringList &); + public slots: + void updateUserSetting (const QString &, const QStringList &); }; } #endif // CSMSETTINGS_SETTINGMANAGER_HPP diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 75a3a0797a..63caed923e 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -58,10 +58,6 @@ namespace CSMSettings { private: void buildSettingModelDefaults(); - - signals: - - void userSettingUpdated(const QString &, const QStringList &); }; } #endif // USERSETTINGS_HPP diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 47e1a80de3..397567f99e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -492,18 +492,7 @@ void CSVDoc::View::resizeViewHeight (int height) void CSVDoc::View::updateUserSetting (const QString &name, const QStringList &list) -{ - if (list.isEmpty()) - return; - - int value = list.at(0).toInt(); - - if (name == "Width") - resizeViewWidth (value); - - else if (name == "Height") - resizeViewHeight (value); -} +{} void CSVDoc::View::toggleShowStatusBar (bool show) { diff --git a/apps/opencs/view/settings/listview.cpp b/apps/opencs/view/settings/listview.cpp index b2a47903ff..36cdbb0ae6 100644 --- a/apps/opencs/view/settings/listview.cpp +++ b/apps/opencs/view/settings/listview.cpp @@ -49,7 +49,7 @@ void CSVSettings::ListView::buildAbstractItemViewModel() void CSVSettings::ListView::emitItemViewUpdate (int idx) { - emit viewUpdated (objectName(), selectedValues()); + updateView(); } QWidget *CSVSettings::ListView::buildWidget(bool isMultiLine, int width) diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index 665326c2c0..a5711c8f81 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -52,7 +52,7 @@ void CSVSettings::Page::addView (CSMSettings::Setting *setting) if (setting->isEditorSetting()) { connect (view, SIGNAL (viewUpdated(const QString&, const QStringList&)), &CSMSettings::UserSettings::instance(), - SIGNAL (userSettingUpdated (const QString &, const QStringList &))); + SLOT (updateUserSetting (const QString &, const QStringList &))); } } diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 259dd518b6..4f93b1c0fe 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -151,6 +151,11 @@ void CSVSettings::View::setSelectedValues (const QStringList &list, } select (selection); + //push changes to model side + + + //update the view if the selection was set from the model side, not by the + //user if (doViewUpdate) updateView (signalUpdate); } @@ -198,7 +203,7 @@ QList CSVSettings::View::toStandardItemList void CSVSettings::View::updateView (bool signalUpdate) const { if (signalUpdate) - emit viewUpdated(objectName(), selectedValues()); + emit viewUpdated(viewKey(), selectedValues()); } QString CSVSettings::View::value (int row) const diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 995de21fc1..902ab268a3 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -456,12 +456,14 @@ void CSVWorld::Table::updateUserSetting for (int i=0; i - (*delegate).updateUserSetting (name, list)) + { + dynamic_cast + (*delegate).updateUserSetting (name, list); { emit dataChanged (mModel->index (0, i), mModel->index (mModel->rowCount()-1, i)); } + } } void CSVWorld::Table::tableSizeUpdate() diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index dfc74b3eb8..c2811b8932 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -78,8 +78,6 @@ namespace CSVWorld CSMWorld::UniversalId getUniversalId (int row) const; - void updateUserSetting (const QString &name, const QStringList &list); - std::vector getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; signals: @@ -123,6 +121,8 @@ namespace CSVWorld void requestFocus (const std::string& id); void recordFilterChanged (boost::shared_ptr filter); + + void updateUserSetting (const QString &name, const QStringList &list); }; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 16310c8a97..ea8a7c5415 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -196,12 +196,6 @@ bool CSVWorld::CommandDelegate::isEditLocked() const return mEditLock; } -bool CSVWorld::CommandDelegate::updateUserSetting (const QString &name, - const QStringList &list) -{ - return false; -} - void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const { QVariant v = index.data(Qt::EditRole); diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 50e2cf858e..1c7e37818b 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -136,17 +136,15 @@ namespace CSVWorld bool isEditLocked() const; - virtual bool updateUserSetting - (const QString &name, const QStringList &list); - ///< \return Does column require update? virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const; - private slots: + public slots: - virtual void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue) {} + virtual void updateUserSetting + (const QString &name, const QStringList &list) {} }; } From c3e08916dadd70ac926cb6f3d92ee8c4b4efa50f Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Thu, 24 Apr 2014 20:40:17 -0400 Subject: [PATCH 032/545] Sneak: Added support for state checking I need advice one what I should do in order to pass mActors over to the player. Particularly line 139 in player.cpp --- apps/openmw/mwbase/mechanicsmanager.hpp | 3 +++ apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 5 +++++ apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 ++ apps/openmw/mwworld/player.cpp | 15 +++++++++++++-- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 22dda0ce09..7d27e73bd1 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -164,6 +164,9 @@ namespace MWBase ///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor) virtual std::list getActorsFollowing(const MWWorld::Ptr& actor) = 0; + ///return the list of actors + virtual MWMechanics::Actors& getActors() = 0; + virtual void playerLoaded() = 0; }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 84dc337c95..868a09e2e8 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -989,4 +989,9 @@ namespace MWMechanics { return mActors.getActorsFollowing(actor); } + + MWMechanics::Actors& MechanicsManager::getActors() + { + return *mActors; + } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 761caf586c..a00c795254 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -137,6 +137,8 @@ namespace MWMechanics virtual std::list getActorsFollowing(const MWWorld::Ptr& actor); + virtual MWMechanics::Actors& getActors(); + virtual void toggleAI(); virtual bool isAIActive(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index a4a4e95684..9cc873c0f9 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -9,6 +9,8 @@ #include #include +#include "../mwworld/esmstore.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" @@ -16,6 +18,8 @@ #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/actors.hpp" +#include "../mwmechanics/mechanicsmanagerimp.hpp" #include "class.hpp" #include "ptr.hpp" @@ -130,8 +134,15 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - // TODO show sneak indicator only when the player is not detected by any actor - MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); + // Find all the actors who might be able to see the player + std::vector neighbors; + MWBase::Environment::get().getMechanicsManager()->getActors().getObjectsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + esmStore.get().find("fSneakUseDist")->getInt(), neighbors); + for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) + if ( MechanicsManager::awarenessCheck(ptr, *it) ) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); + if (!neighbors) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); } void Player::yaw(float yaw) From 42b879a9a542a9392352be885b0b8c206f8dfe4e Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Thu, 24 Apr 2014 22:41:05 -0400 Subject: [PATCH 033/545] Reworked the accusation of actors --- apps/openmw/mwbase/mechanicsmanager.hpp | 6 ++---- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 10 +++++----- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 3 +-- apps/openmw/mwworld/player.cpp | 8 +++++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 7d27e73bd1..d0a0783d31 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -160,13 +160,11 @@ namespace MWBase virtual bool isAIActive() = 0; virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector& objects) = 0; + virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) = 0; ///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor) virtual std::list getActorsFollowing(const MWWorld::Ptr& actor) = 0; - - ///return the list of actors - virtual MWMechanics::Actors& getActors() = 0; - + virtual void playerLoaded() = 0; }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 868a09e2e8..0ef94c13cf 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -985,13 +985,13 @@ namespace MWMechanics mObjects.getObjectsInRange(position, radius, objects); } + void MechanicsManager::getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) + { + mActors.getObjectsInRange(position, radius, objects); + } + std::list MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor) { return mActors.getActorsFollowing(actor); } - - MWMechanics::Actors& MechanicsManager::getActors() - { - return *mActors; - } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index a00c795254..6038157444 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -134,11 +134,10 @@ namespace MWMechanics virtual void updateMagicEffects (const MWWorld::Ptr& ptr); virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector& objects); + virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects); virtual std::list getActorsFollowing(const MWWorld::Ptr& actor); - virtual MWMechanics::Actors& getActors(); - virtual void toggleAI(); virtual bool isAIActive(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 9cc873c0f9..f4ca5ee27f 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -134,14 +134,16 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + // Find all the actors who might be able to see the player std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActors().getObjectsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), esmStore.get().find("fSneakUseDist")->getInt(), neighbors); for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - if ( MechanicsManager::awarenessCheck(ptr, *it) ) + if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); - if (!neighbors) + if (!neighbors.size()) MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); } From f3272c941f0caca478418e0b32cd651db33dd526 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 24 Apr 2014 22:47:45 -0400 Subject: [PATCH 034/545] Fix for bug #1080, can't read/repair/make potions/use soul gems/rest/sleep while in combat. The radius for being in combat with the player is fAlarmDistance, which looked like the only pertinent thing. --- apps/openmw/mwbase/mechanicsmanager.hpp | 7 ++++- apps/openmw/mwinput/inputmanagerimp.cpp | 9 +++++-- apps/openmw/mwmechanics/actors.cpp | 26 +++++++++++++++++-- apps/openmw/mwmechanics/actors.hpp | 7 ++++- .../mwmechanics/mechanicsmanagerimp.cpp | 23 +++++++++++----- .../mwmechanics/mechanicsmanagerimp.hpp | 4 ++- apps/openmw/mwstate/statemanagerimp.cpp | 4 +++ apps/openmw/mwworld/actionalchemy.cpp | 8 ++++++ apps/openmw/mwworld/actionread.cpp | 12 +++++++-- apps/openmw/mwworld/actionrepair.cpp | 7 +++++ apps/openmw/mwworld/actionsoulgem.cpp | 22 ++++++++++------ apps/openmw/mwworld/player.cpp | 5 ++++ apps/openmw/mwworld/player.hpp | 5 +++- 13 files changed, 114 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index e4c480a8c0..44b3d0229e 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -161,9 +161,14 @@ namespace MWBase virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector& 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 getActorsFollowing(const MWWorld::Ptr& actor) = 0; + ///Returns a list of actors who are fighting the given actor within the fAlarmDistance + /** ie AiCombat is active and the target is the actor **/ + virtual std::list getActorsFighting(const MWWorld::Ptr& actor) = 0; + virtual void playerLoaded() = 0; }; } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 51c0a1621e..75c9015a0a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -19,6 +19,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/statemanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" @@ -693,8 +694,12 @@ namespace MWInput if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ()) return; - /// \todo check if resting is currently allowed (enemies nearby?) - MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); + if(mPlayer->isInCombat()) {//Check if in combat + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope, + return; + } + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); //Open rest GUI + } void InputManager::screenshot() diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 7b83ff1f1d..804ec7a41e 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -176,7 +176,7 @@ namespace MWMechanics adjustMagicEffects (ptr); if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats()) calculateDynamicStats (ptr); - + calculateCreatureStatModifiers (ptr, duration); // AI @@ -764,7 +764,7 @@ namespace MWMechanics creatureStats.setHostile(false); creatureStats.setAttacked(false); creatureStats.setAlarmed(false); - + // Update witness crime id npcStats.setCrimeId(-1); } @@ -1038,4 +1038,26 @@ namespace MWMechanics } return list; } + + std::list Actors::getActorsFighting(const MWWorld::Ptr& actor) { + std::list list; + std::vector neighbors; + Ogre::Vector3 position = Ogre::Vector3(actor.getRefData().getPosition().pos); + getObjectsInRange(position, + MWBase::Environment::get().getWorld()->getStore().get().find("fAlarmRadius")->getFloat(), + neighbors); //only care about those within the alarm disance + for(std::vector::iterator iter(neighbors.begin());iter != neighbors.end();iter++) + { + const MWWorld::Class &cls = MWWorld::Class::get(*iter); + CreatureStats &stats = cls.getCreatureStats(*iter); + + if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) + { + MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); + if(package->getTargetId() == actor.getCellRef().mRefID) + list.push_front(*iter); + } + } + return list; + } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index d61d742587..f7dff1058b 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -98,8 +98,13 @@ namespace MWMechanics void getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector& out); + ///Returns the list of actors which are following the given actor + /**ie AiFollow is active and the target is the actor **/ std::list getActorsFollowing(const MWWorld::Ptr& actor); - /// getActorsFighting(const MWWorld::Ptr& actor); private: PtrControllerMap mActors; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index d24191d889..90c00a36ee 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -772,6 +772,11 @@ namespace MWMechanics bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed) { + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); + return true; + } + MWWorld::Ptr victim; if (isAllowedToUse(ptr, bed, victim)) return false; @@ -832,17 +837,17 @@ namespace MWMechanics // Find all the NPCs within the alarm radius std::vector neighbors; - mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), + mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), esmStore.get().find("fAlarmRadius")->getInt(), neighbors); // Find an actor who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - { + { if (*it == ptr) continue; // not the player // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || - type == OT_Assault ) + type == OT_Assault ) { // Will the witness report the crime? @@ -853,7 +858,7 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) - { + { if (*it1 == ptr) continue; // not the player // TODO: Add more messages @@ -861,9 +866,9 @@ namespace MWMechanics MWBase::Environment::get().getDialogueManager()->say(*it1, "thief"); else if (type == OT_Assault) MWBase::Environment::get().getDialogueManager()->say(*it1, "attack"); - + // Will other witnesses paticipate in crime - if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm + if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm || type == OT_Assault ) { it1->getClass().getNpcStats(*it1).setCrimeId(id); @@ -884,7 +889,7 @@ namespace MWMechanics void MechanicsManager::reportCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg) { const MWWorld::Store& store = MWBase::Environment::get().getWorld()->getStore().get(); - + // Bounty for each type of crime if (type == OT_Trespassing || type == OT_SleepingInOwnedBed) arg = store.find("iCrimeTresspass")->getInt(); @@ -993,4 +998,8 @@ namespace MWMechanics { return mActors.getActorsFollowing(actor); } + + std::list MechanicsManager::getActorsFighting(const MWWorld::Ptr& actor) { + return mActors.getActorsFighting(actor); + } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 5dd7583779..4d59379d68 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -120,7 +120,7 @@ namespace MWMechanics /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item); /// Attempt sleeping in a bed. If this is illegal, call commitCrime. - /// @return was it illegal, and someone saw you doing it? + /// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed); virtual void forceStateUpdate(const MWWorld::Ptr &ptr); @@ -137,6 +137,8 @@ namespace MWMechanics virtual std::list getActorsFollowing(const MWWorld::Ptr& actor); + virtual std::list getActorsFighting(const MWWorld::Ptr& actor); + virtual bool toggleAI(); virtual bool isAIActive(); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index a0971b9427..6c834a2bee 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -235,9 +235,12 @@ void MWState::StateManager::quickSave(std::string name) { if (it->mProfile.mDescription == name) slot = &*it; } + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage4}"); //Saving... MWBase::Environment::get().getStateManager()->saveGame(name, slot); } } + else + MWBase::Environment::get().getWindowManager()->messageBox("#{sSaveGameDenied}"); //You can not save your game right now } void MWState::StateManager::loadGame (const Character *character, const Slot *slot) @@ -351,6 +354,7 @@ void MWState::StateManager::quickLoad() { if(mCurrentCharacter) { //Ensure a current character exists const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save if(slot) //Don't even try loading it if there's no prior save. + //MWBase::Environment::get().getWindowManager()->messageBox("#{sLoadingMessage14}"); //it overlaps MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy! } } diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index bba75bc499..bbba1081c3 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -2,11 +2,19 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/player.hpp" namespace MWWorld { void ActionAlchemy::executeImp (const Ptr& actor) { + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage3}"); + return; + } + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy); } } diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 67755259e0..433237e26a 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -3,6 +3,9 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/player.hpp" #include "../mwmechanics/npcstats.hpp" @@ -19,8 +22,13 @@ namespace MWWorld { } - void ActionRead::executeImp (const MWWorld::Ptr& actor) - { + void ActionRead::executeImp (const MWWorld::Ptr& actor) { + + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage4}"); + return; + } + LiveCellRef *ref = getTarget().get(); if (ref->mBase->mData.mIsScroll) diff --git a/apps/openmw/mwworld/actionrepair.cpp b/apps/openmw/mwworld/actionrepair.cpp index bd56421165..a86dc38b1c 100644 --- a/apps/openmw/mwworld/actionrepair.cpp +++ b/apps/openmw/mwworld/actionrepair.cpp @@ -2,6 +2,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwworld/player.hpp" namespace MWWorld { @@ -12,6 +14,11 @@ namespace MWWorld void ActionRepair::executeImp (const Ptr& actor) { + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage2}"); + return; + } + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair); MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget()); } diff --git a/apps/openmw/mwworld/actionsoulgem.cpp b/apps/openmw/mwworld/actionsoulgem.cpp index 6746f692f1..7237fd3342 100644 --- a/apps/openmw/mwworld/actionsoulgem.cpp +++ b/apps/openmw/mwworld/actionsoulgem.cpp @@ -2,20 +2,26 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwworld/player.hpp" namespace MWWorld { -ActionSoulgem::ActionSoulgem(const Ptr &object) - : Action(false, object) -{ + ActionSoulgem::ActionSoulgem(const Ptr &object) + : Action(false, object) + { -} + } -void ActionSoulgem::executeImp(const Ptr &actor) -{ - MWBase::Environment::get().getWindowManager()->showSoulgemDialog(getTarget()); -} + void ActionSoulgem::executeImp(const Ptr &actor) + { + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage5}"); + return; + } + MWBase::Environment::get().getWindowManager()->showSoulgemDialog(getTarget()); + } } diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index a4a4e95684..9202118a4a 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -13,6 +13,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" @@ -166,6 +167,10 @@ namespace MWWorld mTeleported = teleported; } + bool Player::isInCombat() { + return MWBase::Environment::get().getMechanicsManager()->getActorsFighting(getPlayer()).size() != 0; + } + void Player::markPosition(CellStore *markedCell, ESM::Position markedPosition) { mMarkedCell = markedCell; diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 7dbaaddb43..7e3f7a3cf2 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -44,7 +44,7 @@ namespace MWWorld int mCurrentCrimeId; // the id assigned witnesses int mPayedCrimeId; // the last id payed off (0 bounty) - + public: Player(const ESM::NPC *player, const MWBase::World& world); @@ -90,6 +90,9 @@ namespace MWWorld bool wasTeleported() const; void setTeleported(bool teleported); + ///Checks all actors to see if anyone has an aipackage against you + bool isInCombat(); + void clear(); void write (ESM::ESMWriter& writer) const; From 4a4c08946c5b75701a5eb9b3e878c0727380909d Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Thu, 24 Apr 2014 23:02:11 -0400 Subject: [PATCH 035/545] Checks the state of the passed sneak variable --- apps/openmw/mwworld/player.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index f4ca5ee27f..8588547d28 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -134,17 +134,25 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + if (sneak == true) + { + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - // Find all the actors who might be able to see the player - std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), - esmStore.get().find("fSneakUseDist")->getInt(), neighbors); - for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); - if (!neighbors.size()) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); + // Find all the actors who might be able to see the player + std::vector neighbors; + MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + esmStore.get().find("fSneakUseDist")->getInt(), neighbors); + for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) + { + if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) + { + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + break; + } + } + if (neighbors.size() == 0) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + } } void Player::yaw(float yaw) From 2e06414b43663684df1ec2b8e2b59391b2f32f17 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Fri, 25 Apr 2014 07:16:40 -0500 Subject: [PATCH 036/545] Fixed broken delegate display modes (Display Format settings). Moved UserSetting update functions to DataDisplayDelegate. --- apps/opencs/model/settings/settingmanager.cpp | 2 +- apps/opencs/model/settings/usersettings.cpp | 9 ++-- apps/opencs/model/settings/usersettings.hpp | 2 +- apps/opencs/view/doc/view.cpp | 4 +- .../opencs/view/world/datadisplaydelegate.cpp | 44 +++++++++++++++++-- .../opencs/view/world/datadisplaydelegate.hpp | 12 ++++- apps/opencs/view/world/idtypedelegate.cpp | 25 ++--------- apps/opencs/view/world/idtypedelegate.hpp | 3 -- .../view/world/recordstatusdelegate.cpp | 23 ++-------- .../view/world/recordstatusdelegate.hpp | 3 -- 10 files changed, 67 insertions(+), 60 deletions(-) diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index 450252cd90..eec4c54cf3 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -338,5 +338,5 @@ void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, setting->setDefinedValues (list); - emit userSettingUpdated (names.at(1), list); + emit userSettingUpdated (settingKey, list); } diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index db31f42552..badb73ece2 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -260,13 +260,16 @@ void CSMSettings::UserSettings::saveSettings writeFilestream (openFilestream (mUserFilePath, false), settingMap); } -QString CSMSettings::UserSettings::settingValue (const QString §ion, - const QString &name) +QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { - Setting *setting = findSetting(section, name); + QStringList names = settingKey.split('.'); + qDebug () << "looking for " << names.at(0) << ',' << names.at(1); + + Setting *setting = findSetting(names.at(0), names.at(1)); if (setting) { + qDebug() << "setting found"; if (!setting->definedValues().isEmpty()) return setting->definedValues().at(0); } diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 63caed923e..f0ed7af41a 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -53,7 +53,7 @@ namespace CSMSettings { /// Writes settings to the user's config file path void saveSettings (const QMap &settingMap); - QString settingValue (const QString §ion, const QString &name); + QString settingValue (const QString &settingKey); private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 397567f99e..acb272553e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -236,10 +236,10 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mViewTotal (totalViews) { QString width = CSMSettings::UserSettings::instance().settingValue - (QString("Window Size"), QString("Width")); + ("Window Size.Width"); QString height = CSMSettings::UserSettings::instance().settingValue - (QString("Window Size"), QString("Height")); + ("Window Size.Height"); resize (width.toInt(), height.toInt()); diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index d838395f6e..ef0da56ac7 100755 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -1,16 +1,26 @@ #include "datadisplaydelegate.hpp" +#include "../../model/settings/usersettings.hpp" + #include #include CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const IconList &icons, - QUndoStack &undoStack, QObject *parent) - : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), mIcons (icons) - , mIconSize (QSize(16, 16)), mIconLeftOffset(3), mTextLeftOffset(8) + QUndoStack &undoStack, + const QString &settingKey, + QObject *parent) + : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), + mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), + mTextLeftOffset(8), mSettingKey (settingKey) { mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); buildPixmaps(); + + QString value = + CSMSettings::UserSettings::instance().settingValue (settingKey); + + updateDisplayMode(value); } void CSVWorld::DataDisplayDelegate::buildPixmaps () @@ -89,6 +99,30 @@ void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOp painter->drawPixmap (iconRect, mPixmaps.at(index).second); } +void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name, + const QStringList &list) +{ + if (list.isEmpty()) + return; + + QString value = list.at(0); + + if (name == mSettingKey) + updateDisplayMode (value); +} + +void CSVWorld::DataDisplayDelegate::updateDisplayMode (const QString &mode) +{ + if (mode == "Icon and Text") + mDisplayMode = Mode_IconAndText; + + else if (mode == "Icon Only") + mDisplayMode = Mode_IconOnly; + + else if (mode == "Text Only") + mDisplayMode = Mode_TextOnly; +} + CSVWorld::DataDisplayDelegate::~DataDisplayDelegate() { mIcons.clear(); @@ -106,5 +140,7 @@ CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (Q QObject *parent) const { - return new DataDisplayDelegate (mValues, mIcons, undoStack, parent); + return new DataDisplayDelegate (mValues, mIcons, undoStack, "", parent); } + + diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index d23b86631c..f11c4a2b9e 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -35,10 +35,14 @@ namespace CSVWorld int mIconLeftOffset; int mTextLeftOffset; + QString mSettingKey; + public: explicit DataDisplayDelegate (const ValueList & values, const IconList & icons, - QUndoStack& undoStack, QObject *parent); + QUndoStack& undoStack, + const QString &settingKey, + QObject *parent); ~DataDisplayDelegate(); @@ -53,8 +57,14 @@ namespace CSVWorld /// offset the horizontal position of the text from the right edge of the icon. Default is 8 pixels. void setTextLeftOffset (int offset); + ///update the display mode for the delegate + void updateUserSetting (const QString &name, const QStringList &list); + private: + /// update the display mode based on a passed string + void updateDisplayMode (const QString &); + /// custom paint function for painting the icon. Mode_IconAndText and Mode_Icon only. void paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int i) const; diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index ce4e8f0148..485ca57ac9 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -4,30 +4,11 @@ CSVWorld::IdTypeDelegate::IdTypeDelegate (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) - : DataDisplayDelegate (values, icons, undoStack, parent) + : DataDisplayDelegate (values, icons, undoStack, + "Display Format.Referenceable ID Type Display", + parent) {} -bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) -{ - /// \todo make the setting key a member variable, that is initialised from a constructor argument - if (settingName == "Referenceable ID Type Display") - { - if (settingValue == "Icon and Text") - mDisplayMode = Mode_IconAndText; - - else if (settingValue == "Icon Only") - mDisplayMode = Mode_IconOnly; - - else if (settingValue == "Text Only") - mDisplayMode = Mode_TextOnly; - - return true; - } - - return false; -} - - CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory() { for (int i=0; i enums = diff --git a/apps/opencs/view/world/recordstatusdelegate.hpp b/apps/opencs/view/world/recordstatusdelegate.hpp index d9126fee04..1b42223afc 100644 --- a/apps/opencs/view/world/recordstatusdelegate.hpp +++ b/apps/opencs/view/world/recordstatusdelegate.hpp @@ -20,9 +20,6 @@ namespace CSVWorld explicit RecordStatusDelegate(const ValueList& values, const IconList& icons, QUndoStack& undoStack, QObject *parent = 0); - - virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue); - }; class RecordStatusDelegateFactory : public DataDisplayDelegateFactory From 42b332775a4b6623f4cacd3c7de25f18ead56b40 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Apr 2014 15:30:46 +0200 Subject: [PATCH 037/545] removed some debug statements --- apps/opencs/model/settings/usersettings.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index badb73ece2..808fbfc70f 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -11,8 +11,6 @@ #include #include -#include - #include #include @@ -263,13 +261,11 @@ void CSMSettings::UserSettings::saveSettings QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { QStringList names = settingKey.split('.'); - qDebug () << "looking for " << names.at(0) << ',' << names.at(1); Setting *setting = findSetting(names.at(0), names.at(1)); if (setting) { - qDebug() << "setting found"; if (!setting->definedValues().isEmpty()) return setting->definedValues().at(0); } From f3626adc868c7e3a9080e63dd102219c294c20f0 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sat, 26 Apr 2014 00:20:55 +0400 Subject: [PATCH 038/545] remake of z-moving in combat for flying/swimming enemies --- apps/openmw/mwmechanics/aicombat.cpp | 52 ++++++++++++++----------- apps/openmw/mwmechanics/aicombat.hpp | 4 -- apps/openmw/mwmechanics/character.cpp | 9 ++--- apps/openmw/mwmechanics/pathfinding.hpp | 2 +- apps/openmw/mwmechanics/steering.cpp | 29 ++++++++++++++ apps/openmw/mwmechanics/steering.hpp | 2 + 6 files changed, 65 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 807e08c1db..8a3c23aefd 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -38,6 +38,13 @@ namespace return Ogre::Radian( Ogre::Math::ACos(dir.y / len) * sgn(Ogre::Math::ASin(dir.x / len)) ).valueDegrees(); } + float getXAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) + { + float len = (dirLen >= 0.0f)? dirLen : dir.length(); + return Ogre::Radian(-Ogre::Math::ASin(dir.z / len)).valueDegrees(); + } + + const float PATHFIND_Z_REACH = 50.0f; // distance at which actor pays more attention to decide whether to shortcut or stick to pathgrid const float PATHFIND_CAUTION_DIST = 500.0f; @@ -79,7 +86,6 @@ namespace MWMechanics mStrike(false), mCombatMove(false), mMovement(), - mTargetAngle(0), mForceNoShortcut(false), mShortcutFailPos() { @@ -108,13 +114,18 @@ namespace MWMechanics } actor.getClass().getMovementSettings(actor) = mMovement; + actor.getClass().getMovementSettings(actor).mRotation[0] = 0; + actor.getClass().getMovementSettings(actor).mRotation[2] = 0; - if(actor.getRefData().getPosition().rot[2] != mTargetAngle) + if(mMovement.mRotation[2] != 0) { - zTurn(actor, Ogre::Degree(mTargetAngle)); + if(zTurn(actor, Ogre::Degree(mMovement.mRotation[2]))) mMovement.mRotation[2] = 0; + } + + if(mMovement.mRotation[0] != 0) + { + if(smoothTurn(actor, Ogre::Degree(mMovement.mRotation[0]), 0)) mMovement.mRotation[0] = 0; } - - mTimerAttack -= duration; actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike); @@ -225,7 +236,7 @@ namespace MWMechanics bool isStuck = false; float speed = 0.0f; - if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = cls.getSpeed(actor)) / 10.0f) + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = cls.getSpeed(actor)) / 10.0f) isStuck = true; mLastPos = pos; @@ -235,31 +246,28 @@ namespace MWMechanics if(canMoveByZ = ((actor.getClass().isNpc() || actor.getClass().canSwim(actor)) && MWBase::Environment::get().getWorld()->isSwimming(actor)) || (actor.getClass().canFly(actor) && MWBase::Environment::get().getWorld()->isFlying(actor))) { - float zToTarget = vTargetPos.z - pos.pos[2]; - - mMovement.mPosition[1] = sqrt(distToTarget*distToTarget - zToTarget*zToTarget); // XY-plane vec length - mMovement.mPosition[2] = zToTarget; + // determine vertical angle to target + mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); } if(distToTarget < rangeMelee || (distToTarget <= rangeCloseUp && mFollowTarget && !isStuck) ) { //Melee and Close-up combat vDirToTarget.z = 0; - mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); if (mFollowTarget && distToTarget > rangeMelee) { //Close-up combat: just run up on target - if(!canMoveByZ) mMovement.mPosition[1] = 1; + mMovement.mPosition[1] = 1; } else { //Melee: stop running and attack mMovement.mPosition[1] = 0; - if(canMoveByZ) mMovement.mPosition[2] = 0; // When attacking with a weapon, choose between slash, thrust or chop - if (actor.getClass().hasInventoryStore(actor)) + if (mStrike && actor.getClass().hasInventoryStore(actor)) chooseBestAttack(weapon, mMovement); if(mMovement.mPosition[0] || mMovement.mPosition[1]) @@ -304,15 +312,15 @@ namespace MWMechanics if(speed == 0.0f) speed = cls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; - //if(actor.getRefData().getPosition().rot[2] != mTargetAngle) preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); } + // don't use pathgrid when actor can move in 3 dimensions if(canMoveByZ) preferShortcut = true; if(preferShortcut) { - mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); mForceNoShortcut = false; mShortcutFailPos.pos[0] = mShortcutFailPos.pos[1] = mShortcutFailPos.pos[2] = 0; mPathFinder.clearPath(); @@ -338,12 +346,12 @@ namespace MWMechanics // get point just before target std::list::iterator pntIter = --mPathFinder.getPath().end(); --pntIter; - Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ); + Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ); // if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target if(distToTarget <= (vTargetPos - vBeforeTarget).length()) { - mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); preferShortcut = true; } } @@ -352,13 +360,13 @@ namespace MWMechanics if(!preferShortcut) { if(!mPathFinder.getPath().empty()) - mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + mMovement.mRotation[2] = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); else - mTargetAngle = getZAngleToDir(vDirToTarget, distToTarget); + mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); } } - if(!canMoveByZ) mMovement.mPosition[1] = 1; + mMovement.mPosition[1] = 1; mReadyToAttack = false; } @@ -392,8 +400,6 @@ namespace MWMechanics } } - actor.getClass().getMovementSettings(actor) = mMovement; - return false; } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index b71dd9cf0e..8130df0e8e 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -36,10 +36,6 @@ namespace MWMechanics // when mCombatMove is true float mTimerCombatMove; - // the z rotation angle (degrees) we want to reach - // used every frame when mRotate is true - float mTargetAngle; - bool mReadyToAttack, mStrike; bool mFollowTarget; bool mCombatMove; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2c63d5a142..21f2ed8832 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1014,11 +1014,11 @@ void CharacterController::update(float duration) if(mHitState != CharState_None && mJumpState == JumpState_None) vec = Ogre::Vector3(0.0f); Ogre::Vector3 rot = cls.getRotationVector(mPtr); + mMovementSpeed = cls.getSpeed(mPtr); vec.x *= mMovementSpeed; vec.y *= mMovementSpeed; - if(inwater || flying) vec.z *= mMovementSpeed; CharacterState movestate = CharState_None; CharacterState idlestate = CharState_SpecialIdle; @@ -1085,8 +1085,7 @@ void CharacterController::update(float duration) fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss, fatigue.getCurrent() < 0); cls.getCreatureStats(mPtr).setFatigue(fatigue); - // kind of hack, reason - creatures can move along z when in water/flying - if(sneak || ((inwater || flying) && mPtr.getRefData().getHandle() == "player")) + if(sneak || inwater || flying) vec.z = 0.0f; if (inwater || flying) @@ -1121,7 +1120,7 @@ void CharacterController::update(float duration) vec.y *= mult; vec.z = 0.0f; } - else if(!inwater && !flying && vec.z > 0.0f && mJumpState == JumpState_None) + else if(vec.z > 0.0f && mJumpState == JumpState_None) { // Started a jump. float z = cls.getJump(mPtr); @@ -1183,7 +1182,7 @@ void CharacterController::update(float duration) { if(!(vec.z > 0.0f)) mJumpState = JumpState_None; - if(!inwater && !flying) vec.z = 0.0f; + vec.z = 0.0f; if(std::abs(vec.x/2.0f) > std::abs(vec.y)) { diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 86fa3b6bc5..ff3bf06fa7 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -67,7 +67,7 @@ namespace MWMechanics /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times @note If the first point is chosen as the nearest one - the cituation can occure when the 1st point of the new path is undesirable + the situation can occur when the 1st point of the new path is undesirable (i.e. the 2nd point of new path == the 1st point of old path). @param path - old path @return true if such point was found and deleted diff --git a/apps/openmw/mwmechanics/steering.cpp b/apps/openmw/mwmechanics/steering.cpp index 7646e832da..d10733b36f 100644 --- a/apps/openmw/mwmechanics/steering.cpp +++ b/apps/openmw/mwmechanics/steering.cpp @@ -10,6 +10,35 @@ namespace MWMechanics { +bool smoothTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, int axis) +{ + Ogre::Radian currentAngle (actor.getRefData().getPosition().rot[axis]); + Ogre::Radian diff (targetAngle - currentAngle); + if (diff >= Ogre::Degree(180)) + { + // Turning the other way would be a better idea + diff = diff-Ogre::Degree(360); + } + else if (diff <= Ogre::Degree(-180)) + { + diff = Ogre::Degree(360)-diff; + } + Ogre::Radian absDiff = Ogre::Math::Abs(diff); + + // The turning animation actually moves you slightly, so the angle will be wrong again. + // Use epsilon to prevent jerkiness. + const Ogre::Degree epsilon (0.5); + if (absDiff < epsilon) + return true; + + Ogre::Radian limit = MAX_VEL_ANGULAR * MWBase::Environment::get().getFrameDuration(); + if (absDiff > limit) + diff = Ogre::Math::Sign(diff) * limit; + + actor.getClass().getMovementSettings(actor).mRotation[axis] = diff.valueRadians(); + return false; +} + bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle) { Ogre::Radian currentAngle (actor.getRefData().getPosition().rot[2]); diff --git a/apps/openmw/mwmechanics/steering.hpp b/apps/openmw/mwmechanics/steering.hpp index 9bdf7d4a3b..1c00b508db 100644 --- a/apps/openmw/mwmechanics/steering.hpp +++ b/apps/openmw/mwmechanics/steering.hpp @@ -17,6 +17,8 @@ const Ogre::Radian MAX_VEL_ANGULAR(10); /// @return have we reached the target angle? bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle); +bool smoothTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, int axis); + } #endif From 5b011e43a7a30f6d428f095031f4593e968b1f8b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 Apr 2014 19:49:09 +0200 Subject: [PATCH 039/545] Fix a crash after loading game --- apps/openmw/mwgui/hud.cpp | 8 +++++++- apps/openmw/mwgui/hud.hpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 06a228a1fb..02cc5c6a90 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -52,7 +52,7 @@ namespace MWGui , mWeaponVisible(true) , mSpellVisible(true) , mWorldMouseOver(false) - , mEnemyHealthTimer(0) + , mEnemyHealthTimer(-1) , mIsDrowning(false) , mWeaponSpellTimer(0.f) , mDrowningFlashTheta(0.f) @@ -639,4 +639,10 @@ namespace MWGui updateEnemyHealthBar(); } + void HUD::resetEnemy() + { + mEnemy = MWWorld::Ptr(); + mEnemyHealthTimer = -1; + } + } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 1645d8db01..38535630fb 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -56,6 +56,7 @@ namespace MWGui void update(); void setEnemy(const MWWorld::Ptr& enemy); + void resetEnemy(); private: MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index db19070a6e..2b98408765 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -289,6 +289,10 @@ namespace MWGui void WindowManager::setNewGame(bool newgame) { + // This method will always be called after loading a savegame or starting a new game + // Reset enemy, it could be a dangling pointer from a previous game + mHud->resetEnemy(); + if (newgame) { disallowAll(); From 91e50585ff1984f0f44a9983d38c16552f144cc7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 Apr 2014 05:17:01 +0200 Subject: [PATCH 040/545] AiWander: make sure to walk, not run --- apps/openmw/mwmechanics/aitravel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index c62c4e9702..024656b38a 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -8,6 +8,7 @@ #include "steering.hpp" #include "movement.hpp" +#include "creaturestats.hpp" namespace MWMechanics { @@ -30,6 +31,8 @@ namespace MWMechanics Movement &movement = actor.getClass().getMovementSettings(actor); const ESM::Cell *cell = actor.getCell()->getCell(); + actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); + MWWorld::Ptr player = world->getPlayerPtr(); if(cell->mData.mX != player.getCell()->getCell()->mData.mX) { From f05606657cbfabbdc03fdff822149a2b83bc41c0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 Apr 2014 10:01:03 +0200 Subject: [PATCH 041/545] Correctly insert pasted text at cursor position --- apps/openmw/mwinput/inputmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index deeb934405..42362fde71 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -484,7 +484,7 @@ namespace MWInput if (text) { - edit->addText(MyGUI::UString(text)); + edit->insertText(MyGUI::UString(text), edit->getTextCursor()); SDL_free(text); } } From cd1b4218e79f7c7cad2d7ff32962eb281deb01d4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 03:15:50 +0200 Subject: [PATCH 042/545] Fix dynamically placed objects being discarded when loading game --- apps/openmw/mwworld/cellstore.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 6bc7657e4d..bbd968a7b2 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -52,7 +52,7 @@ namespace iter!=collection.mList.end(); ++iter) { if (iter->mData.getCount()==0 && iter->mRef.mRefNum.mContentFile==-1) - continue; // deleted file that did not came from a content file -> ignore + continue; // deleted reference that did not come from a content file -> ignore RecordType state; iter->save (state); @@ -72,13 +72,17 @@ namespace RecordType state; state.load (reader); - std::map::const_iterator iter = - contentFileMap.find (state.mRef.mRefNum.mContentFile); + // If the reference came from a content file, make sure this content file is loaded + if (state.mRef.mRefNum.mContentFile != -1) + { + std::map::const_iterator iter = + contentFileMap.find (state.mRef.mRefNum.mContentFile); - if (iter==contentFileMap.end()) - return; // content file has been removed -> skip + if (iter==contentFileMap.end()) + return; // content file has been removed -> skip - state.mRef.mRefNum.mContentFile = iter->second; + state.mRef.mRefNum.mContentFile = iter->second; + } if (!MWWorld::LiveCellRef::checkState (state)) return; // not valid anymore with current content files -> skip From 6eca5ac4bbab19dcf2a2a751431a655108718d45 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 07:46:19 +0200 Subject: [PATCH 043/545] Fixes #1296: Streamlined cellChanged detection --- apps/openmw/engine.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 508b195e92..03361408cf 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -59,9 +59,6 @@ void OMW::Engine::executeLocalScripts() MWScript::InterpreterContext interpreterContext ( &script.second.getRefData().getLocals(), script.second); MWBase::Environment::get().getScriptManager()->run (script.first, interpreterContext); - - if (MWBase::Environment::get().getWorld()->hasCellChanged()) - break; } localScripts.setIgnore (MWWorld::Ptr()); @@ -101,15 +98,10 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // global scripts MWBase::Environment::get().getScriptManager()->getGlobalScripts().run(); - bool changed = MWBase::Environment::get().getWorld()->hasCellChanged(); - // local scripts - executeLocalScripts(); // This does not handle the case where a global script causes a - // cell change, followed by a cell change in a local script during - // the same frame. + executeLocalScripts(); - if (changed) // keep change flag for another frame, if cell changed happened in local script - MWBase::Environment::get().getWorld()->markCellAsUnchanged(); + MWBase::Environment::get().getWorld()->markCellAsUnchanged(); if (!paused) MWBase::Environment::get().getWorld()->advanceTime( From b13b25dd1b1a94c13b61f569051382f7218304a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 11:03:17 +0200 Subject: [PATCH 044/545] Fixes #1295: Support partial matches in Cell filter --- apps/openmw/mwdialogue/filter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 18ae7dd1b0..b1c700e315 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -111,8 +111,14 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const // check cell if (!info.mCell.empty()) - if (!Misc::StringUtils::ciEqual(player.getCell()->getCell()->mName, info.mCell)) + { + // supports partial matches, just like getPcCell + const std::string& playerCell = player.getCell()->getCell()->mName; + bool match = playerCell.length()>=info.mCell.length() && + Misc::StringUtils::ciEqual(playerCell.substr (0, info.mCell.length()), info.mCell); + if (!match) return false; + } return true; } From 45d2a00717a504d65679978954876120f9ec00ca Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 11:36:27 +0200 Subject: [PATCH 045/545] Fixes #1293: Allow interpolation type 0 in case of 0 keys --- apps/openmw/mwrender/npcanimation.cpp | 3 ++- components/nif/niffile.hpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a09a581910..14f5cc4e7f 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -68,7 +68,8 @@ namespace MWRender float HeadAnimationTime::getValue() const { - // TODO: Handle eye blinking (time is in the text keys) + // TODO use time from text keys (Talk Start/Stop, Blink Start/Stop) + // TODO: Handle eye blinking if (MWBase::Environment::get().getSoundManager()->sayDone(mReference)) return 0; else diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 79e1cc2a52..d4b042726f 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -199,6 +199,11 @@ struct KeyListT { key.mContinuity = nif->getFloat(); } } + else if (mInterpolationType == 0) + { + if (count != 0) + nif->file->fail("Interpolation type 0 doesn't work with keys"); + } else nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } From ef39b0f6abb7fb6de34fa0934398798a09a0f9fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 11:41:44 +0200 Subject: [PATCH 046/545] Fixes #1291: Faction rank saving issue A value of 0 is the first rank, -1 means not a member --- apps/openmw/mwmechanics/npcstats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index e11e3b0c48..819c2701c7 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -491,7 +491,7 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state) if (iter->second.mExpelled) mExpelled.insert (iter->first); - if (iter->second.mRank) + if (iter->second.mRank >= 0) mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank)); if (iter->second.mReputation) From f921f2e7db8e62cb1f1588b26b2969a4286855a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 12:04:37 +0200 Subject: [PATCH 047/545] Make PcRaiseRank, PcLowerRank and PcJoinFaction properly accept references instead of using the actor that the player talked to last. This also solves a potential crash when no actor has been talked to yet, e.g. immediately after loading a savegame. --- apps/openmw/mwbase/dialoguemanager.hpp | 3 --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 5 ---- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 3 --- apps/openmw/mwscript/docs/vmformat.txt | 5 +++- apps/openmw/mwscript/statsextensions.cpp | 25 ++++++++++++------- components/compiler/extensions0.cpp | 6 ++--- components/compiler/opcodes.hpp | 4 +++ 7 files changed, 27 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index 3d70fdc6a7..e1d1246c84 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -45,9 +45,6 @@ namespace MWBase virtual void goodbye() = 0; - virtual MWWorld::Ptr getActor() const = 0; - ///< Return the actor the player is currently talking to. - virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const = 0; //calbacks for the GUI diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 88f1302bbf..32535f33e2 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -468,11 +468,6 @@ namespace MWDialogue mIsInChoice = true; } - MWWorld::Ptr DialogueManager::getActor() const - { - return mActor; - } - void DialogueManager::goodbye() { mIsInChoice = true; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index b9284dc1af..a2e31e791f 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -68,9 +68,6 @@ namespace MWDialogue virtual void goodbye(); - virtual MWWorld::Ptr getActor() const; - ///< Return the actor the player is currently talking to. - virtual bool checkServiceRefused (); virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 70186a089b..ceea344665 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -54,7 +54,10 @@ op 0x20025: AiFollowCell, explicit reference op 0x20026: ModRegion op 0x20027: RemoveSoulGem op 0x20028: RemoveSoulGem, explicit reference -opcodes 0x20029-0x3ffff unused +op 0x20029: PCRaiseRank, explicit reference +op 0x2002a: PCLowerRank, explicit reference +op 0x2002b: PCJoinFaction, explicit reference +opcodes 0x2002c-0x3ffff unused Segment 4: (not implemented yet) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 80467f58ad..36083e4b0a 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -29,10 +29,8 @@ namespace { - std::string getDialogueActorFaction() + std::string getDialogueActorFaction(MWWorld::Ptr actor) { - MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor(); - const MWMechanics::NpcStats &stats = MWWorld::Class::get (actor).getNpcStats (actor); if (stats.getFactionRanks().empty()) @@ -523,6 +521,7 @@ namespace MWScript } }; + template class OpPCJoinFaction : public Interpreter::Opcode1 { public: @@ -533,7 +532,8 @@ namespace MWScript if(arg0==0) { - factionID = getDialogueActorFaction(); + MWWorld::Ptr actor = R()(runtime); + factionID = getDialogueActorFaction(actor); } else { @@ -552,6 +552,7 @@ namespace MWScript } }; + template class OpPCRaiseRank : public Interpreter::Opcode1 { public: @@ -562,7 +563,8 @@ namespace MWScript if(arg0==0) { - factionID = getDialogueActorFaction(); + MWWorld::Ptr actor = R()(runtime); + factionID = getDialogueActorFaction(actor); } else { @@ -585,6 +587,7 @@ namespace MWScript } }; + template class OpPCLowerRank : public Interpreter::Opcode1 { public: @@ -595,7 +598,8 @@ namespace MWScript if(arg0==0) { - factionID = getDialogueActorFaction(); + MWWorld::Ptr actor = R()(runtime); + factionID = getDialogueActorFaction(actor); } else { @@ -1180,9 +1184,12 @@ namespace MWScript interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell); interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell); - interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRank,new OpPCRaiseRank); - interpreter.installSegment3(Compiler::Stats::opcodePCLowerRank,new OpPCLowerRank); - interpreter.installSegment3(Compiler::Stats::opcodePCJoinFaction,new OpPCJoinFaction); + interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRank,new OpPCRaiseRank); + interpreter.installSegment3(Compiler::Stats::opcodePCLowerRank,new OpPCLowerRank); + interpreter.installSegment3(Compiler::Stats::opcodePCJoinFaction,new OpPCJoinFaction); + interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRankExplicit,new OpPCRaiseRank); + interpreter.installSegment3(Compiler::Stats::opcodePCLowerRankExplicit,new OpPCLowerRank); + interpreter.installSegment3(Compiler::Stats::opcodePCJoinFactionExplicit,new OpPCJoinFaction); interpreter.installSegment3(Compiler::Stats::opcodeGetPCRank,new OpGetPCRank); interpreter.installSegment3(Compiler::Stats::opcodeGetPCRankExplicit,new OpGetPCRank); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 78b6409f22..531fe29590 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -409,9 +409,9 @@ namespace Compiler opcodeResurrectExplicit); extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit); - extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank); - extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank); - extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction); + extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank, opcodePCRaiseRankExplicit); + extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank, opcodePCLowerRankExplicit); + extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction, opcodePCJoinFactionExplicit); extensions.registerInstruction ("moddisposition","l",opcodeModDisposition, opcodeModDispositionExplicit); extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition, diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 1dbdbf7e72..27ee182cf1 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -330,6 +330,10 @@ namespace Compiler const int opcodePCRaiseRank = 0x2000b; const int opcodePCLowerRank = 0x2000c; const int opcodePCJoinFaction = 0x2000d; + const int opcodePCRaiseRankExplicit = 0x20029; + const int opcodePCLowerRankExplicit = 0x2002a; + const int opcodePCJoinFactionExplicit = 0x2002b; + const int opcodeGetPCRank = 0x2000e; const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeModDisposition = 0x200014d; From ddb0496dca76d7aa357f20feabc857abc74dc151 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Apr 2014 13:11:27 +0200 Subject: [PATCH 048/545] replaced return value of removeDocument with a signal --- apps/opencs/editor.cpp | 7 +++++++ apps/opencs/editor.hpp | 2 ++ apps/opencs/model/doc/documentmanager.cpp | 8 ++++---- apps/opencs/model/doc/documentmanager.hpp | 6 ++++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index de68098395..f13c85e73e 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -39,6 +39,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)), this, SLOT (documentAdded (CSMDoc::Document *))); + connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()), + this, SLOT (lastDocumentDeleted())); connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ())); connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ())); @@ -290,4 +292,9 @@ std::auto_ptr CS::Editor::setupGraphics() void CS::Editor::documentAdded (CSMDoc::Document *document) { mViewManager.addView (document); +} + +void CS::Editor::lastDocumentDeleted() +{ + exit (0); } \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 53afee0484..d1825e5af3 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -87,6 +87,8 @@ namespace CS void documentAdded (CSMDoc::Document *document); + void lastDocumentDeleted(); + private: QString mIpcServerName; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 51774e4ffa..b8372eb4c5 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -53,17 +53,18 @@ void CSMDoc::DocumentManager::addDocument (const std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); if (iter==mDocuments.end()) - throw std::runtime_error ("removing invalid document"); + throw std::runtime_error ("removing invalid document"); mDocuments.erase (iter); delete document; - return mDocuments.empty(); + if (mDocuments.empty()) + emit lastDocumentDeleted(); } void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir) @@ -80,5 +81,4 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std:: { removeDocument (document); /// \todo report error - /// \todo handle removeDocument returning true } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index c30c83c066..1af18a1484 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -43,8 +43,8 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. - bool removeDocument (Document *document); - ///< \return last document removed? + void removeDocument (Document *document); + ///< Emits the lastDocumentDeleted signal, if applicable. void setResourceDir (const boost::filesystem::path& parResDir); @@ -66,6 +66,8 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); void loadRequest (Document *document, bool _new); + + void lastDocumentDeleted(); }; } From 30666f2cce17357336b70507ef9428dd4e433f77 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 13:42:32 +0200 Subject: [PATCH 049/545] Fixes #1297: Store global map markers in savegame --- apps/openmw/mwgui/mapwindow.cpp | 37 ++++++-- apps/openmw/mwgui/mapwindow.hpp | 3 + apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- apps/openmw/mwrender/globalmap.cpp | 126 ++++++++++--------------- apps/openmw/mwrender/globalmap.hpp | 7 +- components/esm/globalmap.cpp | 17 ++++ components/esm/globalmap.hpp | 3 + 7 files changed, 104 insertions(+), 91 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 1cc9610df4..aa48631e41 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -14,6 +14,8 @@ #include "../mwrender/globalmap.hpp" +#include "../components/esm/globalmap.hpp" + #include "widgets.hpp" namespace MWGui @@ -436,7 +438,6 @@ namespace MWGui worldY * mGlobalMapRender->getHeight()+6, 12, 12); - static int _counter=0; MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget("ButtonImage", widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast(_counter)); @@ -452,6 +453,11 @@ namespace MWGui markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("Caption_TextOneLine", name); + + CellId cell; + cell.first = x; + cell.second = y; + mMarkers.push_back(cell); } void MapWindow::cellExplored(int x, int y) @@ -580,6 +586,7 @@ namespace MWGui void MapWindow::clear() { + mMarkers.clear(); mGlobalMapRender->clear(); while (mEventBoxGlobal->getChildCount()) @@ -590,19 +597,31 @@ namespace MWGui void MapWindow::write(ESM::ESMWriter &writer) { - mGlobalMapRender->write(writer); + ESM::GlobalMap map; + mGlobalMapRender->write(map); + + map.mMarkers = mMarkers; + + writer.startRecord(ESM::REC_GMAP); + map.save(writer); + writer.endRecord(ESM::REC_GMAP); } void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type) { - std::vector > exploredCells; - mGlobalMapRender->readRecord(reader, type, exploredCells); - - for (std::vector >::iterator it = exploredCells.begin(); it != exploredCells.end(); ++it) + if (type == ESM::REC_GMAP) { - const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get().search(it->first, it->second); - if (cell && !cell->mName.empty()) - addVisitedLocation(cell->mName, it->first, it->second); + ESM::GlobalMap map; + map.load(reader); + + mGlobalMapRender->read(map); + + for (std::vector::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it) + { + const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get().search(it->first, it->second); + if (cell && !cell->mName.empty()) + addVisitedLocation(cell->mName, it->first, it->second); + } } } } diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 2494775513..0b549147c6 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -55,6 +55,9 @@ namespace MWGui bool mChanged; bool mFogOfWar; + typedef std::pair CellId; + std::vector mMarkers; + std::vector mMapWidgets; std::vector mFogWidgets; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2b98408765..0457fcb599 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -187,7 +187,7 @@ namespace MWGui MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); - SDL_ShowCursor(false); + //SDL_ShowCursor(false); mCursorManager->setEnabled(true); diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 76ad1890fa..0537ed5160 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -231,9 +231,8 @@ namespace MWRender mOverlayTexture->getBuffer()->blitFromMemory(pb); } - void GlobalMap::write(ESM::ESMWriter &writer) + void GlobalMap::write(ESM::GlobalMap& map) { - ESM::GlobalMap map; map.mBounds.mMinX = mMinX; map.mBounds.mMaxX = mMaxX; map.mBounds.mMinY = mMinY; @@ -244,95 +243,68 @@ namespace MWRender Ogre::DataStreamPtr encoded = image.encode("png"); map.mImageData.resize(encoded->size()); encoded->read(&map.mImageData[0], encoded->size()); - - writer.startRecord(ESM::REC_GMAP); - map.save(writer); - writer.endRecord(ESM::REC_GMAP); } - void GlobalMap::readRecord(ESM::ESMReader &reader, int32_t type, std::vector >& exploredCells) + void GlobalMap::read(ESM::GlobalMap& map) { - if (type == ESM::REC_GMAP) - { - ESM::GlobalMap map; - map.load(reader); + const ESM::GlobalMap::Bounds& bounds = map.mBounds; - const ESM::GlobalMap::Bounds& bounds = map.mBounds; + if (bounds.mMaxX-bounds.mMinX <= 0) + return; + if (bounds.mMaxY-bounds.mMinY <= 0) + return; - if (bounds.mMaxX-bounds.mMinX <= 0) - return; - if (bounds.mMaxY-bounds.mMinY <= 0) - return; + if (bounds.mMinX > bounds.mMaxX + || bounds.mMinY > bounds.mMaxY) + throw std::runtime_error("invalid map bounds"); - if (bounds.mMinX > bounds.mMaxX - || bounds.mMinY > bounds.mMaxY) - throw std::runtime_error("invalid map bounds"); + Ogre::Image image; + Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&map.mImageData[0], map.mImageData.size())); + image.load(stream, "png"); - Ogre::Image image; - Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&map.mImageData[0], map.mImageData.size())); - image.load(stream, "png"); + int xLength = (bounds.mMaxX-bounds.mMinX+1); + int yLength = (bounds.mMaxY-bounds.mMinY+1); - int xLength = (bounds.mMaxX-bounds.mMinX+1); - int yLength = (bounds.mMaxY-bounds.mMinY+1); + // Size of one cell in image space + int cellImageSizeSrc = image.getWidth() / xLength; + if (int(image.getHeight() / yLength) != cellImageSizeSrc) + throw std::runtime_error("cell size must be quadratic"); - // Size of one cell in image space - int cellImageSizeSrc = image.getWidth() / xLength; - if (int(image.getHeight() / yLength) != cellImageSizeSrc) - throw std::runtime_error("cell size must be quadratic"); + // If cell bounds of the currently loaded content and the loaded savegame do not match, + // we need to resize source/dest boxes to accommodate + // This means nonexisting cells will be dropped silently + int cellImageSizeDst = 24; - // Determine which cells were explored by reading the image data - for (int x=0; x < xLength; ++x) - { - for (int y=0; y < yLength; ++y) - { - unsigned int imageX = (x) * cellImageSizeSrc; - // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is - unsigned int imageY = (yLength - (y + 1)) * cellImageSizeSrc; + // Completely off-screen? -> no need to blit anything + if (bounds.mMaxX < mMinX + || bounds.mMaxY < mMinY + || bounds.mMinX > mMaxX + || bounds.mMinY > mMaxY) + return; - assert(imageX < image.getWidth()); - assert(imageY < image.getHeight()); + int leftDiff = (mMinX - bounds.mMinX); + int topDiff = (bounds.mMaxY - mMaxY); + int rightDiff = (bounds.mMaxX - mMaxX); + int bottomDiff = (mMinY - bounds.mMinY); + Ogre::Image::Box srcBox ( std::max(0, leftDiff * cellImageSizeSrc), + std::max(0, topDiff * cellImageSizeSrc), + std::min(image.getWidth(), image.getWidth() - rightDiff * cellImageSizeSrc), + std::min(image.getHeight(), image.getHeight() - bottomDiff * cellImageSizeSrc)); - if (image.getColourAt(imageX, imageY, 0).a > 0) - exploredCells.push_back(std::make_pair(x+bounds.mMinX,y+bounds.mMinY)); - } - } + Ogre::Image::Box destBox ( std::max(0, -leftDiff * cellImageSizeDst), + std::max(0, -topDiff * cellImageSizeDst), + std::min(mOverlayTexture->getWidth(), mOverlayTexture->getWidth() + rightDiff * cellImageSizeDst), + std::min(mOverlayTexture->getHeight(), mOverlayTexture->getHeight() + bottomDiff * cellImageSizeDst)); - // If cell bounds of the currently loaded content and the loaded savegame do not match, - // we need to resize source/dest boxes to accommodate - // This means nonexisting cells will be dropped silently - int cellImageSizeDst = 24; + // Looks like there is no interface for blitting from memory with src/dst boxes. + // So we create a temporary texture for blitting. + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual("@temp", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(), + image.getHeight(), 0, Ogre::PF_A8B8G8R8); + tex->loadImage(image); - // Completely off-screen? -> no need to blit anything - if (bounds.mMaxX < mMinX - || bounds.mMaxY < mMinY - || bounds.mMinX > mMaxX - || bounds.mMinY > mMaxY) - return; + mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); - int leftDiff = (mMinX - bounds.mMinX); - int topDiff = (bounds.mMaxY - mMaxY); - int rightDiff = (bounds.mMaxX - mMaxX); - int bottomDiff = (mMinY - bounds.mMinY); - Ogre::Image::Box srcBox ( std::max(0, leftDiff * cellImageSizeSrc), - std::max(0, topDiff * cellImageSizeSrc), - std::min(image.getWidth(), image.getWidth() - rightDiff * cellImageSizeSrc), - std::min(image.getHeight(), image.getHeight() - bottomDiff * cellImageSizeSrc)); - - Ogre::Image::Box destBox ( std::max(0, -leftDiff * cellImageSizeDst), - std::max(0, -topDiff * cellImageSizeDst), - std::min(mOverlayTexture->getWidth(), mOverlayTexture->getWidth() + rightDiff * cellImageSizeDst), - std::min(mOverlayTexture->getHeight(), mOverlayTexture->getHeight() + bottomDiff * cellImageSizeDst)); - - // Looks like there is no interface for blitting from memory with src/dst boxes. - // So we create a temporary texture for blitting. - Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual("@temp", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(), - image.getHeight(), 0, Ogre::PF_A8B8G8R8); - tex->loadImage(image); - - mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); - - Ogre::TextureManager::getSingleton().remove("@temp"); - } + Ogre::TextureManager::getSingleton().remove("@temp"); } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 5fe878cd45..6075d042e9 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -12,8 +12,7 @@ namespace Loading namespace ESM { - class ESMWriter; - class ESMReader; + class GlobalMap; } namespace MWRender @@ -40,8 +39,8 @@ namespace MWRender /// Clears the overlay void clear(); - void write (ESM::ESMWriter& writer); - void readRecord (ESM::ESMReader& reader, int32_t type, std::vector >& exploredCells); + void write (ESM::GlobalMap& map); + void read (ESM::GlobalMap& map); private: std::string mCacheDir; diff --git a/components/esm/globalmap.cpp b/components/esm/globalmap.cpp index 1fa5f907e0..f17c071ffc 100644 --- a/components/esm/globalmap.cpp +++ b/components/esm/globalmap.cpp @@ -14,6 +14,15 @@ void ESM::GlobalMap::load (ESMReader &esm) esm.getSubHeader(); mImageData.resize(esm.getSubSize()); esm.getExact(&mImageData[0], mImageData.size()); + + while (esm.isNextSub("MRK_")) + { + esm.getSubHeader(); + CellId cell; + esm.getT(cell.first); + esm.getT(cell.second); + mMarkers.push_back(cell); + } } void ESM::GlobalMap::save (ESMWriter &esm) const @@ -23,4 +32,12 @@ void ESM::GlobalMap::save (ESMWriter &esm) const esm.startSubRecord("DATA"); esm.write(&mImageData[0], mImageData.size()); esm.endRecord("DATA"); + + for (std::vector::const_iterator it = mMarkers.begin(); it != mMarkers.end(); ++it) + { + esm.startSubRecord("MRK_"); + esm.writeT(it->first); + esm.writeT(it->second); + esm.endRecord("MRK_"); + } } diff --git a/components/esm/globalmap.hpp b/components/esm/globalmap.hpp index 5d036c736f..158f70a6e5 100644 --- a/components/esm/globalmap.hpp +++ b/components/esm/globalmap.hpp @@ -25,6 +25,9 @@ namespace ESM std::vector mImageData; + typedef std::pair CellId; + std::vector mMarkers; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; From afe624bd07822ca9ee9fd6ba120c9036b4ffe743 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 26 Apr 2014 08:12:57 -0400 Subject: [PATCH 050/545] Cleaned up update in Actors.cpp Removed unnecessary for loops --- apps/openmw/mwmechanics/actors.cpp | 35 +++++++++--------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ca37b152cf..267170214f 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -852,39 +852,29 @@ namespace MWMechanics // Note, the new hit object for this frame may be set by CharacterController::update -> Animation::runAnimation // (below) iter->first.getClass().getCreatureStats(iter->first).setLastHitObject(std::string()); - } - // AI and magic effects update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) - { + // AI and magic effects update if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); if(iter->first.getTypeName() == typeid(ESM::NPC).name()) updateNpc(iter->first, duration, paused); } - } - // Looping magic VFX update - // Note: we need to do this before any of the animations are updated. - // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), - // so updating VFX immediately after that would just remove the particle effects instantly. - // There needs to be a magic effect update in between. - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + // Looping magic VFX update + // Note: we need to do this before any of the animations are updated. + // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), + // so updating VFX immediately after that would just remove the particle effects instantly. + // There needs to be a magic effect update in between. iter->second->updateContinuousVfx(); - // Animation/movement update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) - { + // Animation/movement update if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).mMagnitude > 0) iter->second->skipAnim(); iter->second->update(duration); - } - // Kill dead actors - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) - { + // Kill dead actors const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); @@ -912,13 +902,8 @@ namespace MWMechanics continue; } - // Make sure spell effects with CasterLinked flag are removed - // TODO: would be nice not to do this all the time... - for(PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) - { - MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); - spells.purge(iter->first.getRefData().getHandle()); - } + MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); + spells.purge(iter->first.getRefData().getHandle()); // FIXME: see http://bugs.openmw.org/issues/869 MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); From 48b2c0073b1dceecb940eed8e54ff061833bc773 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 26 Apr 2014 08:29:28 -0400 Subject: [PATCH 051/545] fix, sorry for being sloppy.. --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 267170214f..a08cd9c338 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -845,7 +845,7 @@ namespace MWMechanics { if(!paused) { - // Reset data from previous frame + // Update actors from previous frame for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { // Reset last hit object, which is only valid for one frame @@ -902,7 +902,7 @@ namespace MWMechanics continue; } - MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); + MWMechanics::ActiveSpells& spells = iter->first.getClass().getCreatureStats(iter->first).getActiveSpells(); spells.purge(iter->first.getRefData().getHandle()); // FIXME: see http://bugs.openmw.org/issues/869 From d5dd864404c783464cb089ba9eeca8d1b48eb6ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 14:33:45 +0200 Subject: [PATCH 052/545] Fixes #1236: Disable all controls while playing movie --- apps/openmw/mwinput/inputmanagerimp.cpp | 15 +++++++++------ apps/openmw/mwinput/inputmanagerimp.hpp | 4 +++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 42362fde71..8095b0d05d 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -114,6 +114,7 @@ namespace MWInput , mTimeIdle(0.f) , mOverencumberedMessageDelay(0.f) , mAlwaysRunActive(false) + , mControlsDisabled(false) { Ogre::RenderWindow* window = ogre.getWindow (); @@ -265,19 +266,20 @@ namespace MWInput void InputManager::update(float dt, bool disableControls, bool disableEvents) { + mControlsDisabled = disableControls; + mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible()); mInputManager->capture(disableEvents); // inject some fake mouse movement to force updating MyGUI's widget states MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); - // update values of channels (as a result of pressed keys) - if (!disableControls) - mInputBinder->update(dt); - - if (disableControls) + if (mControlsDisabled) return; + // update values of channels (as a result of pressed keys) + mInputBinder->update(dt); + bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console; @@ -509,7 +511,8 @@ namespace MWInput } } - mInputBinder->keyPressed (arg); + if (!mControlsDisabled) + mInputBinder->keyPressed (arg); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 5eb355566b..3787a9c071 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -68,7 +68,7 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); - virtual void update(float dt, bool disableControls, bool disableEvents=false); + virtual void update(float dt, bool disableControls=false, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } @@ -145,6 +145,8 @@ namespace MWInput bool mInvertY; + bool mControlsDisabled; + float mCameraSensitivity; float mUISensitivity; float mCameraYMultiplier; From f0c5d1a7e1eba636e3b0baa9ead6d00e70b059b3 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 26 Apr 2014 10:03:56 -0400 Subject: [PATCH 053/545] Revert "Checks the state of the passed sneak variable" This reverts commit 4a4c08946c5b75701a5eb9b3e878c0727380909d. --- apps/openmw/mwworld/player.cpp | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 8588547d28..f4ca5ee27f 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -134,25 +134,17 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - if (sneak == true) - { - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - // Find all the actors who might be able to see the player - std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), - esmStore.get().find("fSneakUseDist")->getInt(), neighbors); - for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - { - if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - { - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); - break; - } - } - if (neighbors.size() == 0) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); - } + // Find all the actors who might be able to see the player + std::vector neighbors; + MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + esmStore.get().find("fSneakUseDist")->getInt(), neighbors); + for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) + if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); + if (!neighbors.size()) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); } void Player::yaw(float yaw) From b28dfa94cd5b92f47d9adef8ee06d7a1908cc7a1 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 26 Apr 2014 10:07:56 -0400 Subject: [PATCH 054/545] Revert 4a4c089..f0c5d1a This rolls back to commit 4a4c08946c5b75701a5eb9b3e878c0727380909d. --- apps/openmw/mwmechanics/actors.cpp | 37 +++++++++++++++++++++--------- apps/openmw/mwworld/player.cpp | 28 ++++++++++++++-------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a08cd9c338..ca37b152cf 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -845,36 +845,46 @@ namespace MWMechanics { if(!paused) { - // Update actors from previous frame + // Reset data from previous frame for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { // Reset last hit object, which is only valid for one frame // Note, the new hit object for this frame may be set by CharacterController::update -> Animation::runAnimation // (below) iter->first.getClass().getCreatureStats(iter->first).setLastHitObject(std::string()); + } - // AI and magic effects update + // AI and magic effects update + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + { if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); if(iter->first.getTypeName() == typeid(ESM::NPC).name()) updateNpc(iter->first, duration, paused); } + } - // Looping magic VFX update - // Note: we need to do this before any of the animations are updated. - // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), - // so updating VFX immediately after that would just remove the particle effects instantly. - // There needs to be a magic effect update in between. + // Looping magic VFX update + // Note: we need to do this before any of the animations are updated. + // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), + // so updating VFX immediately after that would just remove the particle effects instantly. + // There needs to be a magic effect update in between. + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) iter->second->updateContinuousVfx(); - // Animation/movement update + // Animation/movement update + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + { if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).mMagnitude > 0) iter->second->skipAnim(); iter->second->update(duration); + } - // Kill dead actors + // Kill dead actors + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) + { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); @@ -902,8 +912,13 @@ namespace MWMechanics continue; } - MWMechanics::ActiveSpells& spells = iter->first.getClass().getCreatureStats(iter->first).getActiveSpells(); - spells.purge(iter->first.getRefData().getHandle()); + // Make sure spell effects with CasterLinked flag are removed + // TODO: would be nice not to do this all the time... + for(PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) + { + MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); + spells.purge(iter->first.getRefData().getHandle()); + } // FIXME: see http://bugs.openmw.org/issues/869 MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index f4ca5ee27f..8588547d28 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -134,17 +134,25 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + if (sneak == true) + { + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - // Find all the actors who might be able to see the player - std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), - esmStore.get().find("fSneakUseDist")->getInt(), neighbors); - for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); - if (!neighbors.size()) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(sneak); + // Find all the actors who might be able to see the player + std::vector neighbors; + MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + esmStore.get().find("fSneakUseDist")->getInt(), neighbors); + for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) + { + if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) + { + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + break; + } + } + if (neighbors.size() == 0) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + } } void Player::yaw(float yaw) From ab33e78b6799c8875d262048651787ee83a8f044 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 26 Apr 2014 09:40:58 -0500 Subject: [PATCH 055/545] Added RangeView class files --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/settings/booleanview.hpp | 2 +- apps/opencs/view/settings/rangeview.cpp | 91 +++++++++++++++++++++++ apps/opencs/view/settings/rangeview.hpp | 44 +++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/settings/rangeview.cpp create mode 100644 apps/opencs/view/settings/rangeview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8ab44243dc..680c8f8b7b 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -95,6 +95,7 @@ opencs_units (view/settings booleanview textview listview + rangeview resizeablestackedwidget ) diff --git a/apps/opencs/view/settings/booleanview.hpp b/apps/opencs/view/settings/booleanview.hpp index 52f9e05f1f..55ef0bb085 100644 --- a/apps/opencs/view/settings/booleanview.hpp +++ b/apps/opencs/view/settings/booleanview.hpp @@ -1,5 +1,5 @@ #ifndef CSVSETTINGS_BOOLEANVIEW_HPP -#define CSVSETTINGS_BOOELANVIEW_HPP +#define CSVSETTINGS_BOOLEANVIEW_HPP #include #include diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp new file mode 100644 index 0000000000..411e12775b --- /dev/null +++ b/apps/opencs/view/settings/rangeview.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include +#include +#include + +#include + +#include "rangeview.hpp" +#include "../../model/settings/setting.hpp" + +CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, + Page *parent) + : View (setting, parent) +{ + foreach (const QString &value, setting->declaredValues()) + { + QAbstractButton *button = 0; + + if (isMultiValue()) + button = new QCheckBox (value, this); + else + button = new QRadioButton (value, this); + + connect (button, SIGNAL (clicked (bool)), + this, SLOT (slotToggled (bool))); + + button->setObjectName (value); + + addWidget (button); + + mButtons[value] = button; + } +} + +void CSVSettings::RangeView::slotToggled (bool state) +{ + //test only for true to avoid multiple selection updates with radiobuttons + if (!isMultiValue() && !state) + return; + + QStringList values; + + foreach (QString key, mButtons.keys()) + { + if (mButtons.value(key)->isChecked()) + values.append (key); + } + setSelectedValues (values, false); + + View::updateView(); +} + +void CSVSettings::RangeView::updateView (bool signalUpdate) const +{ + + QStringList values = selectedValues(); + + foreach (const QString &buttonName, mButtons.keys()) + { + QAbstractButton *button = mButtons[buttonName]; + + //if the value is not found in the list, the widget is checked false + bool buttonValue = values.contains(buttonName); + + //skip if the butotn value will not change + if (button->isChecked() == buttonValue) + continue; + + //disable autoexclusive if it's enabled and we're setting + //the button value to false + bool switchExclusive = (!buttonValue && button->autoExclusive()); + + if (switchExclusive) + button->setAutoExclusive (false); + + button->setChecked (buttonValue); + + if (switchExclusive) + button->setAutoExclusive(true); + } + View::updateView (signalUpdate); +} + +CSVSettings::RangeView *CSVSettings::RangeViewFactory::createView + (CSMSettings::Setting *setting, + Page *parent) +{ + return new RangeView (setting, parent); +} diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp new file mode 100644 index 0000000000..1df0c7bd63 --- /dev/null +++ b/apps/opencs/view/settings/rangeview.hpp @@ -0,0 +1,44 @@ +#ifndef CSVSETTINGS_RANGEVIEW_HPP +#define CSVSETTINGS_RANGEVIEW_HPP + +#include +#include + +#include "view.hpp" +#include "../../model/settings/support.hpp" + +class QStringListModel; + +namespace CSVSettings +{ + class RangeView : public View + { + Q_OBJECT + + QMap mButtons; + + public: + explicit RangeView (CSMSettings::Setting *setting, + Page *parent); + + protected: + void updateView (bool signalUpdate = true) const; + + private slots: + void slotToggled (bool state); + }; + + class RangeViewFactory : public QObject, public IViewFactory + { + Q_OBJECT + + public: + explicit RangeViewFactory (QWidget *parent = 0) + : QObject (parent) + {} + + RangeView *createView (CSMSettings::Setting *setting, + Page *parent); + }; +} +#endif // CSVSETTINGS_RANGEVIEW_HPP From 04964595efb1d1ab55a68f49c43172aae54de16b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Apr 2014 16:44:20 +0200 Subject: [PATCH 056/545] Fixes #1270, Fixes #1201: Update active weapon/spell icons every frame --- apps/openmw/mwgui/quickkeysmenu.cpp | 1 - apps/openmw/mwgui/spellwindow.cpp | 1 - apps/openmw/mwmechanics/character.cpp | 4 ---- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 13 +++++++++++++ apps/openmw/mwmechanics/spellcasting.cpp | 1 - apps/openmw/mwstate/statemanagerimp.cpp | 7 ------- apps/openmw/mwworld/inventorystore.cpp | 15 --------------- apps/openmw/mwworld/worldimp.cpp | 1 - 8 files changed, 13 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 4c0faeac1f..dc72269099 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -325,7 +325,6 @@ namespace MWGui } store.setSelectedEnchantItem(it); - MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); } } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index b052739bda..a00c2480e2 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -322,7 +322,6 @@ namespace MWGui } store.setSelectedEnchantItem(it); - MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); updateSpells(); } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 93c789af1a..4cabaee094 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -740,10 +740,6 @@ bool CharacterController::updateWeaponState() MWBase::Environment::get().getWindowManager()->messageBox(resultMessage); if(!resultSound.empty()) MWBase::Environment::get().getSoundManager()->playSound(resultSound, 1.0f, 1.0f); - - // Set again, just to update the charge bar - if(item.getRefData().getCount()) - MWBase::Environment::get().getWindowManager()->setSelectedWeapon(item); } else if (ammunition) { diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2b1fdd365c..ff9bacf7b1 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -325,6 +325,19 @@ namespace MWMechanics winMgr->updateSkillArea(); winMgr->setValue("level", stats.getLevel()); + + // Update the equipped weapon icon + MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weapon == inv.end()) + winMgr->unsetSelectedWeapon(); + else + winMgr->setSelectedWeapon(*weapon); + + // Update the selected spell icon + MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); + if (enchantItem != inv.end()) + winMgr->setSelectedEnchantItem(*enchantItem); } if (mUpdatePlayer) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 9a6cd6b896..21aee5b98a 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -575,7 +575,6 @@ namespace MWMechanics { if (mCaster.getRefData().getHandle() == "player") { - MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); // Set again to show the modified charge mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 3); } } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 0b3f3438da..acf1cf3f2d 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -335,13 +335,6 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - //Update the weapon icon in the hud with whatever the player is currently holding. - MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr); - MWWorld::ContainerStoreIterator item = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - - if (item != invStore.end()) - MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*item); - ESM::CellId cellId = ptr.getCell()->getCell()->getCellId(); MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition()); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index e002762939..9610171b23 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -8,7 +8,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" -#include "../mwbase/windowmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwmechanics/npcstats.hpp" @@ -150,10 +149,6 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite fireEquipmentChangedEvent(); updateMagicEffects(actor); - - // Update HUD icon for player weapon - if (slot == MWWorld::InventoryStore::Slot_CarriedRight) - MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*getSlot(slot)); } void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) @@ -494,7 +489,6 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor && *mSelectedEnchantItem == item && actor.getRefData().getHandle() == "player") { mSelectedEnchantItem = end(); - MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); } updateRechargingItems(); @@ -532,18 +526,9 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c if (script != "") (*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0); - // Update HUD icon when removing player weapon or selected enchanted item. - // We have to check for both as the weapon could also be the enchanted item. - if (slot == MWWorld::InventoryStore::Slot_CarriedRight) - { - // weapon - MWBase::Environment::get().getWindowManager()->unsetSelectedWeapon(); - } if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it)) { - // enchanted item mSelectedEnchantItem = end(); - MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 87bdd2f9d2..46bb4db581 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2056,7 +2056,6 @@ namespace MWWorld { // Update the GUI only when called on the player MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager(); - windowManager->unsetSelectedWeapon(); if (werewolf) { From dbe1307de0914d3eb6ecda03b59bf624366dca85 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sat, 26 Apr 2014 22:21:20 +0400 Subject: [PATCH 057/545] code refining + minor fixes --- apps/openmw/mwmechanics/aicombat.cpp | 35 ++++++++++++++-------------- apps/openmw/mwmechanics/steering.cpp | 26 +-------------------- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8a3c23aefd..fa7ef28a34 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -175,23 +175,23 @@ namespace MWMechanics mStrike = false; } - const MWWorld::Class &cls = actor.getClass(); + const MWWorld::Class &actorCls = actor.getClass(); const ESM::Weapon *weapon = NULL; MWMechanics::WeaponType weaptype; float weapRange, weapSpeed = 1.0f; - actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); + actorCls.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); // Get weapon characteristics - if (actor.getClass().hasInventoryStore(actor)) + if (actorCls.hasInventoryStore(actor)) { - MWMechanics::DrawState_ state = actor.getClass().getCreatureStats(actor).getDrawState(); + MWMechanics::DrawState_ state = actorCls.getCreatureStats(actor).getDrawState(); if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - actor.getClass().getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + actorCls.getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon); //Get weapon speed and range MWWorld::ContainerStoreIterator weaponSlot = - MWMechanics::getActiveWeapon(cls.getCreatureStats(actor), cls.getInventoryStore(actor), &weaptype); + MWMechanics::getActiveWeapon(actorCls.getCreatureStats(actor), actorCls.getInventoryStore(actor), &weaptype); if (weaptype == WeapType_HandToHand) { @@ -216,7 +216,7 @@ namespace MWMechanics float rangeMelee; float rangeCloseUp; bool distantCombat = false; - if (weaptype==WeapType_BowAndArrow || weaptype==WeapType_Crossbow || weaptype==WeapType_Thrown) + if (weaptype == WeapType_BowAndArrow || weaptype == WeapType_Crossbow || weaptype == WeapType_Thrown) { rangeMelee = 1000; // TODO: should depend on archer skill rangeCloseUp = 0; // not needed in ranged combat @@ -236,15 +236,15 @@ namespace MWMechanics bool isStuck = false; float speed = 0.0f; - if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = cls.getSpeed(actor)) / 10.0f) + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f) isStuck = true; mLastPos = pos; // check if can move along z-axis bool canMoveByZ; - if(canMoveByZ = ((actor.getClass().isNpc() || actor.getClass().canSwim(actor)) && MWBase::Environment::get().getWorld()->isSwimming(actor)) - || (actor.getClass().canFly(actor) && MWBase::Environment::get().getWorld()->isFlying(actor))) + if(canMoveByZ = ((actorCls.isNpc() || actorCls.canSwim(actor)) && MWBase::Environment::get().getWorld()->isSwimming(actor)) + || (actorCls.canFly(actor) && MWBase::Environment::get().getWorld()->isFlying(actor))) { // determine vertical angle to target mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); @@ -266,16 +266,15 @@ namespace MWMechanics //Melee: stop running and attack mMovement.mPosition[1] = 0; - // When attacking with a weapon, choose between slash, thrust or chop - if (mStrike && actor.getClass().hasInventoryStore(actor)) - chooseBestAttack(weapon, mMovement); + // set slash/thrust/chop attack + if (mStrike) chooseBestAttack(weapon, mMovement); if(mMovement.mPosition[0] || mMovement.mPosition[1]) { mTimerCombatMove = 0.1f + 0.1f * static_cast(rand())/RAND_MAX; mCombatMove = true; } - else if(actor.getClass().isNpc() && (!distantCombat || (distantCombat && rangeMelee/5))) + else if(actorCls.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeMelee/2))) { //apply sideway movement (kind of dodging) with some probability if(static_cast(rand())/RAND_MAX < 0.25) @@ -309,7 +308,7 @@ namespace MWMechanics || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) && (inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))) { - if(speed == 0.0f) speed = cls.getSpeed(actor); + if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); @@ -370,15 +369,15 @@ namespace MWMechanics mReadyToAttack = false; } - if(distToTarget > rangeMelee) + if(distToTarget > rangeMelee && !distantCombat) { //special run attack; it shouldn't affect melee combat tactics - if(actor.getClass().getMovementSettings(actor).mPosition[1] == 1) + if(actorCls.getMovementSettings(actor).mPosition[1] == 1) { //check if actor can overcome the distance = distToTarget - attackerWeapRange //less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing) //then start attacking - float speed1 = cls.getSpeed(actor); + float speed1 = actorCls.getSpeed(actor); float speed2 = mTarget.getClass().getSpeed(mTarget); if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0 && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) diff --git a/apps/openmw/mwmechanics/steering.cpp b/apps/openmw/mwmechanics/steering.cpp index d10733b36f..0a8a37ecbb 100644 --- a/apps/openmw/mwmechanics/steering.cpp +++ b/apps/openmw/mwmechanics/steering.cpp @@ -41,31 +41,7 @@ bool smoothTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, int axis) bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle) { - Ogre::Radian currentAngle (actor.getRefData().getPosition().rot[2]); - Ogre::Radian diff (targetAngle - currentAngle); - if (diff >= Ogre::Degree(180)) - { - // Turning the other way would be a better idea - diff = diff-Ogre::Degree(360); - } - else if (diff <= Ogre::Degree(-180)) - { - diff = Ogre::Degree(360)-diff; - } - Ogre::Radian absDiff = Ogre::Math::Abs(diff); - - // The turning animation actually moves you slightly, so the angle will be wrong again. - // Use epsilon to prevent jerkiness. - const Ogre::Degree epsilon (0.5); - if (absDiff < epsilon) - return true; - - Ogre::Radian limit = MAX_VEL_ANGULAR * MWBase::Environment::get().getFrameDuration(); - if (absDiff > limit) - diff = Ogre::Math::Sign(diff) * limit; - - actor.getClass().getMovementSettings(actor).mRotation[2] = diff.valueRadians(); - return false; + return smoothTurn(actor, targetAngle, 2); } } From c2b692e124f0eb3079499d393cfc2a86bfa134ec Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 26 Apr 2014 17:21:53 -0400 Subject: [PATCH 058/545] getActorsFollowing/Fighting no longer returns dead actors --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 804ec7a41e..d51b02a158 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1029,7 +1029,7 @@ namespace MWMechanics const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); - if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) + if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow && !stats.isDead()) { MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); if(package->getFollowedActor() == actor.getCellRef().mRefID) @@ -1051,7 +1051,7 @@ namespace MWMechanics const MWWorld::Class &cls = MWWorld::Class::get(*iter); CreatureStats &stats = cls.getCreatureStats(*iter); - if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) + if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat && !stats.isDead()) { MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); if(package->getTargetId() == actor.getCellRef().mRefID) From 1fb2c8d87bf505ccf003415e2fafcefb218e4688 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 26 Apr 2014 19:47:47 +1000 Subject: [PATCH 059/545] NPC turning is less hacky but still not perfect. NPC's should walk away after a period of non-action by the player (vanilla behaviour) - not yet implemented. --- apps/openmw/mwmechanics/aiwander.cpp | 41 +++++++++++++++++----------- apps/openmw/mwmechanics/aiwander.hpp | 1 + 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ad94be0eb4..2d1fbdd78f 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -1,6 +1,7 @@ #include "aiwander.hpp" #include +#include #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -211,7 +212,7 @@ namespace MWMechanics // Reduce the turning animation glitch by using a *HUGE* value of // epsilon... TODO: a proper fix might be in either the physics or the // animation subsystem - if (zTurn(actor, Ogre::Degree(mTargetAngle), Ogre::Degree(12))) + if (zTurn(actor, Ogre::Degree(mTargetAngle), Ogre::Degree(5))) mRotate = false; } @@ -333,18 +334,7 @@ namespace MWMechanics if(mChooseAction) { mPlayedIdle = 0; - unsigned short idleRoll = 0; - - for(unsigned int counter = 0; counter < mIdle.size(); counter++) - { - unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter]; - unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier)); - if(randSelect < idleChance && randSelect > idleRoll) - { - mPlayedIdle = counter+2; - idleRoll = randSelect; - } - } + getRandomIdle(); // NOTE: sets mPlayedIdle with a random selection if(!mPlayedIdle && mDistance) { @@ -395,6 +385,8 @@ namespace MWMechanics mMoveNow = false; mWalking = false; mObstacleCheck.clear(); + mIdleNow = true; + getRandomIdle(); } if(!mRotate) @@ -402,11 +394,11 @@ namespace MWMechanics Ogre::Vector3 dir = playerPos - actorPos; float length = dir.length(); - // FIXME: horrible hack float faceAngle = Ogre::Radian(Ogre::Math::ACos(dir.y / length) * ((Ogre::Math::ASin(dir.x / length).valueRadians()>0)?1.0:-1.0)).valueDegrees(); + float actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll().valueDegrees(); // an attempt at reducing the turning animation glitch - if(abs(faceAngle) > 10) + if(abs(abs(faceAngle) - abs(actorAngle)) >= 5) // TODO: is there a better way? { mTargetAngle = faceAngle; mRotate = true; @@ -432,7 +424,8 @@ namespace MWMechanics } // Check if idle animation finished - if(!checkIdle(actor, mPlayedIdle)) + // FIXME: don't stay forever + if(!checkIdle(actor, mPlayedIdle) && playerDistSqr > helloDistance*helloDistance) { mPlayedIdle = 0; mIdleNow = false; @@ -586,5 +579,21 @@ namespace MWMechanics else return false; } + + void AiWander::getRandomIdle() + { + unsigned short idleRoll = 0; + + for(unsigned int counter = 0; counter < mIdle.size(); counter++) + { + unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter]; + unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier)); + if(randSelect < idleChance && randSelect > idleRoll) + { + mPlayedIdle = counter+2; + idleRoll = randSelect; + } + } + } } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index fe14abeb61..35ecc83e04 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -26,6 +26,7 @@ namespace MWMechanics void stopWalking(const MWWorld::Ptr& actor); void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); + void getRandomIdle(); int mDistance; // how far the actor can wander from the spawn point int mDuration; From e8210c92c688d527db9a24df475161fef259ac47 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 04:27:26 +0200 Subject: [PATCH 060/545] Fixes #1240: Don't hardcode drowning time --- apps/openmw/mwbase/windowmanager.hpp | 5 +++-- apps/openmw/mwgui/hud.cpp | 4 ++-- apps/openmw/mwgui/hud.hpp | 5 +++-- apps/openmw/mwgui/windowmanagerimp.cpp | 4 ++-- apps/openmw/mwgui/windowmanagerimp.hpp | 5 +++-- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 6 ++++-- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index e3bd428e22..eb84741c4a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -156,8 +156,9 @@ namespace MWBase virtual void setValue (const std::string& id, int value) = 0; /// Set time left for the player to start drowning (update the drowning bar) - /// @param time value from [0,20] - virtual void setDrowningTimeLeft (float time) =0; + /// @param time time left to start drowning + /// @param maxTime how long we can be underwater (in total) until drowning starts + virtual void setDrowningTimeLeft (float time, float maxTime) = 0; virtual void setPlayerClass (const ESM::Class &class_) = 0; ///< set current class of player diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 02cc5c6a90..946259e106 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -203,9 +203,9 @@ namespace MWGui } } - void HUD::setDrowningTimeLeft(float time) + void HUD::setDrowningTimeLeft(float time, float maxTime) { - size_t progress = time/20.0*200.0; + size_t progress = time/maxTime*200.0; mDrowning->setProgressPosition(progress); bool isDrowning = (progress == 0); diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 38535630fb..973ac07457 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -22,8 +22,9 @@ namespace MWGui void setBatchCount(unsigned int count); /// Set time left for the player to start drowning - /// @param time value from [0,20] - void setDrowningTimeLeft(float time); + /// @param time time left to start drowning + /// @param maxTime how long we can be underwater (in total) until drowning starts + void setDrowningTimeLeft(float time, float maxTime); void setDrowningBarVisible(bool visible); void setHmsVisible(bool visible); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 0457fcb599..2ed1131269 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -625,9 +625,9 @@ namespace MWGui mStatsWindow->setValue (id, value); } - void WindowManager::setDrowningTimeLeft (float time) + void WindowManager::setDrowningTimeLeft (float time, float maxTime) { - mHud->setDrowningTimeLeft(time); + mHud->setDrowningTimeLeft(time, maxTime); } void WindowManager::setPlayerClass (const ESM::Class &class_) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index ab9770a41b..074cb3208d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -166,8 +166,9 @@ namespace MWGui virtual void setValue (const std::string& id, int value); /// Set time left for the player to start drowning (update the drowning bar) - /// @param time value from [0,20] - virtual void setDrowningTimeLeft (float time); + /// @param time time left to start drowning + /// @param maxTime how long we can be underwater (in total) until drowning starts + virtual void setDrowningTimeLeft (float time, float maxTime); virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index ff9bacf7b1..34402977ce 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -298,13 +298,15 @@ namespace MWMechanics if(stats.getTimeToStartDrowning() != mWatchedStats.getTimeToStartDrowning()) { + const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get() + .find("fHoldBreathTime")->getFloat(); mWatchedStats.setTimeToStartDrowning(stats.getTimeToStartDrowning()); - if(stats.getTimeToStartDrowning() >= 20.0f) + if(stats.getTimeToStartDrowning() >= fHoldBreathTime) winMgr->setDrowningBarVisibility(false); else { winMgr->setDrowningBarVisibility(true); - winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning()); + winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning(), fHoldBreathTime); } } From 0d711e51b00463308d455510d8668322fec81099 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 26 Apr 2014 21:32:36 -0500 Subject: [PATCH 061/545] Converted SettingType enums to indicate widget type. --- apps/opencs/model/settings/setting.cpp | 17 ++++++------ apps/opencs/model/settings/support.hpp | 29 +++++++++++++++------ apps/opencs/model/settings/usersettings.cpp | 18 ++++++------- apps/opencs/view/settings/page.cpp | 2 ++ apps/opencs/view/settings/rangeview.cpp | 4 +++ apps/opencs/view/settings/settingwindow.cpp | 12 +++++---- 6 files changed, 51 insertions(+), 31 deletions(-) diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index 6c7e780879..ca682b454d 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -12,15 +12,14 @@ CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, { buildDefaultSetting(); - int vType = static_cast (typ); + int settingType = static_cast (typ); - if ((vType % 2) == 0) - setProperty (Property_IsMultiValue, - QVariant(true).toString()); - else - vType--; + //even-numbered setting types are multi-valued + if ((settingType % 2) == 0) + setProperty (Property_IsMultiValue, QVariant(true).toString()); - setProperty (Property_ViewType, QVariant (vType / 2).toString()); + //view type is related to setting type by an order of magnitude + setProperty (Property_ViewType, QVariant (settingType / 10).toString()); setProperty (Property_Page, pageName); setProperty (Property_Name, settingName); setProperty (Property_DeclaredValues, values); @@ -267,9 +266,9 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting) { - stream << setting.properties(); + // stream << setting.properties(); - stream << setting.proxies(); + // stream << setting.proxies(); return stream; } diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index abc86a0cb6..ce808587fc 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -47,14 +47,27 @@ namespace CSMSettings enum SettingType { - Type_MultiBool = 0, - Type_SingleBool = 1, - Type_MultiList = 2, - Type_SingleList = 3, - Type_MultiRange = 4, - Type_SingleRange = 5, - Type_MultiText = 6, - Type_SingleText = 7 + /* + * 0 - 9 - Boolean widgets + * 10-19 - List widgets + * 21-29 - Range widgets + * 31-39 - Text widgets + * + * Each range corresponds to a View_Type enum by a factor of 10. + * + * Even-numbered values are single-value widgets + * Odd-numbered values are multi-valued widgets + */ + + Type_CheckBox = 0, + Type_RadioButton = 1, + Type_ListView = 10, + Type_ComboBox = 11, + Type_SpinBox = 21, + Type_Slider = 23, + Type_Dial = 24, + Type_TextArea = 30, + Type_LineEdit = 31 }; enum MergeMethod diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 808fbfc70f..2f8e8098da 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -47,8 +47,8 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() { QString section = "Window Size"; { - Setting *width = createSetting (Type_SingleText, section, "Width"); - Setting *height = createSetting (Type_SingleText, section, "Height"); + Setting *width = createSetting (Type_LineEdit, section, "Width"); + Setting *height = createSetting (Type_LineEdit, section, "Height"); width->setWidgetWidth (5); height->setWidgetWidth (5); @@ -65,7 +65,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() /* *Create the proxy setting for predefined values */ - Setting *preDefined = createSetting (Type_SingleList, section, + Setting *preDefined = createSetting (Type_ComboBox, section, "Pre-Defined", QStringList() << "640 x 480" @@ -94,11 +94,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() QStringList values = QStringList() << defaultValue << "Icon Only" << "Text Only"; - Setting *rsd = createSetting (Type_SingleBool, + Setting *rsd = createSetting (Type_RadioButton, section, "Record Status Display", values); - Setting *ritd = createSetting (Type_SingleBool, + Setting *ritd = createSetting (Type_RadioButton, section, "Referenceable ID Type Display", values); @@ -110,24 +110,24 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() { //create three setting objects, specifying the basic widget type, //the setting view name, the page name, and the default value - Setting *masterBoolean = createSetting (Type_SingleBool, section, + Setting *masterBoolean = createSetting (Type_RadioButton, section, "Master Proxy", QStringList() << "Profile One" << "Profile Two" << "Profile Three" << "Profile Four" ); - Setting *slaveBoolean = createSetting (Type_MultiBool, section, + Setting *slaveBoolean = createSetting (Type_CheckBox, section, "Proxy Checkboxes", QStringList() << "One" << "Two" << "Three" << "Four" << "Five" ); - Setting *slaveSingleText = createSetting (Type_SingleText, section, + Setting *slaveSingleText = createSetting (Type_LineEdit, section, "Proxy TextBox 1" ); - Setting *slaveMultiText = createSetting (Type_SingleText, section, + Setting *slaveMultiText = createSetting (Type_LineEdit, section, "ProxyTextBox 2" ); diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index a5711c8f81..e674458739 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -3,6 +3,7 @@ #include "booleanview.hpp" #include "textview.hpp" #include "listview.hpp" +#include "rangeview.hpp" #include "../../model/settings/usersettings.hpp" #include "../../model/settings/connector.hpp" @@ -85,4 +86,5 @@ void CSVSettings::Page::buildFactories() mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this); mViewFactories[ViewType_Text] = new TextViewFactory (this); mViewFactories[ViewType_List] = new ListViewFactory (this); + mViewFactories[ViewType_Range] = new RangeViewFactory (this); } diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 411e12775b..12b71d28fb 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -10,6 +10,9 @@ #include "rangeview.hpp" #include "../../model/settings/setting.hpp" + +#include + CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, Page *parent) : View (setting, parent) @@ -87,5 +90,6 @@ CSVSettings::RangeView *CSVSettings::RangeViewFactory::createView (CSMSettings::Setting *setting, Page *parent) { + qDebug() << "adding a new range view"; return new RangeView (setting, parent); } diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index 9283bbf51b..8eccee6464 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -14,16 +14,18 @@ CSVSettings::SettingWindow::SettingWindow(QWidget *parent) void CSVSettings::SettingWindow::createPages() { + qDebug () << "getting page map"; CSMSettings::SettingPageMap pageMap = mModel->settingPageMap(); QList connectedSettings; - + qDebug () << "iterating map"; foreach (const QString &pageName, pageMap.keys()) - { + { + qDebug() << "iterating page: " << pageName; QList pageSettings = pageMap.value (pageName); - + qDebug () << "appending page: " << pageName << "; settings = " << pageSettings.size(); mPages.append (new Page (pageName, pageSettings, this)); - + qDebug() << "iterating page " << pageName << " settings"; for (int i = 0; i < pageSettings.size(); i++) { CSMSettings::Setting *setting = pageSettings.at(i); @@ -32,7 +34,7 @@ void CSVSettings::SettingWindow::createPages() connectedSettings.append (setting); } } - + qDebug() << "making connections"; if (!connectedSettings.isEmpty()) createConnections(connectedSettings); } From 985af15a12f2645c1fe47f25c67e460d2f4d39da Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 26 Apr 2014 21:43:42 -0500 Subject: [PATCH 062/545] removed qdebug references --- apps/opencs/view/settings/rangeview.cpp | 1 - apps/opencs/view/settings/settingwindow.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 12b71d28fb..2bb5863bc4 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -90,6 +90,5 @@ CSVSettings::RangeView *CSVSettings::RangeViewFactory::createView (CSMSettings::Setting *setting, Page *parent) { - qDebug() << "adding a new range view"; return new RangeView (setting, parent); } diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index 8eccee6464..7bd0b228e4 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -14,18 +14,16 @@ CSVSettings::SettingWindow::SettingWindow(QWidget *parent) void CSVSettings::SettingWindow::createPages() { - qDebug () << "getting page map"; CSMSettings::SettingPageMap pageMap = mModel->settingPageMap(); QList connectedSettings; - qDebug () << "iterating map"; + foreach (const QString &pageName, pageMap.keys()) { - qDebug() << "iterating page: " << pageName; QList pageSettings = pageMap.value (pageName); - qDebug () << "appending page: " << pageName << "; settings = " << pageSettings.size(); + mPages.append (new Page (pageName, pageSettings, this)); - qDebug() << "iterating page " << pageName << " settings"; + for (int i = 0; i < pageSettings.size(); i++) { CSMSettings::Setting *setting = pageSettings.at(i); @@ -34,7 +32,7 @@ void CSVSettings::SettingWindow::createPages() connectedSettings.append (setting); } } - qDebug() << "making connections"; + if (!connectedSettings.isEmpty()) createConnections(connectedSettings); } From 93b76a603b5128ebd4da0787f6ea77bad2ccb0c9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 05:40:07 +0200 Subject: [PATCH 063/545] Fixes #1100: Looting a corpse is no longer considered stealing --- apps/openmw/mwgui/companionitemmodel.cpp | 4 ++-- apps/openmw/mwgui/companionitemmodel.hpp | 2 +- apps/openmw/mwgui/container.cpp | 13 ++++++++----- apps/openmw/mwgui/containeritemmodel.cpp | 2 +- apps/openmw/mwgui/containeritemmodel.hpp | 2 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 18 ++++++++++++++++-- apps/openmw/mwgui/inventoryitemmodel.hpp | 5 ++++- apps/openmw/mwgui/itemmodel.cpp | 10 ++++++++-- apps/openmw/mwgui/itemmodel.hpp | 8 ++++++-- apps/openmw/mwgui/tradeitemmodel.cpp | 9 +++------ apps/openmw/mwworld/containerstore.cpp | 15 ++++++++++++--- 11 files changed, 62 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwgui/companionitemmodel.cpp b/apps/openmw/mwgui/companionitemmodel.cpp index bb6cf28006..9c4ea2d291 100644 --- a/apps/openmw/mwgui/companionitemmodel.cpp +++ b/apps/openmw/mwgui/companionitemmodel.cpp @@ -10,7 +10,7 @@ namespace MWGui { } - void CompanionItemModel::copyItem (const ItemStack& item, size_t count) + void CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) { if (mActor.getClass().isNpc()) { @@ -18,7 +18,7 @@ namespace MWGui stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); } - InventoryItemModel::copyItem(item, count); + InventoryItemModel::copyItem(item, count, setNewOwner); } void CompanionItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/companionitemmodel.hpp b/apps/openmw/mwgui/companionitemmodel.hpp index c11e11c325..49c58c8963 100644 --- a/apps/openmw/mwgui/companionitemmodel.hpp +++ b/apps/openmw/mwgui/companionitemmodel.hpp @@ -13,7 +13,7 @@ namespace MWGui public: CompanionItemModel (const MWWorld::Ptr& actor); - virtual void copyItem (const ItemStack& item, size_t count); + virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner); virtual void removeItem (const ItemStack& item, size_t count); }; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 34ac8d9f4d..5856473388 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -13,6 +13,7 @@ #include "../mwworld/containerstore.hpp" #include "../mwmechanics/pickpocket.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "countdialog.hpp" #include "tradewindow.hpp" @@ -84,8 +85,7 @@ namespace MWGui // otherwise, do the transfer if (targetModel != mSourceModel) { - targetModel->copyItem(mItem, mDraggedCount); - mSourceModel->removeItem(mItem, mDraggedCount); + mSourceModel->moveItem(mItem, mDraggedCount, targetModel); } mSourceModel->update(); @@ -292,8 +292,7 @@ namespace MWGui if (!onTakeItem(item, item.mCount)) break; - playerModel->copyItem(item, item.mCount); - mModel->removeItem(item, item.mCount); + mModel->moveItem(item, item.mCount, playerModel); } MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); @@ -341,7 +340,11 @@ namespace MWGui } else { - MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count); + // Looting a dead corpse is considered OK + if (mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead()) + return true; + else + MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count); } return true; } diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index bcb8440bfb..e702c073dd 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -71,7 +71,7 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) return -1; } -void ContainerItemModel::copyItem (const ItemStack& item, size_t count) +void ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source)) diff --git a/apps/openmw/mwgui/containeritemmodel.hpp b/apps/openmw/mwgui/containeritemmodel.hpp index 22595582ef..4b9b4ff991 100644 --- a/apps/openmw/mwgui/containeritemmodel.hpp +++ b/apps/openmw/mwgui/containeritemmodel.hpp @@ -21,7 +21,7 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count); + virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual void update(); diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index 97e1e9a2b1..c0847929b3 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -4,6 +4,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwmechanics/creaturestats.hpp" + namespace MWGui { @@ -38,11 +40,11 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item) return -1; } -void InventoryItemModel::copyItem (const ItemStack& item, size_t count) +void InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor)) throw std::runtime_error("Item to copy needs to be from a different container!"); - mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor); + mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); } @@ -57,6 +59,18 @@ void InventoryItemModel::removeItem (const ItemStack& item, size_t count) throw std::runtime_error("Not enough items in the stack to remove"); } +void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) +{ + bool setNewOwner = false; + + // Are you dead? Then you wont need that anymore + if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead()) + setNewOwner = true; + + otherModel->copyItem(item, count, setNewOwner); + removeItem(item, count); +} + void InventoryItemModel::update() { MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor); diff --git a/apps/openmw/mwgui/inventoryitemmodel.hpp b/apps/openmw/mwgui/inventoryitemmodel.hpp index 23856395e8..78dcc9497d 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.hpp +++ b/apps/openmw/mwgui/inventoryitemmodel.hpp @@ -15,9 +15,12 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count); + virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); + /// Move items from this model to \a otherModel. + virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + virtual void update(); protected: diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 58e89c4fc4..7b2ea4d4a3 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -71,16 +71,22 @@ namespace MWGui { } + void ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) + { + otherModel->copyItem(item, count); + removeItem(item, count); + } + ProxyItemModel::~ProxyItemModel() { delete mSourceModel; } - void ProxyItemModel::copyItem (const ItemStack& item, size_t count) + void ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { // no need to use mapToSource since itemIndex refers to an index in the sourceModel - mSourceModel->copyItem (item, count); + mSourceModel->copyItem (item, count, setNewOwner); } void ProxyItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/itemmodel.hpp b/apps/openmw/mwgui/itemmodel.hpp index 47aaf79e85..684771b86b 100644 --- a/apps/openmw/mwgui/itemmodel.hpp +++ b/apps/openmw/mwgui/itemmodel.hpp @@ -55,7 +55,11 @@ namespace MWGui virtual void update() = 0; - virtual void copyItem (const ItemStack& item, size_t count) = 0; + /// Move items from this model to \a otherModel. + virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + + /// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner? + virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0; virtual void removeItem (const ItemStack& item, size_t count) = 0; private: @@ -69,7 +73,7 @@ namespace MWGui { public: virtual ~ProxyItemModel(); - virtual void copyItem (const ItemStack& item, size_t count); + virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual ModelIndex getIndex (ItemStack item); diff --git a/apps/openmw/mwgui/tradeitemmodel.cpp b/apps/openmw/mwgui/tradeitemmodel.cpp index c9c65a1524..ad18a13e81 100644 --- a/apps/openmw/mwgui/tradeitemmodel.cpp +++ b/apps/openmw/mwgui/tradeitemmodel.cpp @@ -120,14 +120,11 @@ namespace MWGui if (i == sourceModel->getItemCount()) throw std::runtime_error("The borrowed item disappeared"); - // reset owner before copying + // reset owner while copying, but only for items bought by the player + bool setNewOwner = (mMerchant.isEmpty()); const ItemStack& item = sourceModel->getItem(i); - std::string owner = item.mBase.getCellRef().mOwner; - if (mMerchant.isEmpty()) // only for items bought by player - item.mBase.getCellRef().mOwner = ""; // copy the borrowed items to our model - copyItem(item, it->mCount); - item.mBase.getCellRef().mOwner = owner; + copyItem(item, it->mCount, setNewOwner); // then remove them from the source model sourceModel->removeItem(item, it->mCount); } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index bd0704724f..dd2f2f3c10 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -199,16 +199,25 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.getCellRef().mPos.pos[1] = 0; item.getCellRef().mPos.pos[2] = 0; + Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); + if (setOwner && actorPtr.getClass().isActor()) - item.getCellRef().mOwner = actorPtr.getCellRef().mRefID; + { + if (actorPtr == player) + { + // No point in setting owner to the player - NPCs will not respect this anyway + // Additionally, setting it to "player" would make those items not stack with items that don't have an owner + item.getCellRef().mOwner = ""; + } + else + item.getCellRef().mOwner = actorPtr.getCellRef().mRefID; + } std::string script = MWWorld::Class::get(item).getScript(item); if(script != "") { CellStore *cell; - Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) { cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed From d92f95f5bf6f524bafb29a0435c658e4ac4c6c86 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 05:54:19 +0200 Subject: [PATCH 064/545] Fix a stacking issue --- apps/openmw/mwworld/containerstore.cpp | 45 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index dd2f2f3c10..b1cbcc9c26 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -187,11 +187,38 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string & MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner) { - MWWorld::ContainerStoreIterator it = addImp(itemPtr, count); + Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); + + MWWorld::ContainerStoreIterator it = end(); + + if (setOwner && actorPtr.getClass().isActor()) + { + // HACK: Set owner on the original item, then reset it after we have copied it + // If we set the owner on the copied item, it would not stack correctly... + std::string oldOwner = itemPtr.getCellRef().mOwner; + if (actorPtr == player) + { + // No point in setting owner to the player - NPCs will not respect this anyway + // Additionally, setting it to "player" would make those items not stack with items that don't have an owner + itemPtr.getCellRef().mOwner = ""; + } + else + itemPtr.getCellRef().mOwner = actorPtr.getCellRef().mRefID; + + it = addImp(itemPtr, count); + + itemPtr.getCellRef().mOwner = oldOwner; + } + else + { + it = addImp(itemPtr, count); + } + + // The copy of the original item we just made MWWorld::Ptr item = *it; // we may have copied an item from the world, so reset a few things first - item.getRefData().setBaseNode(NULL); + item.getRefData().setBaseNode(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell item.getCellRef().mPos.rot[0] = 0; item.getCellRef().mPos.rot[1] = 0; item.getCellRef().mPos.rot[2] = 0; @@ -199,20 +226,6 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.getCellRef().mPos.pos[1] = 0; item.getCellRef().mPos.pos[2] = 0; - Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - - if (setOwner && actorPtr.getClass().isActor()) - { - if (actorPtr == player) - { - // No point in setting owner to the player - NPCs will not respect this anyway - // Additionally, setting it to "player" would make those items not stack with items that don't have an owner - item.getCellRef().mOwner = ""; - } - else - item.getCellRef().mOwner = actorPtr.getCellRef().mRefID; - } - std::string script = MWWorld::Class::get(item).getScript(item); if(script != "") { From dd14dec8dc3b82a89322cc46027d910c3916ff41 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 08:16:35 +0200 Subject: [PATCH 065/545] Tweak loading screen progress bar positioning to match vanilla --- files/mygui/openmw_loading_screen.layout | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_loading_screen.layout b/files/mygui/openmw_loading_screen.layout index 19649cfd21..faa0d8637a 100644 --- a/files/mygui/openmw_loading_screen.layout +++ b/files/mygui/openmw_loading_screen.layout @@ -4,13 +4,13 @@ - + - + - + From 14757a856b6077ab2f00f3fa2b94974efb776a9a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 08:17:14 +0200 Subject: [PATCH 066/545] Tweak settings window size and encumbrance bar text align --- files/mygui/openmw_settings_window.layout | 6 +++--- files/mygui/openmw_text.skin.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index e348323be5..bcf4374a46 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -3,10 +3,10 @@ - - + + - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 15287bc74e..d75abc8735 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -152,7 +152,7 @@ - + From 3161647809b31c8e97802d6fe7a058084a4acd4b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 09:12:49 +0200 Subject: [PATCH 067/545] Fix for not being able to pick up scrolls during combat This is the behaviour I observed in vanilla morrowind. --- apps/openmw/mwworld/actionread.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 433237e26a..60af3d9b9e 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -3,7 +3,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" -#include "../mwbase/world.hpp" #include "../mwworld/player.hpp" @@ -24,7 +23,12 @@ namespace MWWorld void ActionRead::executeImp (const MWWorld::Ptr& actor) { - if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat + //Ensure we're not in combat + if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat() + // Reading in combat is still allowed if the scroll/book is not in the player inventory yet + // (since otherwise, there would be no way to pick it up) + && getTarget().getContainerStore() == &actor.getClass().getContainerStore(actor) + ) { MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage4}"); return; } From dac0b7090abc046a938f38de5597987455c8bdec Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 09:14:14 +0200 Subject: [PATCH 068/545] Get rid of bigbars.png and smallbars.png Changed loading bar colour to match vanilla --- apps/openmw/mwgui/hud.cpp | 2 +- files/mygui/CMakeLists.txt | 2 - files/mygui/bigbars.png | Bin 387 -> 0 bytes files/mygui/openmw_hud.layout | 2 +- files/mygui/openmw_hud_energybar.skin.xml | 28 ++++++----- files/mygui/openmw_progress.skin.xml | 57 +++++++++++++--------- files/mygui/smallbars.png | Bin 2985 -> 0 bytes 7 files changed, 53 insertions(+), 38 deletions(-) delete mode 100644 files/mygui/bigbars.png delete mode 100644 files/mygui/smallbars.png diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 946259e106..be4a9a14ee 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -625,7 +625,7 @@ namespace MWGui if (mIsDrowning) { float intensity = (cos(mDrowningFlashTheta) + 1.0f) / 2.0f; - mDrowningFlash->setColour(MyGUI::Colour(intensity, intensity, intensity)); + mDrowningFlash->setColour(MyGUI::Colour(intensity, 0, 0)); } } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index ef223a6177..2135f4dde3 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -4,7 +4,6 @@ set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui) set(MYGUI_FILES - bigbars.png black.png core.skin core.xml @@ -81,7 +80,6 @@ set(MYGUI_FILES openmw_companion_window.layout openmw_savegame_dialog.layout openmw_recharge_dialog.layout - smallbars.png DejaVuLGCSansMono.ttf markers.png ../launcher/images/openmw.png diff --git a/files/mygui/bigbars.png b/files/mygui/bigbars.png deleted file mode 100644 index ee91da19e3bc85b5601375d9e84fb45384da5ced..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 387 zcmV-}0et?6P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RU0tXKrA*QRh;Q#;u6-h)vR4C7N zl1)wnF${%2XN-{8vEl|uY&aALV8>}VBdAn`cJkxLqBD~e)GQ)>vg15I+uolaSdS;O z4xR{+j1Vb@0?xPZO7ygk(gv6Z_#7j-sl)L<7zq3n0&bJdA+IK&N*D&Xp!xQ zm%Cm72Q7U&ZUiI|`A|`Xb>+oiu2iT2p7=&^h=0hH)z$sw+v@{GnQNl3+)V8T! z-#p#FUf7FtZaXao0A?Qbv`*13P5fi;V0_I#qrLf>*DV8Plhih^C#ktCkfeaK>Mj&x h-3y1lAs1=a;TPg - + diff --git a/files/mygui/openmw_hud_energybar.skin.xml b/files/mygui/openmw_hud_energybar.skin.xml index f10908d7b0..d5078e994d 100644 --- a/files/mygui/openmw_hud_energybar.skin.xml +++ b/files/mygui/openmw_hud_energybar.skin.xml @@ -19,24 +19,28 @@ - - - + + + + - - - + + + + - - - + + + + - - - + + + + diff --git a/files/mygui/openmw_progress.skin.xml b/files/mygui/openmw_progress.skin.xml index f5418e3f88..a09011e10d 100644 --- a/files/mygui/openmw_progress.skin.xml +++ b/files/mygui/openmw_progress.skin.xml @@ -2,35 +2,48 @@ - - - + + + + - - - + + + + - - - + + + + - - - + + + + + - - - + + + + + + + + + + + - + @@ -39,7 +52,7 @@ - + @@ -47,7 +60,7 @@ - + @@ -55,15 +68,15 @@ - + - - + + @@ -82,7 +95,7 @@ - + diff --git a/files/mygui/smallbars.png b/files/mygui/smallbars.png deleted file mode 100644 index 3c007a55cea32c99bbb4acb41e27419cc0290d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2985 zcmV;a3s&@rP)Oz@Z0f2-7z;ux~O9+4z06=<WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bXU&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWwr)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>={htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!hR|78Dq|Iq-afF%KE1Brn_fm;Im z_u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWi{{a60 z|De66lK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^RY2Oa|$Dm!$xI{*Lx+et)0 zR4C6~(mhTCF%X8~cLqx-K%%6er{p$VgA1jn<21CnKtxu_CQE|6YY)ZlO89d#(&HKb zjBVT3r{Ld6ZZsn$H)?r$FgMJch>Drx08!?3 zq7>4Uhqh$Qy}++RKDDra`<8RK^n;B-0UW5{ Date: Sun, 27 Apr 2014 09:28:17 +0200 Subject: [PATCH 069/545] Fixes #1241: Removed disposition-based combat conditions The information for this code came from UESP, which in turn cites a (extremely vague) section from the TES-CS help text, so no surprise that it wasn't accurate. The guard on the boat has a fight rating of 70, so with the old code it would attack on sight if the disposition is low enough. BTB-Character.esp includes something (not sure what) that drops his disposition to 35 when playing as a Khajiit, making him attack. Testing in Vanilla it appears that disposition has no effect on combat engagement at all. Even with disposition 0 and fight 70 the NPCs don't attack. Setting an NPCs fight rating to 70 or less still has a meaning, because the higher it is, the easier it becomes to raise the fight rating to 80 (by taunting, for example). --- apps/openmw/mwmechanics/actors.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 804ec7a41e..96194d2921 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -204,11 +204,6 @@ namespace MWMechanics || (fight >= 95 && d <= 3000) || (fight >= 90 && d <= 2000) || (fight >= 80 && d <= 1000) - || (fight >= 80 && disp <= 40) - || (fight >= 70 && disp <= 35 && d <= 1000) - || (fight >= 60 && disp <= 30 && d <= 1000) - || (fight >= 50 && disp == 0) - || (fight >= 40 && disp <= 10 && d <= 500) ) { bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player) From e42855d522101adc45cbc733dbe8bb96c28b652b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 Apr 2014 12:54:18 +0200 Subject: [PATCH 070/545] Minor fix for spell icon --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 34402977ce..841f617b78 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -340,6 +340,8 @@ namespace MWMechanics MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); if (enchantItem != inv.end()) winMgr->setSelectedEnchantItem(*enchantItem); + else if (winMgr->getSelectedSpell() == "") + winMgr->unsetSelectedSpell(); } if (mUpdatePlayer) From 82121e040172b4d586363e427c09f2df795e443a Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 27 Apr 2014 16:59:21 +0400 Subject: [PATCH 071/545] some checks reworked --- apps/openmw/mwclass/npc.hpp | 8 ++++++++ apps/openmw/mwmechanics/aicombat.cpp | 4 ++-- apps/openmw/mwworld/physicssystem.cpp | 5 +++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 596bf0e56b..4b9c8988ec 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -170,6 +170,14 @@ namespace MWClass virtual int getBaseGold(const MWWorld::Ptr& ptr) const; virtual bool isClass(const MWWorld::Ptr& ptr, const std::string &className) const; + + virtual bool canSwim (const MWWorld::Ptr &ptr) const { + return true; + } + + virtual bool canWalk (const MWWorld::Ptr &ptr) const { + return true; + } }; } diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 2b612d734f..42d963117c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -341,8 +341,8 @@ namespace MWMechanics // check if can move along z-axis bool canMoveByZ; - if(canMoveByZ = ((actorCls.isNpc() || actorCls.canSwim(actor)) && MWBase::Environment::get().getWorld()->isSwimming(actor)) - || (actorCls.canFly(actor) && MWBase::Environment::get().getWorld()->isFlying(actor))) + if(canMoveByZ = (actorCls.canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) + || MWBase::Environment::get().getWorld()->isFlying(actor)) { // determine vertical angle to target mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 7d531d6d3f..5bf8305ba9 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -313,8 +313,9 @@ namespace MWWorld // NOTE: stepMove modifies newPosition if successful if(stepMove(colobj, newPosition, velocity, remainingTime, engine)) { - // don't let slaughterfish move out of water after stepMove - if(ptr.getClass().canSwim(ptr) && newPosition.z > (waterlevel - halfExtents.z * 0.5)) + // don't let pure water creatures move out of water after stepMove + if((ptr.getClass().canSwim(ptr) && !ptr.getClass().canWalk(ptr)) + && newPosition.z > (waterlevel - halfExtents.z * 0.5)) newPosition = oldPosition; else // Only on the ground if there's gravity isOnGround = !(newPosition.z < waterlevel || isFlying); From ce106d3becb8b1b7739f21011578d86a76f61c7b Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 09:34:33 -0400 Subject: [PATCH 072/545] Revert "NPCs detect crime exclusively" This reverts commit 54d9615d85ae856ad4fdd2c130ac9cb0cd847c72. Conflicts: apps/openmw/mwmechanics/mechanicsmanagerimp.cpp --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2b1fdd365c..26c629fb89 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -843,7 +843,10 @@ namespace MWMechanics // Find an actor who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { +<<<<<<< HEAD +======= if (*it == ptr) continue; // not the player +>>>>>>> parent of 54d9615... NPCs detect crime exclusively // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || From b9bd4bc1265a4f4c531b1456f9a4fcf21076cd55 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 09:34:59 -0400 Subject: [PATCH 073/545] broken --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 26c629fb89..88d07cfa64 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -844,6 +844,8 @@ namespace MWMechanics for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { <<<<<<< HEAD + if ( *it == ptr + && it->getClass().isNpc()) continue; // not the player and is an NPC ======= if (*it == ptr) continue; // not the player >>>>>>> parent of 54d9615... NPCs detect crime exclusively @@ -862,7 +864,8 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if (*it1 == ptr) continue; // not the player + if ( *it == ptr + && it->getClass().isNpc()) continue; // not the player and is an NPC // TODO: Add more messages if (type == OT_Theft) From 0409e18a0e7a903a00bc4c4b0951ee7532ec0317 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 09:35:49 -0400 Subject: [PATCH 074/545] revert --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 88d07cfa64..2b1fdd365c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -843,12 +843,7 @@ namespace MWMechanics // Find an actor who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { -<<<<<<< HEAD - if ( *it == ptr - && it->getClass().isNpc()) continue; // not the player and is an NPC -======= if (*it == ptr) continue; // not the player ->>>>>>> parent of 54d9615... NPCs detect crime exclusively // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || @@ -864,8 +859,7 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if ( *it == ptr - && it->getClass().isNpc()) continue; // not the player and is an NPC + if (*it1 == ptr) continue; // not the player // TODO: Add more messages if (type == OT_Theft) From 7599b26d309bba10a22adab0abd051674a31eb5a Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 09:37:43 -0400 Subject: [PATCH 075/545] Fixed: creatures won't witness crimes and potential crash. --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2b1fdd365c..03beed5a50 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -843,7 +843,8 @@ namespace MWMechanics // Find an actor who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - if (*it == ptr) continue; // not the player + if ( *it == ptr + && it->getClass().isNpc()) continue; // not the player and is an NPC // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || @@ -859,7 +860,8 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if (*it1 == ptr) continue; // not the player + if ( *it == ptr + && it->getClass().isNpc()) continue; // not the player and is an NPC // TODO: Add more messages if (type == OT_Theft) From 52bb7c3f69914084eacd1affa8470017286a4b1d Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 09:55:38 -0400 Subject: [PATCH 076/545] fixed logic. ! --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 03beed5a50..8b87887411 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -844,7 +844,7 @@ namespace MWMechanics for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { if ( *it == ptr - && it->getClass().isNpc()) continue; // not the player and is an NPC + && !it->getClass().isNpc()) continue; // not the player and is an NPC // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || @@ -861,7 +861,7 @@ namespace MWMechanics for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { if ( *it == ptr - && it->getClass().isNpc()) continue; // not the player and is an NPC + && !it->getClass().isNpc()) continue; // not the player and is an NPC // TODO: Add more messages if (type == OT_Theft) From edbc319c424d6fd29b00338608f6e52fc2f7b644 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 27 Apr 2014 10:05:34 -0400 Subject: [PATCH 077/545] fixed logic. || --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 8b87887411..eca0c2289f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -844,7 +844,7 @@ namespace MWMechanics for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { if ( *it == ptr - && !it->getClass().isNpc()) continue; // not the player and is an NPC + || !it->getClass().isNpc()) continue; // not the player and is an NPC // Was the crime seen? if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || @@ -861,7 +861,7 @@ namespace MWMechanics for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { if ( *it == ptr - && !it->getClass().isNpc()) continue; // not the player and is an NPC + || !it->getClass().isNpc()) continue; // not the player and is an NPC // TODO: Add more messages if (type == OT_Theft) From 1b8c975d5ba62a501ff160a69ef1af7051acf816 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sun, 27 Apr 2014 19:03:33 +0200 Subject: [PATCH 078/545] minor performance improvements in apps/openmw Checking for emptiness using size() might be inefficient, because it can take linear time, while empty() is guaranteed to take only constant time. For non-primitive types, postfix ++ operators are inefficient compared to prefix ++ operators, because post-increment usually involves keeping a copy of the previous value around. --- apps/openmw/mwgui/tradewindow.cpp | 12 ++++++------ apps/openmw/mwmechanics/activespells.cpp | 4 ++-- apps/openmw/mwmechanics/aisequence.cpp | 8 ++++---- apps/openmw/mwmechanics/pathgrid.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 4 ++-- apps/openmw/mwmechanics/spells.cpp | 8 ++++---- apps/openmw/mwrender/animation.cpp | 24 ++++++++++++------------ apps/openmw/mwrender/debugging.cpp | 2 +- apps/openmw/mwrender/objects.cpp | 8 ++++---- apps/openmw/mwsound/soundmanagerimp.cpp | 2 +- apps/openmw/mwworld/actionteleport.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 1 - apps/openmw/mwworld/physicssystem.cpp | 4 ++-- apps/openmw/mwworld/player.cpp | 6 +++--- 14 files changed, 43 insertions(+), 44 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 3e15bcd78c..9cabab3e8e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -78,13 +78,13 @@ namespace MWGui } void TradeWindow::startTrade(const MWWorld::Ptr& actor) - { + { mPtr = actor; mCurrentBalance = 0; mCurrentMerchantOffer = 0; - checkTradeTime(); + checkTradeTime(); std::vector itemSources; MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); @@ -245,7 +245,7 @@ namespace MWGui // were there any items traded at all? std::vector playerBought = playerItemModel->getItemsBorrowedToUs(); std::vector merchantBought = mTradeModel->getItemsBorrowedToUs(); - if (!playerBought.size() && !merchantBought.size()) + if (playerBought.empty() && merchantBought.empty()) { // user notification MWBase::Environment::get().getWindowManager()-> @@ -476,7 +476,7 @@ namespace MWGui } // Relates to NPC gold reset delay - void TradeWindow::checkTradeTime() + void TradeWindow::checkTradeTime() { MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); double delay = boost::lexical_cast(MWBase::Environment::get().getWorld()->getStore().get().find("fBarterGoldResetDelay")->getInt()); @@ -488,14 +488,14 @@ namespace MWGui } } - void TradeWindow::updateTradeTime() + void TradeWindow::updateTradeTime() { MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr); MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); double delay = boost::lexical_cast(MWBase::Environment::get().getWorld()->getStore().get().find("fBarterGoldResetDelay")->getInt()); // If trade timestamp is within reset delay don't set - if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() && + if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() && MWBase::Environment::get().getWorld()->getTimeStamp() < sellerStats.getTradeTime() + delay) ) { sellerStats.setTradeTime(MWBase::Environment::get().getWorld()->getTimeStamp()); diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 0c5bd9afab..86db207a4a 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -206,7 +206,7 @@ namespace MWMechanics if (effectIt->mKey.mId == effectId) effectIt = it->second.mEffects.erase(effectIt); else - effectIt++; + ++effectIt; } } mSpellsChanged = true; @@ -224,7 +224,7 @@ namespace MWMechanics && it->second.mCasterHandle == actorHandle) effectIt = it->second.mEffects.erase(effectIt); else - effectIt++; + ++effectIt; } } mSpellsChanged = true; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index c67367a6c7..294c9b6a14 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -38,7 +38,7 @@ MWMechanics::AiSequence& MWMechanics::AiSequence::operator= (const AiSequence& s copy (sequence); mDone = sequence.mDone; } - + return *this; } @@ -51,7 +51,7 @@ int MWMechanics::AiSequence::getTypeId() const { if (mPackages.empty()) return -1; - + return mPackages.front()->getTypeId(); } @@ -102,7 +102,7 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) } else { - mDone = false; + mDone = false; } } } @@ -118,7 +118,7 @@ void MWMechanics::AiSequence::clear() void MWMechanics::AiSequence::stack (const AiPackage& package) { - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); it++) + for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { if(mPackages.front()->getPriority() <= package.getPriority()) { diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index cb9f051e32..82d815d681 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -296,7 +296,7 @@ namespace MWMechanics // add this edge to openset, lowest cost goes to the front // TODO: if this causes performance problems a hash table may help std::list::iterator it = openset.begin(); - for(it = openset.begin(); it!= openset.end(); it++) + for(it = openset.begin(); it!= openset.end(); ++it) { if(fScore[*it] > fScore[dest]) break; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 21aee5b98a..e6342e661a 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -401,10 +401,10 @@ namespace MWMechanics if (!exploded) MWBase::Environment::get().getWorld()->explodeSpell(mHitPosition, mTarget, effects, caster, mId, mSourceName); - if (reflectedEffects.mList.size()) + if (!reflectedEffects.mList.empty()) inflict(caster, target, reflectedEffects, range, true); - if (appliedLastingEffects.size()) + if (!appliedLastingEffects.empty()) target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, mSourceName, caster.getRefData().getHandle()); diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 21781c530c..c2bf794f19 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -129,7 +129,7 @@ namespace MWMechanics if (spell->mData.mType == ESM::Spell::ST_Disease) mSpells.erase(iter++); else - iter++; + ++iter; } } @@ -143,7 +143,7 @@ namespace MWMechanics if (spell->mData.mType == ESM::Spell::ST_Blight) mSpells.erase(iter++); else - iter++; + ++iter; } } @@ -157,7 +157,7 @@ namespace MWMechanics if (Misc::StringUtils::ciEqual(spell->mId, "corprus")) mSpells.erase(iter++); else - iter++; + ++iter; } } @@ -171,7 +171,7 @@ namespace MWMechanics if (spell->mData.mType == ESM::Spell::ST_Curse) mSpells.erase(iter++); else - iter++; + ++iter; } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index e62fee6e20..3b8b91b0e4 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -411,7 +411,7 @@ Ogre::Node *Animation::getNode(const std::string &name) NifOgre::TextKeyMap::const_iterator Animation::findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname) { NifOgre::TextKeyMap::const_iterator iter(keys.begin()); - for(;iter != keys.end();iter++) + for(;iter != keys.end();++iter) { if(iter->second.compare(0, groupname.size(), groupname) == 0 && iter->second.compare(groupname.size(), 2, ": ") == 0) @@ -424,7 +424,7 @@ NifOgre::TextKeyMap::const_iterator Animation::findGroupStart(const NifOgre::Tex bool Animation::hasAnimation(const std::string &anim) { AnimSourceList::const_iterator iter(mAnimSources.begin()); - for(;iter != mAnimSources.end();iter++) + for(;iter != mAnimSources.end();++iter) { const NifOgre::TextKeyMap &keys = (*iter)->mTextKeys; if(findGroupStart(keys, anim) != keys.end()) @@ -465,7 +465,7 @@ float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::Node stoptime = keyiter->first; break; } - keyiter++; + ++keyiter; } if(stoptime > starttime) @@ -585,13 +585,13 @@ bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, const s std::string starttag = groupname+": "+start; NifOgre::TextKeyMap::const_iterator startkey(groupstart); while(startkey != keys.end() && startkey->second != starttag) - startkey++; + ++startkey; if(startkey == keys.end() && start == "loop start") { starttag = groupname+": start"; startkey = groupstart; while(startkey != keys.end() && startkey->second != starttag) - startkey++; + ++startkey; } if(startkey == keys.end()) return false; @@ -603,7 +603,7 @@ bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, const s // The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop". // Why, just why? :( && (stopkey->second.size() < stoptag.size() || stopkey->second.substr(0,stoptag.size()) != stoptag)) - stopkey++; + ++stopkey; if(stopkey == keys.end()) return false; @@ -627,7 +627,7 @@ bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, const s state.mLoopStartTime = key->first; else if(key->second == loopstoptag) state.mLoopStopTime = key->first; - key++; + ++key; } } @@ -776,7 +776,7 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo /* Look in reverse; last-inserted source has priority. */ AnimSourceList::reverse_iterator iter(mAnimSources.rbegin()); - for(;iter != mAnimSources.rend();iter++) + for(;iter != mAnimSources.rend();++iter) { const NifOgre::TextKeyMap &textkeys = (*iter)->mTextKeys; AnimState state; @@ -795,7 +795,7 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo while(textkey != textkeys.end() && textkey->first <= state.mTime) { handleTextKey(state, groupname, textkey); - textkey++; + ++textkey; } if(state.mTime >= state.mLoopStopTime && state.mLoopCount > 0) @@ -810,7 +810,7 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo while(textkey != textkeys.end() && textkey->first <= state.mTime) { handleTextKey(state, groupname, textkey); - textkey++; + ++textkey; } } @@ -965,7 +965,7 @@ Ogre::Vector3 Animation::runAnimation(float duration) while(textkey != textkeys.end() && textkey->first <= state.mTime) { handleTextKey(state, stateiter->first, textkey); - textkey++; + ++textkey; } if(state.mTime >= state.mLoopStopTime && state.mLoopCount > 0) @@ -979,7 +979,7 @@ Ogre::Vector3 Animation::runAnimation(float duration) while(textkey != textkeys.end() && textkey->first <= state.mTime) { handleTextKey(state, stateiter->first, textkey); - textkey++; + ++textkey; } if(state.mTime >= state.mLoopStopTime) diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index ba39d10d5f..4f5536ca32 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -106,7 +106,7 @@ ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid) uint32 startIndex = 0; for(ESM::Pathgrid::PointList::const_iterator it = pathgrid->mPoints.begin(); it != pathgrid->mPoints.end(); - it++, startIndex += 6) + ++it, startIndex += 6) { Vector3 pointPos(it->mX, it->mY, it->mZ); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 9c10ca84b0..f1b1325f73 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -240,25 +240,25 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::CellStore* cell) void Objects::enableLights() { PtrAnimationMap::const_iterator it = mObjects.begin(); - for(;it != mObjects.end();it++) + for(;it != mObjects.end();++it) it->second->enableLights(true); } void Objects::disableLights() { PtrAnimationMap::const_iterator it = mObjects.begin(); - for(;it != mObjects.end();it++) + for(;it != mObjects.end();++it) it->second->enableLights(false); } void Objects::update(float dt, Ogre::Camera* camera) { PtrAnimationMap::const_iterator it = mObjects.begin(); - for(;it != mObjects.end();it++) + for(;it != mObjects.end();++it) it->second->runAnimation(dt); it = mObjects.begin(); - for(;it != mObjects.end();it++) + for(;it != mObjects.end();++it) it->second->preRender(camera); } diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 0720e798a5..33032477fb 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -442,7 +442,7 @@ namespace MWSound { snditer->first->setFadeout(duration); } - snditer++; + ++snditer; } } diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 150f0bed24..627c05251f 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -20,7 +20,7 @@ namespace MWWorld //find any NPC that is following the actor and teleport him too std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); - for(std::list::iterator it = followers.begin();it != followers.end();it++) + for(std::list::iterator it = followers.begin();it != followers.end();++it) { std::cout << "teleporting someone!" << (*it).getCellRef().mRefID; executeImp(*it); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index bbd968a7b2..e5f0c4b88a 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -433,7 +433,6 @@ namespace MWWorld while(mCell->getNextRef(esm[index], ref, deleted)) { // Don't load reference if it was moved to a different cell. - std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID); ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum); if (iter != mCell->mMovedRefs.end()) { diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 7d531d6d3f..d1f328f066 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -671,7 +671,7 @@ namespace MWWorld void PhysicsSystem::queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &movement) { PtrVelocityList::iterator iter = mMovementQueue.begin(); - for(;iter != mMovementQueue.end();iter++) + for(;iter != mMovementQueue.end();++iter) { if(iter->first == ptr) { @@ -692,7 +692,7 @@ namespace MWWorld { const MWBase::World *world = MWBase::Environment::get().getWorld(); PtrVelocityList::iterator iter = mMovementQueue.begin(); - for(;iter != mMovementQueue.end();iter++) + for(;iter != mMovementQueue.end();++iter) { float waterlevel = -std::numeric_limits::max(); const ESM::Cell *cell = iter->first.getCell()->getCell(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 5e4211faa8..b93632d192 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -141,17 +141,17 @@ namespace MWWorld // Find all the actors who might be able to see the player std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), + MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), esmStore.get().find("fSneakUseDist")->getInt(), neighbors); for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - { + { MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); break; } } - if (neighbors.size() == 0) + if (neighbors.empty()) MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); } } From 22cdb166f2227ff6f6653027ed56485dd22d47ad Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 27 Apr 2014 22:38:04 +0400 Subject: [PATCH 079/545] warning fix, vars renaming --- apps/openmw/mwmechanics/aicombat.cpp | 89 +++++++++++++--------------- apps/openmw/mwmechanics/aicombat.hpp | 2 +- 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 42d963117c..e64639c34c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -76,6 +76,7 @@ namespace namespace MWMechanics { + static const float MAX_ATTACK_DURATION = 0.35f; static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp @@ -86,7 +87,7 @@ namespace MWMechanics mTimerCombatMove(0), mFollowTarget(false), mReadyToAttack(false), - mStrike(false), + mAttack(false), mCombatMove(false), mMovement(), mForceNoShortcut(false), @@ -182,7 +183,7 @@ namespace MWMechanics } mTimerAttack -= duration; - actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike); + actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mAttack); float tReaction = 0.25f; if(mTimerReact < tReaction) @@ -203,16 +204,16 @@ namespace MWMechanics //actual attacking logic //TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f - float attackPeriod = 1.0f; + float attacksPeriod = 1.0f; if(mReadyToAttack) { - if(mTimerAttack <= -attackPeriod) + if(mTimerAttack <= -attacksPeriod) { //TODO: should depend on time between 'start' to 'min attack' //for better controlling of NPCs' attack strength. //Also it seems that this time is different for slash/thrust/chop - mTimerAttack = 0.35f * static_cast(rand())/RAND_MAX; - mStrike = true; + mTimerAttack = MAX_ATTACK_DURATION * static_cast(rand())/RAND_MAX; + mAttack = true; //say a provoking combat phrase if (actor.getClass().isNpc()) @@ -227,12 +228,12 @@ namespace MWMechanics } } else if (mTimerAttack <= 0) - mStrike = false; + mAttack = false; } else { - mTimerAttack = -attackPeriod; - mStrike = false; + mTimerAttack = -attacksPeriod; + mAttack = false; } const MWWorld::Class &actorCls = actor.getClass(); @@ -277,31 +278,23 @@ namespace MWMechanics /* * Some notes on meanings of variables: * - * rangeMelee: + * rangeAttack: * - * - Distance where attack using the actor's weapon is possible - * - longer for ranged weapons (obviously?) vs. melee weapons + * - Distance where attack using the actor's weapon is possible: + * longer for ranged weapons (obviously?) vs. melee weapons + * - Determined by weapon's reach parameter; hardcoded value + * for ranged weapon and for creatures * - Once within this distance mFollowTarget is triggered - * (TODO: check whether the follow logic still works for ranged - * weapons, since rangeCloseup is set to zero) - * - TODO: The variable name is confusing. It was ok when AiCombat only - * had melee weapons but now that ranged weapons are supported that is - * no longer the case. It should really be renamed to something - * like rangeStrike - alternatively, keep this name for melee - * weapons and use a different variable for tracking ranged weapon - * distance (rangeRanged maybe?) * - * rangeCloseup: + * rangeFollow: * * - Applies to melee weapons or hand to hand only (or creatures without * weapons) - * - Distance a little further away from the actor's weapon strike - * i.e. rangeCloseup > rangeMelee for melee weapons - * (the variable names make this simple concept counter-intuitive, - * something like rangeMelee > rangeStrike may be better) + * - Distance a little further away than the actor's weapon reach + * i.e. rangeFollow > rangeAttack for melee weapons + * - Hardcoded value (0 for ranged weapons) * - Once the target gets beyond this distance mFollowTarget is cleared * and a path to the target needs to be found - * - TODO: Possibly rename this variable to rangeMelee or even rangeFollow * * mFollowTarget: * @@ -311,19 +304,19 @@ namespace MWMechanics * target even if LOS is not achieved) */ - float rangeMelee; - float rangeCloseUp; + float rangeAttack; + float rangeFollow; bool distantCombat = false; if (weaptype == WeapType_BowAndArrow || weaptype == WeapType_Crossbow || weaptype == WeapType_Thrown) { - rangeMelee = 1000; // TODO: should depend on archer skill - rangeCloseUp = 0; // not needed in ranged combat + rangeAttack = 1000; // TODO: should depend on archer skill + rangeFollow = 0; // not needed in ranged combat distantCombat = true; } else { - rangeMelee = weapRange; - rangeCloseUp = 300; + rangeAttack = weapRange; + rangeFollow = 300; } ESM::Position pos = actor.getRefData().getPosition(); @@ -339,42 +332,42 @@ namespace MWMechanics mLastPos = pos; - // check if can move along z-axis - bool canMoveByZ; - if(canMoveByZ = (actorCls.canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) - || MWBase::Environment::get().getWorld()->isFlying(actor)) + // check if actor can move along z-axis + bool canMoveByZ = (actorCls.canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) + || MWBase::Environment::get().getWorld()->isFlying(actor); + if(canMoveByZ) { // determine vertical angle to target mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); } // (within strike dist) || (not quite strike dist while following) - if(distToTarget < rangeMelee || (distToTarget <= rangeCloseUp && mFollowTarget && !isStuck) ) + if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat vDirToTarget.z = 0; mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); // (not quite strike dist while following) - if (mFollowTarget && distToTarget > rangeMelee) + if (mFollowTarget && distToTarget > rangeAttack) { //Close-up combat: just run up on target mMovement.mPosition[1] = 1; } else // (within strike dist) { - //Melee: stop running and attack mMovement.mPosition[1] = 0; // set slash/thrust/chop attack - if (mStrike && !distantCombat) chooseBestAttack(weapon, mMovement); + if (mAttack && !distantCombat) chooseBestAttack(weapon, mMovement); if(mMovement.mPosition[0] || mMovement.mPosition[1]) { mTimerCombatMove = 0.1f + 0.1f * static_cast(rand())/RAND_MAX; mCombatMove = true; } - else if(actorCls.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeMelee/2))) + // only NPCs are smart enough to use dodge movements + else if(actorCls.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeAttack/2))) { //apply sideway movement (kind of dodging) with some probability if(static_cast(rand())/RAND_MAX < 0.25) @@ -385,7 +378,7 @@ namespace MWMechanics } } - if(distantCombat && distToTarget < rangeMelee/4) + if(distantCombat && distToTarget < rangeAttack/4) { mMovement.mPosition[1] = -1; } @@ -469,7 +462,7 @@ namespace MWMechanics mReadyToAttack = false; } - if(distToTarget > rangeMelee && !distantCombat) + if(distToTarget > rangeAttack && !distantCombat) { //special run attack; it shouldn't affect melee combat tactics if(actorCls.getMovementSettings(actor).mPosition[1] == 1) @@ -486,14 +479,14 @@ namespace MWMechanics float s1 = distToTarget - weapRange; float t = s1/speed1; float s2 = speed2 * t; - float t_swing = 0.17f/weapSpeed;//instead of 0.17 should be the time of playing weapon anim from 'start' to 'hit' tags + float t_swing = (MAX_ATTACK_DURATION/2) / weapSpeed;//instead of 0.17 should be the time of playing weapon anim from 'start' to 'hit' tags if (t + s2/speed1 <= t_swing) { mReadyToAttack = true; - if(mTimerAttack <= -attackPeriod) + if(mTimerAttack <= -attacksPeriod) { - mTimerAttack = 0.3f*static_cast(rand())/RAND_MAX; - mStrike = true; + mTimerAttack = MAX_ATTACK_DURATION * static_cast(rand())/RAND_MAX; + mAttack = true; } } } @@ -503,7 +496,7 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? - if((distToTarget > rangeMelee || mFollowTarget) && + if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { // first check if we're walking into a door diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 716101637f..30b72acd92 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -40,7 +40,7 @@ namespace MWMechanics float mTimerCombatMove; // AiCombat states - bool mReadyToAttack, mStrike; + bool mReadyToAttack, mAttack; bool mFollowTarget; bool mCombatMove; bool mBackOffDoor; From f69d61976eff72c00434027fe36db5a3c2d8135a Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sun, 27 Apr 2014 23:24:25 +0200 Subject: [PATCH 080/545] minor performance improvements in other apps subdirectories --- apps/esmtool/esmtool.cpp | 2 +- apps/esmtool/record.cpp | 2 +- apps/launcher/graphicspage.cpp | 4 ++-- apps/opencs/view/world/datadisplaydelegate.cpp | 4 ++-- apps/opencs/view/world/table.cpp | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) mode change 100755 => 100644 apps/opencs/view/world/datadisplaydelegate.cpp diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index e9731d6267..eef96c8c99 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -333,7 +333,7 @@ int load(Arguments& info) // Is the user interested in this record type? bool interested = true; - if (info.types.size() > 0) + if (!info.types.empty()) { std::vector::iterator match; match = std::find(info.types.begin(), info.types.end(), diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 184d11bb40..25b2a45050 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -124,7 +124,7 @@ void printEffectList(ESM::EffectList effects) { int i = 0; std::vector::iterator eit; - for (eit = effects.mList.begin(); eit != effects.mList.end(); eit++) + for (eit = effects.mList.begin(); eit != effects.mList.end(); ++eit) { std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID) << " (" << eit->mEffectID << ")" << std::endl; diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 8abdf00198..638237f340 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -214,13 +214,13 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre uint row = 0; Ogre::ConfigOptionMap options = renderer->getConfigOptions(); - for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++) + for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); ++i, ++row) { Ogre::StringVector::iterator opt_it; uint idx = 0; for (opt_it = i->second.possibleValues.begin(); - opt_it != i->second.possibleValues.end(); opt_it++, idx++) + opt_it != i->second.possibleValues.end(); ++opt_it, ++idx) { if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) { result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp old mode 100755 new mode 100644 index ef0da56ac7..c3ec68b527 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -25,7 +25,7 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, void CSVWorld::DataDisplayDelegate::buildPixmaps () { - if (mPixmaps.size() > 0) + if (!mPixmaps.empty()) mPixmaps.clear(); IconList::iterator it = mIcons.begin(); @@ -33,7 +33,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps () while (it != mIcons.end()) { mPixmaps.push_back (std::make_pair (it->first, it->second.pixmap (mIconSize) ) ); - it++; + ++it; } } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 902ab268a3..a5a98aac73 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -298,7 +298,7 @@ void CSVWorld::Table::revertRecord() { std::vector revertableIds = listRevertableSelectedIds(); - if (revertableIds.size()>0) + if (!revertableIds.empty()) { if (revertableIds.size()>1) mDocument.getUndoStack().beginMacro (tr ("Revert multiple records")); @@ -318,7 +318,7 @@ void CSVWorld::Table::deleteRecord() { std::vector deletableIds = listDeletableSelectedIds(); - if (deletableIds.size()>0) + if (!deletableIds.empty()) { if (deletableIds.size()>1) mDocument.getUndoStack().beginMacro (tr ("Delete multiple records")); From c2127845af27a724d0cf55adb614fbfe0c0c5bbb Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 27 Apr 2014 20:54:22 -0400 Subject: [PATCH 081/545] Added onKnockdown command --- apps/openmw/mwmechanics/actors.cpp | 13 ++++++++++- apps/openmw/mwmechanics/creaturestats.cpp | 27 +++++++++++++++++++---- apps/openmw/mwmechanics/creaturestats.hpp | 9 ++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +++- apps/openmw/mwscript/statsextensions.cpp | 20 ++++++++++++++++- apps/openmw/mwworld/player.hpp | 2 +- components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 2 ++ 8 files changed, 70 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d51b02a158..0b05693767 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -889,12 +889,23 @@ namespace MWMechanics iter->second->update(duration); } - // Kill dead actors + // Kill dead actors, update some variables for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); + //KnockedOutOneFrameLogic + //Used for "OnKnockedOut" command + //Put here to ensure that it's run for PRECISELY one frame. + if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary + stats.setKnockedDownOneFrame(true); + } + else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe + stats.setKnockedDownOneFrame(false); + stats.setKnockedDownOverOneFrame(true); + } + if(!stats.isDead()) { if(iter->second->isDead()) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index f81613ed1f..40ac92251d 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -17,7 +17,7 @@ namespace MWMechanics mAttacked (false), mHostile (false), mAttackingOrSpell(false), mIsWerewolf(false), - mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mHitRecovery(false), mBlock(false), + mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) { for (int i=0; i<4; ++i) @@ -387,6 +387,8 @@ namespace MWMechanics void CreatureStats::setKnockedDown(bool value) { mKnockdown = value; + if(!value) //Resets the "OverOneFrame" flag + setKnockedDownOverOneFrame(false); } bool CreatureStats::getKnockedDown() const @@ -394,6 +396,23 @@ namespace MWMechanics return mKnockdown; } + void CreatureStats::setKnockedDownOneFrame(bool value) + { + mKnockdownOneFrame = value; + } + + bool CreatureStats::getKnockedDownOneFrame() const + { + return mKnockdownOneFrame; + } + + void CreatureStats::setKnockedDownOverOneFrame(bool value) { + mKnockdownOverOneFrame = value; + } + bool CreatureStats::getKnockedDownOverOneFrame() const { + return mKnockdownOverOneFrame; + } + void CreatureStats::setHitRecovery(bool value) { mHitRecovery = value; @@ -479,7 +498,7 @@ namespace MWMechanics } // Relates to NPC gold reset delay - void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime) + void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime) { mTradeTime = tradeTime; } @@ -489,11 +508,11 @@ namespace MWMechanics return mTradeTime; } - void CreatureStats::setGoldPool(int pool) + void CreatureStats::setGoldPool(int pool) { mGoldPool = pool; } - int CreatureStats::getGoldPool() const + int CreatureStats::getGoldPool() const { return mGoldPool; } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 5dc59e5abb..633dc285c9 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -41,6 +41,8 @@ namespace MWMechanics bool mHostile; bool mAttackingOrSpell; bool mKnockdown; + bool mKnockdownOneFrame; + bool mKnockdownOverOneFrame; bool mHitRecovery; bool mBlock; unsigned int mMovementFlags; @@ -188,7 +190,14 @@ namespace MWMechanics float getEvasion() const; void setKnockedDown(bool value); + ///Returns true for the entire duration of the actor being knocked down bool getKnockedDown() const; + void setKnockedDownOneFrame(bool value); + ///Returns true only for the first frame of the actor being knocked out; used for "onKnockedOut" command + bool getKnockedDownOneFrame() const; + void setKnockedDownOverOneFrame(bool value); + ///Returns true for all but the first frame of being knocked out; used to know to not reset mKnockedDownOneFrame + bool getKnockedDownOverOneFrame() const; void setHitRecovery(bool value); bool getHitRecovery() const; void setBlock(bool value); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index ceea344665..bf2273b17e 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -388,5 +388,7 @@ op 0x200023c: StopCombat op 0x200023d: StopCombatExplicit op 0x200023e: GetPcInJail op 0x200023f: GetPcTraveling +op 0x2000240: onKnockout +op 0x2000241: onKnockoutExplicit -opcodes 0x2000240-0x3ffffff unused +opcodes 0x2000242-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 36083e4b0a..2f584e7edf 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1060,6 +1060,22 @@ namespace MWScript } }; + template + class OpOnKnockout : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = + MWWorld::Class::get (ptr).getCreatureStats (ptr).getKnockedDownOneFrame(); + + runtime.push (value); + } + }; + template class OpIsWerewolf : public Interpreter::Opcode0 { @@ -1236,6 +1252,8 @@ namespace MWScript interpreter.installSegment5 (Compiler::Stats::opcodeOnDeath, new OpOnDeath); interpreter.installSegment5 (Compiler::Stats::opcodeOnDeathExplicit, new OpOnDeath); + interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockout, new OpOnKnockout); + interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockoutExplicit, new OpOnKnockout); interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolf, new OpIsWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolfExplicit, new OpIsWerewolf); @@ -1245,7 +1263,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolf, new OpSetWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolfExplicit, new OpSetWerewolf); interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobatics, new OpSetWerewolfAcrobatics); - interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics); + interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics); } } } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 7e3f7a3cf2..638c738bd4 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -90,7 +90,7 @@ namespace MWWorld bool wasTeleported() const; void setTeleported(bool teleported); - ///Checks all actors to see if anyone has an aipackage against you + ///Checks all nearby actors to see if anyone has an aipackage against you bool isInCombat(); void clear(); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 531fe29590..db1ac16095 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -444,6 +444,7 @@ namespace Compiler extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit); extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath, opcodeOnDeathExplicit); + extensions.registerFunction ("onknockout", 'l', "", opcodeOnKnockout, opcodeOnKnockoutExplicit); extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 27ee182cf1..9e36cb68d7 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -377,6 +377,8 @@ namespace Compiler const int opcodeLowerRankExplicit = 0x20001eb; const int opcodeOnDeath = 0x20001fc; const int opcodeOnDeathExplicit = 0x2000205; + const int opcodeOnKnockout = 0x2000240; + const int opcodeOnKnockoutExplicit = 0x2000241; const int opcodeBecomeWerewolf = 0x2000217; const int opcodeBecomeWerewolfExplicit = 0x2000218; From 1da19585dc2f279417ad1660d3842bded75f112d Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 07:49:08 +0200 Subject: [PATCH 082/545] Remove some unneeded includes --- apps/openmw/mwrender/videoplayer.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 80704ca7c9..82400aac43 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -6,14 +6,9 @@ #include #include -#include #include -#include #include -#include -#include -#include -#include +#include #include @@ -21,9 +16,6 @@ #include "../mwbase/soundmanager.hpp" #include "../mwsound/sound_decoder.hpp" #include "../mwsound/sound.hpp" -#include "../mwbase/inputmanager.hpp" - -#include "renderconst.hpp" #ifdef _WIN32 #include From b89463db091936aa5017cadaae99883efafbc375 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 09:12:03 +0200 Subject: [PATCH 083/545] Fix #1207: Remember previous choice in class creation dialog --- apps/openmw/mwgui/charactercreation.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 5526bd26df..fa1bd28be2 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -188,12 +188,13 @@ namespace MWGui break; case GM_ClassCreate: - MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); - mCreateClassDialog = 0; - mCreateClassDialog = new CreateClassDialog(); + if (!mCreateClassDialog) + { + mCreateClassDialog = new CreateClassDialog(); + mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); + mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); + } mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); - mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); - mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); mCreateClassDialog->setVisible(true); if (mCreationStage < CSE_RaceChosen) mCreationStage = CSE_RaceChosen; @@ -531,8 +532,8 @@ namespace MWGui mPlayerClass = klass; MWBase::Environment::get().getWindowManager()->setPlayerClass(klass); - MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); - mCreateClassDialog = 0; + // Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later + mCreateClassDialog->setVisible(false); } updatePlayerHealth(); @@ -554,8 +555,8 @@ namespace MWGui void CharacterCreation::onCreateClassDialogBack() { - MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); - mCreateClassDialog = 0; + // Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later + mCreateClassDialog->setVisible(false); MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); From 1da99d9fc76cc52856d6ceda9a6f8a888f5e66f2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 10:26:24 +0200 Subject: [PATCH 084/545] Remove unused variable --- apps/openmw/mwmechanics/actors.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 96194d2921..a0680c037a 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -194,11 +194,6 @@ namespace MWMechanics +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified(); - float disp = 100; //creatures don't have disposition, so set it to 100 by default - if(ptr.getTypeName() == typeid(ESM::NPC).name()) - { - disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr); - } if( (fight == 100 ) || (fight >= 95 && d <= 3000) From 4555f6ddf6d017156081e484b8f7ceacd527e709 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 11:19:12 +0200 Subject: [PATCH 085/545] Add text shadow to progress bar labels --- files/mygui/openmw_progress.skin.xml | 1 + files/mygui/openmw_text.skin.xml | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/files/mygui/openmw_progress.skin.xml b/files/mygui/openmw_progress.skin.xml index a09011e10d..5ef3d73046 100644 --- a/files/mygui/openmw_progress.skin.xml +++ b/files/mygui/openmw_progress.skin.xml @@ -45,6 +45,7 @@ + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index d75abc8735..b80859ea1a 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -147,29 +147,29 @@ - + - + - + - + - + From 27a05027f42e524ca2d1125b0501226a5aabe310 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 11:29:57 +0200 Subject: [PATCH 086/545] Fixes #1172: Added basic loading/saving progress bar The progress is not particularly accurate. It simply uses the current / total number of records written/read as indication. Cell records are currently the largest by far, but there is a good chance that could be optimized using a change tracking system. --- apps/openmw/mwbase/dialoguemanager.hpp | 7 ++- apps/openmw/mwbase/journal.hpp | 7 ++- apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 3 +- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 2 +- apps/openmw/mwdialogue/journalimp.cpp | 6 ++- apps/openmw/mwdialogue/journalimp.hpp | 2 +- apps/openmw/mwgui/loadingscreen.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 3 +- apps/openmw/mwgui/mapwindow.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 4 +- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwscript/globalscripts.cpp | 3 +- apps/openmw/mwscript/globalscripts.hpp | 7 ++- apps/openmw/mwstate/statemanagerimp.cpp | 45 +++++++++++++------ apps/openmw/mwworld/cells.cpp | 8 +++- apps/openmw/mwworld/cells.hpp | 7 ++- apps/openmw/mwworld/esmstore.cpp | 20 ++++----- apps/openmw/mwworld/esmstore.hpp | 2 +- apps/openmw/mwworld/globals.cpp | 3 +- apps/openmw/mwworld/globals.hpp | 7 ++- apps/openmw/mwworld/player.cpp | 4 +- apps/openmw/mwworld/player.hpp | 7 ++- apps/openmw/mwworld/store.hpp | 5 ++- apps/openmw/mwworld/weather.cpp | 3 +- apps/openmw/mwworld/weather.hpp | 7 ++- apps/openmw/mwworld/worldimp.cpp | 17 +++---- apps/openmw/mwworld/worldimp.hpp | 2 +- components/esm/esmreader.hpp | 1 + components/esm/esmwriter.hpp | 5 +++ components/esm/loadtes3.hpp | 4 +- .../loadinglistener/loadinglistener.hpp | 2 +- 33 files changed, 142 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index e1d1246c84..f51fba07b7 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -5,6 +5,11 @@ #include +namespace Loading +{ + class Listener; +} + namespace ESM { class ESMReader; @@ -60,7 +65,7 @@ namespace MWBase virtual int countSavedGameRecords() const = 0; - virtual void write (ESM::ESMWriter& writer) const = 0; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; }; diff --git a/apps/openmw/mwbase/journal.hpp b/apps/openmw/mwbase/journal.hpp index 8e4e9703fa..7f06320aad 100644 --- a/apps/openmw/mwbase/journal.hpp +++ b/apps/openmw/mwbase/journal.hpp @@ -11,6 +11,11 @@ #include "../mwdialogue/topic.hpp" #include "../mwdialogue/quest.hpp" +namespace Loading +{ + class Listener; +} + namespace ESM { class ESMReader; @@ -80,7 +85,7 @@ namespace MWBase virtual int countSavedGameRecords() const = 0; - virtual void write (ESM::ESMWriter& writer) const = 0; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; }; diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index eb84741c4a..4287e466bd 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -303,7 +303,7 @@ namespace MWBase /// Clear all savegame-specific data virtual void clear() = 0; - virtual void write (ESM::ESMWriter& writer) = 0; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; }; } diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index f03a9197d9..d68228904c 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -108,7 +108,7 @@ namespace MWBase virtual int countSavedGameRecords() const = 0; - virtual void write (ESM::ESMWriter& writer) const = 0; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type, const std::map& contentFileMap) = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 32535f33e2..caaf7c91f4 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -609,7 +609,7 @@ namespace MWDialogue return 1; // known topics } - void DialogueManager::write (ESM::ESMWriter& writer) const + void DialogueManager::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { ESM::DialogueState state; @@ -621,6 +621,7 @@ namespace MWDialogue writer.startRecord (ESM::REC_DIAS); state.save (writer); writer.endRecord (ESM::REC_DIAS); + progress.increaseProgress(); } void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index a2e31e791f..6cd2c75afb 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -83,7 +83,7 @@ namespace MWDialogue virtual int countSavedGameRecords() const; - virtual void write (ESM::ESMWriter& writer) const; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; virtual void readRecord (ESM::ESMReader& reader, int32_t type); }; diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index 26383b3a7b..724d531cfb 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -167,7 +167,7 @@ namespace MWDialogue return count; } - void Journal::write (ESM::ESMWriter& writer) const + void Journal::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter) { @@ -178,6 +178,7 @@ namespace MWDialogue writer.startRecord (ESM::REC_QUES); state.save (writer); writer.endRecord (ESM::REC_QUES); + progress.increaseProgress(); for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter) { @@ -188,6 +189,7 @@ namespace MWDialogue writer.startRecord (ESM::REC_JOUR); entry.save (writer); writer.endRecord (ESM::REC_JOUR); + progress.increaseProgress(); } } @@ -199,6 +201,7 @@ namespace MWDialogue writer.startRecord (ESM::REC_JOUR); entry.save (writer); writer.endRecord (ESM::REC_JOUR); + progress.increaseProgress(); } for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter) @@ -214,6 +217,7 @@ namespace MWDialogue writer.startRecord (ESM::REC_JOUR); entry.save (writer); writer.endRecord (ESM::REC_JOUR); + progress.increaseProgress(); } } } diff --git a/apps/openmw/mwdialogue/journalimp.hpp b/apps/openmw/mwdialogue/journalimp.hpp index 1b4803ba21..00511f47c1 100644 --- a/apps/openmw/mwdialogue/journalimp.hpp +++ b/apps/openmw/mwdialogue/journalimp.hpp @@ -64,7 +64,7 @@ namespace MWDialogue virtual int countSavedGameRecords() const; - virtual void write (ESM::ESMWriter& writer) const; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; virtual void readRecord (ESM::ESMReader& reader, int32_t type); }; diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 55235173f1..96e0e1ed47 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -25,7 +25,7 @@ namespace MWGui virtual void setProgressRange (size_t range); virtual void setProgress (size_t value); - virtual void increaseProgress (size_t increase); + virtual void increaseProgress (size_t increase=1); virtual void setVisible(bool visible); diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index aa48631e41..284e5c4e2e 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -595,7 +595,7 @@ namespace MWGui MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0)); } - void MapWindow::write(ESM::ESMWriter &writer) + void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress) { ESM::GlobalMap map; mGlobalMapRender->write(map); @@ -605,6 +605,7 @@ namespace MWGui writer.startRecord(ESM::REC_GMAP); map.save(writer); writer.endRecord(ESM::REC_GMAP); + progress.increaseProgress(); } void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 0b549147c6..7f4f18893c 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -108,7 +108,7 @@ namespace MWGui /// Clear all savegame-specific data void clear(); - void write (ESM::ESMWriter& writer); + void write (ESM::ESMWriter& writer, Loading::Listener& progress); void readRecord (ESM::ESMReader& reader, int32_t type); private: diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2ed1131269..e2e4e157c1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1407,9 +1407,9 @@ namespace MWGui mMap->clear(); } - void WindowManager::write(ESM::ESMWriter &writer) + void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) { - mMap->write(writer); + mMap->write(writer, progress); } void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 074cb3208d..064ca89bac 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -291,7 +291,7 @@ namespace MWGui /// Clear all savegame-specific data virtual void clear(); - virtual void write (ESM::ESMWriter& writer); + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress); virtual void readRecord (ESM::ESMReader& reader, int32_t type); private: diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 527c576cc7..8e118e2f8c 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -97,7 +97,7 @@ namespace MWScript return mScripts.size(); } - void GlobalScripts::write (ESM::ESMWriter& writer) const + void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (std::map >::const_iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) @@ -113,6 +113,7 @@ namespace MWScript writer.startRecord (ESM::REC_GSCR); script.save (writer); writer.endRecord (ESM::REC_GSCR); + progress.increaseProgress(); } } diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index de63b99067..97584a5b88 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -14,6 +14,11 @@ namespace ESM class ESMReader; } +namespace Loading +{ + class Listener; +} + namespace MWWorld { struct ESMStore; @@ -46,7 +51,7 @@ namespace MWScript int countSavedGameRecords() const; - void write (ESM::ESMWriter& writer) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord (ESM::ESMReader& reader, int32_t type); ///< Records for variables that do not exist are dropped silently. diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index acf1cf3f2d..33a78330d0 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -196,26 +196,35 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 writer.setFormat (ESM::Header::CurrentFormat); - writer.setRecordCount ( - 1 // saved game header - +MWBase::Environment::get().getJournal()->countSavedGameRecords() - +MWBase::Environment::get().getWorld()->countSavedGameRecords() - +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() - +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() - +1 // global map - ); + int recordCount = 1 // saved game header + +MWBase::Environment::get().getJournal()->countSavedGameRecords() + +MWBase::Environment::get().getWorld()->countSavedGameRecords() + +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() + +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() + +1; // global map + writer.setRecordCount (recordCount); writer.save (stream); + Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + listener.setProgressRange(recordCount); + listener.setLabel("#{sNotifyMessage4}"); + + Loading::ScopedLoad load(&listener); + writer.startRecord (ESM::REC_SAVE); slot->mProfile.save (writer); writer.endRecord (ESM::REC_SAVE); + listener.increaseProgress(); - MWBase::Environment::get().getJournal()->write (writer); - MWBase::Environment::get().getDialogueManager()->write (writer); - MWBase::Environment::get().getWorld()->write (writer); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer); - MWBase::Environment::get().getWindowManager()->write(writer); + MWBase::Environment::get().getJournal()->write (writer, listener); + MWBase::Environment::get().getDialogueManager()->write (writer, listener); + MWBase::Environment::get().getWorld()->write (writer, listener); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener); + MWBase::Environment::get().getWindowManager()->write(writer, listener); + + // Ensure we have written the number of records that was estimated + assert (writer.getRecordCount() == recordCount+1); // 1 extra for TES3 record writer.close(); @@ -261,6 +270,15 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl std::map contentFileMap = buildContentFileIndexMap (reader); + Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + + // FIXME: +1 is actually not needed, but older savegames had an off-by-one error with the record count + // So we leave this in for now so that these old savegames still work + listener.setProgressRange(reader.getRecordCount()+1); + listener.setLabel("#{sLoadingMessage14}"); + + Loading::ScopedLoad load(&listener); + while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); @@ -318,6 +336,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl /// \todo log error reader.skipRecord(); } + listener.increaseProgress(); } mCharacterManager.setCurrentCharacter(character); diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index acffe20f36..7f2a87eec4 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -277,17 +277,23 @@ int MWWorld::Cells::countSavedGameRecords() const return count; } -void MWWorld::Cells::write (ESM::ESMWriter& writer) const +void MWWorld::Cells::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (std::map, CellStore>::iterator iter (mExteriors.begin()); iter!=mExteriors.end(); ++iter) if (iter->second.hasState()) + { writeCell (writer, iter->second); + progress.increaseProgress(); // Assumes that each cell writes one record + } for (std::map::iterator iter (mInteriors.begin()); iter!=mInteriors.end(); ++iter) if (iter->second.hasState()) + { writeCell (writer, iter->second); + progress.increaseProgress(); // Assumes that each cell writes one record + } } bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type, diff --git a/apps/openmw/mwworld/cells.hpp b/apps/openmw/mwworld/cells.hpp index 5209aa51aa..a9c17fa930 100644 --- a/apps/openmw/mwworld/cells.hpp +++ b/apps/openmw/mwworld/cells.hpp @@ -15,6 +15,11 @@ namespace ESM struct Cell; } +namespace Loading +{ + class Listener; +} + namespace MWWorld { class ESMStore; @@ -69,7 +74,7 @@ namespace MWWorld int countSavedGameRecords() const; - void write (ESM::ESMWriter& writer) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord (ESM::ESMReader& reader, int32_t type, const std::map& contentFileMap); diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index c5c826d471..ebe0aa08a6 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -153,17 +153,17 @@ void ESMStore::setUp() +mWeapons.getDynamicSize(); } - void ESMStore::write (ESM::ESMWriter& writer) const + void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { - mPotions.write (writer); - mArmors.write (writer); - mBooks.write (writer); - mClasses.write (writer); - mClothes.write (writer); - mEnchants.write (writer); - mSpells.write (writer); - mWeapons.write (writer); - mNpcs.write (writer); + mPotions.write (writer, progress); + mArmors.write (writer, progress); + mBooks.write (writer, progress); + mClasses.write (writer, progress); + mClothes.write (writer, progress); + mEnchants.write (writer, progress); + mSpells.write (writer, progress); + mWeapons.write (writer, progress); + mNpcs.write (writer, progress); } bool ESMStore::readRecord (ESM::ESMReader& reader, int32_t type) diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index e6730c3074..ea6d3d0064 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -212,7 +212,7 @@ namespace MWWorld int countSavedGameRecords() const; - void write (ESM::ESMWriter& writer) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord (ESM::ESMReader& reader, int32_t type); ///< \return Known type? diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 879ffa8e34..663af640b8 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -77,7 +77,7 @@ namespace MWWorld return mVariables.size(); } - void Globals::write (ESM::ESMWriter& writer) const + void Globals::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (Collection::const_iterator iter (mVariables.begin()); iter!=mVariables.end(); ++iter) { @@ -85,6 +85,7 @@ namespace MWWorld writer.writeHNString ("NAME", iter->first); iter->second.write (writer, ESM::Variant::Format_Global); writer.endRecord (ESM::REC_GLOB); + progress.increaseProgress(); } } diff --git a/apps/openmw/mwworld/globals.hpp b/apps/openmw/mwworld/globals.hpp index d8d2cefbf7..3ff4a5d6e0 100644 --- a/apps/openmw/mwworld/globals.hpp +++ b/apps/openmw/mwworld/globals.hpp @@ -16,6 +16,11 @@ namespace ESM class ESMReader; } +namespace Loading +{ + class Listener; +} + namespace MWWorld { class ESMStore; @@ -46,7 +51,7 @@ namespace MWWorld int countSavedGameRecords() const; - void write (ESM::ESMWriter& writer) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord (ESM::ESMReader& reader, int32_t type); ///< Records for variables that do not exist are dropped silently. diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 5e4211faa8..0aeb0ae5cd 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -215,7 +215,7 @@ namespace MWWorld mTeleported = false; } - void Player::write (ESM::ESMWriter& writer) const + void Player::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { ESM::Player player; @@ -245,6 +245,8 @@ namespace MWWorld writer.startRecord (ESM::REC_PLAY); player.save (writer); writer.endRecord (ESM::REC_PLAY); + + progress.increaseProgress(); } bool Player::readRecord (ESM::ESMReader& reader, int32_t type) diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 7e3f7a3cf2..8d27b27120 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -21,6 +21,11 @@ namespace MWBase class Ptr; } +namespace Loading +{ + class Listener; +} + namespace MWWorld { class CellStore; @@ -95,7 +100,7 @@ namespace MWWorld void clear(); - void write (ESM::ESMWriter& writer) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; bool readRecord (ESM::ESMReader& reader, int32_t type); diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 0fc2d547cb..0f8ab86824 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -8,6 +8,8 @@ #include +#include + #include "recordcmp.hpp" namespace MWWorld @@ -313,7 +315,7 @@ namespace MWWorld return erase(item.mId); } - void write (ESM::ESMWriter& writer) const + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (typename Dynamic::const_iterator iter (mDynamic.begin()); iter!=mDynamic.end(); ++iter) @@ -322,6 +324,7 @@ namespace MWWorld writer.writeHNString ("NAME", iter->second.mId); iter->second.save (writer); writer.endRecord (T::sRecordId); + progress.increaseProgress(); } } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 335702c665..3611114a93 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -686,7 +686,7 @@ bool WeatherManager::isDark() const return exterior && (mHour < mSunriseTime || mHour > mNightStart - 1); } -void WeatherManager::write(ESM::ESMWriter& writer) +void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress) { ESM::WeatherState state; state.mHour = mHour; @@ -701,6 +701,7 @@ void WeatherManager::write(ESM::ESMWriter& writer) writer.startRecord(ESM::REC_WTHR); state.save(writer); writer.endRecord(ESM::REC_WTHR); + progress.increaseProgress(); } bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type) diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index cad3a4492e..3e9df504ba 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -18,6 +18,11 @@ namespace MWRender class RenderingManager; } +namespace Loading +{ + class Listener; +} + namespace MWWorld { class Fallback; @@ -158,7 +163,7 @@ namespace MWWorld /// @see World::isDark bool isDark() const; - void write(ESM::ESMWriter& writer); + void write(ESM::ESMWriter& writer, Loading::Listener& progress); bool readRecord(ESM::ESMReader& reader, int32_t type); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 46bb4db581..0e825e2639 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -268,19 +268,20 @@ namespace MWWorld int World::countSavedGameRecords() const { return - mStore.countSavedGameRecords() + mCells.countSavedGameRecords() + +mStore.countSavedGameRecords() +mGlobalVariables.countSavedGameRecords() +1 // player record - +mCells.countSavedGameRecords(); + +1; // weather record } - void World::write (ESM::ESMWriter& writer) const + void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { - mStore.write (writer); - mGlobalVariables.write (writer); - mCells.write (writer); - mPlayer->write (writer); - mWeatherManager->write (writer); + mCells.write (writer, progress); + mStore.write (writer, progress); + mGlobalVariables.write (writer, progress); + mPlayer->write (writer, progress); + mWeatherManager->write (writer, progress); } void World::readRecord (ESM::ESMReader& reader, int32_t type, diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f1e89bf6bc..40ba8fa824 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -194,7 +194,7 @@ namespace MWWorld virtual int countSavedGameRecords() const; - virtual void write (ESM::ESMWriter& writer) const; + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; virtual void readRecord (ESM::ESMReader& reader, int32_t type, const std::map& contentFileMap); diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index b6c0ebc701..6b0bb9a27f 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -31,6 +31,7 @@ public: *************************************************************************/ int getVer() const { return mHeader.mData.version; } + int getRecordCount() const { return mHeader.mData.records; } float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; } const std::string getAuthor() const { return mHeader.mData.author.toString(); } const std::string getDesc() const { return mHeader.mData.desc.toString(); } diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index 33650e6784..b385ac0671 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -29,7 +29,12 @@ class ESMWriter void setEncoder(ToUTF8::Utf8Encoder *encoding); void setAuthor(const std::string& author); void setDescription(const std::string& desc); + // Set the record count for writing it in the file header void setRecordCount (int count); + // Counts how many records we have actually written. + // It is a good idea to compare this with the value you wrote into the header (setRecordCount) + // It should be the record count you set + 1 (1 additional record for the TES3 header) + int getRecordCount() { return mRecordCount; } void setFormat (int format); void clearMaster(); diff --git a/components/esm/loadtes3.hpp b/components/esm/loadtes3.hpp index 5614d295f6..eb5e14daf4 100644 --- a/components/esm/loadtes3.hpp +++ b/components/esm/loadtes3.hpp @@ -28,7 +28,7 @@ namespace ESM int type; // 0=esp, 1=esm, 32=ess (unused) NAME32 author; // Author's name NAME256 desc; // File description - int records; // Number of records? Not used. + int records; // Number of records }; // Defines another files (esm or esp) that this file depends upon. @@ -52,4 +52,4 @@ namespace ESM } -#endif \ No newline at end of file +#endif diff --git a/components/loadinglistener/loadinglistener.hpp b/components/loadinglistener/loadinglistener.hpp index 483d524910..f6a7b71e9d 100644 --- a/components/loadinglistener/loadinglistener.hpp +++ b/components/loadinglistener/loadinglistener.hpp @@ -17,7 +17,7 @@ namespace Loading virtual void setProgressRange (size_t range) = 0; virtual void setProgress (size_t value) = 0; - virtual void increaseProgress (size_t increase) = 0; + virtual void increaseProgress (size_t increase = 1) = 0; /// Indicate the scene is now ready to be shown virtual void removeWallpaper() = 0; From 0796815da0a7f903566f827bf370a325023dd286 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 11:44:56 +0200 Subject: [PATCH 087/545] Ignore dead actors in getActorsFollowing/Fighting Prevents dead enemies from disallowing resting near them --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a0680c037a..2de5e268fc 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1019,7 +1019,7 @@ namespace MWMechanics const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); - if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) + if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) { MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); if(package->getFollowedActor() == actor.getCellRef().mRefID) @@ -1041,7 +1041,7 @@ namespace MWMechanics const MWWorld::Class &cls = MWWorld::Class::get(*iter); CreatureStats &stats = cls.getCreatureStats(*iter); - if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) + if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) { MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); if(package->getTargetId() == actor.getCellRef().mRefID) From 138fb4e29a91dfbf56612c09573223d5ec5826b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 12:51:46 +0200 Subject: [PATCH 088/545] Bug #1265: Fixed confirmation buttons align --- files/mygui/openmw_confirmation_dialog.layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index 47e1fd2b85..2bd9d89972 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -13,7 +13,7 @@ - + From 35c1724d39d5ca8d9a36107ac3514fd2bf78e765 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Mon, 28 Apr 2014 16:34:49 +0400 Subject: [PATCH 089/545] unblock vertical aiming for combatants --- apps/openmw/mwmechanics/aicombat.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index e64639c34c..d0555cdc3c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -34,13 +34,13 @@ namespace float getZAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) { - float len = (dirLen >= 0.0f)? dirLen : dir.length(); + float len = (dirLen > 0.0f)? dirLen : dir.length(); return Ogre::Radian( Ogre::Math::ACos(dir.y / len) * sgn(Ogre::Math::ASin(dir.x / len)) ).valueDegrees(); } float getXAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) { - float len = (dirLen >= 0.0f)? dirLen : dir.length(); + float len = (dirLen > 0.0f)? dirLen : dir.length(); return Ogre::Radian(-Ogre::Math::ASin(dir.z / len)).valueDegrees(); } @@ -323,7 +323,6 @@ namespace MWMechanics Ogre::Vector3 vActorPos(pos.pos); Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; - float distToTarget = vDirToTarget.length(); bool isStuck = false; float speed = 0.0f; @@ -335,17 +334,19 @@ namespace MWMechanics // check if actor can move along z-axis bool canMoveByZ = (actorCls.canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) || MWBase::Environment::get().getWorld()->isFlying(actor); - if(canMoveByZ) - { - // determine vertical angle to target - mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); - } + + // determine vertical angle to target + // if actor can move along z-axis it will control movement dir + // if can't - it will control correct aiming + mMovement.mRotation[0] = getXAngleToDir(vDirToTarget); + + vDirToTarget.z = 0; + float distToTarget = vDirToTarget.length(); // (within strike dist) || (not quite strike dist while following) if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - vDirToTarget.z = 0; mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); // (not quite strike dist while following) From 7e4a0c24780a38e741a054ed64bcf5397ccaf819 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 15:00:52 +0200 Subject: [PATCH 090/545] Removed asserts --- apps/openmw/mwgui/loadingscreen.cpp | 2 -- apps/openmw/mwstate/statemanagerimp.cpp | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 7917c75f3b..7c915ebebf 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -160,7 +160,6 @@ namespace MWGui void LoadingScreen::setProgress (size_t value) { - assert(value < mProgressBar->getScrollRange()); if (value - mProgress < mProgressBar->getScrollRange()/100.f) return; mProgress = value; @@ -174,7 +173,6 @@ namespace MWGui mProgressBar->setScrollPosition(0); size_t value = mProgress + increase; mProgress = value; - assert(mProgress < mProgressBar->getScrollRange()); mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); draw(); } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 33a78330d0..6fbd4bb237 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -224,7 +224,8 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot MWBase::Environment::get().getWindowManager()->write(writer, listener); // Ensure we have written the number of records that was estimated - assert (writer.getRecordCount() == recordCount+1); // 1 extra for TES3 record + if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record + std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl; writer.close(); @@ -272,9 +273,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); - // FIXME: +1 is actually not needed, but older savegames had an off-by-one error with the record count - // So we leave this in for now so that these old savegames still work - listener.setProgressRange(reader.getRecordCount()+1); + listener.setProgressRange(reader.getRecordCount()); listener.setLabel("#{sLoadingMessage14}"); Loading::ScopedLoad load(&listener); From b2119441b9bed515eb8eddd64b6fac528ca9cc2b Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 15:26:40 +0200 Subject: [PATCH 091/545] Fix bug in PcRank / PcNextRank It was using the first faction instead of the actor's faction. --- apps/openmw/mwscript/interpretercontext.cpp | 39 +++++++++++---------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index b79808d08b..9a55b3dcfb 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -302,15 +302,18 @@ namespace MWScript std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); - std::map::const_iterator it = ranks.begin(); + std::map::const_iterator it = ranks.find(factionId); + int rank = -1; + if (it != ranks.end()) + rank = it->second; const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(factionId); - if(it->second < 0 || it->second > 9) // there are only 10 ranks + if(rank < 0 || rank > 9) // there are only 10 ranks return ""; - return faction->mRanks[it->second]; + return faction->mRanks[rank]; } std::string InterpreterContext::getPCNextRank() const @@ -320,25 +323,25 @@ namespace MWScript std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; + std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + std::map::const_iterator it = ranks.find(factionId); + int rank = -1; + if (it != ranks.end()) + rank = it->second; + + ++rank; // Next rank + + // if we are already at max rank, there is no next rank + if (rank > 9) + rank = 9; + const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(factionId); - std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + if(rank < 0 || rank > 9) + return ""; - if (!ranks.empty()) - { - std::map::const_iterator it = ranks.begin(); - - if(it->second < -1 || it->second > 9) - return ""; - - if(it->second <= 8) // If player is at max rank, there is no next rank - return faction->mRanks[it->second + 1]; - else - return faction->mRanks[it->second]; - } - else - return faction->mRanks[0]; + return faction->mRanks[rank]; } int InterpreterContext::getPCBounty() const From 84961d78434ca5a6651eb4d7565ed7ec1d8b6140 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 15:30:57 +0200 Subject: [PATCH 092/545] Fixes #1254: PcRank should return first rank if not in the faction --- apps/openmw/mwscript/interpretercontext.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 9a55b3dcfb..b97be61e17 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -307,6 +307,11 @@ namespace MWScript if (it != ranks.end()) rank = it->second; + // If you are not in the faction, PcRank returns the first rank, for whatever reason. + // This is used by the dialogue when joining the Thieves Guild in Balmora. + if (rank == -1) + rank = 0; + const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(factionId); From b0bdd233eea81bdf3c42346cc1a75767c7179fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Mon, 28 Apr 2014 16:05:27 +0200 Subject: [PATCH 093/545] Center, switch and change text for confirmation buttons The confirmation buttons for quitting or starting a new game were driving me crazy by not being ok left and cancel right, as e.g. vanilla is. Then I noticed the text isn't the same as in vanilla either. It should be yes/no, not ok/cancel. To make it even more authentic I also centered the buttons. Had to remove autosized buttons for this. I think it looks fine still. Comments? --- files/mygui/openmw_confirmation_dialog.layout | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index 2bd9d89972..b5bf6405d2 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -4,7 +4,7 @@ - + @@ -13,18 +13,13 @@ - - - + + + - - - - - + + - - - + \ No newline at end of file From 04e5b9c72c86d04118f6a3e7e22939bd3c9f9963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Mon, 28 Apr 2014 16:23:07 +0200 Subject: [PATCH 094/545] Right aligned version/revision I've always felt that having the version/revision text at the bottom center in the main menu was a bit out of place. A more common place for this kind of thing is in one of the corners. I chose bottom right. Aditionally I right aligned it and changed the v and r in version and revision to capital letters. Comments? --- apps/openmw/mwgui/mainmenu.cpp | 4 ++-- files/mygui/openmw_mainmenu.layout | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index b6e3915bbe..df9c53ea87 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -28,7 +28,7 @@ namespace MWGui { getWidget(mVersionText, "VersionText"); std::stringstream sstream; - sstream << "OpenMW version: " << OPENMW_VERSION; + sstream << "OpenMW Version: " << OPENMW_VERSION; // adding info about git hash if available std::string rev = OPENMW_VERSION_COMMITHASH; @@ -36,7 +36,7 @@ namespace MWGui if (!rev.empty() && !tag.empty()) { rev = rev.substr(0,10); - sstream << "\nrevision: " << rev; + sstream << "\nRevision: " << rev; } std::string output = sstream.str(); diff --git a/files/mygui/openmw_mainmenu.layout b/files/mygui/openmw_mainmenu.layout index e8cb23b773..f4c7142ce7 100644 --- a/files/mygui/openmw_mainmenu.layout +++ b/files/mygui/openmw_mainmenu.layout @@ -2,11 +2,11 @@ - - - + + + - + From 0513d0837c32dace48eee31ff373886745ca356f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Mon, 28 Apr 2014 17:54:55 +0200 Subject: [PATCH 095/545] Alignment tweaks and autosized buttons workaround --- files/mygui/openmw_confirmation_dialog.layout | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index b5bf6405d2..e299c7b0ba 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -4,7 +4,7 @@ - + @@ -13,13 +13,25 @@ - - + + + + + + - + + + + + + + + + \ No newline at end of file From 518a32c19d93599af37b691b685eef8857103e75 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 18:33:42 +0200 Subject: [PATCH 096/545] Fixes #1195: Make NPCs equip torches in interiors under certain conditions --- apps/openmw/mwworld/worldimp.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0e825e2639..4c1a8b1c01 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2506,7 +2506,17 @@ namespace MWWorld bool World::isDark() const { - return mWeatherManager->isDark(); + MWWorld::CellStore* cell = mPlayer->getPlayer().getCell(); + if (cell->isExterior()) + return mWeatherManager->isDark(); + else + { + uint32_t ambient = cell->getCell()->mAmbi.mAmbient; + int ambientTotal = (ambient & 0xff) + + ((ambient>>8) & 0xff) + + ((ambient>>16) & 0xff); + return !(cell->getCell()->mData.mFlags & ESM::Cell::NoSleep) && ambientTotal <= 201; + } } bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) From a35f7c73ae0679acea383eab14628b4713453d18 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 18:40:29 +0200 Subject: [PATCH 097/545] Fixes #1286 (Dialogue topic list clips with window frame) The first problem was with the ScrollView skin, which had a full-sized client area. Since the scrollbar starts out visible, MyGUI expects the client area to be smaller to accomodate for the scrollbar width. As a result, the starting canvas size becomes bigger than the view size. Another bug was with the MWList code: reducing the canvas size for the scrollbar is not needed, since MyGUI is already doing that, and attempting to do it manually interferes with the view offset. --- apps/openmw/mwgui/list.cpp | 6 +++--- files/mygui/openmw_scroll_skin.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index 8dda041ca6..eff7aea248 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -48,7 +48,7 @@ namespace MWGui void MWList::redraw(bool scrollbarShown) { - const int _scrollBarWidth = 24; // fetch this from skin? + const int _scrollBarWidth = 20; // fetch this from skin? const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int spacing = 3; size_t scrollbarPosition = mScrollView->getScrollPosition(); @@ -83,7 +83,7 @@ namespace MWGui else { MyGUI::ImageBox* separator = mScrollView->createWidget("MW_HLine", - MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth()-4, 18), + MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth() - scrollBarWidth - 4, 18), MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); separator->setNeedMouseFocus(false); @@ -91,7 +91,7 @@ namespace MWGui } ++i; } - mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height)); + mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height)); if (!scrollbarShown && mItemHeight > mClient->getSize().height) redraw(true); diff --git a/files/mygui/openmw_scroll_skin.xml b/files/mygui/openmw_scroll_skin.xml index b6ed9155f1..b5dfd333dd 100644 --- a/files/mygui/openmw_scroll_skin.xml +++ b/files/mygui/openmw_scroll_skin.xml @@ -3,12 +3,12 @@ - + - + From d530bbe5cddd96b0483f2c35573901d22de4cf73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Mon, 28 Apr 2014 18:52:53 +0200 Subject: [PATCH 098/545] Implemented Scrawls alternative workaround. --- files/mygui/openmw_confirmation_dialog.layout | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index e299c7b0ba..edeed539c6 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -13,25 +13,19 @@ - - - + + + + + + + + + + - - - + - - - - - - - - - - - \ No newline at end of file From 7f37f2c2be7d598af1cd3cd621e03dac658ac2b8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 19:23:25 +0200 Subject: [PATCH 099/545] Fixes #1187: Make GetDistance handle actors in remote cells gracefully --- apps/openmw/mwscript/interpretercontext.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index b97be61e17..1f5ad5b071 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -378,10 +378,14 @@ namespace MWScript float InterpreterContext::getDistance (const std::string& name, const std::string& id) const { - // TODO handle exterior cells (when ref and ref2 are located in different cells) - const MWWorld::Ptr ref2 = getReference (id, false); + const MWWorld::Ptr ref2 = getReference (id, false, false); + // If either actor is in a non-active cell, return a large value (just like vanilla) + if (ref2.isEmpty()) + return std::numeric_limits().max(); - const MWWorld::Ptr ref = MWBase::Environment::get().getWorld()->getPtr (name, true); + const MWWorld::Ptr ref = getReference (name, false, false); + if (ref.isEmpty()) + return std::numeric_limits().max(); double diff[3]; From 7a0aeeaa38498be4805dc4eb5a0864b526522580 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 Apr 2014 20:57:45 +0200 Subject: [PATCH 100/545] Allow to delete savegames (shift + click) --- apps/openmw/mwbase/statemanager.hpp | 2 + apps/openmw/mwgui/savegamedialog.cpp | 84 ++++++++++++++++-------- apps/openmw/mwgui/savegamedialog.hpp | 9 +++ apps/openmw/mwstate/character.cpp | 32 ++++++++- apps/openmw/mwstate/character.hpp | 8 +++ apps/openmw/mwstate/charactermanager.cpp | 19 ++++++ apps/openmw/mwstate/charactermanager.hpp | 2 + apps/openmw/mwstate/statemanagerimp.cpp | 5 ++ apps/openmw/mwstate/statemanagerimp.hpp | 3 + 9 files changed, 134 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwbase/statemanager.hpp b/apps/openmw/mwbase/statemanager.hpp index fc4a2d806e..121a73a485 100644 --- a/apps/openmw/mwbase/statemanager.hpp +++ b/apps/openmw/mwbase/statemanager.hpp @@ -55,6 +55,8 @@ namespace MWBase virtual void endGame() = 0; + virtual void deleteGame (const MWState::Character *character, const MWState::Slot *slot) = 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. /// diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index bb4373cbac..74ccc82f4c 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -23,6 +23,7 @@ namespace MWGui : WindowModal("openmw_savegame_dialog.layout") , mSaving(true) , mCurrentCharacter(NULL) + , mCurrentSlot(NULL) { getWidget(mScreenshot, "Screenshot"); getWidget(mCharacterSelection, "SelectCharacter"); @@ -36,6 +37,7 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onCancelButtonClicked); mCharacterSelection->eventComboChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onCharacterSelected); mSaveList->eventListChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onSlotSelected); + mSaveList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SaveGameDialog::onSlotMouseClick); mSaveList->eventListSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onSlotActivated); mSaveNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onEditSelectAccept); mSaveNameEdit->eventEditTextChange += MyGUI::newDelegate(this, &SaveGameDialog::onSaveNameChanged); @@ -47,6 +49,37 @@ namespace MWGui accept(); } + void SaveGameDialog::onSlotMouseClick(MyGUI::ListBox* sender, size_t pos) + { + onSlotSelected(sender, pos); + + if (MyGUI::InputManager::getInstance().isShiftPressed()) + { + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); + dialog->open("#{sMessage3}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed); + dialog->eventCancelClicked.clear(); + } + } + + void SaveGameDialog::onDeleteSlotConfirmed() + { + MWBase::Environment::get().getStateManager()->deleteGame (mCurrentCharacter, mCurrentSlot); + mSaveList->removeItemAt(mSaveList->getIndexSelected()); + onSlotSelected(mSaveList, MyGUI::ITEM_NONE); + + // The character might be deleted now + size_t previousIndex = mCharacterSelection->getIndexSelected(); + open(); + if (mCharacterSelection->getItemCount()) + { + size_t nextCharacter = std::min(previousIndex, mCharacterSelection->getItemCount()-1); + mCharacterSelection->setIndexSelected(nextCharacter); + onCharacterSelected(mCharacterSelection, nextCharacter); + } + } + void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender) { // This might have previously been a save slot from the list. If so, that is no longer the case @@ -69,6 +102,12 @@ namespace MWGui center(); + mCharacterSelection->setCaption(""); + mCharacterSelection->removeAllItems(); + mCurrentCharacter = NULL; + mCurrentSlot = NULL; + mSaveList->removeAllItems(); + MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager(); if (mgr->characterBegin() == mgr->characterEnd()) return; @@ -78,8 +117,6 @@ namespace MWGui std::string directory = Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves")); - mCharacterSelection->removeAllItems(); - int selectedIndex = MyGUI::ITEM_NONE; for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it) @@ -152,23 +189,10 @@ namespace MWGui { MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL); - // Get the selected slot, if any - unsigned int i=0; - const MWState::Slot* slot = NULL; - - if (mCurrentCharacter) - { - for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it,++i) - { - if (i == mSaveList->getIndexSelected()) - slot = &*it; - } - } - if (mSaving) { // If overwriting an existing slot, ask for confirmation first - if (slot != NULL && !reallySure) + if (mCurrentSlot != NULL && !reallySure) { ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sMessage4}"); @@ -182,13 +206,13 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}"); return; } - MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), slot); + MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), mCurrentSlot); } else { - if (mCurrentCharacter && slot) + if (mCurrentCharacter && mCurrentSlot) { - MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); + MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot); MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); } } @@ -221,6 +245,7 @@ namespace MWGui assert(character && "Can't find selected character"); mCurrentCharacter = character; + mCurrentSlot = NULL; fillSaveList(); } @@ -240,6 +265,7 @@ namespace MWGui { if (pos == MyGUI::ITEM_NONE) { + mCurrentSlot = NULL; mInfoText->setCaption(""); mScreenshot->setImageTexture(""); return; @@ -248,17 +274,17 @@ namespace MWGui if (mSaving) mSaveNameEdit->setCaption(sender->getItemNameAt(pos)); - const MWState::Slot* slot = NULL; + mCurrentSlot = NULL; unsigned int i=0; for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it, ++i) { if (i == pos) - slot = &*it; + mCurrentSlot = &*it; } - assert(slot && "Can't find selected slot"); + assert(mCurrentSlot && "Can't find selected slot"); std::stringstream text; - time_t time = slot->mTimeStamp; + time_t time = mCurrentSlot->mTimeStamp; struct tm* timeinfo; timeinfo = localtime(&time); @@ -269,24 +295,24 @@ namespace MWGui char buffer[size]; if (std::strftime(buffer, size, "%x %X", timeinfo) > 0) text << buffer << "\n"; - text << "Level " << slot->mProfile.mPlayerLevel << "\n"; - text << slot->mProfile.mPlayerCell << "\n"; + text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; + text << mCurrentSlot->mProfile.mPlayerCell << "\n"; // text << "Time played: " << slot->mProfile.mTimePlayed << "\n"; - int hour = int(slot->mProfile.mInGameTime.mGameHour); + int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour); bool pm = hour >= 12; if (hour >= 13) hour -= 12; if (hour == 0) hour = 12; text - << slot->mProfile.mInGameTime.mDay << " " - << MWBase::Environment::get().getWorld()->getMonthName(slot->mProfile.mInGameTime.mMonth) + << mCurrentSlot->mProfile.mInGameTime.mDay << " " + << MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth) << " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}"); mInfoText->setCaptionWithReplacing(text.str()); // Decode screenshot - std::vector data = slot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :( + std::vector data = mCurrentSlot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :( Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size())); Ogre::Image image; image.load(stream, "jpg"); diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index 8d09a1cbc1..42c29f4bc9 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -6,6 +6,7 @@ namespace MWState { class Character; + class Slot; } namespace MWGui @@ -24,8 +25,15 @@ namespace MWGui void onCancelButtonClicked (MyGUI::Widget* sender); void onOkButtonClicked (MyGUI::Widget* sender); void onCharacterSelected (MyGUI::ComboBox* sender, size_t pos); + // Slot selected (mouse click or arrow keys) void onSlotSelected (MyGUI::ListBox* sender, size_t pos); + // Slot activated (double click or enter key) void onSlotActivated (MyGUI::ListBox* sender, size_t pos); + // Slot clicked with mouse + void onSlotMouseClick(MyGUI::ListBox* sender, size_t pos); + + void onDeleteSlotConfirmed(); + void onEditSelectAccept (MyGUI::EditBox* sender); void onSaveNameChanged (MyGUI::EditBox* sender); void onConfirmationGiven(); @@ -46,6 +54,7 @@ namespace MWGui MyGUI::Widget* mSpacer; const MWState::Character* mCurrentCharacter; + const MWState::Slot* mCurrentSlot; }; diff --git a/apps/openmw/mwstate/character.cpp b/apps/openmw/mwstate/character.cpp index 304eaddd35..5fe80ce0ca 100644 --- a/apps/openmw/mwstate/character.cpp +++ b/apps/openmw/mwstate/character.cpp @@ -95,6 +95,21 @@ MWState::Character::Character (const boost::filesystem::path& saves, const std:: } } +void MWState::Character::cleanup() +{ + if (mSlots.size() == 0) + { + // All slots are gone, no need to keep the empty directory + if (boost::filesystem::is_directory (mPath)) + { + // Extra safety check to make sure the directory is empty (e.g. slots failed to parse header) + boost::filesystem::directory_iterator it(mPath); + if (it == boost::filesystem::directory_iterator()) + boost::filesystem::remove_all(mPath); + } + } +} + const MWState::Slot *MWState::Character::createSlot (const ESM::SavedGame& profile) { addSlot (profile); @@ -102,6 +117,21 @@ const MWState::Slot *MWState::Character::createSlot (const ESM::SavedGame& profi return &mSlots.back(); } +void MWState::Character::deleteSlot (const Slot *slot) +{ + int index = slot - &mSlots[0]; + + if (index<0 || index>=static_cast (mSlots.size())) + { + // sanity check; not entirely reliable + throw std::logic_error ("slot not found"); + } + + boost::filesystem::remove(slot->mPath); + + mSlots.erase (mSlots.begin()+index); +} + const MWState::Slot *MWState::Character::updateSlot (const Slot *slot, const ESM::SavedGame& profile) { int index = slot - &mSlots[0]; @@ -150,4 +180,4 @@ ESM::SavedGame MWState::Character::getSignature() const slot = *iter; return slot.mProfile; -} \ No newline at end of file +} diff --git a/apps/openmw/mwstate/character.hpp b/apps/openmw/mwstate/character.hpp index 61e4e5b25f..8745332892 100644 --- a/apps/openmw/mwstate/character.hpp +++ b/apps/openmw/mwstate/character.hpp @@ -36,11 +36,19 @@ namespace MWState Character (const boost::filesystem::path& saves, const std::string& game); + void cleanup(); + ///< Delete the directory we used, if it is empty + const Slot *createSlot (const ESM::SavedGame& profile); ///< Create new slot. /// /// \attention The ownership of the slot is not transferred. + /// \note Slot must belong to this character. + /// + /// \attention The \a slot pointer will be invalidated by this call. + void deleteSlot (const Slot *slot); + const Slot *updateSlot (const Slot *slot, const ESM::SavedGame& profile); /// \note Slot must belong to this character. /// diff --git a/apps/openmw/mwstate/charactermanager.cpp b/apps/openmw/mwstate/charactermanager.cpp index 2a40fb1cc5..822e2d88e1 100644 --- a/apps/openmw/mwstate/charactermanager.cpp +++ b/apps/openmw/mwstate/charactermanager.cpp @@ -47,6 +47,25 @@ MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create) return mCurrent; } +void MWState::CharacterManager::deleteSlot(const MWState::Character *character, const MWState::Slot *slot) +{ + int index = character - &mCharacters[0]; + + if (index<0 || index>=static_cast (mCharacters.size())) + throw std::logic_error ("invalid character"); + + mCharacters[index].deleteSlot(slot); + + if (mCharacters[index].begin() == mCharacters[index].end()) + { + // All slots deleted, cleanup and remove this character + mCharacters[index].cleanup(); + if (character == mCurrent) + mCurrent = NULL; + mCharacters.erase(mCharacters.begin() + index); + } +} + void MWState::CharacterManager::createCharacter() { std::ostringstream stream; diff --git a/apps/openmw/mwstate/charactermanager.hpp b/apps/openmw/mwstate/charactermanager.hpp index bc2e23f89a..869d34f21c 100644 --- a/apps/openmw/mwstate/charactermanager.hpp +++ b/apps/openmw/mwstate/charactermanager.hpp @@ -30,6 +30,8 @@ namespace MWState Character *getCurrentCharacter (bool create = true); ///< \param create Create a new character, if there is no current character. + void deleteSlot(const MWState::Character *character, const MWState::Slot *slot); + void createCharacter(); ///< Create new character within saved game management diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 6fbd4bb237..635ad1ff42 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -374,6 +374,11 @@ void MWState::StateManager::quickLoad() } } +void MWState::StateManager::deleteGame(const MWState::Character *character, const MWState::Slot *slot) +{ + mCharacterManager.deleteSlot(character, slot); +} + MWState::Character *MWState::StateManager::getCurrentCharacter (bool create) { return mCharacterManager.getCurrentCharacter (create); diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index 2d3ca21fbc..40c36deb5e 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -44,6 +44,9 @@ namespace MWState virtual void endGame(); + virtual void deleteGame (const MWState::Character *character, const MWState::Slot *slot); + ///< Delete a saved game slot from this character. If all save slots are deleted, the character will be deleted too. + virtual void saveGame (const std::string& description, const Slot *slot = 0); ///< Write a saved game to \a slot or create a new slot if \a slot == 0. /// From 3780503275d2e3380ff10c2e91231e25402db4a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 07:07:03 +0200 Subject: [PATCH 101/545] Removed quicksave/quickload message boxes, now that the same text is shown in the progress bar --- apps/openmw/mwstate/statemanagerimp.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 635ad1ff42..33f2dce7c3 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -253,8 +253,6 @@ void MWState::StateManager::quickSave (std::string name) slot = &*it; } - MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage4}"); - saveGame(name, slot); } @@ -368,10 +366,7 @@ void MWState::StateManager::quickLoad() { if (Character* mCurrentCharacter = getCurrentCharacter (false)) if (const MWState::Slot* slot = &*mCurrentCharacter->begin()) //Get newest save - { - //MWBase::Environment::get().getWindowManager()->messageBox("#{sLoadingMessage14}"); //it overlaps loadGame (mCurrentCharacter, slot); - } } void MWState::StateManager::deleteGame(const MWState::Character *character, const MWState::Slot *slot) From 9b36a138217389315f8be4c7b85878f1a4998c68 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 09:09:51 +0200 Subject: [PATCH 102/545] Feature #1289: NPCs return to default position Make stationary NPCs return to their previous position once combat/crime AI finishes. --- apps/openmw/mwmechanics/actors.cpp | 12 ++++---- apps/openmw/mwmechanics/aisequence.cpp | 12 +++++++- apps/openmw/mwmechanics/aisequence.hpp | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 40 +++++++++++++++++++++++++- apps/openmw/mwmechanics/aiwander.hpp | 11 +++++++ apps/openmw/mwscript/aiextensions.cpp | 16 +++++------ 6 files changed, 76 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 2de5e268fc..b87bc453c4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -206,7 +206,7 @@ namespace MWMechanics if (LOS) { - creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr())); + creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr); creatureStats.setHostile(true); } } @@ -537,7 +537,7 @@ namespace MWMechanics // TODO: Add AI to follow player and fight for him AiFollow package(ptr.getRefData().getHandle()); - MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package); + MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr); // TODO: VFX_SummonStart, VFX_SummonEnd creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle())); @@ -732,7 +732,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ); } @@ -761,9 +761,9 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player))); + creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); else - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); } } @@ -771,7 +771,7 @@ namespace MWMechanics // if I didn't report a crime was I attacked? else if (creatureStats.getAttacked() && !creatureStats.isHostile()) { - creatureStats.getAiSequence().stack(AiCombat(player)); + creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); } } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index c67367a6c7..2581d52c9f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -116,8 +116,18 @@ void MWMechanics::AiSequence::clear() mPackages.clear(); } -void MWMechanics::AiSequence::stack (const AiPackage& package) +void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) { + if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPersue) + { + // Notify AiWander of our current position so we can return to it after combat finished + for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) + { + if ((*iter)->getTypeId() == AiPackage::TypeIdWander) + static_cast(*iter)->setReturnPosition(Ogre::Vector3(actor.getRefData().getPosition().pos)); + } + } + for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); it++) { if(mPackages.front()->getPriority() <= package.getPriority()) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 07b7c898ce..cb1b0de02f 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -62,7 +62,7 @@ namespace MWMechanics void clear(); ///< Remove all packages. - void stack (const AiPackage& package); + void stack (const AiPackage& package, const MWWorld::Ptr& actor); ///< Add \a package to the front of the sequence (suspends current package) void queue (const AiPackage& package); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ad94be0eb4..972c4553d7 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -37,6 +37,8 @@ namespace MWMechanics , mRotate(false) , mTargetAngle(0) , mSaidGreeting(false) + , mHasReturnPosition(false) + , mReturnPosition(0,0,0) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) { @@ -330,6 +332,37 @@ namespace MWMechanics if(mDistance && cellChange) mDistance = 0; + // For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere + if (cellChange) + mHasReturnPosition = false; + if (mDistance == 0 && mHasReturnPosition && Ogre::Vector3(pos.pos).squaredDistance(mReturnPosition) > 20*20) + { + mChooseAction = false; + mIdleNow = false; + + Ogre::Vector3 destNodePos = mReturnPosition; + + ESM::Pathgrid::Point dest; + dest.mX = destNodePos[0]; + dest.mY = destNodePos[1]; + dest.mZ = destNodePos[2]; + + // actor position is already in world co-ordinates + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + // don't take shortcuts for wandering + mPathFinder.buildPath(start, dest, actor.getCell(), false); + + if(mPathFinder.isPathConstructed()) + { + mMoveNow = false; + mWalking = true; + } + } + if(mChooseAction) { mPlayedIdle = 0; @@ -375,7 +408,7 @@ namespace MWMechanics } // Allow interrupting a walking actor to trigger a greeting - if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState())) + if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState() && mDistance)) { // Play a random voice greeting if the player gets too close int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); @@ -586,5 +619,10 @@ namespace MWMechanics else return false; } + + void AiWander::setReturnPosition(const Ogre::Vector3& position) + { + mHasReturnPosition = true; mReturnPosition = position; + } } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index fe14abeb61..a789a372ed 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -2,8 +2,11 @@ #define GAME_MWMECHANICS_AIWANDER_H #include "aipackage.hpp" + #include +#include + #include "pathfinding.hpp" #include "obstacle.hpp" @@ -22,6 +25,10 @@ namespace MWMechanics virtual int getTypeId() const; ///< 0: Wander + void setReturnPosition (const Ogre::Vector3& position); + ///< Set the position to return to for a stationary (non-wandering) actor, in case + /// another AI package moved the actor elsewhere + private: void stopWalking(const MWWorld::Ptr& actor); void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); @@ -38,6 +45,10 @@ namespace MWMechanics float mGreetDistanceReset; float mChance; + bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, + // if we had the actor in the AiWander constructor... + Ogre::Vector3 mReturnPosition; + // Cached current cell location int mCellX; int mCellY; diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index a34c5476c9..43da111bf4 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -48,7 +48,7 @@ namespace MWScript for (unsigned int i=0; igetPtr(targetID, true) )); + MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor); } }; From 28ef236f0e878523f0c36544136d2516d14764ee Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 11:17:07 +0200 Subject: [PATCH 103/545] Don't allow setting a new return position if there already is one and we haven't reached it yet --- apps/openmw/mwmechanics/aiwander.cpp | 48 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 722010686a..7120ff5afc 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -341,26 +341,29 @@ namespace MWMechanics mChooseAction = false; mIdleNow = false; - Ogre::Vector3 destNodePos = mReturnPosition; - - ESM::Pathgrid::Point dest; - dest.mX = destNodePos[0]; - dest.mY = destNodePos[1]; - dest.mZ = destNodePos[2]; - - // actor position is already in world co-ordinates - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - // don't take shortcuts for wandering - mPathFinder.buildPath(start, dest, actor.getCell(), false); - - if(mPathFinder.isPathConstructed()) + if (!mPathFinder.isPathConstructed()) { - mMoveNow = false; - mWalking = true; + Ogre::Vector3 destNodePos = mReturnPosition; + + ESM::Pathgrid::Point dest; + dest.mX = destNodePos[0]; + dest.mY = destNodePos[1]; + dest.mZ = destNodePos[2]; + + // actor position is already in world co-ordinates + ESM::Pathgrid::Point start; + start.mX = pos.pos[0]; + start.mY = pos.pos[1]; + start.mZ = pos.pos[2]; + + // don't take shortcuts for wandering + mPathFinder.buildPath(start, dest, actor.getCell(), false); + + if(mPathFinder.isPathConstructed()) + { + mMoveNow = false; + mWalking = true; + } } } @@ -529,6 +532,7 @@ namespace MWMechanics mMoveNow = false; mWalking = false; mChooseAction = true; + mHasReturnPosition = false; } return false; // AiWander package not yet completed @@ -615,7 +619,11 @@ namespace MWMechanics void AiWander::setReturnPosition(const Ogre::Vector3& position) { - mHasReturnPosition = true; mReturnPosition = position; + if (!mHasReturnPosition) + { + mHasReturnPosition = true; + mReturnPosition = position; + } } void AiWander::getRandomIdle() From 853abb65c3e7b87bcaced7225bebe9d7ea358644 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 29 Apr 2014 11:19:19 +0200 Subject: [PATCH 104/545] added new, later common, base for the regionmap and the table --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/tablemimedata.cpp | 2 +- apps/opencs/model/world/tablemimedata.hpp | 2 +- apps/opencs/view/world/dragrecordtable.cpp | 21 ++++++++++ apps/opencs/view/world/dragrecordtable.hpp | 36 ++++++++++++++++ apps/opencs/view/world/regionmap.cpp | 7 +++- apps/opencs/view/world/regionmap.hpp | 2 + apps/opencs/view/world/table.cpp | 49 ++++++++-------------- apps/opencs/view/world/table.hpp | 7 +++- 9 files changed, 90 insertions(+), 38 deletions(-) create mode 100644 apps/opencs/view/world/dragrecordtable.cpp create mode 100644 apps/opencs/view/world/dragrecordtable.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cbe90b1d3e..7a9320904f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool - scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap + scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable ) opencs_units (view/render diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index d7b7728a5e..93810a252e 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -11,7 +11,7 @@ mDocument(document) mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str()); } -CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : +CSMWorld::TableMimeData::TableMimeData (const std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : mUniversalId (id), mDocument(document) { for (std::vector::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it) diff --git a/apps/opencs/model/world/tablemimedata.hpp b/apps/opencs/model/world/tablemimedata.hpp index adcb147c18..9ca7128018 100644 --- a/apps/opencs/model/world/tablemimedata.hpp +++ b/apps/opencs/model/world/tablemimedata.hpp @@ -33,7 +33,7 @@ namespace CSMWorld public: TableMimeData(UniversalId id, const CSMDoc::Document& document); - TableMimeData(std::vector& id, const CSMDoc::Document& document); + TableMimeData(const std::vector& id, const CSMDoc::Document& document); ~TableMimeData(); diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp new file mode 100644 index 0000000000..4aa13308a1 --- /dev/null +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -0,0 +1,21 @@ +#include + +#include "../../model/world/tablemimedata.hpp" +#include "dragrecordtable.hpp" + +void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table) +{ + CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDragedRecords(), mDocument); + + if (mime) + { + QDrag* drag = new QDrag (this); + drag->setMimeData (mime); + drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str())); + drag->exec (Qt::CopyAction); + } +} + +CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document) : +mDocument(document) +{} diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp new file mode 100644 index 0000000000..4e5389f061 --- /dev/null +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -0,0 +1,36 @@ +#ifndef CSV_WORLD_REGIONMAP_H +#define CSV_WORLD_REGIONMAP_H + +#include + +class QAction; + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class UniversalId; +} + +namespace CSVWorld +{ + class DragRecordTable : public QTableView + { + protected: + CSMDoc::Document& mDocument; + + public: + DragRecordTable(CSMDoc::Document& document); + + virtual std::vector getDragedRecords() const = 0; + + protected: + void startDrag(const DragRecordTable& table); + }; +} + +#endif + diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 738de89ae6..bfce1fce46 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -17,6 +17,7 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" +#include "../../model/world/tablemimedata.hpp" void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event) { @@ -343,4 +344,8 @@ void CSVWorld::RegionMap::viewInTable() hint << ")"; emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str()); -} \ No newline at end of file +} + +void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) +{ +} diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index c3757fe45b..d894fd9ccf 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -50,6 +50,8 @@ namespace CSVWorld void setRegion (const std::string& regionId); ///< Set region Id of selected cells. + void mouseMoveEvent(QMouseEvent *event); + public: RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 712b8f5569..d700d5f2e2 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -189,7 +189,7 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) : mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), - mDocument (document) + DragRecordTable(document) { mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); @@ -512,37 +512,8 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) { if (event->buttons() & Qt::LeftButton) { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - if (selectedRows.size() == 0) - { - return; - } - - QDrag* drag = new QDrag (this); - CSMWorld::TableMimeData* mime = NULL; - - if (selectedRows.size() == 1) - { - mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument); - } - else - { - std::vector idToDrag; - - foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW. - { - idToDrag.push_back (getUniversalId (it.row())); - } - - mime = new CSMWorld::TableMimeData (idToDrag, mDocument); - } - - drag->setMimeData (mime); - drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str())); - drag->exec(Qt::CopyAction); + startDrag(*this); } - } void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event) @@ -598,4 +569,18 @@ std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column } } return titles; -} \ No newline at end of file +} + +std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDragedRecords() const +{ + + QModelIndexList selectedRows = selectionModel()->selectedRows(); + std::vector idToDrag; + + foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW. + { + idToDrag.push_back (getUniversalId (it.row())); + } + + return idToDrag; +} diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 4231a4a432..926ba0e956 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -9,6 +9,7 @@ #include "../../model/filter/node.hpp" #include "../../model/world/columnbase.hpp" +#include "dragrecordtable.hpp" class QUndoStack; class QAction; @@ -24,6 +25,7 @@ namespace CSMWorld class UniversalId; class IdTableProxyModel; class IdTable; + class TableMimeData; } namespace CSVWorld @@ -31,7 +33,7 @@ namespace CSVWorld class CommandDelegate; ///< Table widget - class Table : public QTableView + class Table : public DragRecordTable { Q_OBJECT @@ -49,7 +51,6 @@ namespace CSVWorld CSMWorld::IdTable *mModel; bool mEditLock; int mRecordStatusDisplay; - CSMDoc::Document& mDocument; private: @@ -82,6 +83,8 @@ namespace CSVWorld std::vector getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; + virtual std::vector getDragedRecords() const; + signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); From 18fc8acc71c5d8839668c1cadc2555fdc6b4b438 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 29 Apr 2014 12:27:26 +0200 Subject: [PATCH 105/545] able to drag existing cells from the regionmap --- apps/opencs/view/world/dragrecordtable.cpp | 5 +++-- apps/opencs/view/world/dragrecordtable.hpp | 9 +++++---- apps/opencs/view/world/regionmap.cpp | 17 ++++++++++++++++- apps/opencs/view/world/regionmap.hpp | 11 +++++++++-- apps/opencs/view/world/table.hpp | 2 -- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 4aa13308a1..f962f6f10f 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -16,6 +16,7 @@ void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& tabl } } -CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document) : -mDocument(document) +CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) : +mDocument(document), +QTableView(parent) {} diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 4e5389f061..7a2b517430 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -1,8 +1,9 @@ -#ifndef CSV_WORLD_REGIONMAP_H -#define CSV_WORLD_REGIONMAP_H +#ifndef CSV_WORLD_DRAGRECORDTABLE_H +#define CSV_WORLD_DRAGRECORDTABLE_H #include +class QWidget; class QAction; namespace CSMDoc @@ -23,7 +24,7 @@ namespace CSVWorld CSMDoc::Document& mDocument; public: - DragRecordTable(CSMDoc::Document& document); + DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL); virtual std::vector getDragedRecords() const = 0; @@ -33,4 +34,4 @@ namespace CSVWorld } #endif - + diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index bfce1fce46..85b79c3f2c 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -181,7 +181,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId) CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent) -: QTableView (parent), mEditLock (false), mDocument (document) +: mEditLock (false), DragRecordTable(document, parent) { verticalHeader()->hide(); horizontalHeader()->hide(); @@ -348,4 +348,19 @@ void CSVWorld::RegionMap::viewInTable() void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) { + startDrag(*this); +} + +std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDragedRecords() const +{ + QModelIndexList selected = getSelectedCells(); + std::vector ids; + foreach (QModelIndex it, selected) + { + ids.push_back( + CSMWorld::UniversalId + (CSMWorld::UniversalId::Type_Cell, + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + } + return ids; } diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index d894fd9ccf..596ddfaed5 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -1,8 +1,14 @@ #ifndef CSV_WORLD_REGIONMAP_H #define CSV_WORLD_REGIONMAP_H +#include +#include + +#include #include +#include "./dragrecordtable.hpp" + class QAction; namespace CSMDoc @@ -17,7 +23,7 @@ namespace CSMWorld namespace CSVWorld { - class RegionMap : public QTableView + class RegionMap : public DragRecordTable { Q_OBJECT @@ -30,7 +36,6 @@ namespace CSVWorld QAction *mViewAction; QAction *mViewInTableAction; bool mEditLock; - CSMDoc::Document& mDocument; std::string mRegionId; private: @@ -59,6 +64,8 @@ namespace CSVWorld void setEditLock (bool locked); + virtual std::vector getDragedRecords() const; + signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 926ba0e956..30b487ce84 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include "../../model/filter/node.hpp" @@ -25,7 +24,6 @@ namespace CSMWorld class UniversalId; class IdTableProxyModel; class IdTable; - class TableMimeData; } namespace CSVWorld From 2906ade5316099ed899906d26eb66391a72aed45 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 13:16:58 +0200 Subject: [PATCH 106/545] string fix --- apps/opencs/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 2dfdb1de66..f6370ac51f 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -121,7 +121,7 @@ std::pair > CS::Editor::readConfi //iterate the data directories and add them to the file dialog for loading for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) { - QString path = QString::fromStdString(iter->string()); + QString path = QString::fromUtf8 (iter->string().c_str()); mFileDialog.addFiles(path); } /* From 5f1d2f72f6bf052f142485ba6cb5c1f7733ab40d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 14:17:25 +0200 Subject: [PATCH 107/545] added basic loading GUI --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/documentmanager.cpp | 7 ++-- apps/opencs/model/doc/documentmanager.hpp | 5 ++- apps/opencs/model/doc/loader.cpp | 2 +- apps/opencs/model/doc/loader.hpp | 2 +- apps/opencs/view/doc/loader.cpp | 44 ++++++++++++++++++++++ apps/opencs/view/doc/loader.hpp | 46 +++++++++++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 7 ++++ apps/opencs/view/doc/viewmanager.hpp | 3 ++ 9 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 apps/opencs/view/doc/loader.cpp create mode 100644 apps/opencs/view/doc/loader.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f1d50467bd..e19242e092 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -44,7 +44,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc viewmanager view operations operation subview startup filedialog newgame - filewidget adjusterwidget + filewidget adjusterwidget loader ) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index b8372eb4c5..4658667c3b 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,8 +27,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentLoaded (Document *))); connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)), this, SLOT (documentNotLoaded (Document *, const std::string&))); - connect (this, SIGNAL (loadRequest (Document *, bool)), - &mLoader, SLOT (loadDocument (Document *, bool))); + connect (this, SIGNAL (loadRequest (CSMDoc::Document *, bool)), + &mLoader, SLOT (loadDocument (CSMDoc::Document *, bool))); } CSMDoc::DocumentManager::~DocumentManager() @@ -75,10 +75,11 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par void CSMDoc::DocumentManager::documentLoaded (Document *document) { emit documentAdded (document); + emit loadingStopped (document, true, ""); } void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error) { +// emit loadingStopped (document, false, error); removeDocument (document); - /// \todo report error } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 1af18a1484..63ee5eb68d 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -65,9 +65,12 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); - void loadRequest (Document *document, bool _new); + void loadRequest (CSMDoc::Document *document, bool _new); void lastDocumentDeleted(); + + void loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 722e903641..53827deb0b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -46,7 +46,7 @@ void CSMDoc::Loader::load() } } -void CSMDoc::Loader::loadDocument (Document *document, bool new_) +void CSMDoc::Loader::loadDocument (CSMDoc::Document *document, bool new_) { mDocuments.push_back (std::make_pair (document, new_)); } diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index eae0c8001a..af266d52bf 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -31,7 +31,7 @@ namespace CSMDoc public slots: - void loadDocument (Document *document, bool new_); + void loadDocument (CSMDoc::Document *document, bool new_); ///< The ownership of \a document is not transferred. /// \param new_ Do not load the last content file in the files list specified in /// \a document and instead create it in an appropriate way. diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp new file mode 100644 index 0000000000..f840ab7175 --- /dev/null +++ b/apps/opencs/view/doc/loader.cpp @@ -0,0 +1,44 @@ + +#include "loader.hpp" + +#include "../../model/doc/document.hpp" + +CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) +{ + setWindowTitle (("Loading " + document->getSavePath().filename().string()).c_str()); + show(); +} + + +CSVDoc::Loader::Loader() +{ + +} + +CSVDoc::Loader::~Loader() +{ + for (std::map::iterator iter (mDocuments.begin()); + iter!=mDocuments.end(); ++iter) + delete iter->second; +} + +void CSVDoc::Loader::add (CSMDoc::Document *document, bool new_) +{ + mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); +} + +void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error) +{ + if (completed || error.empty()) + { + for (std::map::iterator iter (mDocuments.begin()); + iter!=mDocuments.end(); ++iter) + if (iter->first==document) + { + delete iter->second; + mDocuments.erase (iter); + break; + } + } +} \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp new file mode 100644 index 0000000000..4aa497482d --- /dev/null +++ b/apps/opencs/view/doc/loader.hpp @@ -0,0 +1,46 @@ +#ifndef CSV_DOC_LOADER_H +#define CSV_DOC_LOADER_H + +#include + +#include +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class LoadingDocument : public QWidget + { + Q_OBJECT + + public: + + LoadingDocument (CSMDoc::Document *document); + }; + + class Loader : public QObject + { + Q_OBJECT + + std::map mDocuments; + + public: + + Loader(); + + virtual ~Loader(); + + public slots: + + void add (CSMDoc::Document *document, bool new_); + + void loadingStopped (CSMDoc::Document *document, bool completed, + const std::string& error); + }; +} + +#endif diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 4a4dbc1244..3ca52c452a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -86,6 +86,13 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); + + connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *, bool)), + &mLoader, SLOT (add (CSMDoc::Document *, bool))); + + connect ( + &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), + &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 01f4951864..cddc1b2359 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -5,6 +5,8 @@ #include +#include "loader.hpp" + namespace CSMDoc { class Document; @@ -29,6 +31,7 @@ namespace CSVDoc CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; bool mExitOnSaveStateChange; bool mUserWarned; + Loader mLoader; // not implemented ViewManager (const ViewManager&); From 8dc6ad505937ad3f9aa80ddc405db703d439976e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 14:27:44 +0200 Subject: [PATCH 108/545] moved new flag from setupData function to Document constructor --- apps/opencs/model/doc/document.cpp | 19 ++++++++++++------- apps/opencs/model/doc/document.hpp | 8 ++++++-- apps/opencs/model/doc/documentmanager.cpp | 8 ++++---- apps/opencs/model/doc/documentmanager.hpp | 2 +- apps/opencs/model/doc/loader.cpp | 7 +++---- apps/opencs/model/doc/loader.hpp | 4 +--- apps/opencs/view/doc/loader.cpp | 2 +- apps/opencs/view/doc/loader.hpp | 2 +- apps/opencs/view/doc/viewmanager.cpp | 4 ++-- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 20a355d483..25b48a3c9a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2220,9 +2220,9 @@ void CSMDoc::Document::createBase() } CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, - const std::vector< boost::filesystem::path >& files, + const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir) -: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir), +: mSavePath (savePath), mContentFiles (files), mNew (new_), mTools (mData), mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSaving (*this, mProjectPath) @@ -2260,21 +2260,21 @@ CSMDoc::Document::~Document() { } -void CSMDoc::Document::setupData (bool new_) +void CSMDoc::Document::setupData() { - if (new_ && mContentFiles.size()==1) + if (mNew && mContentFiles.size()==1) createBase(); else { std::vector::const_iterator end = mContentFiles.end(); - if (new_) + if (mNew) --end; - load (mContentFiles.begin(), end, !new_); + load (mContentFiles.begin(), end, !mNew); } - if (new_) + if (mNew) { mData.setDescription (""); mData.setAuthor (""); @@ -2317,6 +2317,11 @@ const std::vector& CSMDoc::Document::getContentFiles() return mContentFiles; } +bool CSMDoc::Document::isNew() const +{ + return mNew; +} + void CSMDoc::Document::save() { if (mSaving.isRunning()) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index c7d87e16a0..e19efd04ec 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -39,6 +39,7 @@ namespace CSMDoc boost::filesystem::path mSavePath; std::vector mContentFiles; + bool mNew; CSMWorld::Data mData; CSMTools::Tools mTools; boost::filesystem::path mProjectPath; @@ -72,12 +73,12 @@ namespace CSMDoc public: Document (const Files::ConfigurationManager& configuration, - const std::vector< boost::filesystem::path >& files, + const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir); ~Document(); - void setupData (bool new_); + void setupData(); QUndoStack& getUndoStack(); @@ -89,6 +90,9 @@ namespace CSMDoc ///< \attention The last element in this collection is the file that is being edited, /// but with its original path instead of the save path. + bool isNew() const; + ///< Is this a newly created content file? + void save(); CSMWorld::UniversalId verify(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 4658667c3b..ae6f1103fc 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -27,8 +27,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentLoaded (Document *))); connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)), this, SLOT (documentNotLoaded (Document *, const std::string&))); - connect (this, SIGNAL (loadRequest (CSMDoc::Document *, bool)), - &mLoader, SLOT (loadDocument (CSMDoc::Document *, bool))); + connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), + &mLoader, SLOT (loadDocument (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() @@ -44,11 +44,11 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, savePath, mResDir); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir); mDocuments.push_back (document); - emit loadRequest (document, new_); + emit loadRequest (document); mLoader.hasThingsToDo().wakeAll(); } diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 63ee5eb68d..4adc9726ce 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -65,7 +65,7 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); - void loadRequest (CSMDoc::Document *document, bool _new); + void loadRequest (CSMDoc::Document *document); void lastDocumentDeleted(); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 53827deb0b..dbaa2b4d5b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -31,13 +31,12 @@ void CSMDoc::Loader::load() std::vector >::iterator iter = mDocuments.begin(); Document *document = iter->first; - bool new_ = iter->second; mDocuments.erase (iter); try { - document->setupData (new_); + document->setupData(); emit documentLoaded (document); } catch (const std::exception& e) @@ -46,9 +45,9 @@ void CSMDoc::Loader::load() } } -void CSMDoc::Loader::loadDocument (CSMDoc::Document *document, bool new_) +void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) { - mDocuments.push_back (std::make_pair (document, new_)); + mDocuments.push_back (std::make_pair (document, false)); } void CSMDoc::Loader::abortLoading (Document *document) diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index af266d52bf..4e3db1815c 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -31,10 +31,8 @@ namespace CSMDoc public slots: - void loadDocument (CSMDoc::Document *document, bool new_); + void loadDocument (CSMDoc::Document *document); ///< The ownership of \a document is not transferred. - /// \param new_ Do not load the last content file in the files list specified in - /// \a document and instead create it in an appropriate way. void abortLoading (Document *document); ///< Abort loading \a docuemnt (ignored if \a document has already finished being diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index f840ab7175..15296d616b 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -22,7 +22,7 @@ CSVDoc::Loader::~Loader() delete iter->second; } -void CSVDoc::Loader::add (CSMDoc::Document *document, bool new_) +void CSVDoc::Loader::add (CSMDoc::Document *document) { mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index 4aa497482d..cb154b13e6 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -36,7 +36,7 @@ namespace CSVDoc public slots: - void add (CSMDoc::Document *document, bool new_); + void add (CSMDoc::Document *document); void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 3ca52c452a..c18cca8091 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -87,8 +87,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); - connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *, bool)), - &mLoader, SLOT (add (CSMDoc::Document *, bool))); + connect (&mDocumentManager, SIGNAL (loadRequest (CSMDoc::Document *)), + &mLoader, SLOT (add (CSMDoc::Document *))); connect ( &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), From 7d990abd376891c91c233410c4e06e66ae926eff Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 29 Apr 2014 22:46:55 +1000 Subject: [PATCH 109/545] OpenCS changes to allow compilation with MSVC 11.0. --- apps/opencs/model/settings/usersettings.cpp | 6 +++--- apps/opencs/view/world/dialoguesubview.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 2f8e8098da..fa89fceee0 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -195,13 +195,13 @@ CSMSettings::UserSettings::~UserSettings() void CSMSettings::UserSettings::loadSettings (const QString &fileName) { mUserFilePath = QString::fromUtf8 - (mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8(); + (mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8(); QString global = QString::fromUtf8 - (mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8(); + (mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8(); QString local = QString::fromUtf8 - (mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8(); + (mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8(); //open user and global streams QTextStream *userStream = openFilestream (mUserFilePath, true); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index abdc331039..d03bf3f80e 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -183,7 +183,7 @@ CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CS { delegate = CommandDelegateFactoryCollection::get().makeDelegate ( display, mUndoStack, mParent); - mDelegates.insert(std::make_pair(display, delegate)); + mDelegates.insert(std::make_pair(display, delegate)); } else { delegate = delegateIt->second; From f6a876bc3d201baa52de4bc2dc76fe12e63b4fcf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 15:27:49 +0200 Subject: [PATCH 110/545] added actor ID --- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwmechanics/creaturestats.cpp | 18 +++++++++++++- apps/openmw/mwmechanics/creaturestats.hpp | 9 +++++++ apps/openmw/mwworld/cellstore.cpp | 29 +++++++++++++++++++++++ apps/openmw/mwworld/cellstore.hpp | 3 +++ apps/openmw/mwworld/scene.cpp | 10 ++++++++ apps/openmw/mwworld/scene.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 7 +++++- apps/openmw/mwworld/worldimp.hpp | 3 +++ 9 files changed, 82 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96bed..c397b190f5 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -200,6 +200,9 @@ namespace MWBase virtual MWWorld::Ptr searchPtrViaHandle (const std::string& handle) = 0; ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; + ///< Search is limited to the active cells. + /// \todo enable reference in the OGRE scene virtual void enable (const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 40ac92251d..8490226cbf 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -11,6 +11,8 @@ namespace MWMechanics { + int CreatureStats::sActorId = 0; + CreatureStats::CreatureStats() : mLevel (0), mDead (false), mDied (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false), @@ -18,7 +20,8 @@ namespace MWMechanics mAttackingOrSpell(false), mIsWerewolf(false), mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), - mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) + mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), + mActorId (-1) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -516,4 +519,17 @@ namespace MWMechanics { return mGoldPool; } + + int CreatureStats::getActorId() + { + if (mActorId==-1) + mActorId = sActorId++; + + return mActorId; + } + + bool CreatureStats::matchesActorId (int id) const + { + return mActorId!=-1 && id==mActorId; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 633dc285c9..23d9303c01 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -24,6 +24,7 @@ namespace MWMechanics /// class CreatureStats { + static int sActorId; DrawState_ mDrawState; AttributeValue mAttributes[8]; DynamicStat mDynamic[3]; // health, magicka, fatigue @@ -60,6 +61,7 @@ namespace MWMechanics MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay int mGoldPool; // the pool of merchant gold not in inventory + int mActorId; protected: bool mIsWerewolf; @@ -239,6 +241,13 @@ namespace MWMechanics void setGoldPool(int pool); int getGoldPool() const; + + int getActorId(); + ///< Will generate an actor ID, if the actor does not have one yet. + + bool matchesActorId (int id) const; + ///< Check if \a id matches the actor ID of *this (if the actor does not have an ID + /// assigned this function will return false). }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index e5f0c4b88a..7a85623cff 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -15,6 +15,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "ptr.hpp" #include "esmstore.hpp" #include "class.hpp" @@ -40,6 +42,22 @@ namespace return MWWorld::Ptr(); } + template + MWWorld::Ptr searchViaActorId (MWWorld::CellRefList& actorList, int actorId, + MWWorld::CellStore *cell) + { + for (typename MWWorld::CellRefList::List::iterator iter (actorList.mList.begin()); + iter!=actorList.mList.end(); ++iter) + { + MWWorld::Ptr actor (&*iter, cell); + + if (MWWorld::Class::get (actor).getCreatureStats (actor).matchesActorId (actorId)) + return actor; + } + + return MWWorld::Ptr(); + } + template void writeReferenceCollection (ESM::ESMWriter& writer, const MWWorld::CellRefList& collection) @@ -319,6 +337,17 @@ namespace MWWorld return Ptr(); } + Ptr CellStore::searchViaActorId (int id) + { + if (Ptr ptr = ::searchViaActorId (mNpcs, id, this)) + return ptr; + + if (Ptr ptr = ::searchViaActorId (mCreatures, id, this)) + return ptr; + + return Ptr(); + } + float CellStore::getWaterLevel() const { return mWaterLevel; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 88b49ed1c0..69d1a53a3e 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -80,6 +80,9 @@ namespace MWWorld Ptr searchViaHandle (const std::string& handle); ///< Will return an empty Ptr if cell is not loaded. + Ptr searchViaActorId (int id); + ///< Will return an empty Ptr if cell is not loaded. + float getWaterLevel() const; void setWaterLevel (float level); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3d4413a357..9d456e2362 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -496,4 +496,14 @@ namespace MWWorld } return false; } + + Ptr Scene::searchPtrViaActorId (int actorId) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaActorId (actorId)) + return ptr; + + return Ptr(); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 16d4877a92..b85a3d7ce2 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -102,6 +102,8 @@ namespace MWWorld ///< Remove an object from the scene, but not from the world model. bool isCellActive(const CellStore &cell); + + Ptr searchPtrViaActorId (int actorId); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index de9c8f04a6..79c8b38f38 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -549,6 +549,11 @@ namespace MWWorld return MWWorld::Ptr(); } + Ptr World::searchPtrViaActorId (int actorId) + { + return mWorldScene->searchPtrViaActorId (actorId); + } + void World::addContainerScripts(const Ptr& reference, CellStore * cell) { if( reference.getTypeName()==typeid (ESM::Container).name() || @@ -1909,7 +1914,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 645330683b..2328e67a8b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -287,6 +287,9 @@ namespace MWWorld virtual Ptr searchPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual Ptr searchPtrViaActorId (int actorId); + ///< Search is limited to the active cells. + virtual void adjustPosition (const Ptr& ptr); ///< Adjust position after load to be on ground. Must be called after model load. From 9a1b5dc1c64d54f64694eba5f9c21cf0e7dfcd25 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 15:32:00 +0200 Subject: [PATCH 111/545] a bit of cleanup --- apps/openmw/mwworld/scene.cpp | 10 ++++++++++ apps/openmw/mwworld/scene.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 11 +---------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 9d456e2362..b277b24945 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -497,6 +497,16 @@ namespace MWWorld return false; } + Ptr Scene::searchPtrViaHandle (const std::string& handle) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaHandle (handle)) + return ptr; + + return Ptr(); + } + Ptr Scene::searchPtrViaActorId (int actorId) { for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index b85a3d7ce2..a26ad99de6 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -103,6 +103,8 @@ namespace MWWorld bool isCellActive(const CellStore &cell); + Ptr searchPtrViaHandle (const std::string& handle); + Ptr searchPtrViaActorId (int actorId); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 79c8b38f38..6fa1828949 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -536,17 +536,8 @@ namespace MWWorld { if (mPlayer->getPlayer().getRefData().getHandle()==handle) return mPlayer->getPlayer(); - for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); - iter!=mWorldScene->getActiveCells().end(); ++iter) - { - CellStore* cellstore = *iter; - Ptr ptr = cellstore->searchViaHandle (handle); - if (!ptr.isEmpty()) - return ptr; - } - - return MWWorld::Ptr(); + return mWorldScene->searchPtrViaHandle (handle); } Ptr World::searchPtrViaActorId (int actorId) From 8f90dd43ecb62676323fb507ba7d014faa6d22f7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 12:52:08 -0400 Subject: [PATCH 112/545] Changed things to use typedef ScriptARgs/ScriptReturn, which makes finding out what those weird strings meant much much easier --- components/compiler/extensions.cpp | 10 ++++---- components/compiler/extensions.hpp | 38 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/components/compiler/extensions.cpp b/components/compiler/extensions.cpp index c09abcbafd..c2b11c6156 100644 --- a/components/compiler/extensions.cpp +++ b/components/compiler/extensions.cpp @@ -21,7 +21,7 @@ namespace Compiler return iter->second; } - bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType, + bool Extensions::isFunction (int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const { std::map::const_iterator iter = mFunctions.find (keyword); @@ -37,7 +37,7 @@ namespace Compiler return true; } - bool Extensions::isInstruction (int keyword, std::string& argumentType, + bool Extensions::isInstruction (int keyword, ScriptArgs& argumentType, bool& explicitReference) const { std::map::const_iterator iter = mInstructions.find (keyword); @@ -52,8 +52,8 @@ namespace Compiler return true; } - void Extensions::registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int code, int codeExplicit) + void Extensions::registerFunction (const std::string& keyword, ScriptReturn returnType, + const ScriptArgs& argumentType, int code, int codeExplicit) { Function function; @@ -83,7 +83,7 @@ namespace Compiler } void Extensions::registerInstruction (const std::string& keyword, - const std::string& argumentType, int code, int codeExplicit) + const ScriptArgs& argumentType, int code, int codeExplicit) { Instruction instruction; diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 18bb24ed09..5be81ac080 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -11,14 +11,36 @@ namespace Compiler { class Literals; - /// \brief Collection of compiler extensions + /// Typedef for script arguments string + /** Every character reperesents an argument to the command. All arguments are required until a /, after which + every argument is optional.
+ Eg: fff/f represents 3 required floats followed by one optional float
+ f - Float
+ c - String
+ l - Integer
+ s - Short
+ S - Also string (Seemed to be mostly used for Cell Names)
+ x - none? + **/ + typedef std::string ScriptArgs; + + /// Typedef for script return char + /** The character represents the type of data being returned.
+ f - float
+ S - String (Cell names)
+ l - Integer + **/ + typedef char ScriptReturn; + + /// \brief Collection of compiler extensions class Extensions { + struct Function { char mReturn; - std::string mArguments; + ScriptArgs mArguments; int mCode; int mCodeExplicit; int mSegment; @@ -26,7 +48,7 @@ namespace Compiler struct Instruction { - std::string mArguments; + ScriptArgs mArguments; int mCode; int mCodeExplicit; int mSegment; @@ -46,21 +68,21 @@ namespace Compiler /// - if no match is found 0 is returned. /// - keyword must be all lower case. - bool isFunction (int keyword, char& returnType, std::string& argumentType, + bool isFunction (int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const; ///< Is this keyword registered with a function? If yes, return return and argument /// types. /// \param explicitReference In: has explicit reference; Out: set to false, if /// explicit reference is not available for this instruction. - bool isInstruction (int keyword, std::string& argumentType, + bool isInstruction (int keyword, ScriptArgs& argumentType, bool& explicitReference) const; ///< Is this keyword registered with a function? If yes, return argument types. /// \param explicitReference In: has explicit reference; Out: set to false, if /// explicit reference is not available for this instruction. - void registerFunction (const std::string& keyword, char returnType, - const std::string& argumentType, int code, int codeExplicit = -1); + void registerFunction (const std::string& keyword, ScriptReturn returnType, + const ScriptArgs& argumentType, int code, int codeExplicit = -1); ///< Register a custom function /// - keyword must be all lower case. /// - keyword must be unique @@ -68,7 +90,7 @@ namespace Compiler /// \note Currently only segment 3 and segment 5 opcodes are supported. void registerInstruction (const std::string& keyword, - const std::string& argumentType, int code, int codeExplicit = -1); + const ScriptArgs& argumentType, int code, int codeExplicit = -1); ///< Register a custom instruction /// - keyword must be all lower case. /// - keyword must be unique From d376efe30bba36ebb427b3503cb9a387566b3bf5 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 29 Apr 2014 15:46:36 +0200 Subject: [PATCH 113/545] handle dragging not-existing records --- apps/opencs/model/world/columnbase.hpp | 1 + apps/opencs/model/world/tablemimedata.cpp | 8 +++++++- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 1 + apps/opencs/view/world/regionmap.cpp | 14 +++++++++++--- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index fe310d0aa4..53b55939b4 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -27,6 +27,7 @@ namespace CSMWorld enum Display { Display_None, //Do not use + Display_Cell_Missing, //Do not used, actually. It is here to simplify dragging non-existed cells handling Display_String, Display_LongString, diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index 93810a252e..e0a735e35b 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -33,7 +33,7 @@ std::string CSMWorld::TableMimeData::getIcon() const { if (mUniversalId.empty()) { - throw ("TableMimeData holds no UniversalId"); + return ""; } std::string tmpIcon; @@ -360,6 +360,8 @@ CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::Col case CSMWorld::ColumnBase::Display_Script: return CSMWorld::UniversalId::Type_Script; + case CSMWorld::ColumnBase::Display_Cell_Missing: + return CSMWorld::UniversalId::Type_Cell_Missing; //this one actually never happens, since there is no display_Cell_missing column anywhere. default: return CSMWorld::UniversalId::Type_None; @@ -375,6 +377,10 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U return CSMWorld::ColumnBase::Display_Race; + case CSMWorld::UniversalId::Type_Cell_Missing: + return CSMWorld::ColumnBase::Display_Cell_Missing; + + case CSMWorld::UniversalId::Type_Skill: return CSMWorld::ColumnBase::Display_Skill; diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index a62acc02bb..94b042ec5c 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -64,6 +64,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 34167cd854..24fb543996 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -60,6 +60,7 @@ namespace CSMWorld Type_Spell, Type_Cells, Type_Cell, + Type_Cell_Missing, //For cells that does not exist yet. Type_Referenceables, Type_Referenceable, Type_Activator, diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 85b79c3f2c..beb2e849e6 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -353,13 +353,21 @@ void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDragedRecords() const { - QModelIndexList selected = getSelectedCells(); + QModelIndexList selected(getSelectedCells(true, false)); std::vector ids; foreach (QModelIndex it, selected) { ids.push_back( - CSMWorld::UniversalId - (CSMWorld::UniversalId::Type_Cell, + CSMWorld::UniversalId( + CSMWorld::UniversalId::Type_Cell, + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + } + selected = getSelectedCells(false, true); + foreach (QModelIndex it, selected) + { + ids.push_back( + CSMWorld::UniversalId( + CSMWorld::UniversalId::Type_Cell_Missing, model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); } return ids; From 0c2843b0f7e081bfe64c9362f4101462f1223a2d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Apr 2014 19:56:33 +0200 Subject: [PATCH 114/545] some missing cleanup --- apps/openmw/mwmechanics/creaturestats.cpp | 5 +++++ apps/openmw/mwmechanics/creaturestats.hpp | 2 ++ apps/openmw/mwstate/statemanagerimp.cpp | 3 +++ 3 files changed, 10 insertions(+) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 8490226cbf..9107606857 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -532,4 +532,9 @@ namespace MWMechanics { return mActorId!=-1 && id==mActorId; } + + void CreatureStats::cleanup() + { + sActorId = 0; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 23d9303c01..aee11a358e 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -248,6 +248,8 @@ namespace MWMechanics bool matchesActorId (int id) const; ///< Check if \a id matches the actor ID of *this (if the actor does not have an ID /// assigned this function will return false). + + static void cleanup(); }; } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 33f2dce7c3..6dcfd90765 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -28,6 +28,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwscript/globalscripts.hpp" @@ -46,6 +47,8 @@ void MWState::StateManager::cleanup (bool force) mState = State_NoGame; mCharacterManager.clearCurrentCharacter(); mTimePlayed = 0; + + MWMechanics::CreatureStats::cleanup(); } } From eeb18b533e1006663b2889ec7bd33eeb1d1dab0c Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 29 Apr 2014 19:43:58 +0200 Subject: [PATCH 115/545] moved editlock to the dragrecordtable --- apps/opencs/view/world/dragrecordtable.cpp | 8 +++++++- apps/opencs/view/world/dragrecordtable.hpp | 3 +++ apps/opencs/view/world/regionmap.cpp | 7 +------ apps/opencs/view/world/regionmap.hpp | 3 --- apps/opencs/view/world/table.cpp | 4 ++-- apps/opencs/view/world/table.hpp | 3 +-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index f962f6f10f..8e283294e1 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -18,5 +18,11 @@ void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& tabl CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) : mDocument(document), -QTableView(parent) +QTableView(parent), +mEditLock(false) {} + +void CSVWorld::DragRecordTable::setEditLock (bool locked) +{ + mEditLock = locked; +} diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 7a2b517430..29b590c361 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -22,12 +22,15 @@ namespace CSVWorld { protected: CSMDoc::Document& mDocument; + bool mEditLock; public: DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL); virtual std::vector getDragedRecords() const = 0; + virtual void setEditLock(bool locked); + protected: void startDrag(const DragRecordTable& table); }; diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index beb2e849e6..326f3c60d7 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -181,7 +181,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId) CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent) -: mEditLock (false), DragRecordTable(document, parent) +: DragRecordTable(document, parent) { verticalHeader()->hide(); horizontalHeader()->hide(); @@ -226,11 +226,6 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, addAction (mViewInTableAction); } -void CSVWorld::RegionMap::setEditLock (bool locked) -{ - mEditLock = locked; -} - void CSVWorld::RegionMap::selectAll() { QModelIndexList unselected = getUnselectedCells(); diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index 596ddfaed5..c8b110f4bb 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -35,7 +35,6 @@ namespace CSVWorld QAction *mUnsetRegionAction; QAction *mViewAction; QAction *mViewInTableAction; - bool mEditLock; std::string mRegionId; private: @@ -62,8 +61,6 @@ namespace CSVWorld RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent = 0); - void setEditLock (bool locked); - virtual std::vector getDragedRecords() const; signals: diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index d700d5f2e2..8e98e93a3e 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -188,7 +188,7 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) -: mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), +: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0), DragRecordTable(document) { mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); @@ -282,7 +282,7 @@ void CSVWorld::Table::setEditLock (bool locked) for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); - mEditLock = locked; + DragRecordTable::setEditLock(locked); } CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 30b487ce84..83a294dd87 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -47,7 +47,6 @@ namespace CSVWorld QAction *mPreviewAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; - bool mEditLock; int mRecordStatusDisplay; private: @@ -73,7 +72,7 @@ namespace CSVWorld ///< \param createAndDelete Allow creation and deletion of records. /// \param sorting Allow changing order of rows in the view via column headers. - void setEditLock (bool locked); + virtual void setEditLock (bool locked); CSMWorld::UniversalId getUniversalId (int row) const; From 10a5bb946461ec6d48e184a36b76fbb7e8ef9652 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 29 Apr 2014 23:40:59 -0400 Subject: [PATCH 116/545] Made code a bit more standardized and added a good bit of documentation. --- apps/openmw/mwinput/inputmanagerimp.hpp | 6 +- apps/openmw/mwmechanics/aiactivate.hpp | 9 +-- apps/openmw/mwmechanics/aicombat.hpp | 5 +- apps/openmw/mwmechanics/aiescort.hpp | 10 ++- apps/openmw/mwmechanics/aifollow.hpp | 16 ++++- apps/openmw/mwmechanics/aipackage.hpp | 23 ++++--- apps/openmw/mwmechanics/aipersue.hpp | 6 +- apps/openmw/mwmechanics/aisequence.hpp | 62 ++++++++++------- apps/openmw/mwmechanics/aitravel.hpp | 7 +- apps/openmw/mwmechanics/aiwander.hpp | 23 ++++--- apps/openmw/mwmechanics/alchemy.hpp | 92 ++++++++++++------------- 11 files changed, 152 insertions(+), 107 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 3787a9c071..ace4cc6d0e 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -46,10 +46,7 @@ namespace MyGUI namespace MWInput { - - /** - * @brief Class that handles all input and key bindings for OpenMW. - */ + /// \brief Class that handles all input and key bindings for OpenMW. class InputManager : public MWBase::InputManager, public SFO::KeyListener, @@ -68,6 +65,7 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); + virtual void update(float dt, bool disableControls=false, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index fd54869f6c..b6ce9f85d9 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -7,15 +7,16 @@ #include "pathfinding.hpp" namespace MWMechanics -{ - +{ + /// \brief Causes actor to walk to activatable object and activate it class AiActivate : public AiPackage { - public: + public: + /// Constructor + /** \param objectId Reference to object to activate **/ AiActivate(const std::string &objectId); virtual AiActivate *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; private: diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 30b72acd92..833b0063c9 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -14,20 +14,23 @@ namespace MWMechanics { + /// \brief Causes the actor to fight another actor class AiCombat : public AiPackage { public: + ///Constructor + /** \param actor Actor to fight **/ AiCombat(const MWWorld::Ptr& actor); virtual AiCombat *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; virtual unsigned int getPriority() const; + ///Returns target ID const std::string &getTargetId() const; private: diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 53b57c0580..3771417fa2 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -8,18 +8,22 @@ namespace MWMechanics { + /// \brief AI Package to have an NPC lead the player to a specific point class AiEscort : public AiPackage { public: + /// Implementation of AiEscort + /** The Actor will escort the specified actor to the world position x, y, z until they reach their position, or they run out of time + \implement AiEscort **/ AiEscort(const std::string &actorId,int duration, float x, float y, float z); - ///< \implement AiEscort + /// Implementation of AiEscortCell + /** The Actor will escort the specified actor to the cell position x, y, z until they reach their position, or they run out of time + \implement AiEscortCell **/ AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); - ///< \implement AiEscortCell virtual AiEscort *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 48a8eb4c26..4eb3e3757a 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -8,22 +8,32 @@ namespace MWMechanics { - + /// \brief AiPackage for an actor to follow another actor/the PC + /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely + **/ class AiFollow : public AiPackage { public: + /// Follow Actor for duration or until you arrive at a world position AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + /// Follow Actor for duration or until you arrive at a position in a cell AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); + /// Follow Actor indefinitively AiFollow(const std::string &ActorId); + virtual AiFollow *clone() const; + virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? + virtual int getTypeId() const; + /// Returns the actor being followed std::string getFollowedActor(); private: - bool mAlwaysFollow; //this will make the actor always follow, thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). + /// This will make the actor always follow. + /** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/ + bool mAlwaysFollow; float mDuration; float mX; float mY; diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 8e015da158..30eab7f8b5 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -12,6 +12,7 @@ namespace MWMechanics class AiPackage { public: + ///Enumerates the various AITypes availible. enum TypeId { TypeIdNone = -1, TypeIdWander = 0, @@ -23,18 +24,22 @@ namespace MWMechanics TypeIdPersue = 6 }; + ///Default Deconstructor virtual ~AiPackage(); - - virtual AiPackage *clone() const = 0; - - virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0; - ///< \return Package completed? - - virtual int getTypeId() const = 0; - ///< @see enum TypeId + ///Clones the package + virtual AiPackage *clone() const = 0; + + /// Updates and runs the package (Should run every frame) + /// \return Package completed? + virtual bool execute (const MWWorld::Ptr& actor,float duration) = 0; + + /// Returns the TypeID of the AiPackage + /// \see enum TypeId + virtual int getTypeId() const = 0; + + /// Higher number is higher priority (0 beeing the lowest) virtual unsigned int getPriority() const {return 0;} - ///< higher number is higher priority (0 beeing the lowest) }; } diff --git a/apps/openmw/mwmechanics/aipersue.hpp b/apps/openmw/mwmechanics/aipersue.hpp index 3fd708ab32..bf5410676d 100644 --- a/apps/openmw/mwmechanics/aipersue.hpp +++ b/apps/openmw/mwmechanics/aipersue.hpp @@ -8,14 +8,16 @@ namespace MWMechanics { - + /// \brief Makes the actor very closely follow the actor + /** Used for getting closer to fight, or to arrest (I think?) **/ class AiPersue : public AiPackage { public: + ///Constructor + /** \param objectId Actor to pursue **/ AiPersue(const std::string &objectId); virtual AiPersue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; private: diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index cb1b0de02f..a751e03970 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -13,65 +13,79 @@ namespace MWWorld namespace MWMechanics { class AiPackage; - + /// \brief Sequence of AI-packages for a single actor + /** Each package will be run in succession for an actor until completed **/ class AiSequence { + ///AiPackages to run though std::list mPackages; + ///Finished with all AiPackages bool mDone; + ///Copy AiSequence void copy (const AiSequence& sequence); - // The type of AI package that ran last + /// The type of AI package that ran last int mLastAiPackage; public: - + ///Default constructor AiSequence(); - + + /// Copy Constructor AiSequence (const AiSequence& sequence); - + + /// Assignment operator AiSequence& operator= (const AiSequence& sequence); - + + /// Destructor virtual ~AiSequence(); + /// Returns currently executing AiPackage type + /** \see enum AiPackage::TypeId **/ int getTypeId() const; - ///< @see enum AiPackage::TypeId + /// Get the typeid of the Ai package that ran last + /** NOT the currently "active" Ai package that will be run in the next frame. + This difference is important when an Ai package has just finished and been removed. + \see enum AiPackage::TypeId **/ int getLastRunTypeId() const { return mLastAiPackage; } - ///< Get the typeid of the Ai package that ran last, NOT the currently "active" Ai package that will be run in the next frame. - /// This difference is important when an Ai package has just finished and been removed. + /// Return true and assign target if combat package is currently active, return false otherwise bool getCombatTarget (std::string &targetActorId) const; - ///< Return true and assign target if combat package is currently - /// active, return false otherwise + /// Removes all combat packages until first non-combat or stack empty. void stopCombat(); - ///< Removes all combat packages until first non-combat or stack empty. + /// Removes all persue packages until first non-persue or stack empty. void stopPersue(); - ///< Removes all persue packages until first non-persue or stack empty. - + + /// Has a package been completed during the last update? bool isPackageDone() const; - ///< Has a package been completed during the last update? - + + /// Execute current package, switching if needed. void execute (const MWWorld::Ptr& actor,float duration); - ///< Execute package. - + + /// Remove all packages. void clear(); - ///< Remove all packages. + ///< Add \a package to the front of the sequence + /** Suspends current package **/ void stack (const AiPackage& package, const MWWorld::Ptr& actor); - ///< Add \a package to the front of the sequence (suspends current package) - + + /// Add \a package to the end of the sequence + /** Executed after all other packages have been completed **/ void queue (const AiPackage& package); - ///< Add \a package to the end of the sequence (executed after all other packages have been - /// completed) + /// Return the current active package. + /** If there is no active package, it will throw an exception **/ AiPackage* getActivePackage(); - ///< return the current active package. If there is no active package, throw an exeption + /// Fills the AiSequence with packages + /** Typically used for loading from the ESM + \see ESM::AIPackageList **/ void fill (const ESM::AIPackageList& list); }; } diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index 72f3e02983..ea7f1dc329 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -6,15 +6,16 @@ #include "pathfinding.hpp" namespace MWMechanics -{ +{ + /// \brief Causes the AI to travel to the specified point class AiTravel : public AiPackage { - public: + public: + /// Default constructor AiTravel(float x, float y, float z); virtual AiTravel *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 2975c8315f..6481b2a01c 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -14,20 +14,27 @@ namespace MWMechanics { + /// \brief Causes the Actor to wander within a specified range class AiWander : public AiPackage { public: - + /// Constructor + /** \param distance Max distance the ACtor will wander + \param duration Time, in hours, that this package will be preformed + \param timeOfDay Start time of the package, if it has a duration. Currently unimplemented + \param idle Chances of each idle to play (9 in total) + \param repeat Repeat wander or not **/ AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat); - virtual AiPackage *clone() const; - virtual bool execute (const MWWorld::Ptr& actor,float duration); - ///< \return Package completed? - virtual int getTypeId() const; - ///< 0: Wander + virtual AiPackage *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor,float duration); + + virtual int getTypeId() const; + + /// Set the position to return to for a stationary (non-wandering) actor + /** In case another AI package moved the actor elsewhere **/ void setReturnPosition (const Ogre::Vector3& position); - ///< Set the position to return to for a stationary (non-wandering) actor, in case - /// another AI package moved the actor elsewhere private: void stopWalking(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index 31cafa4dc7..b2b0fe1ee0 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -31,6 +31,8 @@ namespace MWMechanics typedef std::vector TEffectsContainer; typedef TEffectsContainer::const_iterator TEffectsIterator; + /// Result of potion creation + /** Only Result_Success results in success **/ enum Result { Result_Success, @@ -42,6 +44,46 @@ namespace MWMechanics Result_RandomFailure }; + /// Set alchemist and configure alchemy setup accordingly. + /** \a npc may be empty to indicate that there is no alchemist (alchemy session has ended). **/ + void setAlchemist (const MWWorld::Ptr& npc); + + /// \attention Iterates over tool slots, not over tools. Some of the slots may be empty. + TToolsIterator beginTools() const; + + TToolsIterator endTools() const; + + /// \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. + TIngredientsIterator beginIngredients() const; + + TIngredientsIterator endIngredients() const; + + /// Remove alchemist, tools and ingredients. + void clear(); + + /// Add ingredient into the next free slot. + /// + /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being + /// listed already. + int addIngredient (const MWWorld::Ptr& ingredient); + + /// Remove ingredient from slot (calling this function on an empty slot is a no-op). + void removeIngredient (int index); + + TEffectsIterator beginEffects() const; + + TEffectsIterator endEffects() const; + + /// Return the name of the potion that would be created when calling create (if a record for such + /// a potion already exists) or return an empty string. + std::string getPotionName() const; + + /// Try to create a potion from the ingredients, place it in the inventory of the alchemist and + /// adjust the skills of the alchemist accordingly. + /// \param name must not be an empty string, unless there is already a potion record ( + /// getPotionName() does not return an empty string). + Result create (const std::string& name); + private: MWWorld::Ptr mAlchemist; @@ -50,19 +92,19 @@ namespace MWMechanics TEffectsContainer mEffects; int mValue; + /// List all effects shared by at least two ingredients. std::set listEffects() const; - ///< List all effects shared by at least two ingredients. void applyTools (int flags, float& value) const; void updateEffects(); + /// Return existing recrod for created potion (may return 0) const ESM::Potion *getRecord() const; - ///< Return existing recrod for created potion (may return 0) - void removeIngredients(); - ///< Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and + /// Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and /// update effect list accordingly. + void removeIngredients(); void addPotion (const std::string& name); ///< Add a potion to the alchemist's inventory. @@ -74,48 +116,6 @@ namespace MWMechanics ///< Return chance of success. int countIngredients() const; - - public: - - void setAlchemist (const MWWorld::Ptr& npc); - ///< Set alchemist and configure alchemy setup accordingly. \a npc may be empty to indicate that - /// there is no alchemist (alchemy session has ended). - - TToolsIterator beginTools() const; - ///< \attention Iterates over tool slots, not over tools. Some of the slots may be empty. - - TToolsIterator endTools() const; - - TIngredientsIterator beginIngredients() const; - ///< \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. - - TIngredientsIterator endIngredients() const; - - void clear(); - ///< Remove alchemist, tools and ingredients. - - int addIngredient (const MWWorld::Ptr& ingredient); - ///< Add ingredient into the next free slot. - /// - /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being - /// listed already. - - void removeIngredient (int index); - ///< Remove ingredient from slot (calling this function on an empty slot is a no-op). - - TEffectsIterator beginEffects() const; - - TEffectsIterator endEffects() const; - - std::string getPotionName() const; - ///< Return the name of the potion that would be created when calling create (if a record for such - /// a potion already exists) or return an empty string. - - Result create (const std::string& name); - ///< Try to create a potion from the ingredients, place it in the inventory of the alchemist and - /// adjust the skills of the alchemist accordingly. - /// \param name must not be an empty string, unless there is already a potion record ( - /// getPotionName() does not return an empty string). }; } From 4d79f00e284cb00ddf75c9e8142c9ee85db07b73 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 30 Apr 2014 13:32:54 +0200 Subject: [PATCH 117/545] enable dragging on the region map cells --- apps/opencs/view/world/dragrecordtable.cpp | 10 ++++++ apps/opencs/view/world/dragrecordtable.hpp | 5 +++ apps/opencs/view/world/regionmap.cpp | 37 ++++++++++++++++++++++ apps/opencs/view/world/regionmap.hpp | 2 ++ apps/opencs/view/world/table.cpp | 10 ------ apps/opencs/view/world/table.hpp | 5 +-- 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 8e283294e1..d9d891ff19 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -26,3 +26,13 @@ void CSVWorld::DragRecordTable::setEditLock (bool locked) { mEditLock = locked; } + +void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event) +{ + event->acceptProposedAction(); +} + +void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 29b590c361..06ee3b9c60 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -2,6 +2,7 @@ #define CSV_WORLD_DRAGRECORDTABLE_H #include +#include class QWidget; class QAction; @@ -33,6 +34,10 @@ namespace CSVWorld protected: void startDrag(const DragRecordTable& table); + + void dragEnterEvent(QDragEnterEvent *event); + + void dragMoveEvent(QDragMoveEvent *event); }; } diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 326f3c60d7..ccd121204e 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -224,6 +225,8 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, mViewInTableAction = new QAction (tr ("View Cells in Table"), this); connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable())); addAction (mViewInTableAction); + + setAcceptDrops(true); } void CSVWorld::RegionMap::selectAll() @@ -367,3 +370,37 @@ std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDragedRecords() con } return ids; } + +void CSVWorld::RegionMap::dropEvent (QDropEvent* event) +{ + QModelIndex index = indexAt (event->pos()); + + bool exists = QTableView::model()->data(index, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern); + + if (!index.isValid() || !exists) + { + return; + } + + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region)) + { + CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region)); + + QAbstractItemModel *regionModel = model(); + + CSMWorld::IdTable *cellsModel = &dynamic_cast (* + mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + std::string cellId(regionModel->data (index, CSMWorld::RegionMap::Role_CellId). + toString().toUtf8().constData()); + + QModelIndex index2 = cellsModel->getModelIndex (cellId, + cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region)); + + mDocument.getUndoStack().push(new CSMWorld::ModifyCommand + (*cellsModel, index2, QString::fromUtf8(record.getId().c_str()))); + + mRegionId = record.getId(); + } +} \ No newline at end of file diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index c8b110f4bb..08744a4a0f 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -56,6 +56,8 @@ namespace CSVWorld void mouseMoveEvent(QMouseEvent *event); + void dropEvent(QDropEvent* event); + public: RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 8e98e93a3e..e5cfbe3609 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -516,11 +516,6 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) } } -void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event) -{ - event->acceptProposedAction(); -} - void CSVWorld::Table::dropEvent(QDropEvent *event) { QModelIndex index = indexAt (event->pos()); @@ -548,11 +543,6 @@ void CSVWorld::Table::dropEvent(QDropEvent *event) } //TODO handle drops from different document } -void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event) -{ - event->accept(); -} - std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const { const int count = mModel->columnCount(); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 83a294dd87..cfab486e57 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -59,10 +59,6 @@ namespace CSVWorld void mouseMoveEvent(QMouseEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); public: @@ -94,6 +90,7 @@ namespace CSVWorld /// \param modified Number of added and modified records void createRequest(); + void cloneRequest(const CSMWorld::UniversalId&); private slots: From 14ebd8b110ba8a0e9ff86ec92bf81eeaadc28a20 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Wed, 30 Apr 2014 07:44:29 -0400 Subject: [PATCH 118/545] Fixed logic in commit crime --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index eca0c2289f..a16c6588d4 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -860,8 +860,8 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if ( *it == ptr - || !it->getClass().isNpc()) continue; // not the player and is an NPC + if ( *it1 == ptr + || !it1->getClass().isNpc()) continue; // not the player and is an NPC // TODO: Add more messages if (type == OT_Theft) From 5c9c467b2694580627dc0ead360e18f2a5d34c0b Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Wed, 30 Apr 2014 08:06:36 -0400 Subject: [PATCH 119/545] Improved sneak. --- apps/openmw/mwworld/player.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 5e4211faa8..d023d4388b 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -135,7 +135,7 @@ namespace MWWorld ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - if (sneak == true) + if (sneak) { const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -145,15 +145,20 @@ namespace MWWorld esmStore.get().find("fSneakUseDist")->getInt(), neighbors); for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { + if (*it == ptr) // not the player + continue; + if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) { MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); break; } } - if (neighbors.size() == 0) + if (neighbors.empty()) MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); } + else + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } void Player::yaw(float yaw) From 19dac9dc86cdac61a17cc88c3bb2dee76acdbf45 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 30 Apr 2014 14:27:11 +0200 Subject: [PATCH 120/545] that would be it --- .../view/render/pagedworldspacewidget.cpp | 46 ++++++++++++++++++- .../view/render/pagedworldspacewidget.hpp | 8 ++++ apps/opencs/view/world/regionmap.cpp | 1 - 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 0f23dfe7b7..3f40712d27 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -3,9 +3,17 @@ #include +#include + +#include + +#include + CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) : WorldspaceWidget (parent) -{} +{ + setAcceptDrops(true); +} void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) { @@ -44,4 +52,38 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel { mSelection = selection; emit cellSelectionChanged (mSelection); -} \ No newline at end of file +} + +void CSVRender::PagedWorldspaceWidget::dragEnterEvent (QDragEnterEvent* event) +{ + event->accept(); +} + +void CSVRender::PagedWorldspaceWidget::dragMoveEvent (QDragMoveEvent* event) +{ + event->accept(); +} + +void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) +{ + /* + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + if (true) + { + if (mime->holdsType(CSMWorld::UniversalId::Type_Cell)) + { + CSMWorld::UniversalId record(mime->returnMatching (CSMWorld::UniversalId::Type_Cell)); + QString id(QString::fromUtf8(record.getId().c_str())); + if (*id.begin() == '#') + { + id.remove(0,1); + QStringList splited(id.split(' ')); + int x = splited.begin()->toInt(); + int y = (splited.begin()+1)->toInt(); + mSelection.add(CSMWorld::CellCoordinates(x, y)); + } + } + } + */ + //TODO! +} diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index f6ff32dc1f..c6fdbf3beb 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -13,6 +13,14 @@ namespace CSVRender CSMWorld::CellSelection mSelection; + private: + + void dropEvent(QDropEvent* event); + + void dragEnterEvent(QDragEnterEvent *event); + + void dragMoveEvent(QDragMoveEvent *event); + public: PagedWorldspaceWidget (QWidget *parent); diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index ccd121204e..de46f175fb 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include From 6aaa15b2e86f5ddc69e6e4250bccf2a7b65f0831 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 30 Apr 2014 15:03:46 +0200 Subject: [PATCH 121/545] paged worldspace drop --- .../view/render/pagedworldspacewidget.cpp | 40 ++++++++++++------- .../view/render/pagedworldspacewidget.hpp | 6 ++- apps/opencs/view/world/scenesubview.cpp | 2 +- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 3f40712d27..d916e33e91 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -9,8 +9,9 @@ #include -CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) -: WorldspaceWidget (parent) +CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document) +: WorldspaceWidget (parent), +mDocument(document) { setAcceptDrops(true); } @@ -66,24 +67,33 @@ void CSVRender::PagedWorldspaceWidget::dragMoveEvent (QDragMoveEvent* event) void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) { - /* const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); - if (true) + if (mime->fromDocument(mDocument)) { - if (mime->holdsType(CSMWorld::UniversalId::Type_Cell)) + std::vector data(mime->getData()); + + for (unsigned i = 0; i < data.size(); ++i) { - CSMWorld::UniversalId record(mime->returnMatching (CSMWorld::UniversalId::Type_Cell)); - QString id(QString::fromUtf8(record.getId().c_str())); - if (*id.begin() == '#') + if (data[i].getType() == CSMWorld::UniversalId::Type_Cell || + data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing) { - id.remove(0,1); - QStringList splited(id.split(' ')); - int x = splited.begin()->toInt(); - int y = (splited.begin()+1)->toInt(); - mSelection.add(CSMWorld::CellCoordinates(x, y)); + if (*(data[i].getId().begin()) == '#') + { + std::pair coordinate(getCoordinatesFromId(data[i].getId())); + mSelection.add(CSMWorld::CellCoordinates(coordinate.first, coordinate.second)); + } } } } - */ - //TODO! } + +std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const +{ + QString id(QString::fromUtf8(record.c_str())); + id.remove(0,1); + QStringList splited(id.split(' ')); //Well, this is the simplest approach + int x = splited.begin()->toInt(); + int y = (splited.begin()+1)->toInt(); + return std::make_pair(x, y); +} + diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index c6fdbf3beb..bfcb25e669 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -2,6 +2,7 @@ #define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #include "../../model/world/cellselection.hpp" +#include #include "worldspacewidget.hpp" @@ -12,6 +13,7 @@ namespace CSVRender Q_OBJECT CSMWorld::CellSelection mSelection; + const CSMDoc::Document& mDocument; //for checking if drop comes from same document private: @@ -21,9 +23,11 @@ namespace CSVRender void dragMoveEvent(QDragMoveEvent *event); + std::pair getCoordinatesFromId(const std::string& record) const; + public: - PagedWorldspaceWidget (QWidget *parent); + PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document); ///< \note Sets the cell area selection to an invalid value to indicate that currently /// no cells are displayed. The cells to be displayed will be specified later through /// hint system. diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 0bb11ce8cc..506a0288da 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -40,7 +40,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D if (id.getId()=="sys::default") { - CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this); + CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this, document); mScene = widget; connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); From 9e01a54d72096a63b521ab83e594e0e16532c780 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 30 Apr 2014 15:17:20 +0200 Subject: [PATCH 122/545] minor correction --- apps/opencs/view/world/regionmap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index de46f175fb..260b3b8253 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -394,8 +394,8 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event) std::string cellId(regionModel->data (index, CSMWorld::RegionMap::Role_CellId). toString().toUtf8().constData()); - QModelIndex index2 = cellsModel->getModelIndex (cellId, - cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region)); + QModelIndex index2(cellsModel->getModelIndex (cellId, + cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region))); mDocument.getUndoStack().push(new CSMWorld::ModifyCommand (*cellsModel, index2, QString::fromUtf8(record.getId().c_str()))); From e8f7d12c01300fe703c6439db05ebca9cabfc580 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Wed, 30 Apr 2014 23:57:19 +0400 Subject: [PATCH 123/545] uninit bool and invalid iterator bugs fixes --- apps/openmw/mwmechanics/aicombat.cpp | 6 +++--- apps/openmw/mwmechanics/aiwander.cpp | 4 ++-- apps/openmw/mwmechanics/aiwander.hpp | 2 +- apps/openmw/mwmechanics/pathfinding.hpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index d0555cdc3c..fdaec28b49 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -392,7 +392,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS; + bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); if(mReadyToAttack) isStuck = false; @@ -400,7 +400,7 @@ namespace MWMechanics if(!isStuck && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) - && (inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))) + && inLOS) { if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed @@ -437,7 +437,7 @@ namespace MWMechanics if(inLOS && mPathFinder.getPath().size() > 1) { // get point just before target - std::list::iterator pntIter = --mPathFinder.getPath().end(); + std::list::const_iterator pntIter = --mPathFinder.getPath().end(); --pntIter; Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7120ff5afc..f95c858c99 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -539,14 +539,14 @@ namespace MWMechanics } void AiWander::trimAllowedNodes(std::vector& nodes, - const PathFinder& pathfinder) + PathFinder& pathfinder) { // TODO: how to add these back in once the door opens? // Idea: keep a list of detected closed doors (see aicombat.cpp) // Every now and then check whether one of the doors is opened. (maybe // at the end of playing idle?) If the door is opened then re-calculate // allowed nodes starting from the spawn point. - std::list paths = pathfinder.getPath(); + std::list& paths = pathfinder.getPath(); while(paths.size() >= 2) { ESM::Pathgrid::Point pt = paths.back(); diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 2975c8315f..3be74010d1 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -77,7 +77,7 @@ namespace MWMechanics ESM::Pathgrid::Point mCurrentNode; bool mTrimCurrentNode; void trimAllowedNodes(std::vector& nodes, - const PathFinder& pathfinder); + PathFinder& pathfinder); PathFinder mPathFinder; diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 97bb88c52b..ec9c867541 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -57,7 +57,7 @@ namespace MWMechanics return mPath.size(); } - std::list getPath() const + std::list& getPath() { return mPath; } From 9e79fb5b87c8513792212f398ad6068e717823b5 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Thu, 1 May 2014 11:41:25 +0400 Subject: [PATCH 124/545] fix to broken aiwander logic --- apps/openmw/mwmechanics/aiwander.cpp | 4 ++-- apps/openmw/mwmechanics/aiwander.hpp | 2 +- apps/openmw/mwmechanics/pathfinding.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index f95c858c99..7120ff5afc 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -539,14 +539,14 @@ namespace MWMechanics } void AiWander::trimAllowedNodes(std::vector& nodes, - PathFinder& pathfinder) + const PathFinder& pathfinder) { // TODO: how to add these back in once the door opens? // Idea: keep a list of detected closed doors (see aicombat.cpp) // Every now and then check whether one of the doors is opened. (maybe // at the end of playing idle?) If the door is opened then re-calculate // allowed nodes starting from the spawn point. - std::list& paths = pathfinder.getPath(); + std::list paths = pathfinder.getPath(); while(paths.size() >= 2) { ESM::Pathgrid::Point pt = paths.back(); diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 3be74010d1..2975c8315f 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -77,7 +77,7 @@ namespace MWMechanics ESM::Pathgrid::Point mCurrentNode; bool mTrimCurrentNode; void trimAllowedNodes(std::vector& nodes, - PathFinder& pathfinder); + const PathFinder& pathfinder); PathFinder mPathFinder; diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index ec9c867541..29577542e6 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -57,7 +57,7 @@ namespace MWMechanics return mPath.size(); } - std::list& getPath() + const std::list& getPath() const { return mPath; } From 57131332f4908ad753a9cc373fe9cedb012aaaa0 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Thu, 1 May 2014 12:34:54 +0200 Subject: [PATCH 125/545] fixing minor issues --- apps/opencs/model/world/columnbase.hpp | 1 - apps/opencs/model/world/tablemimedata.cpp | 16 +++++++--------- apps/opencs/model/world/tablemimedata.hpp | 1 + .../opencs/view/render/pagedworldspacewidget.cpp | 15 ++++++++------- apps/opencs/view/world/dragrecordtable.cpp | 2 +- apps/opencs/view/world/dragrecordtable.hpp | 4 ++-- apps/opencs/view/world/regionmap.cpp | 2 +- apps/opencs/view/world/regionmap.hpp | 2 +- apps/opencs/view/world/table.cpp | 2 +- apps/opencs/view/world/table.hpp | 2 +- 10 files changed, 23 insertions(+), 24 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 53b55939b4..fe310d0aa4 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -27,7 +27,6 @@ namespace CSMWorld enum Display { Display_None, //Do not use - Display_Cell_Missing, //Do not used, actually. It is here to simplify dragging non-existed cells handling Display_String, Display_LongString, diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index e0a735e35b..6d65d0ff80 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -1,6 +1,9 @@ #include "tablemimedata.hpp" + #include +#include + #include "universalid.hpp" #include "columnbase.hpp" @@ -33,7 +36,8 @@ std::string CSMWorld::TableMimeData::getIcon() const { if (mUniversalId.empty()) { - return ""; + qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic + throw("TableMimeData object does not hold any records!"); } std::string tmpIcon; @@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const if (tmpIcon != mUniversalId[i].getIcon()) { - return ":/multitype.png"; //icon stolen from gnome + return ":/multitype.png"; //icon stolen from gnome TODO: get new icon } tmpIcon = mUniversalId[i].getIcon(); @@ -360,8 +364,6 @@ CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::Col case CSMWorld::ColumnBase::Display_Script: return CSMWorld::UniversalId::Type_Script; - case CSMWorld::ColumnBase::Display_Cell_Missing: - return CSMWorld::UniversalId::Type_Cell_Missing; //this one actually never happens, since there is no display_Cell_missing column anywhere. default: return CSMWorld::UniversalId::Type_None; @@ -377,10 +379,6 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U return CSMWorld::ColumnBase::Display_Race; - case CSMWorld::UniversalId::Type_Cell_Missing: - return CSMWorld::ColumnBase::Display_Cell_Missing; - - case CSMWorld::UniversalId::Type_Skill: return CSMWorld::ColumnBase::Display_Skill; @@ -537,4 +535,4 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const { return &mDocument; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/tablemimedata.hpp b/apps/opencs/model/world/tablemimedata.hpp index 9ca7128018..85c243944c 100644 --- a/apps/opencs/model/world/tablemimedata.hpp +++ b/apps/opencs/model/world/tablemimedata.hpp @@ -56,6 +56,7 @@ namespace CSMWorld UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const; static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type); + static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type); private: diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index d916e33e91..cdbd88278e 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -5,8 +5,6 @@ #include -#include - #include CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document) @@ -89,11 +87,14 @@ void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const { - QString id(QString::fromUtf8(record.c_str())); - id.remove(0,1); - QStringList splited(id.split(' ')); //Well, this is the simplest approach - int x = splited.begin()->toInt(); - int y = (splited.begin()+1)->toInt(); + std::istringstream stream (record.c_str()); + char ignore; + stream >> ignore; + char ignore1; // : or ; + char ignore2; // # + int x, y; + + stream >> ignore1 >> ignore2 >> x >> y; return std::make_pair(x, y); } diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index d9d891ff19..c33fa58ad6 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -5,7 +5,7 @@ void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table) { - CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDragedRecords(), mDocument); + CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument); if (mime) { diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 06ee3b9c60..8c5f1b8418 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -28,9 +28,9 @@ namespace CSVWorld public: DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL); - virtual std::vector getDragedRecords() const = 0; + virtual std::vector getDraggedRecords() const = 0; - virtual void setEditLock(bool locked); + void setEditLock(bool locked); protected: void startDrag(const DragRecordTable& table); diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 260b3b8253..849a1988af 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -348,7 +348,7 @@ void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) startDrag(*this); } -std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDragedRecords() const +std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const { QModelIndexList selected(getSelectedCells(true, false)); std::vector ids; diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index 08744a4a0f..0097a16dc2 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -63,7 +63,7 @@ namespace CSVWorld RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent = 0); - virtual std::vector getDragedRecords() const; + virtual std::vector getDraggedRecords() const; signals: diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index e5cfbe3609..cc51a22135 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -561,7 +561,7 @@ std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column return titles; } -std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDragedRecords() const +std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const { QModelIndexList selectedRows = selectionModel()->selectedRows(); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index cfab486e57..8e874ec564 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -76,7 +76,7 @@ namespace CSVWorld std::vector getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; - virtual std::vector getDragedRecords() const; + virtual std::vector getDraggedRecords() const; signals: From ab94e7072459fa513b611cc2c19af8893e6cc41b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 May 2014 13:04:48 +0200 Subject: [PATCH 126/545] more cleanup of document setup --- apps/opencs/model/doc/document.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 25b48a3c9a..760c675a02 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2245,6 +2245,18 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, } } + if (mNew) + { + mData.setDescription (""); + mData.setAuthor (""); + + if (mContentFiles.size()==1) + createBase(); + } + + addOptionalGmsts(); + addOptionalGlobals(); + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); @@ -2262,9 +2274,7 @@ CSMDoc::Document::~Document() void CSMDoc::Document::setupData() { - if (mNew && mContentFiles.size()==1) - createBase(); - else + if (!mNew || mContentFiles.size()>1) { std::vector::const_iterator end = mContentFiles.end(); @@ -2274,16 +2284,7 @@ void CSMDoc::Document::setupData() load (mContentFiles.begin(), end, !mNew); } - if (mNew) - { - mData.setDescription (""); - mData.setAuthor (""); - } - getData().loadFile (mProjectPath, false, true); - - addOptionalGmsts(); - addOptionalGlobals(); } QUndoStack& CSMDoc::Document::getUndoStack() From 36914b43d776ce0dde24df6c5acf0972d8f19289 Mon Sep 17 00:00:00 2001 From: Sandy Date: Thu, 1 May 2014 08:19:05 -0400 Subject: [PATCH 127/545] Remove install of License of no longer used font --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 392fdfc66c..bd45a207c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,7 +434,6 @@ IF(NOT WIN32 AND NOT APPLE) # Install licenses INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" ) - INSTALL(FILES "OFL.txt" DESTINATION "${LICDIR}" ) INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" ) ENDIF (DPKG_PROGRAM) From d00dbf47d5cf79b6652deccef5420670ba9d4189 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Thu, 1 May 2014 15:09:47 +0200 Subject: [PATCH 128/545] working on worldspace drops --- .../view/render/pagedworldspacewidget.cpp | 68 +++++++++-------- .../view/render/pagedworldspacewidget.hpp | 10 +-- .../view/render/unpagedworldspacewidget.cpp | 38 +++++++++- .../view/render/unpagedworldspacewidget.hpp | 11 +++ apps/opencs/view/render/worldspacewidget.cpp | 76 ++++++++++++++++++- apps/opencs/view/render/worldspacewidget.hpp | 26 ++++++- 6 files changed, 184 insertions(+), 45 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index cdbd88278e..3691a7a4da 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -8,11 +8,8 @@ #include CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document) -: WorldspaceWidget (parent), -mDocument(document) -{ - setAcceptDrops(true); -} +: WorldspaceWidget (document, parent) +{} void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) { @@ -53,48 +50,55 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel emit cellSelectionChanged (mSelection); } -void CSVRender::PagedWorldspaceWidget::dragEnterEvent (QDragEnterEvent* event) -{ - event->accept(); -} - -void CSVRender::PagedWorldspaceWidget::dragMoveEvent (QDragMoveEvent* event) -{ - event->accept(); -} - void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + if (mime->fromDocument(mDocument)) { - std::vector data(mime->getData()); + const std::vector data(mime->getData()); + CSVRender::WorldspaceWidget::dropType whatHappend = getDropType(data); - for (unsigned i = 0; i < data.size(); ++i) + std::cout< coordinate(getCoordinatesFromId(data[i].getId())); - mSelection.add(CSMWorld::CellCoordinates(coordinate.first, coordinate.second)); - } - } + case CSVRender::WorldspaceWidget::cellsExterior: + handleDrop(data); + break; + + case CSVRender::WorldspaceWidget::cellsInterior: + emit interiorCellsDropped(data); + break; + + default: + //not interior or exterior = either mixed or not actually cells. We don't need to do anything in this case. + break; } - } + } //not handling drops from different documents at the moment } std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const { std::istringstream stream (record.c_str()); char ignore; - stream >> ignore; - char ignore1; // : or ; - char ignore2; // # int x, y; - - stream >> ignore1 >> ignore2 >> x >> y; + stream >> ignore >> x >> y; return std::make_pair(x, y); } +void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) +{ + bool selectionChanged = false; + for (unsigned i = 0; i < data.size(); ++i) + { + std::pair coordinates(getCoordinatesFromId(data[i].getId())); + if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second))) + { + selectionChanged = true; + } + } + if (selectionChanged) + { + emit cellSelectionChanged(mSelection); + } +} diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index bfcb25e669..f9215f5960 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -2,7 +2,6 @@ #define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #include "../../model/world/cellselection.hpp" -#include #include "worldspacewidget.hpp" @@ -13,18 +12,15 @@ namespace CSVRender Q_OBJECT CSMWorld::CellSelection mSelection; - const CSMDoc::Document& mDocument; //for checking if drop comes from same document private: void dropEvent(QDropEvent* event); - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); - std::pair getCoordinatesFromId(const std::string& record) const; + void handleDrop(const std::vector& data); + public: PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document); @@ -39,6 +35,8 @@ namespace CSVRender signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); + + void interiorCellsDropped(const std::vector& data); }; } diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index fb74788cc2..43c8dbd8d5 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -3,10 +3,13 @@ #include +#include + #include "../../model/doc/document.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/tablemimedata.hpp" void CSVRender::UnpagedWorldspaceWidget::update() { @@ -22,7 +25,7 @@ void CSVRender::UnpagedWorldspaceWidget::update() CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget *parent) -: WorldspaceWidget (parent), mCellId (cellId) +: WorldspaceWidget (document, parent), mCellId (cellId) { mCellsModel = &dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); @@ -63,4 +66,35 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI if (cellIndex.row()>=start && cellIndex.row()<=end) emit closeRequest(); -} \ No newline at end of file +} + +void CSVRender::UnpagedWorldspaceWidget::dropEvent (QDropEvent* event) +{ + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + + if (mime->fromDocument (mDocument)) + { + const std::vector data (mime->getData()); + CSVRender::WorldspaceWidget::dropType whatHappend = getDropType (data); + + switch (whatHappend) + { + case CSVRender::WorldspaceWidget::cellsExterior: + emit exteriorCellsDropped(data); + break; + + case CSVRender::WorldspaceWidget::cellsInterior: + handleDrop(data); + break; + + default: + //not interior or exterior = either mixed or not actually cells. We don't need to do anything in this case. + break; + } + } //not handling drops from different documents at the moment +} + +void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) +{ + +} diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index 17dc46918d..d5b62b8edf 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -33,11 +33,22 @@ namespace CSVRender UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget *parent); + private: + + void handleDrop(const std::vector& data); + + void dropEvent(QDropEvent* event); + private slots: void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); + + signals: + + void exteriorCellsDropped(const std::vector& data); + }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 4d2442c89f..925dd921b0 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -5,15 +5,20 @@ #include #include -#include "../world/scenetoolmode.hpp" +#include -CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) -: SceneWidget (parent) +#include "../world/scenetoolmode.hpp" +#include + +CSVRender::WorldspaceWidget::WorldspaceWidget (const CSMDoc::Document& document, QWidget* parent) +: SceneWidget (parent), mDocument(document) { Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE); ent->setMaterialName("BaseWhite"); getSceneManager()->getRootSceneNode()->attachObject(ent); + + setAcceptDrops(true); } void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) @@ -46,4 +51,67 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( this, SLOT (selectNavigationMode (const std::string&))); return tool; -} \ No newline at end of file +} + +CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType ( + const std::vector< CSMWorld::UniversalId >& data) const +{ + dropType output = notCells; + bool firstIteration = true; + + for (unsigned i = 0; i < data.size(); ++i) + { + if (data[i].getType() == CSMWorld::UniversalId::Type_Cell || + data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing) + { + if (*(data[i].getId().begin()) == '#') //exterior + { + if (firstIteration) + { + output = cellsExterior; + firstIteration = false; + continue; + } + + if (output == cellsInterior) + { + output = cellsMixed; + break; + } else { + output = cellsInterior; + } + } else //interior + { + if (firstIteration) + { + output = cellsInterior; + firstIteration = false; + continue; + } + + if (output == cellsExterior) + { + output = cellsMixed; + break; + } else { + output = cellsInterior; + } + } + } else { + output = notCells; + break; + } + } + + return output; +} + +void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event) +{ + event->accept(); +} + +void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index f7208d7a14..83ef593d6b 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -6,7 +6,12 @@ #include "navigation1st.hpp" #include "navigationfree.hpp" #include "navigationorbit.hpp" +#include +namespace CSMWorld +{ + class UniversalId; +} namespace CSVWorld { class SceneToolMode; @@ -25,7 +30,7 @@ namespace CSVRender public: - WorldspaceWidget (QWidget *parent = 0); + WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); ///< \attention The created tool is not added to the toolbar (via addTool). Doing that @@ -36,6 +41,25 @@ namespace CSVRender virtual void useViewHint (const std::string& hint); ///< Default-implementation: ignored. + protected: + const CSMDoc::Document& mDocument; //for checking if drop comes from same document + + enum dropType + { + cellsMixed, + cellsInterior, + cellsExterior, + notCells + }; + + dropType getDropType(const std::vector& data) const; + + private: + + void dragEnterEvent(QDragEnterEvent *event); + + void dragMoveEvent(QDragMoveEvent *event); + private slots: void selectNavigationMode (const std::string& mode); From 5415ca6a6311215b5b3aab84526d7044f7c6280f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 13:04:09 +0200 Subject: [PATCH 129/545] Fix exception when shift+click on empty space in save dialog --- apps/openmw/mwgui/savegamedialog.cpp | 2 +- apps/openmw/mwgui/statswindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 74ccc82f4c..a77c625f90 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -53,7 +53,7 @@ namespace MWGui { onSlotSelected(sender, pos); - if (MyGUI::InputManager::getInstance().isShiftPressed()) + if (pos != MyGUI::ITEM_NONE && MyGUI::InputManager::getInstance().isShiftPressed()) { ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sMessage3}"); diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 3d4c741a3e..31a3b6fdd0 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -475,7 +475,7 @@ namespace MWGui text += std::string("#DDC79E") + faction->mName; if (expelled.find(it->first) != expelled.end()) - text += "\n#{sExpelled}"; + text += "\n#BF9959#{sExpelled}"; else { text += std::string("\n#BF9959") + faction->mRanks[it->second]; From f99eda1a543c79bad59e23e9ed5a0fcd9215644d Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 Apr 2014 13:34:06 +0200 Subject: [PATCH 130/545] Fixes #1302: Do not attempt to set OnPcAdd before the script has been added --- apps/openmw/mwworld/containerstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index b1cbcc9c26..eb6760d14c 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -231,6 +231,8 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr { CellStore *cell; + MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); + if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) { cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed @@ -243,7 +245,6 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.mCell = cell; item.mContainerStore = 0; - MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); } return it; From 6f7fbc867f6e4ba8acb9fe03d7169c819cfecf91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 Apr 2014 21:15:14 +0200 Subject: [PATCH 131/545] Fix several leaks --- apps/openmw/mwgui/inventorywindow.cpp | 10 +++++----- apps/openmw/mwgui/inventorywindow.hpp | 4 ++-- apps/openmw/mwrender/characterpreview.hpp | 4 ++++ apps/openmw/mwrender/ripplesimulation.cpp | 5 ++++- components/ogreinit/ogreinit.cpp | 1 + components/terrain/world.cpp | 2 ++ files/mygui/openmw_text.skin.xml | 16 ---------------- 7 files changed, 18 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e9efe75e7f..2bea088e32 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -35,7 +35,7 @@ namespace MWGui , mTrading(false) , mLastXSize(0) , mLastYSize(0) - , mPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr()) + , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) , mSelectedItem(-1) @@ -91,8 +91,8 @@ namespace MWGui mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr()); mSortModel = new SortFilterItemModel(mTradeModel); mItemView->setModel(mSortModel); - mPreview = MWRender::InventoryPreview(mPtr); - mPreview.setup(); + mPreview.reset(new MWRender::InventoryPreview(mPtr)); + mPreview->setup(); } void InventoryWindow::setGuiMode(GuiMode mode) @@ -444,7 +444,7 @@ namespace MWGui MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y) { - int slot = mPreview.getSlotSelected (x, y); + int slot = mPreview->getSlotSelected (x, y); if (slot == -1) return MWWorld::Ptr(); @@ -493,7 +493,7 @@ namespace MWGui mPreviewDirty = false; MyGUI::IntSize size = mAvatarImage->getSize(); - mPreview.update (size.width, size.height); + mPreview->update (size.width, size.height); mAvatarImage->setImageTexture("CharacterPreview"); mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height))); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 7ef168e988..c23a74efad 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -34,7 +34,7 @@ namespace MWGui MWWorld::Ptr getAvatarSelectedItem(int x, int y); void rebuildAvatar() { - mPreview.rebuild(); + mPreview->rebuild(); } TradeItemModel* getTradeModel(); @@ -81,7 +81,7 @@ namespace MWGui int mLastXSize; int mLastYSize; - MWRender::InventoryPreview mPreview; + std::auto_ptr mPreview; bool mTrading; diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 16e6ab017d..60312455ff 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -34,6 +34,10 @@ namespace MWRender virtual void rebuild(); + private: + CharacterPreview(const CharacterPreview&); + CharacterPreview& operator=(const CharacterPreview&); + protected: virtual bool renderHeadOnly() { return false; } diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index f52deedcc6..74216c1de4 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -28,7 +28,9 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) mRippleAreaLength(1000), mImpulseSize(20), mTexelOffset(0,0), - mFirstUpdate(true) + mFirstUpdate(true), + mRectangle(NULL), + mImpulse(NULL) { Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); @@ -105,6 +107,7 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) RippleSimulation::~RippleSimulation() { delete mRectangle; + delete mImpulse; Ogre::Root::getSingleton().destroySceneManager(mSceneMgr); } diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 1b9a899a0b..01b8764c2b 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -62,6 +62,7 @@ namespace OgreInit OgreInit::~OgreInit() { delete mRoot; + delete Ogre::LogManager::getSingletonPtr(); std::vector::iterator ei; for(ei = mEmitterFactories.begin();ei != mEmitterFactories.end();++ei) diff --git a/components/terrain/world.cpp b/components/terrain/world.cpp index 844144d7c4..3d968470f3 100644 --- a/components/terrain/world.cpp +++ b/components/terrain/world.cpp @@ -337,6 +337,8 @@ namespace Terrain it->mTarget->loadLayers(*it); } + delete data; + mRootNode->loadMaterials(); mLayerLoadPending = false; diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index b80859ea1a..d4c72c75b4 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -49,22 +49,6 @@ - - - - - - - - - - - - - - - - From 64a30ad182bdb4caec160b6fd1d53b0caab9e8b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 12:44:31 +0200 Subject: [PATCH 132/545] Fix another leak --- apps/openmw/mwgui/fontloader.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/fontloader.cpp b/apps/openmw/mwgui/fontloader.cpp index 7a6317c163..59c2e7ca68 100644 --- a/apps/openmw/mwgui/fontloader.cpp +++ b/apps/openmw/mwgui/fontloader.cpp @@ -196,6 +196,16 @@ namespace MWGui bitmapFile->read(&textureData[0], width*height*4); bitmapFile->close(); + std::string resourceName; + if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) + resourceName = "Magic Cards"; + else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century")) + resourceName = "Century Gothic"; + else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) + resourceName = "Daedric"; + else + return; // no point in loading it, since there is no way of using additional fonts + std::string textureName = name; Ogre::Image image; image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA); @@ -208,18 +218,11 @@ namespace MWGui // Register the font with MyGUI MyGUI::ResourceManualFont* font = static_cast( MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont")); + // We need to emulate loading from XML because the data members are private as of mygui 3.2.0 MyGUI::xml::Document xmlDocument; MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont"); - - if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) - root->addAttribute("name", "Magic Cards"); - else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century")) - root->addAttribute("name", "Century Gothic"); - else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) - root->addAttribute("name", "Daedric"); - else - return; // no point in loading it, since there is no way of using additional fonts + root->addAttribute("name", resourceName); MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property"); defaultHeight->addAttribute("key", "DefaultHeight"); @@ -285,6 +288,7 @@ namespace MWGui font->deserialization(root, MyGUI::Version(3,2,0)); + MyGUI::ResourceManager::getInstance().removeByName(font->getResourceName()); MyGUI::ResourceManager::getInstance().addResource(font); } From fc7e79027af9df32276211b9f8306c73cb51f1e4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 16:44:39 +0200 Subject: [PATCH 133/545] Fixes #1144: Don't refreshCurrentAnims when adding already dead actors --- apps/openmw/mwmechanics/character.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 8ad2b4a67e..280639f714 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -489,12 +489,13 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim mIdleState = CharState_Idle; } - refreshCurrentAnims(mIdleState, mMovementState, true); if(mDeathState != CharState_None) { playRandomDeath(1.0f); } + else + refreshCurrentAnims(mIdleState, mMovementState, true); } CharacterController::~CharacterController() From ea1aaef8cabd03500a1574f6f87af8f2f19d892c Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Thu, 1 May 2014 18:25:28 +0200 Subject: [PATCH 134/545] replace paged with unpaged (and vice versa) --- apps/opencs/model/world/data.cpp | 2 +- .../view/render/pagedworldspacewidget.cpp | 5 +- .../view/render/pagedworldspacewidget.hpp | 8 +- apps/opencs/view/render/scenewidget.hpp | 2 +- .../view/render/unpagedworldspacewidget.cpp | 8 +- .../view/render/unpagedworldspacewidget.hpp | 1 + apps/opencs/view/world/scenesubview.cpp | 108 +++++++++++++++--- apps/opencs/view/world/scenesubview.hpp | 10 ++ 8 files changed, 115 insertions(+), 29 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d60dcae117..b71f537f37 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -453,7 +453,7 @@ CSMWorld::IdCollection& CSMWorld::Data::getFilters() return mFilters; } -QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) +QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 3691a7a4da..a6bdb51802 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -7,7 +7,7 @@ #include -CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document) +CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) : WorldspaceWidget (document, parent) {} @@ -56,10 +56,9 @@ void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) if (mime->fromDocument(mDocument)) { - const std::vector data(mime->getData()); + const std::vector& data(mime->getData()); CSVRender::WorldspaceWidget::dropType whatHappend = getDropType(data); - std::cout< getCoordinatesFromId(const std::string& record) const; - void handleDrop(const std::vector& data); - public: - PagedWorldspaceWidget (QWidget *parent, const CSMDoc::Document& document); + PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document); ///< \note Sets the cell area selection to an invalid value to indicate that currently /// no cells are displayed. The cells to be displayed will be specified later through /// hint system. - virtual void useViewHint (const std::string& hint); + void useViewHint (const std::string& hint); void setCellSelection (const CSMWorld::CellSelection& selection); + virtual void handleDrop(const std::vector& data); + signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 8df9cf3471..7f8f104f15 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -36,7 +36,7 @@ namespace CSVRender SceneWidget(QWidget *parent); virtual ~SceneWidget(); - QPaintEngine* paintEngine() const; + QPaintEngine* paintEngine() const; CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent); ///< \attention The created tool is not added to the toolbar (via addTool). Doing that diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 43c8dbd8d5..9290887898 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -23,8 +23,7 @@ void CSVRender::UnpagedWorldspaceWidget::update() /// \todo deal with mSunlight and mFog/mForDensity } -CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, - CSMDoc::Document& document, QWidget *parent) +CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent) : WorldspaceWidget (document, parent), mCellId (cellId) { mCellsModel = &dynamic_cast ( @@ -74,7 +73,7 @@ void CSVRender::UnpagedWorldspaceWidget::dropEvent (QDropEvent* event) if (mime->fromDocument (mDocument)) { - const std::vector data (mime->getData()); + const std::vector& data (mime->getData()); CSVRender::WorldspaceWidget::dropType whatHappend = getDropType (data); switch (whatHappend) @@ -96,5 +95,6 @@ void CSVRender::UnpagedWorldspaceWidget::dropEvent (QDropEvent* event) void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) { - + mCellId = data.begin()->getId(); + update(); } diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index d5b62b8edf..ad1e22e396 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -33,6 +33,7 @@ namespace CSVRender UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget *parent); + private: void handleDrop(const std::vector& data); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 506a0288da..45cd116189 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -18,11 +18,10 @@ #include "tablebottombox.hpp" #include "creator.hpp" -#include "scenetoolbar.hpp" #include "scenetoolmode.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id) +: SubView (id), mLayout(new QHBoxLayout), mDocument(document) { QVBoxLayout *layout = new QVBoxLayout; @@ -32,33 +31,43 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, this), 0); - QHBoxLayout *layout2 = new QHBoxLayout; + mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); - layout2->setContentsMargins (QMargins (0, 0, 0, 0)); - - SceneToolbar *toolbar = new SceneToolbar (48+6, this); + mToolbar = new SceneToolbar (48+6, this); if (id.getId()=="sys::default") { CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this, document); + mScene = widget; + connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), - this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + + connect (widget, SIGNAL(interiorCellsDropped (const std::vector&)), + this, SLOT(changeToUnpaged (const std::vector&))); } else - mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); + { + CSVRender::UnpagedWorldspaceWidget *widget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); - SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar); - toolbar->addTool (navigationTool); + mScene = widget; - SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar); - toolbar->addTool (lightingTool); + connect (widget, SIGNAL(exteriorCellsDropped(const std::vector&)), + this, SLOT(changeToUnpaged(const std::vector&))); + } - layout2->addWidget (toolbar, 0); + SceneToolMode *navigationTool = mScene->makeNavigationSelector (mToolbar); + mToolbar->addTool (navigationTool); - layout2->addWidget (mScene, 1); + SceneToolMode *lightingTool = mScene->makeLightingSelector (mToolbar); + mToolbar->addTool (lightingTool); - layout->insertLayout (0, layout2, 1); + mLayout->addWidget (mToolbar, 0); + + mLayout->addWidget (mScene, 1); + + layout->insertLayout (0, mLayout, 1); CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); @@ -126,4 +135,71 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection } setWindowTitle (QString::fromUtf8 (stream.str().c_str())); -} \ No newline at end of file +} + +void CSVWorld::SceneSubView::changeToPaged (const std::vector< CSMWorld::UniversalId >& data) +{ + mLayout->removeWidget(mToolbar); + mLayout->removeWidget(mScene); + + delete mScene; + + delete mToolbar; + + mToolbar = new SceneToolbar (48+6, this); + + CSVRender::PagedWorldspaceWidget* widget = new CSVRender::PagedWorldspaceWidget (this, mDocument); + + mScene = widget; + + SceneToolMode* navigationTool = mScene->makeNavigationSelector (mToolbar); + mToolbar->addTool (navigationTool); + + SceneToolMode* lightingTool = mScene->makeLightingSelector (mToolbar); + mToolbar->addTool (lightingTool); + + connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), + this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + + connect (widget, SIGNAL (interiorCellsDropped (const std::vector&)), + this, SLOT (changeToUnpaged (const std::vector&))); + + mLayout->addWidget (mToolbar, 0); + mLayout->addWidget (mScene, 1); + + mScene->selectDefaultNavigationMode(); + + connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + + widget->handleDrop (data); +} + +void CSVWorld::SceneSubView::changeToUnpaged (const std::vector< CSMWorld::UniversalId >& data) +{ + mLayout->removeWidget(mToolbar); + mLayout->removeWidget(mScene); + + delete mScene; + delete mToolbar; + + mToolbar = new SceneToolbar (48+6, this); + CSVRender::UnpagedWorldspaceWidget* widget = new CSVRender::UnpagedWorldspaceWidget (data.begin()->getId(), mDocument, this); + + mScene = widget; + + SceneToolMode* navigationTool = mScene->makeNavigationSelector (mToolbar); + mToolbar->addTool (navigationTool); + + SceneToolMode* lightingTool = mScene->makeLightingSelector (mToolbar); + mToolbar->addTool (lightingTool); + + connect (widget, SIGNAL (exteriorCellsDropped (const std::vector&)), + this, SLOT (changeToPaged (const std::vector&))); + + mLayout->addWidget (mToolbar, 0); + mLayout->addWidget (mScene, 1); + + mScene->selectDefaultNavigationMode(); + + connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); +} diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 0b15ea5413..9af76ef6a7 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -1,7 +1,10 @@ #ifndef CSV_WORLD_SCENESUBVIEW_H #define CSV_WORLD_SCENESUBVIEW_H +#include + #include "../doc/subview.hpp" +#include "scenetoolbar.hpp" class QModelIndex; @@ -32,6 +35,9 @@ namespace CSVWorld TableBottomBox *mBottom; CSVRender::WorldspaceWidget *mScene; + QHBoxLayout* mLayout; + CSMDoc::Document& mDocument; + SceneToolbar* mToolbar; public: @@ -50,6 +56,10 @@ namespace CSVWorld void closeRequest(); void cellSelectionChanged (const CSMWorld::CellSelection& selection); + + void changeToPaged(const std::vector& data); + + void changeToUnpaged(const std::vector& data); }; } From c2b070f097dcabcff3321f711394f403037bc4a0 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Thu, 1 May 2014 19:17:33 +0200 Subject: [PATCH 135/545] trying to do it right. --- apps/opencs/view/world/scenesubview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 45cd116189..f3807e4e9c 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -143,9 +143,9 @@ void CSVWorld::SceneSubView::changeToPaged (const std::vector< CSMWorld::Univers mLayout->removeWidget(mScene); delete mScene; - delete mToolbar; + setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Cell, "sys::default")); mToolbar = new SceneToolbar (48+6, this); CSVRender::PagedWorldspaceWidget* widget = new CSVRender::PagedWorldspaceWidget (this, mDocument); @@ -184,6 +184,7 @@ void CSVWorld::SceneSubView::changeToUnpaged (const std::vector< CSMWorld::Unive mToolbar = new SceneToolbar (48+6, this); CSVRender::UnpagedWorldspaceWidget* widget = new CSVRender::UnpagedWorldspaceWidget (data.begin()->getId(), mDocument, this); + setUniversalId(*(data.begin())); mScene = widget; From 17bb8d7f9a84fbe5106ab97fbe4407f327b34097 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 21:16:32 +0200 Subject: [PATCH 136/545] Fixes #1252: Add item/magic keybindings to savegame --- apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwgui/quickkeysmenu.cpp | 119 +++++++++++++++++++++++- apps/openmw/mwgui/quickkeysmenu.hpp | 5 + apps/openmw/mwgui/windowmanagerimp.cpp | 15 ++- apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwstate/statemanagerimp.cpp | 4 +- components/esm/defs.hpp | 7 ++ 7 files changed, 144 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 4287e466bd..c78902a60a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -305,6 +305,7 @@ namespace MWBase virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; + virtual int countSavedGameRecords() const = 0; }; } diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index dc72269099..fb41b3b679 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -55,6 +55,14 @@ namespace MWGui } } + void QuickKeysMenu::clear() + { + for (int i=0; i<10; ++i) + { + unassign(mQuickKeyButtons[i], i); + } + } + QuickKeysMenu::~QuickKeysMenu() { delete mAssignDialog; @@ -154,8 +162,6 @@ namespace MWGui frame->setUserString ("ToolTipType", "ItemPtr"); frame->setUserData(item); frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); - - MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); path += MWWorld::Class::get(item).getInventoryIcon(item); @@ -165,7 +171,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mItemSelectionDialog->setVisible(false); + if (mItemSelectionDialog) + mItemSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignItemCancel() @@ -198,7 +205,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mMagicSelectionDialog->setVisible(false); + if (mMagicSelectionDialog) + mMagicSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignMagic (const std::string& spellId) @@ -239,7 +247,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mMagicSelectionDialog->setVisible(false); + if (mMagicSelectionDialog) + mMagicSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignMagicCancel () @@ -374,6 +383,106 @@ namespace MWGui center(); } + void QuickKeysMenu::write(ESM::ESMWriter &writer) + { + const std::string recKey = "KEY_"; + writer.startRecord(ESM::REC_KEYS); + + for (int i=0; i<10; ++i) + { + writer.startSubRecord(recKey); + + MyGUI::Button* button = mQuickKeyButtons[i]; + + int type = *button->getUserData(); + writer.writeHNT("TYPE", type); + + switch (type) + { + case Type_Unassigned: + writer.writeHNString("ID__", ""); + break; + case Type_Item: + case Type_MagicItem: + { + MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); + writer.writeHNString("ID__", item.getCellRef().mRefID); + break; + } + case Type_Magic: + std::string spellId = button->getChildAt(0)->getUserString("Spell"); + writer.writeHNString("ID__", spellId); + break; + } + + writer.endRecord(recKey); + } + + writer.endRecord(ESM::REC_KEYS); + } + + void QuickKeysMenu::readRecord(ESM::ESMReader &reader, int32_t type) + { + if (type != ESM::REC_KEYS) + return; + + int i=0; + while (reader.isNextSub("KEY_")) + { + reader.getSubHeader(); + int keyType; + reader.getHNT(keyType, "TYPE"); + std::string id; + id = reader.getHNString("ID__"); + + mSelectedIndex = i; + + MyGUI::Button* button = mQuickKeyButtons[i]; + + switch (keyType) + { + case Type_Magic: + onAssignMagic(id); + break; + case Type_Item: + case Type_MagicItem: + { + // Find the item by id + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); + MWWorld::Ptr item; + for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) + { + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id)) + { + if (item.isEmpty() || + // Prefer the stack with the lowest remaining uses + (it->getCellRef().mCharge != -1 && (item.getCellRef().mCharge == -1 || it->getCellRef().mCharge < item.getCellRef().mCharge) )) + { + item = *it; + } + } + } + + if (item.isEmpty()) + unassign(button, i); + else + { + if (keyType == Type_Item) + onAssignItem(item); + else if (keyType == Type_MagicItem) + onAssignMagicItem(item); + } + + break; + } + case Type_Unassigned: + unassign(button, i); + break; + } + ++i; + } + } // --------------------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 058519ece4..c0e25a517c 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -41,6 +41,11 @@ namespace MWGui }; + void write (ESM::ESMWriter& writer); + void readRecord (ESM::ESMReader& reader, int32_t type); + void clear(); + + private: MyGUI::EditBox* mInstructionLabel; MyGUI::Button* mOkButton; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e2e4e157c1..1b4145e5c3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1405,16 +1405,29 @@ namespace MWGui void WindowManager::clear() { mMap->clear(); + mQuickKeysMenu->clear(); } void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) { mMap->write(writer, progress); + + mQuickKeysMenu->write(writer); + progress.increaseProgress(); } void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type) { - mMap->readRecord(reader, type); + if (type == ESM::REC_GMAP) + mMap->readRecord(reader, type); + else if (type == ESM::REC_KEYS) + mQuickKeysMenu->readRecord(reader, type); + } + + int WindowManager::countSavedGameRecords() const + { + return 1 // Global map + + 1; // QuickKeysMenu } void WindowManager::playVideo(const std::string &name, bool allowSkipping) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 064ca89bac..44bc566546 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -293,6 +293,7 @@ namespace MWGui virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress); virtual void readRecord (ESM::ESMReader& reader, int32_t type); + virtual int countSavedGameRecords() const; private: bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 33f2dce7c3..48d12f0a6d 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -201,7 +201,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot +MWBase::Environment::get().getWorld()->countSavedGameRecords() +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() - +1; // global map + +MWBase::Environment::get().getWindowManager()->countSavedGameRecords(); writer.setRecordCount (recordCount); writer.save (stream); @@ -323,7 +323,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl break; case ESM::REC_GMAP: - + case ESM::REC_KEYS: MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 4d5b36c740..b2a1637f11 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -34,6 +34,12 @@ struct Position }; #pragma pack(pop) +template +struct FourCC +{ + static const unsigned int value = (((((d << 8) | c) << 8) | b) << 8) | a; +}; + enum RecNameInts { // format 0 / legacy @@ -93,6 +99,7 @@ enum RecNameInts REC_GMAP = 0x50414d47, REC_DIAS = 0x53414944, REC_WTHR = 0x52485457, + REC_KEYS = FourCC<'K','E','Y','S'>::value, // format 1 REC_FILT = 0x544C4946 From 6381b1e9381436a22c8a3af212bd4b4145607529 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 11:20:43 +0200 Subject: [PATCH 137/545] Fixes #1309: Do not allow saving while dialogs are opened, just like vanilla This limitation could be removed post-1.0 by serializing the state of open windows. --- apps/openmw/mwbase/windowmanager.hpp | 3 +++ apps/openmw/mwgui/mainmenu.cpp | 3 ++- apps/openmw/mwgui/referenceinterface.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 20 ++++++++++++++++++++ apps/openmw/mwgui/windowmanagerimp.hpp | 3 +++ apps/openmw/mwstate/statemanagerimp.cpp | 5 +++-- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c78902a60a..9e5230af62 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -306,6 +306,9 @@ namespace MWBase virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; virtual int countSavedGameRecords() const = 0; + + /// Does the current stack of GUI-windows permit saving? + virtual bool isSavingAllowed() const = 0; }; } diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index df9c53ea87..8b44af2ef3 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -170,7 +170,8 @@ namespace MWGui buttons.push_back("loadgame"); if (state==MWBase::StateManager::State_Running && - MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) + MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 && + MWBase::Environment::get().getWindowManager()->isSavingAllowed()) buttons.push_back("savegame"); buttons.push_back("options"); diff --git a/apps/openmw/mwgui/referenceinterface.hpp b/apps/openmw/mwgui/referenceinterface.hpp index 39574d0f7a..df53a42b70 100644 --- a/apps/openmw/mwgui/referenceinterface.hpp +++ b/apps/openmw/mwgui/referenceinterface.hpp @@ -17,6 +17,8 @@ namespace MWGui void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable + void resetReference() { mPtr = MWWorld::Ptr(); mCurrentPlayerCell = NULL; } + protected: virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1b4145e5c3..d2a31e8d15 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1406,6 +1406,19 @@ namespace MWGui { mMap->clear(); mQuickKeysMenu->clear(); + + mTrainingWindow->resetReference(); + mDialogueWindow->resetReference(); + mTradeWindow->resetReference(); + mSpellBuyingWindow->resetReference(); + mSpellCreationDialog->resetReference(); + mEnchantingDialog->resetReference(); + mContainerWindow->resetReference(); + mCompanionWindow->resetReference(); + mConsole->resetReference(); + + mGuiModes.clear(); + updateVisible(); } void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) @@ -1430,6 +1443,13 @@ namespace MWGui + 1; // QuickKeysMenu } + bool WindowManager::isSavingAllowed() const + { + return !MyGUI::InputManager::getInstance().isModalAny() + // TODO: remove this, once we have properly serialized the state of open windows + && (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu)); + } + void WindowManager::playVideo(const std::string &name, bool allowSkipping) { mVideoWidget->playVideo("video\\" + name, allowSkipping); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 44bc566546..e31013b451 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -295,6 +295,9 @@ namespace MWGui virtual void readRecord (ESM::ESMReader& reader, int32_t type); virtual int countSavedGameRecords() const; + /// Does the current stack of GUI-windows permit saving? + virtual bool isSavingAllowed() const; + private: bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 48d12f0a6d..c718eeced7 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -235,8 +235,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot void MWState::StateManager::quickSave (std::string name) { - if (mState!=State_Running || - MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")!=-1) // char gen + if (!(mState==State_Running && + MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 // char gen + && MWBase::Environment::get().getWindowManager()->isSavingAllowed())) { //You can not save your game right now MWBase::Environment::get().getWindowManager()->messageBox("#{sSaveGameDenied}"); From f8cc328b5e63e2eed325cde7b97bc7ee1d8bacb7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 11:26:05 +0200 Subject: [PATCH 138/545] Slightly prettier backdrop when loading game from main menu. --- apps/openmw/mwgui/savegamedialog.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index a77c625f90..c0daa2c0ea 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -206,6 +206,13 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}"); return; } + } + + setVisible(false); + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); + + if (mSaving) + { MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), mCurrentSlot); } else @@ -213,12 +220,9 @@ namespace MWGui if (mCurrentCharacter && mCurrentSlot) { MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot); - MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); } } - setVisible(false); - if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) { From 8560b43464a9af526e34ce23b17423ed9a577fe1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 12:47:28 +0200 Subject: [PATCH 139/545] Move to esm component --- apps/openmw/mwgui/quickkeysmenu.cpp | 36 ++++++++++++++---------- components/CMakeLists.txt | 2 +- components/esm/quickkeys.cpp | 43 +++++++++++++++++++++++++++++ components/esm/quickkeys.hpp | 28 +++++++++++++++++++ 4 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 components/esm/quickkeys.cpp create mode 100644 components/esm/quickkeys.hpp diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index fb41b3b679..51e24e29c8 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -2,6 +2,8 @@ #include +#include + #include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" @@ -385,39 +387,41 @@ namespace MWGui void QuickKeysMenu::write(ESM::ESMWriter &writer) { - const std::string recKey = "KEY_"; writer.startRecord(ESM::REC_KEYS); + ESM::QuickKeys keys; + for (int i=0; i<10; ++i) { - writer.startSubRecord(recKey); - MyGUI::Button* button = mQuickKeyButtons[i]; int type = *button->getUserData(); - writer.writeHNT("TYPE", type); + + ESM::QuickKeys::QuickKey key; + key.mType = type; switch (type) { case Type_Unassigned: - writer.writeHNString("ID__", ""); break; case Type_Item: case Type_MagicItem: { MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); - writer.writeHNString("ID__", item.getCellRef().mRefID); + key.mId = item.getCellRef().mRefID; break; } case Type_Magic: std::string spellId = button->getChildAt(0)->getUserString("Spell"); - writer.writeHNString("ID__", spellId); + key.mId = spellId; break; } - writer.endRecord(recKey); + keys.mKeys.push_back(key); } + keys.save(writer); + writer.endRecord(ESM::REC_KEYS); } @@ -426,17 +430,18 @@ namespace MWGui if (type != ESM::REC_KEYS) return; + ESM::QuickKeys keys; + keys.load(reader); + int i=0; - while (reader.isNextSub("KEY_")) + for (std::vector::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it) { - reader.getSubHeader(); - int keyType; - reader.getHNT(keyType, "TYPE"); - std::string id; - id = reader.getHNString("ID__"); + if (i >= 10) + return; mSelectedIndex = i; - + int keyType = it->mType; + std::string id = it->mId; MyGUI::Button* button = mQuickKeyButtons[i]; switch (keyType) @@ -480,6 +485,7 @@ namespace MWGui unassign(button, i); break; } + ++i; } } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 38be5b11a6..1c60dfb831 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate + npcstats creaturestats weatherstate quickkeys ) add_component_dir (misc diff --git a/components/esm/quickkeys.cpp b/components/esm/quickkeys.cpp new file mode 100644 index 0000000000..ad2b671aab --- /dev/null +++ b/components/esm/quickkeys.cpp @@ -0,0 +1,43 @@ +#include "quickkeys.hpp" + +#include "esmwriter.hpp" +#include "esmreader.hpp" + +namespace ESM +{ + + void QuickKeys::load(ESMReader &esm) + { + while (esm.isNextSub("KEY_")) + { + esm.getSubHeader(); + int keyType; + esm.getHNT(keyType, "TYPE"); + std::string id; + id = esm.getHNString("ID__"); + + QuickKey key; + key.mType = keyType; + key.mId = id; + + mKeys.push_back(key); + } + } + + void QuickKeys::save(ESMWriter &esm) const + { + const std::string recKey = "KEY_"; + + for (std::vector::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) + { + esm.startSubRecord(recKey); + + esm.writeHNT("TYPE", it->mType); + esm.writeHNString("ID__", it->mId); + + esm.endRecord(recKey); + } + } + + +} diff --git a/components/esm/quickkeys.hpp b/components/esm/quickkeys.hpp new file mode 100644 index 0000000000..c52466b13e --- /dev/null +++ b/components/esm/quickkeys.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_COMPONENTS_ESM_QUICKKEYS_H +#define OPENMW_COMPONENTS_ESM_QUICKKEYS_H + +#include +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct QuickKeys + { + struct QuickKey + { + int mType; + std::string mId; // Spell or Item ID + }; + + std::vector mKeys; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + +} + +#endif From 58d868d56af79a09f1a5c567beca27c75f6eb089 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 19:16:10 +0200 Subject: [PATCH 140/545] Change default water setting (current fps is low enough as it is without this setting enabled) --- files/settings-default.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index f24636d151..2b44d0f4e2 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -133,9 +133,9 @@ distant land = false shader = true [Water] -shader = true +shader = false -refraction = true +refraction = false rtt size = 512 reflect terrain = true From 7f1df878f690c11b2e9b2e275ab1a5f01b7ffcb5 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Fri, 2 May 2014 20:15:46 +0200 Subject: [PATCH 141/545] make getDropType static and public. --- apps/opencs/view/render/worldspacewidget.cpp | 2 +- apps/opencs/view/render/worldspacewidget.hpp | 30 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 925dd921b0..16ff0a403f 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -54,7 +54,7 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( } CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType ( - const std::vector< CSMWorld::UniversalId >& data) const + const std::vector< CSMWorld::UniversalId >& data) { dropType output = notCells; bool firstIteration = true; diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 83ef593d6b..f9d4f9a063 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -30,20 +30,6 @@ namespace CSVRender public: - WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); - - CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); - ///< \attention The created tool is not added to the toolbar (via addTool). Doing that - /// is the responsibility of the calling function. - - void selectDefaultNavigationMode(); - - virtual void useViewHint (const std::string& hint); - ///< Default-implementation: ignored. - - protected: - const CSMDoc::Document& mDocument; //for checking if drop comes from same document - enum dropType { cellsMixed, @@ -52,7 +38,21 @@ namespace CSVRender notCells }; - dropType getDropType(const std::vector& data) const; + WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); + + CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); + ///< \attention The created tool is not added to the toolbar (via addTool). Doing that + /// is the responsibility of the calling function. + + void selectDefaultNavigationMode(); + + static dropType getDropType(const std::vector& data); + + virtual void useViewHint (const std::string& hint); + ///< Default-implementation: ignored. + + protected: + const CSMDoc::Document& mDocument; //for checking if drop comes from same document private: From 92467ba6bc5b91f5e4487a5bca5100f8d6a13930 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 20:55:58 +0200 Subject: [PATCH 142/545] Fix sunlight for interiors --- apps/openmw/mwrender/renderingmanager.cpp | 3 ++- apps/openmw/mwworld/weather.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 97283d065e..19d26a176e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -563,7 +563,8 @@ void RenderingManager::configureAmbient(MWWorld::CellStore &mCell) Ogre::ColourValue colour; colour.setAsABGR (mCell.getCell()->mAmbi.mSunlight); mSun->setDiffuseColour (colour); - mSun->setDirection(0,-1,0); + mSun->setDirection(1,-1,-1); + sunEnable(false); } } // Switch through lighting modes. diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 3611114a93..25f523bee9 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -329,7 +329,6 @@ void WeatherManager::update(float duration) const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior()); if (!exterior) { - mRendering->sunDisable(false); mRendering->skyDisable(); mRendering->getSkyManager()->setLightningStrength(0.f); stopSounds(true); From df1694c27b49d239d270b58ddc694c2fc74b13fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 22:19:02 +0200 Subject: [PATCH 143/545] Console autocompletion: List candidates when repeatedly pressing tab (bash-style) --- apps/openmw/mwgui/console.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 01eb770f73..d51d4298f6 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -215,16 +215,22 @@ namespace MWGui { std::vector matches; listNames(); - mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches )); -#if 0 - int i = 0; - for(std::vector::iterator it=matches.begin(); it < matches.end(); ++it,++i ) + std::string oldCaption = mCommandLine->getCaption(); + std::string newCaption = complete( mCommandLine->getOnlyText(), matches ); + mCommandLine->setCaption(newCaption); + + // List candidates if repeatedly pressing tab + if (oldCaption == newCaption && matches.size()) { - printOK( *it ); - if( i == 50 ) - break; + int i = 0; + printOK(""); + for(std::vector::iterator it=matches.begin(); it < matches.end(); ++it,++i ) + { + printOK( *it ); + if( i == 50 ) + break; + } } -#endif } if(mCommandHistory.empty()) return; From 1b074e55243cf17be2f5b5ee9b4783bcacb7c146 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 22:38:39 +0200 Subject: [PATCH 144/545] Call setAttacked even if the attack missed. Unsuccessful hits should also evoke a response. --- apps/openmw/mwclass/npc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e43bfe40dd..5222eac443 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -624,6 +624,8 @@ namespace MWClass if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); + getCreatureStats(ptr).setAttacked(true); + if(!successful) { // TODO: Handle HitAttemptOnMe script function @@ -659,7 +661,6 @@ namespace MWClass { MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); } - getCreatureStats(ptr).setAttacked(true); // Check for knockdown float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat(); From e7b9b6d87abdd1201ec764c5acd2cb6803e6b5f6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 23:07:01 +0200 Subject: [PATCH 145/545] Fix a confusing variable name --- extern/sdl4ogre/sdlinputwrapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index c3ea2fd746..09a2441778 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -241,8 +241,8 @@ namespace SFO //eep, wrap the pointer manually if the input driver doesn't support //relative positioning natively - int success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE); - if(relative && success != 0) + bool success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0; + if(relative && !success) mWrapPointer = true; //now remove all mouse events using the old setting from the queue From 7331a64e34523743b57982e61be6105a91610c6b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 3 May 2014 11:33:20 +0200 Subject: [PATCH 146/545] Restore fix for Bug #875 (commit 602be9bbe7f2, was broken by 43757efdc4af643) --- apps/openmw/mwworld/physicssystem.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 247c0d4bdf..e30a2bbc17 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -227,10 +227,6 @@ namespace MWWorld Ogre::Vector3 inertia(0.0f); Ogre::Vector3 velocity; - bool canWalk = ptr.getClass().canWalk(ptr); - bool isBipedal = ptr.getClass().isBipedal(ptr); - bool isNpc = ptr.getClass().isNpc(); - if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly { // TODO: Shouldn't water have higher drag in calculating velocity? @@ -277,14 +273,11 @@ namespace MWWorld // NOTE: velocity is either z axis only or x & z axis Ogre::Vector3 nextpos = newPosition + velocity * remainingTime; - // If not able to fly, walk or bipedal don't allow to move out of water + // If not able to fly, don't allow to swim up into the air // TODO: this if condition may not work for large creatures or situations // where the creature gets above the waterline for some reason if(newPosition.z < waterlevel && // started 3/4 under water !isFlying && // can't fly - !canWalk && // can't walk - !isBipedal && // not bipedal (assume bipedals can walk) - !isNpc && // FIXME: shouldn't really need this nextpos.z > waterlevel && // but about to go above water newPosition.z <= waterlevel) { From e09218f164f9f2c52a44dfc4146652e426a987d6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 12:07:05 +0200 Subject: [PATCH 147/545] moved load code from Document to Loader class --- apps/opencs/model/doc/document.cpp | 37 ++++----------------------- apps/opencs/model/doc/document.hpp | 8 ++---- apps/opencs/model/doc/loader.cpp | 41 +++++++++++++++++++++++++----- apps/opencs/model/doc/loader.hpp | 9 ++++++- 4 files changed, 50 insertions(+), 45 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 760c675a02..a441f4ae29 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -8,23 +8,6 @@ #include #endif -void CSMDoc::Document::load (const std::vector::const_iterator& begin, - const std::vector::const_iterator& end, bool lastAsModified) -{ - assert (begin!=end); - - std::vector::const_iterator end2 (end); - - if (lastAsModified) - --end2; - - for (std::vector::const_iterator iter (begin); iter!=end2; ++iter) - getData().loadFile (*iter, true, false); - - if (lastAsModified) - getData().loadFile (*end2, false, false); -} - void CSMDoc::Document::addGmsts() { static const char *gmstFloats[] = @@ -2272,21 +2255,6 @@ CSMDoc::Document::~Document() { } -void CSMDoc::Document::setupData() -{ - if (!mNew || mContentFiles.size()>1) - { - std::vector::const_iterator end = mContentFiles.end(); - - if (mNew) - --end; - - load (mContentFiles.begin(), end, !mNew); - } - - getData().loadFile (mProjectPath, false, true); -} - QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; @@ -2313,6 +2281,11 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const return mSavePath; } +const boost::filesystem::path& CSMDoc::Document::getProjectPath() const +{ + return mProjectPath; +} + const std::vector& CSMDoc::Document::getContentFiles() const { return mContentFiles; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e19efd04ec..11a4057d14 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -54,10 +54,6 @@ namespace CSMDoc Document (const Document&); Document& operator= (const Document&); - void load (const std::vector::const_iterator& begin, - const std::vector::const_iterator& end, bool lastAsModified); - ///< \param lastAsModified Store the last file in Modified instead of merging it into Base. - void createBase(); void addGmsts(); @@ -78,14 +74,14 @@ namespace CSMDoc ~Document(); - void setupData(); - QUndoStack& getUndoStack(); int getState() const; const boost::filesystem::path& getSavePath() const; + const boost::filesystem::path& getProjectPath() const; + const std::vector& getContentFiles() const; ///< \attention The last element in this collection is the file that is being edited, /// but with its original path instead of the save path. diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index dbaa2b4d5b..5277b08d2b 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -5,6 +5,9 @@ #include "document.hpp" +CSMDoc::Loader::Stage::Stage() : mFile (0) {} + + CSMDoc::Loader::Loader() { QTimer *timer = new QTimer (this); @@ -28,31 +31,57 @@ void CSMDoc::Loader::load() return; } - std::vector >::iterator iter = mDocuments.begin(); + std::vector >::iterator iter = mDocuments.begin(); Document *document = iter->first; - mDocuments.erase (iter); + int size = static_cast (document->getContentFiles().size()); + + if (document->isNew()) + --size; + + bool done = false; try { - document->setupData(); - emit documentLoaded (document); + if (iter->second.mFilegetData().loadFile (document->getContentFiles()[iter->second.mFile], + iter->second.mFilesecond.mFile==size) + { + document->getData().loadFile (document->getProjectPath(), false, true); + } + else + { + done = true; + } + + ++(iter->second.mFile); } catch (const std::exception& e) { + mDocuments.erase (iter); emit documentNotLoaded (document, e.what()); + return; + } + + if (done) + { + mDocuments.erase (iter); + emit documentLoaded (document); } } void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) { - mDocuments.push_back (std::make_pair (document, false)); + mDocuments.push_back (std::make_pair (document, Stage())); } void CSMDoc::Loader::abortLoading (Document *document) { - for (std::vector >::iterator iter = mDocuments.begin(); + for (std::vector >::iterator iter = mDocuments.begin(); iter!=mDocuments.end(); ++iter) { if (iter->first==document) diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 4e3db1815c..dee7d06cb6 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -15,9 +15,16 @@ namespace CSMDoc { Q_OBJECT + struct Stage + { + int mFile; + + Stage(); + }; + QMutex mMutex; QWaitCondition mThingsToDo; - std::vector > mDocuments; + std::vector > mDocuments; public: From 122e606e30ccc427f3049f653b47e74d49299e59 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 3 May 2014 12:09:34 +0200 Subject: [PATCH 148/545] Crime: improvement to arrest on sight for large bounties iCrimeThreshold controls the needed bounty to have guards run to the player and force dialogue. In vanilla, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or present a death sentence and attack (>= 5000 bounty). --- apps/openmw/mwmechanics/actors.cpp | 18 ++++++++---------- apps/openmw/mwmechanics/aisequence.cpp | 13 +++++++++---- components/esm/loadcrea.hpp | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b0b482cfd1..38ebda2687 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -719,22 +719,21 @@ namespace MWMechanics CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); - // If I'm a guard and I'm not hostile - if (ptr.getClass().isClass(ptr, "Guard") && !creatureStats.isHostile()) + if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPersue && !creatureStats.isHostile()) { /// \todo Move me! I shouldn't be here... const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - float cutoff = float(esmStore.get().find("iCrimeThreshold")->getInt()) * - float(esmStore.get().find("iCrimeThresholdMultiplier")->getInt()) * - esmStore.get().find("fCrimeGoldDiscountMult")->getFloat(); - // Attack on sight if bounty is greater than the cutoff + float cutoff = float(esmStore.get().find("iCrimeThreshold")->getInt()); + // Force dialogue on sight if bounty is greater than the cutoff + // In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty) if ( player.getClass().getNpcStats(player).getBounty() >= cutoff + // TODO: do not run these two every frame. keep an Aware state for each actor and update it every 0.2 s or so? && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); - npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ); + creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); + creatureStats.setAlarmed(true); + npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } } @@ -767,7 +766,6 @@ namespace MWMechanics creatureStats.setHostile(true); } } - // if I didn't report a crime was I attacked? else if (creatureStats.getAttacked() && !creatureStats.isHostile()) { diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 6460b03052..acab7c786a 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -93,11 +93,16 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) { if (!mPackages.empty()) { - mLastAiPackage = mPackages.front()->getTypeId(); - if (mPackages.front()->execute (actor,duration)) + MWMechanics::AiPackage* package = mPackages.front(); + mLastAiPackage = package->getTypeId(); + if (package->execute (actor,duration)) { - delete *mPackages.begin(); - mPackages.erase (mPackages.begin()); + // To account for the rare case where AiPackage::execute() queued another AI package + // (e.g. AiPersue executing a dialogue script that uses startCombat) + std::list::iterator toRemove = + std::find(mPackages.begin(), mPackages.end(), package); + mPackages.erase(toRemove); + delete package; mDone = true; } else diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 817c0e43c5..e459dded72 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -33,7 +33,7 @@ struct Creature Respawn = 0x002, Weapon = 0x004, // Has weapon and shield - None = 0x008, // ?? + None = 0x008, // ?? This flag appears set for every creature in Morrowind.esm Essential = 0x080, // Blood types From 7bddfc002529e0a37cb1a72f47cd5ef8ebb84818 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 3 May 2014 12:23:22 +0200 Subject: [PATCH 149/545] Fix some spelling mistakes. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwmechanics/actors.cpp | 12 ++++++------ apps/openmw/mwmechanics/aipackage.hpp | 2 +- .../mwmechanics/{aipersue.cpp => aipursue.cpp} | 14 +++++++------- .../mwmechanics/{aipersue.hpp => aipursue.hpp} | 10 +++++----- apps/openmw/mwmechanics/aisequence.cpp | 8 ++++---- apps/openmw/mwmechanics/aisequence.hpp | 4 ++-- apps/openmw/mwworld/player.cpp | 10 +++++----- apps/openmw/mwworld/player.hpp | 6 +++--- components/esm/player.cpp | 6 +++--- components/esm/player.hpp | 4 ++-- 11 files changed, 39 insertions(+), 39 deletions(-) rename apps/openmw/mwmechanics/{aipersue.cpp => aipursue.cpp} (91%) rename apps/openmw/mwmechanics/{aipersue.hpp => aipursue.hpp} (68%) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e83ae2d8d7..0661508b89 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -67,7 +67,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects - drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow + drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle ) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 38ebda2687..3c1a75d567 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -29,7 +29,7 @@ #include "aicombat.hpp" #include "aifollow.hpp" -#include "aipersue.hpp" +#include "aipursue.hpp" namespace { @@ -719,7 +719,7 @@ namespace MWMechanics CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); - if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPersue && !creatureStats.isHostile()) + if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile()) { /// \todo Move me! I shouldn't be here... const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -731,7 +731,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -740,12 +740,12 @@ namespace MWMechanics // if I was a witness to a crime if (npcStats.getCrimeId() != -1) { - // if you've payed for your crimes and I havent noticed + // if you've paid for your crimes and I havent noticed if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ) { // Calm witness down if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stopPersue(); + creatureStats.getAiSequence().stopPursuit(); creatureStats.getAiSequence().stopCombat(); // Reset factors to attack @@ -760,7 +760,7 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); else creatureStats.getAiSequence().stack(AiCombat(player), ptr); creatureStats.setHostile(true); diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 8e015da158..bd172c3732 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -20,7 +20,7 @@ namespace MWMechanics TypeIdFollow = 3, TypeIdActivate = 4, TypeIdCombat = 5, - TypeIdPersue = 6 + TypeIdPursue = 6 }; virtual ~AiPackage(); diff --git a/apps/openmw/mwmechanics/aipersue.cpp b/apps/openmw/mwmechanics/aipursue.cpp similarity index 91% rename from apps/openmw/mwmechanics/aipersue.cpp rename to apps/openmw/mwmechanics/aipursue.cpp index 36e18946c3..8da5c640e6 100644 --- a/apps/openmw/mwmechanics/aipersue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -1,4 +1,4 @@ -#include "aipersue.hpp" +#include "aipursue.hpp" #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -11,15 +11,15 @@ #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPersue::AiPersue(const std::string &objectId) +MWMechanics::AiPursue::AiPursue(const std::string &objectId) : mObjectId(objectId) { } -MWMechanics::AiPersue *MWMechanics::AiPersue::clone() const +MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const { - return new AiPersue(*this); + return new AiPursue(*this); } -bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) +bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { MWBase::World *world = MWBase::Environment::get().getWorld(); ESM::Position pos = actor.getRefData().getPosition(); @@ -100,7 +100,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) return false; } -int MWMechanics::AiPersue::getTypeId() const +int MWMechanics::AiPursue::getTypeId() const { - return TypeIdPersue; + return TypeIdPursue; } diff --git a/apps/openmw/mwmechanics/aipersue.hpp b/apps/openmw/mwmechanics/aipursue.hpp similarity index 68% rename from apps/openmw/mwmechanics/aipersue.hpp rename to apps/openmw/mwmechanics/aipursue.hpp index 3fd708ab32..86750acca6 100644 --- a/apps/openmw/mwmechanics/aipersue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_AIPERSUE_H -#define GAME_MWMECHANICS_AIPERSUE_H +#ifndef GAME_MWMECHANICS_AIPURSUE_H +#define GAME_MWMECHANICS_AIPURSUE_H #include "aipackage.hpp" #include @@ -9,11 +9,11 @@ namespace MWMechanics { - class AiPersue : public AiPackage + class AiPursue : public AiPackage { public: - AiPersue(const std::string &objectId); - virtual AiPersue *clone() const; + AiPursue(const std::string &objectId); + virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index acab7c786a..0b1da180d7 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -73,9 +73,9 @@ void MWMechanics::AiSequence::stopCombat() } } -void MWMechanics::AiSequence::stopPersue() +void MWMechanics::AiSequence::stopPursuit() { - while (getTypeId() == AiPackage::TypeIdPersue) + while (getTypeId() == AiPackage::TypeIdPursue) { delete *mPackages.begin(); mPackages.erase (mPackages.begin()); @@ -98,7 +98,7 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) if (package->execute (actor,duration)) { // To account for the rare case where AiPackage::execute() queued another AI package - // (e.g. AiPersue executing a dialogue script that uses startCombat) + // (e.g. AiPursue executing a dialogue script that uses startCombat) std::list::iterator toRemove = std::find(mPackages.begin(), mPackages.end(), package); mPackages.erase(toRemove); @@ -123,7 +123,7 @@ void MWMechanics::AiSequence::clear() void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) { - if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPersue) + if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPursue) { // Notify AiWander of our current position so we can return to it after combat finished for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index cb1b0de02f..614eb4154d 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -50,8 +50,8 @@ namespace MWMechanics void stopCombat(); ///< Removes all combat packages until first non-combat or stack empty. - void stopPersue(); - ///< Removes all persue packages until first non-persue or stack empty. + void stopPursuit(); + ///< Removes all pursue packages until first non-pursue or stack empty. bool isPackageDone() const; ///< Has a package been completed during the last update? diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index c40d47d7f5..12809755e9 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -37,7 +37,7 @@ namespace MWWorld mTeleported(false), mMarkedCell(NULL), mCurrentCrimeId(-1), - mPayedCrimeId(-1) + mPaidCrimeId(-1) { mPlayer.mBase = player; mPlayer.mRef.mRefID = "player"; @@ -223,7 +223,7 @@ namespace MWWorld player.mCellId = mCellStore->getCell()->getCellId(); player.mCurrentCrimeId = mCurrentCrimeId; - player.mPayedCrimeId = mPayedCrimeId; + player.mPaidCrimeId = mPaidCrimeId; player.mBirthsign = mSign; @@ -273,7 +273,7 @@ namespace MWWorld throw std::runtime_error ("invalid player state record (birthsign)"); mCurrentCrimeId = player.mCurrentCrimeId; - mPayedCrimeId = player.mPayedCrimeId; + mPaidCrimeId = player.mPaidCrimeId; mSign = player.mBirthsign; @@ -318,11 +318,11 @@ namespace MWWorld void Player::recordCrimeId() { - mPayedCrimeId = mCurrentCrimeId; + mPaidCrimeId = mCurrentCrimeId; } int Player::getCrimeId() const { - return mPayedCrimeId; + return mPaidCrimeId; } } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index b1de3e5108..d8cde5952b 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -48,7 +48,7 @@ namespace MWWorld bool mTeleported; int mCurrentCrimeId; // the id assigned witnesses - int mPayedCrimeId; // the last id payed off (0 bounty) + int mPaidCrimeId; // the last id paid off (0 bounty) public: @@ -105,8 +105,8 @@ namespace MWWorld bool readRecord (ESM::ESMReader& reader, int32_t type); int getNewCrimeId(); // get new id for witnesses - void recordCrimeId(); // record the payed crime id when bounty is 0 - int getCrimeId() const; // get the last payed crime id + void recordCrimeId(); // record the paid crime id when bounty is 0 + int getCrimeId() const; // get the last paid crime id }; } #endif diff --git a/components/esm/player.cpp b/components/esm/player.cpp index 70f795afe6..52b44c945f 100644 --- a/components/esm/player.cpp +++ b/components/esm/player.cpp @@ -28,8 +28,8 @@ void ESM::Player::load (ESMReader &esm) mCurrentCrimeId = -1; esm.getHNOT (mCurrentCrimeId, "CURD"); - mPayedCrimeId = -1; - esm.getHNOT (mPayedCrimeId, "PAYD"); + mPaidCrimeId = -1; + esm.getHNOT (mPaidCrimeId, "PAYD"); } void ESM::Player::save (ESMWriter &esm) const @@ -52,5 +52,5 @@ void ESM::Player::save (ESMWriter &esm) const esm.writeHNString ("SIGN", mBirthsign); esm.writeHNT ("CURD", mCurrentCrimeId); - esm.writeHNT ("PAYD", mPayedCrimeId); + esm.writeHNT ("PAYD", mPaidCrimeId); } diff --git a/components/esm/player.hpp b/components/esm/player.hpp index 377c8547ad..440d0a2d9e 100644 --- a/components/esm/player.hpp +++ b/components/esm/player.hpp @@ -26,11 +26,11 @@ namespace ESM std::string mBirthsign; int mCurrentCrimeId; - int mPayedCrimeId; + int mPaidCrimeId; void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif From e0e2ad8316eaf097a0191d1b3796ac97ab5e76a8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 13:01:29 +0200 Subject: [PATCH 150/545] content file loading progress bar --- apps/opencs/main.cpp | 6 +++ apps/opencs/model/doc/documentmanager.cpp | 2 + apps/opencs/model/doc/documentmanager.hpp | 2 + apps/opencs/model/doc/loader.cpp | 9 ++++- apps/opencs/model/doc/loader.hpp | 2 + apps/opencs/view/doc/loader.cpp | 46 ++++++++++++++++++++++- apps/opencs/view/doc/loader.hpp | 10 +++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++ 8 files changed, 78 insertions(+), 3 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index eded36394a..1febb16786 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -3,9 +3,11 @@ #include #include +#include #include #include +#include #include @@ -15,6 +17,8 @@ #include #endif +Q_DECLARE_METATYPE (std::string) + class Application : public QApplication { private: @@ -42,6 +46,8 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE (resources); + qRegisterMetaType ("std::string"); + OgreInit::OgreInit ogreInit; std::auto_ptr shinyFactory; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index ae6f1103fc..f102dac702 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -29,6 +29,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentNotLoaded (Document *, const std::string&))); connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), &mLoader, SLOT (loadDocument (CSMDoc::Document *))); + connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), + this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 4adc9726ce..be95286599 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -71,6 +71,8 @@ namespace CSMDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); + + void nextStage (CSMDoc::Document *document, const std::string& name); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 5277b08d2b..47cac17133 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -46,11 +46,16 @@ void CSMDoc::Loader::load() { if (iter->second.mFilegetData().loadFile (document->getContentFiles()[iter->second.mFile], - iter->second.mFilegetContentFiles()[iter->second.mFile]; + + emit nextStage (document, path.filename().string()); + + document->getData().loadFile (path, iter->second.mFilesecond.mFile==size) { + emit nextStage (document, "Project File"); + document->getData().loadFile (document->getProjectPath(), false, true); } else diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index dee7d06cb6..270aeeb003 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -54,6 +54,8 @@ namespace CSMDoc void documentNotLoaded (Document *document, const std::string& error); ///< Document load has been interrupted either because of a call to abortLoading /// or a problem during loading). In the former case error will be an empty string. + + void nextStage (CSMDoc::Document *document, const std::string& name); }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 15296d616b..50c29eedbb 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -1,14 +1,50 @@ #include "loader.hpp" +#include +#include +#include +#include + #include "../../model/doc/document.hpp" CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) { - setWindowTitle (("Loading " + document->getSavePath().filename().string()).c_str()); + setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); + + QVBoxLayout *layout = new QVBoxLayout (this); + + mFileProgress = new QProgressBar (this); + + layout->addWidget (mFileProgress); + + int size = static_cast (document->getContentFiles().size())+1; + if (document->isNew()) + --size; + + mFileProgress->setMinimum (0); + mFileProgress->setMaximum (size); + mFileProgress->setTextVisible (true); + mFileProgress->setValue (0); + + mFile = new QLabel (this); + + layout->addWidget (mFile); + + setLayout (layout); + + move (QCursor::pos()); + show(); } +void CSVDoc::LoadingDocument::nextStage (const std::string& name) +{ + mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str())); + + mFileProgress->setValue (mFileProgress->value()+1); +} + CSVDoc::Loader::Loader() { @@ -41,4 +77,12 @@ void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, break; } } +} + +void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->nextStage (name); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index cb154b13e6..ad1e3ffb81 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -6,6 +6,9 @@ #include #include +class QLabel; +class QProgressBar; + namespace CSMDoc { class Document; @@ -17,9 +20,14 @@ namespace CSVDoc { Q_OBJECT + QLabel *mFile; + QProgressBar *mFileProgress; + public: LoadingDocument (CSMDoc::Document *document); + + void nextStage (const std::string& name); }; class Loader : public QObject @@ -40,6 +48,8 @@ namespace CSVDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); + + void nextStage (CSMDoc::Document *document, const std::string& name); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c18cca8091..877bc1dead 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -93,6 +93,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mDocumentManager, SIGNAL (loadingStopped (CSMDoc::Document *, bool, const std::string&)), &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); + + connect ( + &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), + &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&))); } CSVDoc::ViewManager::~ViewManager() From 5e9938101935cf28f92630c3a6c385a72e0664b8 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sat, 3 May 2014 14:00:30 +0200 Subject: [PATCH 151/545] Drag and drop works. --- .../view/render/pagedworldspacewidget.cpp | 41 ++-- .../view/render/pagedworldspacewidget.hpp | 6 +- apps/opencs/view/render/scenewidget.cpp | 2 +- .../view/render/unpagedworldspacewidget.cpp | 42 ++-- .../view/render/unpagedworldspacewidget.hpp | 12 +- apps/opencs/view/render/worldspacewidget.cpp | 11 ++ apps/opencs/view/render/worldspacewidget.hpp | 30 ++- apps/opencs/view/world/scenesubview.cpp | 180 ++++++++++-------- apps/opencs/view/world/scenesubview.hpp | 16 +- 9 files changed, 186 insertions(+), 154 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index a6bdb51802..c9308fbfb4 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -50,32 +50,6 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel emit cellSelectionChanged (mSelection); } -void CSVRender::PagedWorldspaceWidget::dropEvent (QDropEvent* event) -{ - const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); - - if (mime->fromDocument(mDocument)) - { - const std::vector& data(mime->getData()); - CSVRender::WorldspaceWidget::dropType whatHappend = getDropType(data); - - switch (whatHappend) - { - case CSVRender::WorldspaceWidget::cellsExterior: - handleDrop(data); - break; - - case CSVRender::WorldspaceWidget::cellsInterior: - emit interiorCellsDropped(data); - break; - - default: - //not interior or exterior = either mixed or not actually cells. We don't need to do anything in this case. - break; - } - } //not handling drops from different documents at the moment -} - std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const { std::istringstream stream (record.c_str()); @@ -101,3 +75,18 @@ void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld:: emit cellSelectionChanged(mSelection); } } + +CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const +{ + switch (type) + { + case cellsExterior: + return canHandle; + + case cellsInterior: + return needUnpaged; + + default: + return ignored; + } +} \ No newline at end of file diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index bd5d1107c7..0a73c791cb 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -15,8 +15,6 @@ namespace CSVRender private: - void dropEvent(QDropEvent* event); - std::pair getCoordinatesFromId(const std::string& record) const; public: @@ -32,11 +30,11 @@ namespace CSVRender virtual void handleDrop(const std::vector& data); + virtual dropRequirments getDropRequirements(dropType type) const; + signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); - - void interiorCellsDropped(const std::vector& data); }; } diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 1aee421ed7..8a58b7d328 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -320,7 +320,7 @@ namespace CSVRender } - if (mUpdate) + if (mUpdate && mWindow) { mUpdate = false; mWindow->update(); diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 9290887898..de4dde9ddd 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -67,34 +67,24 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI emit closeRequest(); } -void CSVRender::UnpagedWorldspaceWidget::dropEvent (QDropEvent* event) -{ - const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); - - if (mime->fromDocument (mDocument)) - { - const std::vector& data (mime->getData()); - CSVRender::WorldspaceWidget::dropType whatHappend = getDropType (data); - - switch (whatHappend) - { - case CSVRender::WorldspaceWidget::cellsExterior: - emit exteriorCellsDropped(data); - break; - - case CSVRender::WorldspaceWidget::cellsInterior: - handleDrop(data); - break; - - default: - //not interior or exterior = either mixed or not actually cells. We don't need to do anything in this case. - break; - } - } //not handling drops from different documents at the moment -} - void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) { mCellId = data.begin()->getId(); update(); + emit cellChanged(*data.begin()); +} + +CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const +{ + switch(type) + { + case cellsInterior: + return canHandle; + + case cellsExterior: + return needPaged; + + default: + return ignored; + } } diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index ad1e22e396..bb53408452 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -31,14 +31,11 @@ namespace CSVRender public: UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, - QWidget *parent); + QWidget *parent); + virtual dropRequirments getDropRequirements(dropType type) const; - private: - - void handleDrop(const std::vector& data); - - void dropEvent(QDropEvent* event); + virtual void handleDrop(const std::vector& data); private slots: @@ -48,8 +45,7 @@ namespace CSVRender signals: - void exteriorCellsDropped(const std::vector& data); - + void cellChanged(const CSMWorld::UniversalId& id); }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 16ff0a403f..c83a5a3e15 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -115,3 +115,14 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) { event->accept(); } + + +void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) +{ + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + + if (mime->fromDocument (mDocument)) + { + emit dataDropped(mime->getData()); + } //not handling drops from different documents at the moment +} \ No newline at end of file diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index f9d4f9a063..a14e039154 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -7,6 +7,7 @@ #include "navigationfree.hpp" #include "navigationorbit.hpp" #include +#include namespace CSMWorld { @@ -30,13 +31,21 @@ namespace CSVRender public: - enum dropType - { - cellsMixed, - cellsInterior, - cellsExterior, - notCells - }; + enum dropType + { + cellsMixed, + cellsInterior, + cellsExterior, + notCells + }; + + enum dropRequirments + { + canHandle, + needPaged, + needUnpaged, + ignored //either mixed cells, or not cells + }; WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); @@ -48,9 +57,13 @@ namespace CSVRender static dropType getDropType(const std::vector& data); + virtual dropRequirments getDropRequirements(dropType type) const = 0; + virtual void useViewHint (const std::string& hint); ///< Default-implementation: ignored. + virtual void handleDrop(const std::vector& data) = 0; + protected: const CSMDoc::Document& mDocument; //for checking if drop comes from same document @@ -58,6 +71,8 @@ namespace CSVRender void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent* event); + void dragMoveEvent(QDragMoveEvent *event); private slots: @@ -67,6 +82,7 @@ namespace CSVRender signals: void closeRequest(); + void dataDropped(const std::vector& data); }; } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index f3807e4e9c..d411985b39 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" @@ -21,7 +22,7 @@ #include "scenetoolmode.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id), mLayout(new QHBoxLayout), mDocument(document) +: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL) { QVBoxLayout *layout = new QVBoxLayout; @@ -33,39 +34,26 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); - mToolbar = new SceneToolbar (48+6, this); + CSVRender::WorldspaceWidget* wordspaceWidget = NULL; if (id.getId()=="sys::default") { - CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this, document); + CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document); - mScene = widget; + wordspaceWidget = newWidget; - connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), - this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); - - connect (widget, SIGNAL(interiorCellsDropped (const std::vector&)), - this, SLOT(changeToUnpaged (const std::vector&))); + makeConnections(newWidget); } else { - CSVRender::UnpagedWorldspaceWidget *widget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); + CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); - mScene = widget; + wordspaceWidget = newWidget; - connect (widget, SIGNAL(exteriorCellsDropped(const std::vector&)), - this, SLOT(changeToUnpaged(const std::vector&))); + makeConnections(newWidget); } - SceneToolMode *navigationTool = mScene->makeNavigationSelector (mToolbar); - mToolbar->addTool (navigationTool); - - SceneToolMode *lightingTool = mScene->makeLightingSelector (mToolbar); - mToolbar->addTool (lightingTool); - - mLayout->addWidget (mToolbar, 0); - - mLayout->addWidget (mScene, 1); + replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget)); layout->insertLayout (0, mLayout, 1); @@ -78,10 +66,41 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D widget->setLayout (layout); setWidget (widget); +} - mScene->selectDefaultNavigationMode(); +void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget* widget) +{ + connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest())); - connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + connect(widget, SIGNAL(dataDropped(const std::vector&)), + this, SLOT(handleDrop(const std::vector&))); + + connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)), + this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&))); +} + +void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget) +{ + connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + + connect(widget, SIGNAL(dataDropped(const std::vector&)), + this, SLOT(handleDrop(const std::vector&))); + + connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), + this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); +} + +CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget) +{ + CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this); + + SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar); + toolbar->addTool (navigationTool); + + SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar); + toolbar->addTool (lightingTool); + + return toolbar; } void CSVWorld::SceneSubView::setEditLock (bool locked) @@ -111,8 +130,19 @@ void CSVWorld::SceneSubView::closeRequest() deleteLater(); } +void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id) +{ + setUniversalId(id); + std::ostringstream stream; + stream << "Scene: " << getUniversalId().getId(); + + setWindowTitle (QString::fromUtf8 (stream.str().c_str())); +} + + void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection) { + setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Cell, "sys::default")); int size = selection.getSize(); std::ostringstream stream; @@ -137,70 +167,60 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection setWindowTitle (QString::fromUtf8 (stream.str().c_str())); } -void CSVWorld::SceneSubView::changeToPaged (const std::vector< CSMWorld::UniversalId >& data) +void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data) { - mLayout->removeWidget(mToolbar); - mLayout->removeWidget(mScene); + CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL; + CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL; + SceneToolbar* toolbar = NULL; - delete mScene; - delete mToolbar; + switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data))) + { + case CSVRender::WorldspaceWidget::canHandle: + mScene->handleDrop(data); + break; - setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Cell, "sys::default")); - mToolbar = new SceneToolbar (48+6, this); + case CSVRender::WorldspaceWidget::needPaged: + pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument); + toolbar = makeToolbar(pagedNewWidget); + makeConnections(pagedNewWidget); + replaceToolbarAndWorldspace(pagedNewWidget, toolbar); + mScene->handleDrop(data); + break; - CSVRender::PagedWorldspaceWidget* widget = new CSVRender::PagedWorldspaceWidget (this, mDocument); + case CSVRender::WorldspaceWidget::needUnpaged: + unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this); + toolbar = makeToolbar(unPagedNewWidget); + makeConnections(unPagedNewWidget); + replaceToolbarAndWorldspace(unPagedNewWidget, toolbar); + cellSelectionChanged(*(data.begin())); + break; + + case CSVRender::WorldspaceWidget::ignored: + return; + } +} + +void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar) +{ + assert(mLayout); + + if (mScene) + { + mLayout->removeWidget(mScene); + mScene->deleteLater(); + } + + if (mToolbar) + { + mLayout->removeWidget(mToolbar); + mToolbar->deleteLater(); + } mScene = widget; - - SceneToolMode* navigationTool = mScene->makeNavigationSelector (mToolbar); - mToolbar->addTool (navigationTool); - - SceneToolMode* lightingTool = mScene->makeLightingSelector (mToolbar); - mToolbar->addTool (lightingTool); - - connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), - this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); - - connect (widget, SIGNAL (interiorCellsDropped (const std::vector&)), - this, SLOT (changeToUnpaged (const std::vector&))); + mToolbar = toolbar; mLayout->addWidget (mToolbar, 0); mLayout->addWidget (mScene, 1); mScene->selectDefaultNavigationMode(); - - connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); - - widget->handleDrop (data); -} - -void CSVWorld::SceneSubView::changeToUnpaged (const std::vector< CSMWorld::UniversalId >& data) -{ - mLayout->removeWidget(mToolbar); - mLayout->removeWidget(mScene); - - delete mScene; - delete mToolbar; - - mToolbar = new SceneToolbar (48+6, this); - CSVRender::UnpagedWorldspaceWidget* widget = new CSVRender::UnpagedWorldspaceWidget (data.begin()->getId(), mDocument, this); - setUniversalId(*(data.begin())); - - mScene = widget; - - SceneToolMode* navigationTool = mScene->makeNavigationSelector (mToolbar); - mToolbar->addTool (navigationTool); - - SceneToolMode* lightingTool = mScene->makeLightingSelector (mToolbar); - mToolbar->addTool (lightingTool); - - connect (widget, SIGNAL (exteriorCellsDropped (const std::vector&)), - this, SLOT (changeToPaged (const std::vector&))); - - mLayout->addWidget (mToolbar, 0); - mLayout->addWidget (mScene, 1); - - mScene->selectDefaultNavigationMode(); - - connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); -} +} \ No newline at end of file diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 9af76ef6a7..251ddae1f9 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -21,6 +21,8 @@ namespace CSMDoc namespace CSVRender { class WorldspaceWidget; + class PagedWorldspaceWidget; + class UnpagedWorldspaceWidget; } namespace CSVWorld @@ -51,15 +53,25 @@ namespace CSVWorld virtual void useHint (const std::string& hint); + private: + + void makeConnections(CSVRender::PagedWorldspaceWidget* widget); + + void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget); + + void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar); + + SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget); + private slots: void closeRequest(); void cellSelectionChanged (const CSMWorld::CellSelection& selection); - void changeToPaged(const std::vector& data); + void cellSelectionChanged (const CSMWorld::UniversalId& id); - void changeToUnpaged(const std::vector& data); + void handleDrop(const std::vector& data); }; } From 6692d2dc724d988a6e3224e0946b8cca53b07df4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 15:05:02 +0200 Subject: [PATCH 152/545] split up load function in a start and continue part --- apps/opencs/model/doc/loader.cpp | 18 +- apps/opencs/model/doc/loader.hpp | 1 + apps/opencs/model/world/data.cpp | 289 ++++++++++++++++--------------- apps/opencs/model/world/data.hpp | 20 ++- 4 files changed, 187 insertions(+), 141 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 47cac17133..85bfececd5 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -5,7 +5,7 @@ #include "document.hpp" -CSMDoc::Loader::Stage::Stage() : mFile (0) {} +CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {} CSMDoc::Loader::Loader() @@ -13,7 +13,7 @@ CSMDoc::Loader::Loader() QTimer *timer = new QTimer (this); connect (timer, SIGNAL (timeout()), this, SLOT (load())); - timer->start (1000); + timer->start(); } QWaitCondition& CSMDoc::Loader::hasThingsToDo() @@ -44,19 +44,29 @@ void CSMDoc::Loader::load() try { + if (iter->second.mRecordsLeft) + { + if (document->getData().continueLoading()) + iter->second.mRecordsLeft = false; + + return; + } + if (iter->second.mFilegetContentFiles()[iter->second.mFile]; emit nextStage (document, path.filename().string()); - document->getData().loadFile (path, iter->second.mFilegetData().startLoading (path, iter->second.mFilesecond.mRecordsLeft = true; } else if (iter->second.mFile==size) { emit nextStage (document, "Project File"); - document->getData().loadFile (document->getProjectPath(), false, true); + document->getData().startLoading (document->getProjectPath(), false, true); + iter->second.mRecordsLeft = true; } else { diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 270aeeb003..5e86e4e671 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -18,6 +18,7 @@ namespace CSMDoc struct Stage { int mFile; + bool mRecordsLeft; Stage(); }; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d60dcae117..93b734e271 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -55,7 +55,10 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec return number; } -CSMWorld::Data::Data() : mRefs (mCells) +CSMWorld::Data::Data() +/// \todo set encoding properly, once config implementation has been fixed. +: mEncoder (ToUTF8::calculateEncoding ("win1252")), + mRefs (mCells), mReader (0), mDialogue (0) { mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); @@ -260,6 +263,8 @@ CSMWorld::Data::~Data() { for (std::vector::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) delete *iter; + + delete mReader; } const CSMWorld::IdCollection& CSMWorld::Data::getGlobals() const @@ -481,148 +486,162 @@ void CSMWorld::Data::merge() mGlobals.merge(); } -void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project) +int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project) { - ESM::ESMReader reader; + delete mReader; + mReader = 0; + mDialogue = 0; - /// \todo set encoding properly, once config implementation has been fixed. - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); - reader.setEncoder (&encoder); + mReader = new ESM::ESMReader; + mReader->setEncoder (&mEncoder); + mReader->open (path.string()); - reader.open (path.string()); + mBase = base; + mProject = project; - const ESM::Dialogue *dialogue = 0; + mAuthor = mReader->getAuthor(); + mDescription = mReader->getDesc(); - mAuthor = reader.getAuthor(); - mDescription = reader.getDesc(); + return mReader->getRecordCount(); +} - // Note: We do not need to send update signals here, because at this point the model is not connected - // to any view. - while (reader.hasMoreRecs()) +bool CSMWorld::Data::continueLoading() +{ + if (!mReader) + throw std::logic_error ("can't continue loading, because no load has been started"); + + if (!mReader->hasMoreRecs()) { - ESM::NAME n = reader.getRecName(); - reader.getRecHeader(); - - switch (n.val) - { - case ESM::REC_GLOB: mGlobals.load (reader, base); break; - case ESM::REC_GMST: mGmsts.load (reader, base); break; - case ESM::REC_SKIL: mSkills.load (reader, base); break; - case ESM::REC_CLAS: mClasses.load (reader, base); break; - case ESM::REC_FACT: mFactions.load (reader, base); break; - case ESM::REC_RACE: mRaces.load (reader, base); break; - case ESM::REC_SOUN: mSounds.load (reader, base); break; - case ESM::REC_SCPT: mScripts.load (reader, base); break; - case ESM::REC_REGN: mRegions.load (reader, base); break; - case ESM::REC_BSGN: mBirthsigns.load (reader, base); break; - case ESM::REC_SPEL: mSpells.load (reader, base); break; - - case ESM::REC_CELL: - mCells.load (reader, base); - mRefs.load (reader, mCells.getSize()-1, base); - break; - - case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break; - case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break; - case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break; - case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break; - case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break; - case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break; - case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break; - case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break; - case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break; - case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break; - case ESM::REC_LEVC: - mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break; - case ESM::REC_LEVI: - mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break; - case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break; - case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break; - case ESM::REC_MISC: - mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break; - case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break; - case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break; - case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break; - case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break; - case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break; - - case ESM::REC_DIAL: - { - std::string id = reader.getHNOString ("NAME"); - - ESM::Dialogue record; - record.mId = id; - record.load (reader); - - if (record.mType==ESM::Dialogue::Journal) - { - mJournals.load (record, base); - dialogue = &mJournals.getRecord (id).get(); - } - else if (record.mType==ESM::Dialogue::Deleted) - { - dialogue = 0; // record vector can be shuffled around which would make pointer - // to record invalid - - if (mJournals.tryDelete (id)) - { - /// \todo handle info records - } - else if (mTopics.tryDelete (id)) - { - /// \todo handle info records - } - else - { - /// \todo report deletion of non-existing record - } - } - else - { - mTopics.load (record, base); - dialogue = &mTopics.getRecord (id).get(); - } - - break; - } - - case ESM::REC_INFO: - { - if (!dialogue) - { - /// \todo INFO record without matching DIAL record -> report to user - reader.skipRecord(); - break; - } - - if (dialogue->mType==ESM::Dialogue::Journal) - mJournalInfos.load (reader, base, *dialogue); - else - mTopicInfos.load (reader, base, *dialogue); - - break; - } - - case ESM::REC_FILT: - - if (project) - { - mFilters.load (reader, base); - mFilters.setData (mFilters.getSize()-1, - mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope), - static_cast (CSMFilter::Filter::Scope_Project)); - break; - } - - // fall through (filter record in a content file is an error with format 0) - - default: - - /// \todo throw an exception instead, once all records are implemented - /// or maybe report error and continue? - reader.skipRecord(); - } + delete mReader; + mReader = 0; + mDialogue = 0; + return true; } + + ESM::NAME n = mReader->getRecName(); + mReader->getRecHeader(); + + switch (n.val) + { + case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break; + case ESM::REC_GMST: mGmsts.load (*mReader, mBase); break; + case ESM::REC_SKIL: mSkills.load (*mReader, mBase); break; + case ESM::REC_CLAS: mClasses.load (*mReader, mBase); break; + case ESM::REC_FACT: mFactions.load (*mReader, mBase); break; + case ESM::REC_RACE: mRaces.load (*mReader, mBase); break; + case ESM::REC_SOUN: mSounds.load (*mReader, mBase); break; + case ESM::REC_SCPT: mScripts.load (*mReader, mBase); break; + case ESM::REC_REGN: mRegions.load (*mReader, mBase); break; + case ESM::REC_BSGN: mBirthsigns.load (*mReader, mBase); break; + case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break; + + case ESM::REC_CELL: + mCells.load (*mReader, mBase); + mRefs.load (*mReader, mCells.getSize()-1, mBase); + break; + + case ESM::REC_ACTI: mReferenceables.load (*mReader, mBase, UniversalId::Type_Activator); break; + case ESM::REC_ALCH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Potion); break; + case ESM::REC_APPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Apparatus); break; + case ESM::REC_ARMO: mReferenceables.load (*mReader, mBase, UniversalId::Type_Armor); break; + case ESM::REC_BOOK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Book); break; + case ESM::REC_CLOT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Clothing); break; + case ESM::REC_CONT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Container); break; + case ESM::REC_CREA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Creature); break; + case ESM::REC_DOOR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Door); break; + case ESM::REC_INGR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Ingredient); break; + case ESM::REC_LEVC: + mReferenceables.load (*mReader, mBase, UniversalId::Type_CreatureLevelledList); break; + case ESM::REC_LEVI: + mReferenceables.load (*mReader, mBase, UniversalId::Type_ItemLevelledList); break; + case ESM::REC_LIGH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Light); break; + case ESM::REC_LOCK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Lockpick); break; + case ESM::REC_MISC: + mReferenceables.load (*mReader, mBase, UniversalId::Type_Miscellaneous); break; + case ESM::REC_NPC_: mReferenceables.load (*mReader, mBase, UniversalId::Type_Npc); break; + case ESM::REC_PROB: mReferenceables.load (*mReader, mBase, UniversalId::Type_Probe); break; + case ESM::REC_REPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Repair); break; + case ESM::REC_STAT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Static); break; + case ESM::REC_WEAP: mReferenceables.load (*mReader, mBase, UniversalId::Type_Weapon); break; + + case ESM::REC_DIAL: + { + std::string id = mReader->getHNOString ("NAME"); + + ESM::Dialogue record; + record.mId = id; + record.load (*mReader); + + if (record.mType==ESM::Dialogue::Journal) + { + mJournals.load (record, mBase); + mDialogue = &mJournals.getRecord (id).get(); + } + else if (record.mType==ESM::Dialogue::Deleted) + { + mDialogue = 0; // record vector can be shuffled around which would make pointer + // to record invalid + + if (mJournals.tryDelete (id)) + { + /// \todo handle info records + } + else if (mTopics.tryDelete (id)) + { + /// \todo handle info records + } + else + { + /// \todo report deletion of non-existing record + } + } + else + { + mTopics.load (record, mBase); + mDialogue = &mTopics.getRecord (id).get(); + } + + break; + } + + case ESM::REC_INFO: + { + if (!mDialogue) + { + /// \todo INFO record without matching DIAL record -> report to user + mReader->skipRecord(); + break; + } + + if (mDialogue->mType==ESM::Dialogue::Journal) + mJournalInfos.load (*mReader, mBase, *mDialogue); + else + mTopicInfos.load (*mReader, mBase, *mDialogue); + + break; + } + + case ESM::REC_FILT: + + if (mProject) + { + mFilters.load (*mReader, mBase); + mFilters.setData (mFilters.getSize()-1, + mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope), + static_cast (CSMFilter::Filter::Scope_Project)); + break; + } + + // fall through (filter record in a content file is an error with format 0) + + default: + + /// \todo throw an exception instead, once all records are implemented + /// or maybe report error and continue? + mReader->skipRecord(); + } + + return false; } bool CSMWorld::Data::hasId (const std::string& id) const diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 152c3ac419..234069e3a7 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -33,12 +33,19 @@ class QAbstractItemModel; +namespace ESM +{ + class ESMReader; + struct Dialogue; +} + namespace CSMWorld { class Data : public QObject { Q_OBJECT + ToUTF8::Utf8Encoder mEncoder; IdCollection mGlobals; IdCollection mGmsts; IdCollection mSkills; @@ -62,6 +69,10 @@ namespace CSMWorld std::map mModelIndex; std::string mAuthor; std::string mDescription; + ESM::ESMReader *mReader; + const ESM::Dialogue *mDialogue; // last loaded dialogue + bool mBase; + bool mProject; // not implemented Data (const Data&); @@ -167,10 +178,15 @@ namespace CSMWorld void merge(); ///< Merge modified into base. - void loadFile (const boost::filesystem::path& path, bool base, bool project); - ///< Merging content of a file into base or modified. + int startLoading (const boost::filesystem::path& path, bool base, bool project); + ///< Begin merging content of a file into base or modified. /// /// \param project load project file instead of content file + /// + ///< \return estimated number of records + + bool continueLoading(); + ///< \return Finished? bool hasId (const std::string& id) const; From 6bc58692225073f47117577c0fd8a5f8f8ff1abb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 15:33:35 +0200 Subject: [PATCH 153/545] record loading progress bar --- apps/opencs/model/doc/documentmanager.cpp | 6 ++-- apps/opencs/model/doc/documentmanager.hpp | 4 ++- apps/opencs/model/doc/loader.cpp | 24 ++++++++----- apps/opencs/model/doc/loader.hpp | 7 +++- apps/opencs/view/doc/loader.cpp | 41 +++++++++++++++++++---- apps/opencs/view/doc/loader.hpp | 9 +++-- apps/opencs/view/doc/viewmanager.cpp | 8 +++-- 7 files changed, 77 insertions(+), 22 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index f102dac702..f9e6bd96ac 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -29,8 +29,10 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SLOT (documentNotLoaded (Document *, const std::string&))); connect (this, SIGNAL (loadRequest (CSMDoc::Document *)), &mLoader, SLOT (loadDocument (CSMDoc::Document *))); - connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), - this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&))); + connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)), + this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int))); + connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)), + this, SIGNAL (nextRecord (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index be95286599..47118a0fba 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -72,7 +72,9 @@ namespace CSMDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); - void nextStage (CSMDoc::Document *document, const std::string& name); + void nextStage (CSMDoc::Document *document, const std::string& name, int steps); + + void nextRecord (CSMDoc::Document *document); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 85bfececd5..e2cf6684f2 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -42,12 +42,20 @@ void CSMDoc::Loader::load() bool done = false; + const int batchingSize = 100; + try { if (iter->second.mRecordsLeft) { - if (document->getData().continueLoading()) - iter->second.mRecordsLeft = false; + for (int i=0; igetData().continueLoading()) + { + iter->second.mRecordsLeft = false; + break; + } + + emit nextRecord (document); return; } @@ -56,17 +64,17 @@ void CSMDoc::Loader::load() { boost::filesystem::path path = document->getContentFiles()[iter->second.mFile]; - emit nextStage (document, path.filename().string()); - - document->getData().startLoading (path, iter->second.mFilegetData().startLoading (path, iter->second.mFilesecond.mRecordsLeft = true; + + emit nextStage (document, path.filename().string(), steps/batchingSize); } else if (iter->second.mFile==size) { - emit nextStage (document, "Project File"); - - document->getData().startLoading (document->getProjectPath(), false, true); + int steps = document->getData().startLoading (document->getProjectPath(), false, true); iter->second.mRecordsLeft = true; + + emit nextStage (document, "Project File", steps/batchingSize); } else { diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index 5e86e4e671..f6cfd2a0b1 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -56,7 +56,12 @@ namespace CSMDoc ///< Document load has been interrupted either because of a call to abortLoading /// or a problem during loading). In the former case error will be an empty string. - void nextStage (CSMDoc::Document *document, const std::string& name); + void nextStage (CSMDoc::Document *document, const std::string& name, int steps); + + void nextRecord (CSMDoc::Document *document); + ///< \note This signal is only given once per group of records. The group size is + /// approximately the total number of records divided by the steps value of the + /// previous nextStage signal. }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 50c29eedbb..418dc56381 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -14,6 +14,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) QVBoxLayout *layout = new QVBoxLayout (this); + // file progress + mFile = new QLabel (this); + + layout->addWidget (mFile); + mFileProgress = new QProgressBar (this); layout->addWidget (mFileProgress); @@ -27,9 +32,16 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mFileProgress->setTextVisible (true); mFileProgress->setValue (0); - mFile = new QLabel (this); + // record progress + layout->addWidget (new QLabel ("Records", this)); - layout->addWidget (mFile); + mRecordProgress = new QProgressBar (this); + + layout->addWidget (mRecordProgress); + + mRecordProgress->setMinimum (0); + mRecordProgress->setTextVisible (true); + mRecordProgress->setValue (0); setLayout (layout); @@ -38,19 +50,28 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) show(); } -void CSVDoc::LoadingDocument::nextStage (const std::string& name) +void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) { mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str())); mFileProgress->setValue (mFileProgress->value()+1); + + mRecordProgress->setValue (0); + mRecordProgress->setMaximum (steps); } -CSVDoc::Loader::Loader() +void CSVDoc::LoadingDocument::nextRecord() { + int value = mRecordProgress->value()+1; + if (value<=mRecordProgress->maximum()) + mRecordProgress->setValue (value); } + +CSVDoc::Loader::Loader() {} + CSVDoc::Loader::~Loader() { for (std::map::iterator iter (mDocuments.begin()); @@ -79,10 +100,18 @@ void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, } } -void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name) +void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name, int steps) { std::map::iterator iter = mDocuments.find (document); if (iter!=mDocuments.end()) - iter->second->nextStage (name); + iter->second->nextStage (name, steps); +} + +void CSVDoc::Loader::nextRecord (CSMDoc::Document *document) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->nextRecord(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ad1e3ffb81..0c85223c66 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -22,12 +22,15 @@ namespace CSVDoc QLabel *mFile; QProgressBar *mFileProgress; + QProgressBar *mRecordProgress; public: LoadingDocument (CSMDoc::Document *document); - void nextStage (const std::string& name); + void nextStage (const std::string& name, int steps); + + void nextRecord(); }; class Loader : public QObject @@ -49,7 +52,9 @@ namespace CSVDoc void loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error); - void nextStage (CSMDoc::Document *document, const std::string& name); + void nextStage (CSMDoc::Document *document, const std::string& name, int steps); + + void nextRecord (CSMDoc::Document *document); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c7d9ed4705..1c5f51129b 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -93,8 +93,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) &mLoader, SLOT (loadingStopped (CSMDoc::Document *, bool, const std::string&))); connect ( - &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&)), - &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&))); + &mDocumentManager, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)), + &mLoader, SLOT (nextStage (CSMDoc::Document *, const std::string&, int))); + + connect ( + &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), + &mLoader, SLOT (nextRecord (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From eff648e3ab2509f12f5fe8c0be1aeee6d37c4af1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 3 May 2014 16:16:27 +0200 Subject: [PATCH 154/545] Show unhandled SDL events in hexadecimal (easier to compare with the enum) --- extern/sdl4ogre/sdlinputwrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index 09a2441778..82db5ea99f 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -115,7 +115,7 @@ namespace SFO mWindowListener->windowClosed(); break; default: - std::cerr << "Unhandled SDL event of type " << evt.type << std::endl; + std::cerr << "Unhandled SDL event of type 0x" << std::hex << evt.type << std::endl; break; } } From 3fdd72f2040d5a1c8515bb8ed1033c5be4f0eeb4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 16:44:50 +0200 Subject: [PATCH 155/545] added cancel button to loading window --- apps/opencs/model/doc/documentmanager.cpp | 2 ++ apps/opencs/model/doc/documentmanager.hpp | 2 ++ apps/opencs/model/doc/loader.cpp | 4 ++-- apps/opencs/model/doc/loader.hpp | 2 +- apps/opencs/view/doc/loader.cpp | 20 +++++++++++++++++++- apps/opencs/view/doc/loader.hpp | 14 ++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++++ 7 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index f9e6bd96ac..d44da15c5c 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -33,6 +33,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int))); connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)), this, SIGNAL (nextRecord (CSMDoc::Document *))); + connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)), + &mLoader, SLOT (abortLoading (CSMDoc::Document *))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 47118a0fba..d834d85d47 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -75,6 +75,8 @@ namespace CSMDoc void nextStage (CSMDoc::Document *document, const std::string& name, int steps); void nextRecord (CSMDoc::Document *document); + + void cancelLoading (CSMDoc::Document *document); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index e2cf6684f2..2ef808dd60 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -102,7 +102,7 @@ void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) mDocuments.push_back (std::make_pair (document, Stage())); } -void CSMDoc::Loader::abortLoading (Document *document) +void CSMDoc::Loader::abortLoading (CSMDoc::Document *document) { for (std::vector >::iterator iter = mDocuments.begin(); iter!=mDocuments.end(); ++iter) @@ -114,4 +114,4 @@ void CSMDoc::Loader::abortLoading (Document *document) break; } } -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index f6cfd2a0b1..a6bcb6b87f 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -42,7 +42,7 @@ namespace CSMDoc void loadDocument (CSMDoc::Document *document); ///< The ownership of \a document is not transferred. - void abortLoading (Document *document); + void abortLoading (CSMDoc::Document *document); ///< Abort loading \a docuemnt (ignored if \a document has already finished being /// loaded). Will result in a documentNotLoaded signal, once the Loader has finished /// cleaning up. diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 418dc56381..a9206ef2b8 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -5,10 +5,12 @@ #include #include #include +#include #include "../../model/doc/document.hpp" CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) +: mDocument (document) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); @@ -43,11 +45,18 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mRecordProgress->setTextVisible (true); mRecordProgress->setValue (0); + QDialogButtonBox *buttonBox = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, + this); + + layout->addWidget (buttonBox); + setLayout (layout); move (QCursor::pos()); show(); + + connect (buttonBox, SIGNAL (rejected()), this, SLOT (cancel())); } void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) @@ -69,6 +78,11 @@ void CSVDoc::LoadingDocument::nextRecord() mRecordProgress->setValue (value); } +void CSVDoc::LoadingDocument::cancel() +{ + emit cancel (mDocument); +} + CSVDoc::Loader::Loader() {} @@ -81,7 +95,11 @@ CSVDoc::Loader::~Loader() void CSVDoc::Loader::add (CSMDoc::Document *document) { - mDocuments.insert (std::make_pair (document, new LoadingDocument (document))); + LoadingDocument *loading = new LoadingDocument (document); + mDocuments.insert (std::make_pair (document, loading)); + + connect (loading, SIGNAL (cancel (CSMDoc::Document *)), + this, SIGNAL (cancel (CSMDoc::Document *))); } void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index 0c85223c66..a251e75d95 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -5,6 +5,7 @@ #include #include +#include class QLabel; class QProgressBar; @@ -20,6 +21,7 @@ namespace CSVDoc { Q_OBJECT + CSMDoc::Document *mDocument; QLabel *mFile; QProgressBar *mFileProgress; QProgressBar *mRecordProgress; @@ -31,6 +33,14 @@ namespace CSVDoc void nextStage (const std::string& name, int steps); void nextRecord(); + + private slots: + + void cancel(); + + signals: + + void cancel (CSMDoc::Document *document); }; class Loader : public QObject @@ -45,6 +55,10 @@ namespace CSVDoc virtual ~Loader(); + signals: + + void cancel (CSMDoc::Document *document); + public slots: void add (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 1c5f51129b..b8971a296a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -99,6 +99,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), &mLoader, SLOT (nextRecord (CSMDoc::Document *))); + + connect ( + &mLoader, SIGNAL (cancel (CSMDoc::Document *)), + &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From e9c2f24faaf2838507b52462fa8204020145b946 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 May 2014 17:14:17 +0200 Subject: [PATCH 156/545] intercept close button clicks in loading window --- apps/opencs/view/doc/loader.cpp | 7 +++++++ apps/opencs/view/doc/loader.hpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index a9206ef2b8..3b58904793 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -6,9 +6,16 @@ #include #include #include +#include #include "../../model/doc/document.hpp" +void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) +{ + event->ignore(); + emit cancel (mDocument); +} + CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) : mDocument (document) { diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index a251e75d95..d1c740011d 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -26,6 +26,10 @@ namespace CSVDoc QProgressBar *mFileProgress; QProgressBar *mRecordProgress; + private: + + void closeEvent (QCloseEvent *event); + public: LoadingDocument (CSMDoc::Document *document); From 658c37a29999a55b9d574160066384c54509aed9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 3 May 2014 17:14:59 +0200 Subject: [PATCH 157/545] AiPursue: If we reached the path end, that does not mean we reached the target. Rebuild the path if the target has moved in the meantime. Fixes guards in pursuit activating the dialogue too early. Also tweaked the activation distance. --- apps/openmw/mwmechanics/aipursue.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 8da5c640e6..0c10bd81dd 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -52,11 +52,13 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) } } + // Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code) + MWWorld::Ptr target = world->getPtr(mObjectId,false); ESM::Position targetPos = target.getRefData().getPosition(); bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) + if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { mCellX = cell->mData.mX; mCellY = cell->mData.mY; @@ -76,15 +78,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) + (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100) { movement.mPosition[1] = 0; MWWorld::Ptr target = world->getPtr(mObjectId,false); From 05e326bdc38166e5e9a4de38310fd7cb230f89f9 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 3 May 2014 12:48:07 -0400 Subject: [PATCH 158/545] Added update sneak to actors Intends to check the state of a players sneak by asking the question if each npc can see the player. --- apps/openmw/mwmechanics/actors.cpp | 23 +++++++++++++++++++++++ apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwworld/player.cpp | 5 ----- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 804ec7a41e..f51593088f 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -236,6 +236,7 @@ namespace MWMechanics updateDrowning(ptr, duration); calculateNpcStatModifiers(ptr); updateEquippedLight(ptr, duration); + updateSneak(ptr); } } @@ -720,6 +721,28 @@ namespace MWMechanics } } + void Actors::updateSneak (const MWWorld::Ptr& ptr) + { + const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) + { + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + int radius = esmStore.get().find("fSneakUseDist")->getInt(); + + // am I close enough to the player? + if (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) + <= radius * radius ) + { + bool seen = false; // unseen + if ( !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr) + && !MWBase::Environment::get().getWorld()->getLOS(player, ptr) ) + seen = true; // seen + + MWBase::Environment::get().getWindowManager()->setSneakVisibility(seen); + } + } + } + void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index f7dff1058b..ddd7a47d30 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -44,6 +44,8 @@ namespace MWMechanics void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration); + void updateSneak (const MWWorld::Ptr& ptr); + public: Actors(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index d023d4388b..c0f88249ce 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -100,7 +100,6 @@ namespace MWWorld void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; } @@ -119,7 +118,6 @@ namespace MWWorld void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; } @@ -132,7 +130,6 @@ namespace MWWorld void Player::setSneak(bool sneak) { MWWorld::Ptr ptr = getPlayer(); - ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); if (sneak) @@ -157,8 +154,6 @@ namespace MWWorld if (neighbors.empty()) MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); } - else - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } void Player::yaw(float yaw) From e1e23447f2b2306cf0f1c57fba2f2b6d35954786 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 3 May 2014 13:16:07 -0400 Subject: [PATCH 159/545] Removed initial check form setSneak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It wasn’t needed. --- apps/openmw/mwmechanics/actors.cpp | 20 +++++++++----------- apps/openmw/mwworld/player.cpp | 24 ++---------------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f51593088f..71ccf7ff20 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -728,18 +728,16 @@ namespace MWMechanics { const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); int radius = esmStore.get().find("fSneakUseDist")->getInt(); - - // am I close enough to the player? - if (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) - <= radius * radius ) - { - bool seen = false; // unseen - if ( !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr) - && !MWBase::Environment::get().getWorld()->getLOS(player, ptr) ) - seen = true; // seen + bool seen = false; - MWBase::Environment::get().getWindowManager()->setSneakVisibility(seen); - } + // am I close enough and can I see the player? + if ( (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius) + && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr) + && MWBase::Environment::get().getWorld()->getLOS(player, ptr)) + + seen = true; + + MWBase::Environment::get().getWindowManager()->setSneakVisibility(seen); } } diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index c0f88249ce..d581a86c05 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -132,28 +132,8 @@ namespace MWWorld MWWorld::Ptr ptr = getPlayer(); ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - if (sneak) - { - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - - // Find all the actors who might be able to see the player - std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), - esmStore.get().find("fSneakUseDist")->getInt(), neighbors); - for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - { - if (*it == ptr) // not the player - continue; - - if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - { - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); - break; - } - } - if (neighbors.empty()) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); - } + if(!sneak) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } void Player::yaw(float yaw) From 00b21449a2f26262e54bfb55af3b855b976af22e Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sat, 3 May 2014 19:47:13 +0200 Subject: [PATCH 160/545] replaced type_cell with type_scene --- apps/opencs/view/world/scenesubview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index d411985b39..34008c9a8b 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -142,7 +142,7 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection) { - setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Cell, "sys::default")); + setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default")); int size = selection.getSize(); std::ostringstream stream; From 320411f5b30d854f247fde0238df7c8e7494d02b Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sat, 3 May 2014 21:05:45 +0200 Subject: [PATCH 161/545] remove unused CMake files for Audiere, MPG123 and Sndfile --- cmake/FindAudiere.cmake | 60 ----------------------------------------- cmake/FindMPG123.cmake | 47 -------------------------------- cmake/FindSNDFILE.cmake | 41 ---------------------------- 3 files changed, 148 deletions(-) delete mode 100644 cmake/FindAudiere.cmake delete mode 100644 cmake/FindMPG123.cmake delete mode 100644 cmake/FindSNDFILE.cmake diff --git a/cmake/FindAudiere.cmake b/cmake/FindAudiere.cmake deleted file mode 100644 index 79427309c0..0000000000 --- a/cmake/FindAudiere.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# Locate Audiere -# This module defines -# AUDIERE_LIBRARY -# AUDIERE_FOUND, if false, do not try to link to Audiere -# AUDIERE_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) -# -# More or less a direct ripoff of FindOpenAL.cmake by Eric Wing. - -#============================================================================= -# Copyright 2005-2009 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distributed this file outside of CMake, substitute the full -# License text for the above reference.) - - -FIND_PATH(AUDIERE_INCLUDE_DIR audiere.h - HINTS - PATH_SUFFIXES include - PATHS - $ENV{AUDIERE_DIR} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(AUDIERE_LIBRARY - NAMES audiere - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - $ENV{AUDIERE_DIR} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(AUDIERE_FOUND "NO") -IF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) - SET(AUDIERE_FOUND "YES") -ENDIF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) - diff --git a/cmake/FindMPG123.cmake b/cmake/FindMPG123.cmake deleted file mode 100644 index 51e562c910..0000000000 --- a/cmake/FindMPG123.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# Locate MPG123 -# This module defines -# MPG123_LIBRARY -# MPG123_FOUND, if false, do not try to link to Mpg123 -# MPG123_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) -# -# Ripped off from other sources. In fact, this file is so generic (I -# just did a search and replace on another file) that I wonder why the -# CMake guys haven't wrapped this entire thing in a single -# function. Do we really need to repeat this stuff for every single -# library when they all work the same? - -FIND_PATH(MPG123_INCLUDE_DIR mpg123.h - HINTS - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(MPG123_LIBRARY - NAMES mpg123 - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(MPG123_FOUND "NO") -IF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) - SET(MPG123_FOUND "YES") -ENDIF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) - diff --git a/cmake/FindSNDFILE.cmake b/cmake/FindSNDFILE.cmake deleted file mode 100644 index 5c7664b502..0000000000 --- a/cmake/FindSNDFILE.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# Locate SNDFILE -# This module defines -# SNDFILE_LIBRARY -# SNDFILE_FOUND, if false, do not try to link to Sndfile -# SNDFILE_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) - -FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h - HINTS - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(SNDFILE_LIBRARY - NAMES sndfile - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(SNDFILE_FOUND "NO") -IF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) - SET(SNDFILE_FOUND "YES") -ENDIF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) - From 688d5565107da4d03a4f04599360b3174dc723c5 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sat, 3 May 2014 21:20:22 +0200 Subject: [PATCH 162/545] remove references to Audiere and MPG123 from top-level CMake file --- CMakeLists.txt | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd45a207c9..27007f161d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,8 +86,6 @@ option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock fram # Sound source selection option(USE_FFMPEG "use ffmpeg for sound" ON) -option(USE_AUDIERE "use audiere for sound" ON) -option(USE_MPG123 "use mpg123 + libsndfile for sound" ON) # OS X deployment option(OPENMW_OSX_DEPLOYMENT OFF) @@ -171,27 +169,6 @@ if (USE_FFMPEG) endif (FFMPEG_FOUND) endif (USE_FFMPEG) -if (USE_AUDIERE AND NOT GOT_SOUND_INPUT) - find_package(Audiere) - if (AUDIERE_FOUND) - set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR}) - set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY}) - set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE) - set(GOT_SOUND_INPUT 1) - endif (AUDIERE_FOUND) -endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT) - -if (USE_MPG123 AND NOT GOT_SOUND_INPUT) - find_package(MPG123 REQUIRED) - find_package(SNDFILE REQUIRED) - if (MPG123_FOUND AND SNDFILE_FOUND) - set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) - set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY}) - set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123) - set(GOT_SOUND_INPUT 1) - endif (MPG123_FOUND AND SNDFILE_FOUND) -endif (USE_MPG123 AND NOT GOT_SOUND_INPUT) - if (NOT GOT_SOUND_INPUT) message(WARNING "--------------------") message(WARNING "Failed to find any sound input packages") From 620a8ccaf3f78b28193c215e9f80365dae4cf785 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sat, 3 May 2014 21:49:57 +0200 Subject: [PATCH 163/545] remove Audiere and MPG123+Sndfile decoder sources --- apps/openmw/mwsound/audiere_decoder.cpp | 137 ------------- apps/openmw/mwsound/audiere_decoder.hpp | 46 ----- apps/openmw/mwsound/mpgsnd_decoder.cpp | 247 ------------------------ apps/openmw/mwsound/mpgsnd_decoder.hpp | 59 ------ apps/openmw/mwsound/soundmanagerimp.cpp | 18 +- 5 files changed, 2 insertions(+), 505 deletions(-) delete mode 100644 apps/openmw/mwsound/audiere_decoder.cpp delete mode 100644 apps/openmw/mwsound/audiere_decoder.hpp delete mode 100644 apps/openmw/mwsound/mpgsnd_decoder.cpp delete mode 100644 apps/openmw/mwsound/mpgsnd_decoder.hpp diff --git a/apps/openmw/mwsound/audiere_decoder.cpp b/apps/openmw/mwsound/audiere_decoder.cpp deleted file mode 100644 index 3f3e3a62d2..0000000000 --- a/apps/openmw/mwsound/audiere_decoder.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifdef OPENMW_USE_AUDIERE - -#include -#include - -#include "audiere_decoder.hpp" - - -static void fail(const std::string &msg) -{ throw std::runtime_error("Audiere exception: "+msg); } - -namespace MWSound -{ - -class OgreFile : public audiere::File -{ - Ogre::DataStreamPtr mStream; - - ADR_METHOD(int) read(void* buffer, int size) - { - return mStream->read(buffer, size); - } - - ADR_METHOD(bool) seek(int position, SeekMode mode) - { - if(mode == CURRENT) - mStream->seek(mStream->tell()+position); - else if(mode == BEGIN) - mStream->seek(position); - else if(mode == END) - mStream->seek(mStream->size()+position); - else - return false; - - return true; - } - - ADR_METHOD(int) tell() - { - return mStream->tell(); - } - - size_t refs; - ADR_METHOD(void) ref() { ++refs; } - ADR_METHOD(void) unref() - { - if(--refs == 0) - delete this; - } - -public: - OgreFile(const Ogre::DataStreamPtr &stream) - : mStream(stream), refs(1) - { } - virtual ~OgreFile() { } - - Ogre::String getName() - { return mStream->getName(); } -}; - - -void Audiere_Decoder::open(const std::string &fname) -{ - close(); - - mSoundFile = audiere::FilePtr(new OgreFile(mResourceMgr.openResource(fname))); - mSoundSource = audiere::OpenSampleSource(mSoundFile); - mSoundFileName = fname; - - int channels, srate; - audiere::SampleFormat format; - - mSoundSource->getFormat(channels, srate, format); - if(format == audiere::SF_S16) - mSampleType = SampleType_Int16; - else if(format == audiere::SF_U8) - mSampleType = SampleType_UInt8; - else - fail("Unsupported sample type"); - - if(channels == 1) - mChannelConfig = ChannelConfig_Mono; - else if(channels == 2) - mChannelConfig = ChannelConfig_Stereo; - else - fail("Unsupported channel count"); - - mSampleRate = srate; -} - -void Audiere_Decoder::close() -{ - mSoundFile = NULL; - mSoundSource = NULL; -} - -std::string Audiere_Decoder::getName() -{ - return mSoundFileName; -} - -void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) -{ - *samplerate = mSampleRate; - *chans = mChannelConfig; - *type = mSampleType; -} - -size_t Audiere_Decoder::read(char *buffer, size_t bytes) -{ - int size = bytesToFrames(bytes, mChannelConfig, mSampleType); - size = mSoundSource->read(size, buffer); - return framesToBytes(size, mChannelConfig, mSampleType); -} - -void Audiere_Decoder::rewind() -{ - mSoundSource->reset(); -} - -size_t Audiere_Decoder::getSampleOffset() -{ - return 0; -} - -Audiere_Decoder::Audiere_Decoder() -{ -} - -Audiere_Decoder::~Audiere_Decoder() -{ - close(); -} - -} - -#endif diff --git a/apps/openmw/mwsound/audiere_decoder.hpp b/apps/openmw/mwsound/audiere_decoder.hpp deleted file mode 100644 index f432c32ec2..0000000000 --- a/apps/openmw/mwsound/audiere_decoder.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef GAME_SOUND_AUDIERE_DECODER_H -#define GAME_SOUND_AUDIERE_DECODER_H - -#include - -#include "audiere.h" - -#include "sound_decoder.hpp" - - -namespace MWSound -{ - class Audiere_Decoder : public Sound_Decoder - { - std::string mSoundFileName; - audiere::FilePtr mSoundFile; - audiere::SampleSourcePtr mSoundSource; - int mSampleRate; - SampleType mSampleType; - ChannelConfig mChannelConfig; - - virtual void open(const std::string &fname); - virtual void close(); - - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - - virtual size_t read(char *buffer, size_t bytes); - virtual void rewind(); - virtual size_t getSampleOffset(); - - Audiere_Decoder& operator=(const Audiere_Decoder &rhs); - Audiere_Decoder(const Audiere_Decoder &rhs); - - Audiere_Decoder(); - public: - virtual ~Audiere_Decoder(); - - friend class SoundManager; - }; -#ifndef DEFAULT_DECODER -#define DEFAULT_DECODER (::MWSound::Audiere_Decoder) -#endif -}; - -#endif diff --git a/apps/openmw/mwsound/mpgsnd_decoder.cpp b/apps/openmw/mwsound/mpgsnd_decoder.cpp deleted file mode 100644 index fb187f8442..0000000000 --- a/apps/openmw/mwsound/mpgsnd_decoder.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#ifdef OPENMW_USE_MPG123 - -#include -#include - -#include "mpgsnd_decoder.hpp" - - -static void fail(const std::string &msg) -{ throw std::runtime_error("MpgSnd exception: "+msg); } - -namespace MWSound -{ - -// -// libSndFile io callbacks -// -sf_count_t MpgSnd_Decoder::ogresf_get_filelen(void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->size(); -} - -sf_count_t MpgSnd_Decoder::ogresf_seek(sf_count_t offset, int whence, void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - - if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); - else if(whence == SEEK_SET) - stream->seek(offset); - else if(whence == SEEK_END) - stream->seek(stream->size()+offset); - else - return -1; - - return stream->tell(); -} - -sf_count_t MpgSnd_Decoder::ogresf_read(void *ptr, sf_count_t count, void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->read(ptr, count); -} - -sf_count_t MpgSnd_Decoder::ogresf_write(const void*, sf_count_t, void*) -{ return -1; } - -sf_count_t MpgSnd_Decoder::ogresf_tell(void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->tell(); -} - -// -// libmpg13 io callbacks -// -ssize_t MpgSnd_Decoder::ogrempg_read(void *user_data, void *ptr, size_t count) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->read(ptr, count); -} - -off_t MpgSnd_Decoder::ogrempg_lseek(void *user_data, off_t offset, int whence) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - - if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); - else if(whence == SEEK_SET) - stream->seek(offset); - else if(whence == SEEK_END) - stream->seek(stream->size()+offset); - else - return -1; - - return stream->tell(); -} - - -void MpgSnd_Decoder::open(const std::string &fname) -{ - close(); - mDataStream = mResourceMgr.openResource(fname); - - SF_VIRTUAL_IO streamIO = { - ogresf_get_filelen, ogresf_seek, - ogresf_read, ogresf_write, ogresf_tell - }; - mSndFile = sf_open_virtual(&streamIO, SFM_READ, &mSndInfo, this); - if(mSndFile) - { - if(mSndInfo.channels == 1) - mChanConfig = ChannelConfig_Mono; - else if(mSndInfo.channels == 2) - mChanConfig = ChannelConfig_Stereo; - else - { - sf_close(mSndFile); - mSndFile = NULL; - fail("Unsupported channel count in "+fname); - } - mSampleRate = mSndInfo.samplerate; - return; - } - mDataStream->seek(0); - - mMpgFile = mpg123_new(NULL, NULL); - if(mMpgFile && mpg123_replace_reader_handle(mMpgFile, ogrempg_read, ogrempg_lseek, NULL) == MPG123_OK && - mpg123_open_handle(mMpgFile, this) == MPG123_OK) - { - try - { - int encoding, channels; - long rate; - if(mpg123_getformat(mMpgFile, &rate, &channels, &encoding) != MPG123_OK) - fail("Failed to get audio format"); - if(encoding != MPG123_ENC_SIGNED_16) - fail("Unsupported encoding in "+fname); - if(channels != 1 && channels != 2) - fail("Unsupported channel count in "+fname); - mChanConfig = ((channels==2)?ChannelConfig_Stereo:ChannelConfig_Mono); - mSampleRate = rate; - return; - } - catch(std::exception &e) - { - mpg123_close(mMpgFile); - mpg123_delete(mMpgFile); - mMpgFile = NULL; - throw; - } - mpg123_close(mMpgFile); - } - if(mMpgFile) - mpg123_delete(mMpgFile); - mMpgFile = NULL; - - fail("Unsupported file type: "+fname); -} - -void MpgSnd_Decoder::close() -{ - if(mSndFile) - sf_close(mSndFile); - mSndFile = NULL; - - if(mMpgFile) - { - mpg123_close(mMpgFile); - mpg123_delete(mMpgFile); - mMpgFile = NULL; - } - - mDataStream.setNull(); -} - -std::string MpgSnd_Decoder::getName() -{ - return mDataStream->getName(); -} - -void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) -{ - if(!mSndFile && !mMpgFile) - fail("No open file"); - - *samplerate = mSampleRate; - *chans = mChanConfig; - *type = SampleType_Int16; -} - -size_t MpgSnd_Decoder::read(char *buffer, size_t bytes) -{ - size_t got = 0; - - if(mSndFile) - { - got = sf_read_short(mSndFile, (short*)buffer, bytes/2)*2; - } - else if(mMpgFile) - { - int err; - err = mpg123_read(mMpgFile, (unsigned char*)buffer, bytes, &got); - if(err != MPG123_OK && err != MPG123_DONE) - fail("Failed to read from file"); - } - return got; -} - -void MpgSnd_Decoder::readAll(std::vector &output) -{ - if(mSndFile && mSndInfo.frames > 0) - { - size_t pos = output.size(); - output.resize(pos + mSndInfo.frames*mSndInfo.channels*2); - sf_readf_short(mSndFile, (short*)(&output[0]+pos), mSndInfo.frames); - return; - } - // Fallback in case we don't know the total already - Sound_Decoder::readAll(output); -} - -void MpgSnd_Decoder::rewind() -{ - if(!mSndFile && !mMpgFile) - fail("No open file"); - - if(mSndFile) - { - if(sf_seek(mSndFile, 0, SEEK_SET) == -1) - fail("seek failed"); - } - else if(mMpgFile) - { - if(mpg123_seek(mMpgFile, 0, SEEK_SET) < 0) - fail("seek failed"); - } -} - -size_t MpgSnd_Decoder::getSampleOffset() -{ - return 0; -} - -MpgSnd_Decoder::MpgSnd_Decoder() - : mSndInfo() - , mSndFile(NULL) - , mMpgFile(NULL) - , mDataStream() - , mChanConfig(ChannelConfig_Stereo) - , mSampleRate(0) -{ - static bool initdone = false; - if(!initdone) - mpg123_init(); - initdone = true; -} - -MpgSnd_Decoder::~MpgSnd_Decoder() -{ - close(); -} - -} - -#endif diff --git a/apps/openmw/mwsound/mpgsnd_decoder.hpp b/apps/openmw/mwsound/mpgsnd_decoder.hpp deleted file mode 100644 index be52f6f491..0000000000 --- a/apps/openmw/mwsound/mpgsnd_decoder.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef GAME_SOUND_MPGSND_DECODER_H -#define GAME_SOUND_MPGSND_DECODER_H - -#include - -#include - -#include "mpg123.h" -#include "sndfile.h" - -#include "sound_decoder.hpp" - - -namespace MWSound -{ - class MpgSnd_Decoder : public Sound_Decoder - { - SF_INFO mSndInfo; - SNDFILE *mSndFile; - mpg123_handle *mMpgFile; - - Ogre::DataStreamPtr mDataStream; - static sf_count_t ogresf_get_filelen(void *user_data); - static sf_count_t ogresf_seek(sf_count_t offset, int whence, void *user_data); - static sf_count_t ogresf_read(void *ptr, sf_count_t count, void *user_data); - static sf_count_t ogresf_write(const void*, sf_count_t, void*); - static sf_count_t ogresf_tell(void *user_data); - static ssize_t ogrempg_read(void*, void*, size_t); - static off_t ogrempg_lseek(void*, off_t, int); - - ChannelConfig mChanConfig; - int mSampleRate; - - virtual void open(const std::string &fname); - virtual void close(); - - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - - virtual size_t read(char *buffer, size_t bytes); - virtual void readAll(std::vector &output); - virtual void rewind(); - virtual size_t getSampleOffset(); - - MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs); - MpgSnd_Decoder(const MpgSnd_Decoder &rhs); - - MpgSnd_Decoder(); - public: - virtual ~MpgSnd_Decoder(); - - friend class SoundManager; - }; -#ifndef DEFAULT_DECODER -#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder) -#endif -} - -#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 33032477fb..8ce87a25e0 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -17,8 +17,8 @@ #include "openal_output.hpp" #define SOUND_OUT "OpenAL" -/* Set up the sound manager to use FFMPEG, MPG123+libsndfile, or Audiere for - * input. The OPENMW_USE_x macros are set in CMakeLists.txt. +/* Set up the sound manager to use FFMPEG for input. + * The OPENMW_USE_x macros are set in CMakeLists.txt. */ #ifdef OPENMW_USE_FFMPEG #include "ffmpeg_decoder.hpp" @@ -27,20 +27,6 @@ #endif #endif -#ifdef OPENMW_USE_AUDIERE -#include "audiere_decoder.hpp" -#ifndef SOUND_IN -#define SOUND_IN "Audiere" -#endif -#endif - -#ifdef OPENMW_USE_MPG123 -#include "mpgsnd_decoder.hpp" -#ifndef SOUND_IN -#define SOUND_IN "mpg123,sndfile" -#endif -#endif - namespace MWSound { From be89654eef51fb33701006b9114e804ecf40723e Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sat, 3 May 2014 22:05:21 +0200 Subject: [PATCH 164/545] remove audiere_decoder + mpgsnd_decoder from CMake file for openmw --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0661508b89..89e40c9b19 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,7 +48,7 @@ add_openmw_dir (mwscript ) add_openmw_dir (mwsound - soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder + soundmanagerimp openal_output ffmpeg_decoder ) add_openmw_dir (mwworld From bc6197c5523fc7cc8879910ee9b6d45d154e03e6 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 18:57:34 -0500 Subject: [PATCH 165/545] Added custom spin box class --- apps/opencs/view/settings/spinbox.cpp | 51 +++++++++++++++++++++++++++ apps/opencs/view/settings/spinbox.hpp | 31 ++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 apps/opencs/view/settings/spinbox.cpp create mode 100644 apps/opencs/view/settings/spinbox.hpp diff --git a/apps/opencs/view/settings/spinbox.cpp b/apps/opencs/view/settings/spinbox.cpp new file mode 100644 index 0000000000..bfb1663709 --- /dev/null +++ b/apps/opencs/view/settings/spinbox.cpp @@ -0,0 +1,51 @@ +#include "spinbox.hpp" + +#include +#include + +CSVSettings::SpinBox::SpinBox(QWidget *parent) + : mValueList(QStringList()), QSpinBox(parent) +{ + setRange (0, 0); +} + +QString CSVSettings::SpinBox::textFromValue(int val) const +{ + if (mValueList.isEmpty()) + return QVariant (val).toString(); + + QString value = ""; + + if (val < mValueList.size()) + value = mValueList.at (val); + + return value; +} + +int CSVSettings::SpinBox::valueFromText(const QString &text) const +{ + if (mValueList.isEmpty()) + return -1; + + if (mValueList.contains (text)) + return mValueList.indexOf(text); + + return -1; +} + +void CSVSettings::SpinBox::setValue (const QString &value) +{ + if (!mValueList.isEmpty()) + { + lineEdit()->setText (value); + QSpinBox::setValue(valueFromText(value)); + } + else + QSpinBox::setValue (value.toInt()); +} + +void CSVSettings::SpinBox::setValueList (const QStringList &list) +{ + mValueList = list; + setMaximum (list.size() - 1); +} diff --git a/apps/opencs/view/settings/spinbox.hpp b/apps/opencs/view/settings/spinbox.hpp new file mode 100644 index 0000000000..f8e59fa05a --- /dev/null +++ b/apps/opencs/view/settings/spinbox.hpp @@ -0,0 +1,31 @@ +#ifndef CSVSETTINGS_SPINBOX_HPP +#define CSVSETTINGS_SPINBOX_HPP + +#include +#include +#include + +namespace CSVSettings +{ + class SpinBox : public QSpinBox + { + Q_OBJECT + + QStringList mValueList; + + public: + explicit SpinBox(QWidget *parent = 0); + + void setObjectName (const QString &name); + + void setValue (const QString &value); + void setValueList (const QStringList &list); + const QStringList &valueList() const { return mValueList; } + + protected: + + QString textFromValue (int val) const; + int valueFromText (const QString &text) const; + }; +} +#endif // CSVSETTINGS_SPINBOX_HPP From 1c26741c5618c29321748d15b979813b5ee1618e Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 18:58:43 -0500 Subject: [PATCH 166/545] Implemented rangeview with spinbox as only control. Simplified setting class constructor. --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/model/settings/setting.cpp | 135 ++++++++++++---- apps/opencs/model/settings/setting.hpp | 43 +++-- apps/opencs/model/settings/settingmanager.cpp | 6 +- apps/opencs/model/settings/settingmanager.hpp | 3 +- apps/opencs/model/settings/support.hpp | 43 +++-- apps/opencs/model/settings/usersettings.cpp | 142 +++++++++++----- apps/opencs/view/settings/booleanview.cpp | 13 +- apps/opencs/view/settings/dialog.cpp | 2 - apps/opencs/view/settings/frame.cpp | 2 + apps/opencs/view/settings/page.cpp | 2 + apps/opencs/view/settings/rangeview.cpp | 151 +++++++++++------- apps/opencs/view/settings/rangeview.hpp | 14 +- apps/opencs/view/settings/textview.cpp | 14 +- apps/opencs/view/settings/textview.hpp | 6 - apps/opencs/view/settings/view.cpp | 1 + apps/opencs/view/settings/view.hpp | 2 +- 17 files changed, 398 insertions(+), 182 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 680c8f8b7b..38075ac536 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -97,6 +97,7 @@ opencs_units (view/settings listview rangeview resizeablestackedwidget + spinbox ) opencs_units_noqt (view/settings diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index ca682b454d..1b265759ca 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -1,13 +1,8 @@ #include "setting.hpp" #include "support.hpp" -CSMSettings::Setting::Setting() -{ - buildDefaultSetting(); -} - CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, - const QString &pageName, const QStringList &values) + const QString &pageName) : mIsEditorSetting (false) { buildDefaultSetting(); @@ -19,10 +14,9 @@ CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, setProperty (Property_IsMultiValue, QVariant(true).toString()); //view type is related to setting type by an order of magnitude - setProperty (Property_ViewType, QVariant (settingType / 10).toString()); + setProperty (Property_SettingType, QVariant (settingType).toString()); setProperty (Property_Page, pageName); setProperty (Property_Name, settingName); - setProperty (Property_DeclaredValues, values); } void CSMSettings::Setting::buildDefaultSetting() @@ -73,6 +67,11 @@ int CSMSettings::Setting::columnSpan() const return property (Property_ColumnSpan).at(0).toInt(); } +void CSMSettings::Setting::setDeclaredValues (QStringList list) +{ + setProperty (Property_DeclaredValues, list); +} + QStringList CSMSettings::Setting::declaredValues() const { return property (Property_DeclaredValues); @@ -165,6 +164,16 @@ bool CSMSettings::Setting::serializable() const return (property (Property_Serializable).at(0) == "true"); } +void CSMSettings::Setting::setSpecialValueText(const QString &text) +{ + setProperty (Property_SpecialValueText, text); +} + +QString CSMSettings::Setting::specialValueText() const +{ + return property (Property_SpecialValueText).at(0); +} + void CSMSettings::Setting::setName (const QString &value) { setProperty (Property_Name, value); @@ -185,6 +194,16 @@ QString CSMSettings::Setting::page() const return property (Property_Page).at(0); } +void CSMSettings::Setting::setPrefix (const QString &value) +{ + setProperty (Property_Prefix, value); +} + +QString CSMSettings::Setting::prefix() const +{ + return property (Property_Prefix).at(0); +} + void CSMSettings::Setting::setRowSpan (const int value) { setProperty (Property_RowSpan, value); @@ -195,15 +214,76 @@ int CSMSettings::Setting::rowSpan () const return property (Property_RowSpan).at(0).toInt(); } -void CSMSettings::Setting::setViewType (int vType) +void CSMSettings::Setting::setSingleStep (int value) { - setProperty (Property_ViewType, vType); + setProperty (Property_SingleStep, value); +} + +void CSMSettings::Setting::setSingleStep (double value) +{ + setProperty (Property_SingleStep, value); +} + +QString CSMSettings::Setting::singleStep() const +{ + return property (Property_SingleStep).at(0); +} + +void CSMSettings::Setting::setSuffix (const QString &value) +{ + setProperty (Property_Suffix, value); +} + +QString CSMSettings::Setting::suffix() const +{ + return property (Property_Suffix).at(0); +} + +void CSMSettings::Setting::setType (int settingType) +{ + setProperty (Property_SettingType, settingType); +} + +CSMSettings::SettingType CSMSettings::Setting::type() const +{ + return static_cast ( property ( + Property_SettingType).at(0).toInt()); +} + +void CSMSettings::Setting::setMaximum (int value) +{ + setProperty (Property_Maximum, value); +} + +void CSMSettings::Setting::setMaximum (double value) +{ + setProperty (Property_Maximum, value); +} + +QString CSMSettings::Setting::maximum() const +{ + return property (Property_Maximum).at(0); +} + +void CSMSettings::Setting::setMinimum (int value) +{ + setProperty (Property_Minimum, value); +} + +void CSMSettings::Setting::setMinimum (double value) +{ + setProperty (Property_Minimum, value); +} + +QString CSMSettings::Setting::minimum() const +{ + return property (Property_Minimum).at(0); } CSVSettings::ViewType CSMSettings::Setting::viewType() const { - return static_cast - (property(Property_ViewType).at(0).toInt()); + return static_cast ( property ( + Property_SettingType).at(0).toInt() / 10); } void CSMSettings::Setting::setViewColumn (int value) @@ -241,6 +321,17 @@ int CSMSettings::Setting::widgetWidth() const { return property (Property_WidgetWidth).at(0).toInt(); } + +void CSMSettings::Setting::setWrapping (bool state) +{ + setProperty (Property_Wrapping, state); +} + +bool CSMSettings::Setting::wrapping() const +{ + return (property (Property_Wrapping).at(0) == "true"); +} + void CSMSettings::Setting::setProperty (SettingProperty prop, bool value) { setProperty (prop, QStringList() << QVariant (value).toString()); @@ -251,6 +342,11 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, int value) setProperty (prop, QStringList() << QVariant (value).toString()); } +void CSMSettings::Setting::setProperty (SettingProperty prop, double value) +{ + setProperty (prop, QStringList() << QVariant (value).toString()); +} + void CSMSettings::Setting::setProperty (SettingProperty prop, const QString &value) { @@ -263,18 +359,3 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, if (prop < mProperties.size()) mProperties.replace (prop, value); } - -QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting) -{ - // stream << setting.properties(); - - // stream << setting.proxies(); - return stream; -} - -QDataStream &operator >>(QDataStream& stream, CSMSettings::Setting& setting) -{ - // stream >> setting.properties(); - // stream >> setting.proxies(); - return stream; -} diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index 1463e4d7d2..4e28a23484 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -27,12 +27,8 @@ namespace CSMSettings public: - - explicit Setting(); - explicit Setting(SettingType typ, const QString &settingName, - const QString &pageName, - const QStringList &values = QStringList()); + const QString &pageName); void addProxy (const Setting *setting, const QStringList &vals); void addProxy (const Setting *setting, const QList &list); @@ -66,12 +62,18 @@ namespace CSMSettings void setIsMultiValue (bool state); bool isMultiValue() const; + void setMask (const QString &value); + QString mask() const; + void setName (const QString &value); QString name() const; void setPage (const QString &value); QString page() const; + void setPrefix (const QString &value); + QString prefix() const; + void setRowSpan (const int value); int rowSpan() const; @@ -80,6 +82,24 @@ namespace CSMSettings void setSerializable (bool state); bool serializable() const; + void setSpecialValueText (const QString &text); + QString specialValueText() const; + + void setSingleStep (int value); + void setSingleStep (double value); + QString singleStep() const; + + void setSuffix (const QString &value); + QString suffix() const; + + void setMaximum (int value); + void setMaximum (double value); + QString maximum() const; + + void setMinimum (int value); + void setMinimum (double value); + QString minimum() const; + void setViewColumn (int value); int viewColumn() const; @@ -88,9 +108,14 @@ namespace CSMSettings void setViewRow (int value); int viewRow() const; - void setViewType (int vType); + void setType (int settingType); + CSMSettings::SettingType type() const; + CSVSettings::ViewType viewType() const; + void setWrapping (bool state); + bool wrapping() const; + void setWidgetWidth (int value); int widgetWidth() const; @@ -100,6 +125,7 @@ namespace CSMSettings ///boilerplate code to convert setting values of common types void setProperty (SettingProperty prop, bool value); void setProperty (SettingProperty prop, int value); + void setProperty (SettingProperty prop, double value); void setProperty (SettingProperty prop, const QString &value); void setProperty (SettingProperty prop, const QStringList &value); @@ -111,9 +137,4 @@ namespace CSMSettings }; } -Q_DECLARE_METATYPE(CSMSettings::Setting) - -QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting); -QDataStream &operator >>(QDataStream &stream, CSMSettings::Setting& setting); - #endif // CSMSETTINGS_SETTING_HPP diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index eec4c54cf3..36ca1ae03a 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -30,8 +30,7 @@ void CSMSettings::SettingManager::dumpModel() } CSMSettings::Setting *CSMSettings::SettingManager::createSetting - (CSMSettings::SettingType typ, const QString &page, const QString &name, - const QStringList &values) + (CSMSettings::SettingType typ, const QString &page, const QString &name) { //get list of all settings for the current setting name if (findSetting (page, name)) @@ -41,7 +40,8 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting return 0; } - Setting *setting = new Setting (typ, name, page, values); + Setting *setting = new Setting (typ, name, page); + //add declaration to the model mSettings.append (setting); diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp index ca8a2cc7b9..2efc2929f8 100644 --- a/apps/opencs/model/settings/settingmanager.hpp +++ b/apps/opencs/model/settings/settingmanager.hpp @@ -46,8 +46,7 @@ namespace CSMSettings ///add a new setting to the model and return it Setting *createSetting (CSMSettings::SettingType typ, - const QString &page, const QString &name, - const QStringList &values = QStringList()); + const QString &page, const QString &name); ///add definitions to the settings specified in the page map void addDefinitions (DefinitionPageMap &pageMap); diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index ce808587fc..be5a407adb 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -27,7 +27,7 @@ namespace CSMSettings { Property_Name = 0, Property_Page = 1, - Property_ViewType = 2, + Property_SettingType = 2, Property_IsMultiValue = 3, Property_IsMultiLine = 4, Property_WidgetWidth = 5, @@ -37,12 +37,19 @@ namespace CSMSettings Property_Serializable = 9, Property_ColumnSpan = 10, Property_RowSpan = 11, + Property_Minimum = 12, + Property_Maximum = 13, + Property_SpecialValueText = 14, + Property_Prefix = 15, + Property_Suffix = 16, + Property_SingleStep = 17, + Property_Wrapping = 18, //Stringlists should always be the last items - Property_DefaultValues = 12, - Property_DeclaredValues = 13, - Property_DefinedValues = 14, - Property_Proxies = 15 + Property_DefaultValues = 19, + Property_DeclaredValues = 20, + Property_DefinedValues = 21, + Property_Proxies = 22 }; enum SettingType @@ -64,10 +71,12 @@ namespace CSMSettings Type_ListView = 10, Type_ComboBox = 11, Type_SpinBox = 21, - Type_Slider = 23, - Type_Dial = 24, + Type_DoubleSpinBox = 23, + Type_Slider = 25, + Type_Dial = 27, Type_TextArea = 30, - Type_LineEdit = 31 + Type_LineEdit = 31, + Type_Undefined = 40 }; enum MergeMethod @@ -97,7 +106,7 @@ namespace CSVSettings }; } -// + namespace CSMSettings { struct PropertyDefaultValues @@ -109,9 +118,10 @@ namespace CSMSettings const QString sPropertyNames[] = { - "name", "page", "view_type", "is_multi_value", + "name", "page", "setting_type", "is_multi_value", "is_multi_line", "widget_width", "view_row", "view_column", "delimiter", - "is_serializable","column_span", "row_span", + "is_serializable","column_span", "row_span", "minimum", "maximum", + "special_value_text", "prefix", "suffix", "single_step", "wrapping", "defaults", "declarations", "definitions", "proxies" }; @@ -119,16 +129,23 @@ namespace CSMSettings { "", //name "", //page - "0", //view type + "40", //setting type "false", //multivalue "false", //multiline - "0", //widget width + "7", //widget width "-1", //view row "-1", //view column ",", //delimiter "true", //serialized "1", //column span "1", //row span + "0", //value range + "0", //value minimum + "0", //value maximum + "", //special text + "", //prefix + "", //suffix + "false", //wrapping "", //default values "", //declared values "", //defined values diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 2f8e8098da..17448f1688 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -51,7 +51,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *height = createSetting (Type_LineEdit, section, "Height"); width->setWidgetWidth (5); - height->setWidgetWidth (5); + height->setWidgetWidth (8); width->setDefaultValues (QStringList() << "1024"); height->setDefaultValues (QStringList() << "768"); @@ -66,13 +66,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() *Create the proxy setting for predefined values */ Setting *preDefined = createSetting (Type_ComboBox, section, - "Pre-Defined", - QStringList() - << "640 x 480" - << "800 x 600" - << "1024 x 768" - << "1440 x 900" - ); + "Pre-Defined"); + + preDefined->setDeclaredValues (QStringList() << "640 x 480" + << "800 x 600" << "1024 x 768" << "1440 x 900"); preDefined->setViewLocation (1, 1); preDefined->setWidgetWidth (10); @@ -95,12 +92,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << defaultValue << "Icon Only" << "Text Only"; Setting *rsd = createSetting (Type_RadioButton, - section, "Record Status Display", - values); + section, "Record Status Display"); Setting *ritd = createSetting (Type_RadioButton, - section, "Referenceable ID Type Display", - values); + section, "Referenceable ID Type Display"); + + rsd->setDeclaredValues (values); + ritd->setDeclaredValues (values); rsd->setEditorSetting (true); ritd->setEditorSetting (true); @@ -108,44 +106,63 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() section = "Proxy Selection Test"; { - //create three setting objects, specifying the basic widget type, - //the setting view name, the page name, and the default value + /****************************************************************** + * There are three types of values: + * + * Declared values + * + * Pre-determined values, typically for + * combobox drop downs and boolean (radiobutton / checkbox) labels. + * These values represent the total possible list of values that + * may define a setting. No other values are allowed. + * + * Defined values + * + * Values which represent the actual, current value of + * a setting. For settings with declared values, this must be one or + * several declared values, as appropriate. + * + * Proxy values - values the proxy master updates the proxy slave when + * it's own definition is set / changed. These are definitions for + * proxy slave settings, but must match any declared values the proxy + * slave has, if any. + *******************************************************************/ + + //create setting objects, specifying the basic widget type, + //the page name, and the view name + Setting *masterBoolean = createSetting (Type_RadioButton, section, - "Master Proxy", - QStringList() - << "Profile One" << "Profile Two" - << "Profile Three" << "Profile Four" - ); + "Master Proxy"); Setting *slaveBoolean = createSetting (Type_CheckBox, section, - "Proxy Checkboxes", - QStringList() << "One" << "Two" - << "Three" << "Four" << "Five" - ); + "Proxy Checkboxes"); Setting *slaveSingleText = createSetting (Type_LineEdit, section, - "Proxy TextBox 1" - ); + "Proxy TextBox 1"); Setting *slaveMultiText = createSetting (Type_LineEdit, section, - "ProxyTextBox 2" - ); + "ProxyTextBox 2"); + + Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section, + "Alpha Spinbox"); + + Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section, + "Int Spinbox"); + + Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox, + section, "Double Spinbox"); + + //set declared values for selected views + masterBoolean->setDeclaredValues (QStringList() + << "Profile One" << "Profile Two" + << "Profile Three" << "Profile Four"); + + slaveBoolean->setDeclaredValues (QStringList() + << "One" << "Two" << "Three" << "Four" << "Five"); + + slaveAlphaSpinbox->setDeclaredValues (QStringList() + << "One" << "Two" << "Three" << "Four"); - // There are three types of values: - // - // Declared values - Pre-determined values, typically for - // combobox drop downs and boolean (radiobutton / checkbox) labels. - // These values represent the total possible list of values that may - // define a setting. No other values are allowed. - // - // Defined values - Values which represent the atual, current value of - // a setting. For settings with declared values, this must be one or - // several declared values, as appropriate. - // - // Proxy values - values the proxy master updates the proxy slave when - // it's own definition is set / changed. These are definitions for - // proxy slave settings, but must match any declared values the proxy - // slave has, if any. masterBoolean->addProxy (slaveBoolean, QList () << (QStringList() << "One" << "Three") @@ -168,11 +185,32 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << (QStringList() << "Two" << "Four") ); + masterBoolean->addProxy (slaveAlphaSpinbox, QList () + << (QStringList() << "Four") + << (QStringList() << "Three") + << (QStringList() << "Two") + << (QStringList() << "One")); + + masterBoolean->addProxy (slaveIntegerSpinbox, QList () + << (QStringList() << "0") + << (QStringList() << "7") + << (QStringList() << "14") + << (QStringList() << "21")); + + masterBoolean->addProxy (slaveDoubleSpinbox, QList () + << (QStringList() << "0.17") + << (QStringList() << "0.34") + << (QStringList() << "0.51") + << (QStringList() << "0.68")); + //settings with proxies are not serialized by default //other settings non-serialized for demo purposes slaveBoolean->setSerializable (false); slaveSingleText->setSerializable (false); slaveMultiText->setSerializable (false); + slaveAlphaSpinbox->setSerializable (false); + slaveIntegerSpinbox->setSerializable (false); + slaveDoubleSpinbox->setSerializable (false); slaveBoolean->setDefaultValues (QStringList() << "One" << "Three" << "Five"); @@ -184,7 +222,25 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveSingleText->setWidgetWidth (24); slaveMultiText->setWidgetWidth (24); - } + + slaveAlphaSpinbox->setDefaultValue ("Two"); + slaveAlphaSpinbox->setWidgetWidth (20); + //slaveAlphaSpinbox->setPrefix ("No. "); + //slaveAlphaSpinbox->setSuffix ("!"); + slaveAlphaSpinbox->setWrapping (true); + + slaveIntegerSpinbox->setDefaultValue ("14"); + slaveIntegerSpinbox->setMinimum (0); + slaveIntegerSpinbox->setMaximum (58); + slaveIntegerSpinbox->setPrefix ("$"); + slaveIntegerSpinbox->setSuffix (".00"); + slaveIntegerSpinbox->setWidgetWidth (10); + slaveIntegerSpinbox->setSpecialValueText ("Nothing!"); + + slaveDoubleSpinbox->setDefaultValue ("0.51"); + slaveDoubleSpinbox->setSingleStep(0.17); + slaveDoubleSpinbox->setMaximum(4.0); + } } CSMSettings::UserSettings::~UserSettings() diff --git a/apps/opencs/view/settings/booleanview.cpp b/apps/opencs/view/settings/booleanview.cpp index 1c48199d1d..2a3f0cba6e 100644 --- a/apps/opencs/view/settings/booleanview.cpp +++ b/apps/opencs/view/settings/booleanview.cpp @@ -18,10 +18,19 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, { QAbstractButton *button = 0; - if (isMultiValue()) + switch (setting->type()) + { + case CSMSettings::Type_CheckBox: button = new QCheckBox (value, this); - else + break; + + case CSMSettings::Type_RadioButton: button = new QRadioButton (value, this); + break; + + default: + break; + } connect (button, SIGNAL (clicked (bool)), this, SLOT (slotToggled (bool))); diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index d9d5830d98..3ed4d3b091 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -123,10 +123,8 @@ void CSVSettings::Dialog::show() { if (pages().isEmpty()) buildPages(); - QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); move (screenCenter - geometry().center()); - QWidget::show(); } diff --git a/apps/opencs/view/settings/frame.cpp b/apps/opencs/view/settings/frame.cpp index db5091999a..0190247763 100644 --- a/apps/opencs/view/settings/frame.cpp +++ b/apps/opencs/view/settings/frame.cpp @@ -60,8 +60,10 @@ void CSVSettings::Frame::showWidgets() QWidget *widg = static_cast (obj); if (widg->property("sizePolicy").isValid()) + { widg->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + } } layout()->activate(); setFixedSize(minimumSizeHint()); diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index e674458739..afd4bff5ee 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -7,6 +7,8 @@ #include "../../model/settings/usersettings.hpp" #include "../../model/settings/connector.hpp" +#include "../../model/settings/support.hpp" + #include "settingwindow.hpp" QMap diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 2bb5863bc4..ac9a5da8b8 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -1,88 +1,129 @@ #include #include - -#include -#include #include - -#include +#include +#include +#include #include "rangeview.hpp" +#include "spinbox.hpp" #include "../../model/settings/setting.hpp" - - -#include +#include "../../model/settings/support.hpp" CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, Page *parent) - : View (setting, parent) + : mRangeWidget (0), mRangeType (setting->type()), View (setting, parent) { - foreach (const QString &value, setting->declaredValues()) - { - QAbstractButton *button = 0; - if (isMultiValue()) - button = new QCheckBox (value, this); - else - button = new QRadioButton (value, this); + mRangeWidget = 0; - connect (button, SIGNAL (clicked (bool)), - this, SLOT (slotToggled (bool))); - - button->setObjectName (value); - - addWidget (button); - - mButtons[value] = button; - } -} - -void CSVSettings::RangeView::slotToggled (bool state) -{ - //test only for true to avoid multiple selection updates with radiobuttons - if (!isMultiValue() && !state) + if (isMultiValue()) return; - QStringList values; + buildSpinBox (setting); - foreach (QString key, mButtons.keys()) + mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); + mRangeWidget->setObjectName (setting->name()); + + addWidget (mRangeWidget); +} + +void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) +{ + SpinBox *sb = 0; + + switch (setting->type()) { - if (mButtons.value(key)->isChecked()) - values.append (key); + case CSMSettings::Type_SpinBox: + + sb = new SpinBox (this); + + if (!setting->declaredValues().isEmpty()) + sb->setValueList (setting->declaredValues()); + + mRangeWidget = sb; + + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); + break; + + case CSMSettings::Type_DoubleSpinBox: + mRangeWidget = new QDoubleSpinBox (this); + + connect (mRangeWidget, SIGNAL (valueChanged (double)), + this, SLOT (slotUpdateView (double))); + break; + + default: + break; } - setSelectedValues (values, false); + + //min / max values are set automatically in AlphaSpinBox + if (setting->declaredValues().isEmpty()) + { + mRangeWidget->setProperty ("minimum", setting->minimum()); + mRangeWidget->setProperty ("maximum", setting->maximum()); + mRangeWidget->setProperty ("singleStep", setting->singleStep()); + mRangeWidget->setProperty ("specialValueText", + setting->specialValueText()); + } + + mRangeWidget->setProperty ("prefix", setting->prefix()); + mRangeWidget->setProperty ("suffix", setting->suffix()); + mRangeWidget->setProperty ("wrapping", setting->wrapping()); + +} + +void CSVSettings::RangeView::slotUpdateView (int value) +{ + QString textValue = ""; + + if (mRangeType == CSMSettings::Type_SpinBox) + { + QStringList list = + static_cast (mRangeWidget)->valueList(); + if (!list.isEmpty()) + textValue = list.at(value); + } + + if (textValue.isEmpty()) + textValue = QVariant (value).toString(); + + setSelectedValue (textValue, false); + + View::updateView(); + +} + +void CSVSettings::RangeView::slotUpdateView (double value) +{ + setSelectedValue (QVariant(value).toString(), false); View::updateView(); } void CSVSettings::RangeView::updateView (bool signalUpdate) const { + QString value; - QStringList values = selectedValues(); + if (!selectedValues().isEmpty()) + value = selectedValues().at(0); - foreach (const QString &buttonName, mButtons.keys()) + switch (mRangeType) { - QAbstractButton *button = mButtons[buttonName]; + case CSMSettings::Type_SpinBox: + static_cast (mRangeWidget)->setValue (value); + break; - //if the value is not found in the list, the widget is checked false - bool buttonValue = values.contains(buttonName); + case CSMSettings::Type_DoubleSpinBox: + static_cast (mRangeWidget)->setValue (value.toDouble()); + break; - //skip if the butotn value will not change - if (button->isChecked() == buttonValue) - continue; + default: + break; - //disable autoexclusive if it's enabled and we're setting - //the button value to false - bool switchExclusive = (!buttonValue && button->autoExclusive()); - - if (switchExclusive) - button->setAutoExclusive (false); - - button->setChecked (buttonValue); - - if (switchExclusive) - button->setAutoExclusive(true); } + View::updateView (signalUpdate); } diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp index 1df0c7bd63..6515c91682 100644 --- a/apps/opencs/view/settings/rangeview.hpp +++ b/apps/opencs/view/settings/rangeview.hpp @@ -1,13 +1,11 @@ #ifndef CSVSETTINGS_RANGEVIEW_HPP #define CSVSETTINGS_RANGEVIEW_HPP -#include -#include - #include "view.hpp" #include "../../model/settings/support.hpp" class QStringListModel; +class QAbstractSpinBox; namespace CSVSettings { @@ -15,7 +13,8 @@ namespace CSVSettings { Q_OBJECT - QMap mButtons; + QAbstractSpinBox *mRangeWidget; + CSMSettings::SettingType mRangeType; public: explicit RangeView (CSMSettings::Setting *setting, @@ -24,8 +23,13 @@ namespace CSVSettings protected: void updateView (bool signalUpdate = true) const; + void buildSpinBox (CSMSettings::Setting *setting); + private slots: - void slotToggled (bool state); + + void slotUpdateView (int value); + void slotUpdateView (double value); + }; class RangeViewFactory : public QObject, public IViewFactory diff --git a/apps/opencs/view/settings/textview.cpp b/apps/opencs/view/settings/textview.cpp index 5e10c346f7..6886732dbe 100644 --- a/apps/opencs/view/settings/textview.cpp +++ b/apps/opencs/view/settings/textview.cpp @@ -28,11 +28,6 @@ bool CSVSettings::TextView::isEquivalent return (lhs.trimmed() == rhs.trimmed()); } -void CSVSettings::TextView::setWidgetText (const QString &value) const -{ - mTextWidget->setProperty ("text", value); -} - void CSVSettings::TextView::slotTextEdited (QString value) { QStringList values = value.split (mDelimiter, QString::SkipEmptyParts); @@ -51,19 +46,14 @@ void CSVSettings::TextView::updateView(bool signalUpdate) const { QString values = selectedValues().join (mDelimiter); - if (isEquivalent (widgetText(), values)) + if (isEquivalent (mTextWidget->property("text").toString(), values)) return; - setWidgetText (values); + mTextWidget->setProperty("text", values); View::updateView (signalUpdate); } -QString CSVSettings::TextView::widgetText() const -{ - return mTextWidget->property("text").toString(); -} - CSVSettings::TextView *CSVSettings::TextViewFactory::createView (CSMSettings::Setting *setting, Page *parent) diff --git a/apps/opencs/view/settings/textview.hpp b/apps/opencs/view/settings/textview.hpp index 6d718aad87..c485e7fcf0 100644 --- a/apps/opencs/view/settings/textview.hpp +++ b/apps/opencs/view/settings/textview.hpp @@ -32,12 +32,6 @@ namespace CSVSettings ///Comparison function that returns true if the trimmed() strings ///are equal bool isEquivalent (const QString &lhs, const QString &rhs) const; - - ///Convenience function to return the text of the widget - QString widgetText() const; - - ///Convenience function to set the text of the widget - void setWidgetText (const QString &value) const; }; class TextViewFactory : public QObject, public IViewFactory diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 4f93b1c0fe..2a70152c2d 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -192,6 +192,7 @@ bool CSVSettings::View::stringListsMatch ( QList CSVSettings::View::toStandardItemList (const QStringList &list) const { + QList itemList; foreach (const QString &value, list) diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp index c998797622..23357e45fb 100644 --- a/apps/opencs/view/settings/view.hpp +++ b/apps/opencs/view/settings/view.hpp @@ -101,7 +101,7 @@ namespace CSVSettings void showEvent ( QShowEvent * event ); ///Virtual for updating a specific View subclass - ///bool indicates whether a signal is emitted that the view was updated + ///bool indicates whether viewUpdated() signal is emitted virtual void updateView (bool signalUpdate = true) const; ///Returns the pixel width corresponding to the specified number of From c4a9c180452bdf6a343ef059b78882548b1f350f Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 19:36:52 -0500 Subject: [PATCH 167/545] Commented out "proxy selection test" demo page in user settings --- apps/opencs/model/settings/usersettings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 6e05e9dff4..92ac627c46 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -127,7 +127,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * proxy slave settings, but must match any declared values the proxy * slave has, if any. *******************************************************************/ - +/* //create setting objects, specifying the basic widget type, //the page name, and the view name @@ -240,7 +240,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveDoubleSpinbox->setDefaultValue ("0.51"); slaveDoubleSpinbox->setSingleStep(0.17); slaveDoubleSpinbox->setMaximum(4.0); - } + }*/ } CSMSettings::UserSettings::~UserSettings() From 0a3ab3dcd13eeaec25d2404f050243b5ed7991be Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 19:36:52 -0500 Subject: [PATCH 168/545] Commented out "proxy selection test" demo page in user settings --- apps/opencs/model/settings/usersettings.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 6e05e9dff4..8bfdadf153 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -127,7 +127,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * proxy slave settings, but must match any declared values the proxy * slave has, if any. *******************************************************************/ - +/* //create setting objects, specifying the basic widget type, //the page name, and the view name @@ -240,6 +240,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveDoubleSpinbox->setDefaultValue ("0.51"); slaveDoubleSpinbox->setSingleStep(0.17); slaveDoubleSpinbox->setMaximum(4.0); +*/ } } From 4f876574c15e05a152baeb9788fa21f8dcab65fb Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 21:50:08 -0500 Subject: [PATCH 169/545] Implemented slider widget in rangeView class --- apps/opencs/model/settings/setting.cpp | 30 ++++++++ apps/opencs/model/settings/setting.hpp | 21 ++++-- apps/opencs/model/settings/support.hpp | 15 ++-- apps/opencs/model/settings/usersettings.cpp | 22 +++++- apps/opencs/view/settings/rangeview.cpp | 79 +++++++++++++++++++-- apps/opencs/view/settings/rangeview.hpp | 3 +- 6 files changed, 151 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index 1b265759ca..fe5a26bbc8 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -239,6 +239,36 @@ QString CSMSettings::Setting::suffix() const return property (Property_Suffix).at(0); } +void CSMSettings::Setting::setTickInterval (int value) +{ + setProperty (Property_TickInterval, value); +} + +int CSMSettings::Setting::tickInterval () const +{ + return property (Property_TickInterval).at(0).toInt(); +} + +void CSMSettings::Setting::setTicksAbove (bool state) +{ + setProperty (Property_TicksAbove, state); +} + +bool CSMSettings::Setting::ticksAbove() const +{ + return (property (Property_TicksAbove).at(0) == "true"); +} + +void CSMSettings::Setting::setTicksBelow (bool state) +{ + setProperty (Property_TicksBelow, state); +} + +bool CSMSettings::Setting::ticksBelow() const +{ + return (property (Property_TicksBelow).at(0) == "true"); +} + void CSMSettings::Setting::setType (int settingType) { setProperty (Property_SettingType, settingType); diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index 4e28a23484..8efe330346 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -65,6 +65,14 @@ namespace CSMSettings void setMask (const QString &value); QString mask() const; + void setMaximum (int value); + void setMaximum (double value); + QString maximum() const; + + void setMinimum (int value); + void setMinimum (double value); + QString minimum() const; + void setName (const QString &value); QString name() const; @@ -92,13 +100,14 @@ namespace CSMSettings void setSuffix (const QString &value); QString suffix() const; - void setMaximum (int value); - void setMaximum (double value); - QString maximum() const; + void setTickInterval (int value); + int tickInterval() const; - void setMinimum (int value); - void setMinimum (double value); - QString minimum() const; + void setTicksAbove (bool state); + bool ticksAbove() const; + + void setTicksBelow (bool state); + bool ticksBelow() const; void setViewColumn (int value); int viewColumn() const; diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index be5a407adb..d65de2b91a 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -44,12 +44,15 @@ namespace CSMSettings Property_Suffix = 16, Property_SingleStep = 17, Property_Wrapping = 18, + Property_TickInterval = 19, + Property_TicksAbove = 20, + Property_TicksBelow = 21, //Stringlists should always be the last items - Property_DefaultValues = 19, - Property_DeclaredValues = 20, - Property_DefinedValues = 21, - Property_Proxies = 22 + Property_DefaultValues = 22, + Property_DeclaredValues = 23, + Property_DefinedValues = 24, + Property_Proxies = 25 }; enum SettingType @@ -122,6 +125,7 @@ namespace CSMSettings "is_multi_line", "widget_width", "view_row", "view_column", "delimiter", "is_serializable","column_span", "row_span", "minimum", "maximum", "special_value_text", "prefix", "suffix", "single_step", "wrapping", + "tick_interval", "ticks_above", "ticks_below", "defaults", "declarations", "definitions", "proxies" }; @@ -146,6 +150,9 @@ namespace CSMSettings "", //prefix "", //suffix "false", //wrapping + "1", //tick interval + "false", //ticks above + "true", //ticks below "", //default values "", //declared values "", //defined values diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 8bfdadf153..787e266506 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -127,10 +127,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * proxy slave settings, but must match any declared values the proxy * slave has, if any. *******************************************************************/ -/* + //create setting objects, specifying the basic widget type, //the page name, and the view name - +/* Setting *masterBoolean = createSetting (Type_RadioButton, section, "Master Proxy"); @@ -152,6 +152,8 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox, section, "Double Spinbox"); + Setting *slaveSlider = createSetting (Type_Slider, section, "Slider"); + //set declared values for selected views masterBoolean->setDeclaredValues (QStringList() << "Profile One" << "Profile Two" @@ -203,6 +205,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << (QStringList() << "0.51") << (QStringList() << "0.68")); + masterBoolean->addProxy (slaveSlider, QList () + << (QStringList() << "25") + << (QStringList() << "50") + << (QStringList() << "75") + << (QStringList() << "100") + ); + //settings with proxies are not serialized by default //other settings non-serialized for demo purposes slaveBoolean->setSerializable (false); @@ -211,6 +220,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveAlphaSpinbox->setSerializable (false); slaveIntegerSpinbox->setSerializable (false); slaveDoubleSpinbox->setSerializable (false); + slaveSlider->setSerializable (false); slaveBoolean->setDefaultValues (QStringList() << "One" << "Three" << "Five"); @@ -240,7 +250,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveDoubleSpinbox->setDefaultValue ("0.51"); slaveDoubleSpinbox->setSingleStep(0.17); slaveDoubleSpinbox->setMaximum(4.0); -*/ + + slaveSlider->setMinimum (0); + slaveSlider->setMaximum (100); + slaveSlider->setDefaultValue ("75"); + slaveSlider->setWidgetWidth (100); + slaveSlider->setTicksAbove (true); + slaveSlider->setTickInterval (25);*/ } } diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index ac9a5da8b8..b2701c7bf3 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include "rangeview.hpp" #include "spinbox.hpp" @@ -20,7 +23,21 @@ CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, if (isMultiValue()) return; - buildSpinBox (setting); + switch (mRangeType) + { + case CSMSettings::Type_SpinBox: + case CSMSettings::Type_DoubleSpinBox: + buildSpinBox (setting); + break; + + case CSMSettings::Type_Dial: + case CSMSettings::Type_Slider: + buildSlider (setting); + break; + + default: + break; + } mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); mRangeWidget->setObjectName (setting->name()); @@ -28,6 +45,48 @@ CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, addWidget (mRangeWidget); } +void CSVSettings::RangeView::buildSlider (CSMSettings::Setting *setting) +{ + switch (setting->type()) + { + case CSMSettings::Type_Slider: + mRangeWidget = new QSlider (Qt::Horizontal, this); + mRangeWidget->setProperty ("tickInterval", setting->tickInterval()); + + if (setting->ticksAbove()) + { + if (setting->ticksBelow()) + mRangeWidget->setProperty ("tickPosition", QSlider::TicksBothSides); + else + mRangeWidget->setProperty ("tickPosition", QSlider::TicksAbove); + } + else if (setting->ticksBelow()) + mRangeWidget->setProperty ("tickPosition", QSlider::TicksBelow); + else + mRangeWidget->setProperty ("tickPosition", QSlider::NoTicks); + + break; + + case CSMSettings::Type_Dial: + mRangeWidget = new QDial (this); + mRangeWidget->setProperty ("wrapping", setting->wrapping()); + mRangeWidget->setProperty ("notchesVisible", + (setting->ticksAbove() || setting->ticksBelow())); + break; + + default: + break; + } + + mRangeWidget->setProperty ("minimum", setting->minimum()); + mRangeWidget->setProperty ("maximum", setting->maximum()); + mRangeWidget->setProperty ("tracking", false); + mRangeWidget->setProperty ("singleStep", setting->singleStep()); + + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); +} + void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) { SpinBox *sb = 0; @@ -77,13 +136,18 @@ void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) void CSVSettings::RangeView::slotUpdateView (int value) { QString textValue = ""; + QStringList list; - if (mRangeType == CSMSettings::Type_SpinBox) + switch (mRangeType) { - QStringList list = - static_cast (mRangeWidget)->valueList(); + case CSMSettings::Type_SpinBox: + list = static_cast (mRangeWidget)->valueList(); if (!list.isEmpty()) textValue = list.at(value); + break; + + default: + break; } if (textValue.isEmpty()) @@ -92,7 +156,6 @@ void CSVSettings::RangeView::slotUpdateView (int value) setSelectedValue (textValue, false); View::updateView(); - } void CSVSettings::RangeView::slotUpdateView (double value) @@ -119,6 +182,12 @@ void CSVSettings::RangeView::updateView (bool signalUpdate) const static_cast (mRangeWidget)->setValue (value.toDouble()); break; + case CSMSettings::Type_Slider: + case CSMSettings::Type_Dial: + mRangeWidget->setProperty ("value", value.toInt()); + mRangeWidget->setProperty ("sliderPosition", value.toInt()); + break; + default: break; diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp index 6515c91682..e8d6df88e3 100644 --- a/apps/opencs/view/settings/rangeview.hpp +++ b/apps/opencs/view/settings/rangeview.hpp @@ -13,7 +13,7 @@ namespace CSVSettings { Q_OBJECT - QAbstractSpinBox *mRangeWidget; + QWidget *mRangeWidget; CSMSettings::SettingType mRangeType; public: @@ -23,6 +23,7 @@ namespace CSVSettings protected: void updateView (bool signalUpdate = true) const; + void buildSlider (CSMSettings::Setting *setting); void buildSpinBox (CSMSettings::Setting *setting); private slots: From 3f737bbb44c73fd6833bea73bfadcc05b9eda6fa Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sat, 3 May 2014 22:02:16 -0500 Subject: [PATCH 170/545] implemented QDial into RangeView class --- apps/opencs/model/settings/setting.cpp | 10 ++++++ apps/opencs/model/settings/setting.hpp | 2 ++ apps/opencs/model/settings/usersettings.cpp | 36 +++++++++++++++------ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index fe5a26bbc8..fe15cf7f63 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -95,6 +95,16 @@ QStringList CSMSettings::Setting::property (SettingProperty prop) const return mProperties.at(prop); } +void CSMSettings::Setting::setDefaultValue (int value) +{ + setDefaultValues (QStringList() << QVariant (value).toString()); +} + +void CSMSettings::Setting::setDefaultValue (double value) +{ + setDefaultValues (QStringList() << QVariant (value).toString()); +} + void CSMSettings::Setting::setDefaultValue (const QString &value) { setDefaultValues (QStringList() << value); diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index 8efe330346..cf5dd2a06c 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -45,6 +45,8 @@ namespace CSMSettings void setDefinedValues (QStringList list); QStringList definedValues() const; + void setDefaultValue (int value); + void setDefaultValue (double value); void setDefaultValue (const QString &value); void setDefaultValues (const QStringList &values); diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 787e266506..a8fd752e3e 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -132,28 +132,30 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() //the page name, and the view name /* Setting *masterBoolean = createSetting (Type_RadioButton, section, - "Master Proxy"); + "Master Proxy"); Setting *slaveBoolean = createSetting (Type_CheckBox, section, - "Proxy Checkboxes"); + "Proxy Checkboxes"); Setting *slaveSingleText = createSetting (Type_LineEdit, section, - "Proxy TextBox 1"); + "Proxy TextBox 1"); Setting *slaveMultiText = createSetting (Type_LineEdit, section, - "ProxyTextBox 2"); + "ProxyTextBox 2"); Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section, - "Alpha Spinbox"); + "Alpha Spinbox"); Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section, - "Int Spinbox"); + "Int Spinbox"); Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox, section, "Double Spinbox"); Setting *slaveSlider = createSetting (Type_Slider, section, "Slider"); + Setting *slaveDial = createSetting (Type_Dial, section, "Dial"); + //set declared values for selected views masterBoolean->setDeclaredValues (QStringList() << "Profile One" << "Profile Two" @@ -212,6 +214,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << (QStringList() << "100") ); + masterBoolean->addProxy (slaveDial, QList () + << (QStringList() << "25") + << (QStringList() << "50") + << (QStringList() << "75") + << (QStringList() << "100") + ); + //settings with proxies are not serialized by default //other settings non-serialized for demo purposes slaveBoolean->setSerializable (false); @@ -239,7 +248,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() //slaveAlphaSpinbox->setSuffix ("!"); slaveAlphaSpinbox->setWrapping (true); - slaveIntegerSpinbox->setDefaultValue ("14"); + slaveIntegerSpinbox->setDefaultValue (14); slaveIntegerSpinbox->setMinimum (0); slaveIntegerSpinbox->setMaximum (58); slaveIntegerSpinbox->setPrefix ("$"); @@ -247,16 +256,23 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveIntegerSpinbox->setWidgetWidth (10); slaveIntegerSpinbox->setSpecialValueText ("Nothing!"); - slaveDoubleSpinbox->setDefaultValue ("0.51"); + slaveDoubleSpinbox->setDefaultValue (0.51); slaveDoubleSpinbox->setSingleStep(0.17); slaveDoubleSpinbox->setMaximum(4.0); slaveSlider->setMinimum (0); slaveSlider->setMaximum (100); - slaveSlider->setDefaultValue ("75"); + slaveSlider->setDefaultValue (75); slaveSlider->setWidgetWidth (100); slaveSlider->setTicksAbove (true); - slaveSlider->setTickInterval (25);*/ + slaveSlider->setTickInterval (25); + + slaveDial->setMinimum (0); + slaveDial->setMaximum (100); + slaveDial->setSingleStep (5); + slaveDial->setDefaultValue (75); + slaveDial->setTickInterval (25); +*/ } } From 4a502226e6fc3c4441491fda2d6c9a6be69c5b80 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sun, 4 May 2014 12:30:15 +0200 Subject: [PATCH 171/545] added flag to distingiush widgets --- apps/opencs/view/world/scenesubview.cpp | 25 +++++++++++++++++++++---- apps/opencs/view/world/scenesubview.hpp | 7 ++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 34008c9a8b..36cce9ecd7 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -35,9 +35,12 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); CSVRender::WorldspaceWidget* wordspaceWidget = NULL; + widgetType whatWidget; if (id.getId()=="sys::default") { + whatWidget = widget_Paged; + CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document); wordspaceWidget = newWidget; @@ -46,6 +49,8 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D } else { + whatWidget = widget_Unpaged; + CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); wordspaceWidget = newWidget; @@ -53,7 +58,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D makeConnections(newWidget); } - replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget)); + replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget, whatWidget)); layout->insertLayout (0, mLayout, 1); @@ -90,7 +95,7 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); } -CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget) +CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type) { CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this); @@ -100,6 +105,18 @@ CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldspa SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar); toolbar->addTool (lightingTool); +/* Add buttons specific to the type. For now no need for it. + * + switch (type) + { + case widget_Paged: + break; + + case widget_Unpaged: + break; + + } +*/ return toolbar; } @@ -181,7 +198,7 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI case CSVRender::WorldspaceWidget::needPaged: pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument); - toolbar = makeToolbar(pagedNewWidget); + toolbar = makeToolbar(pagedNewWidget, widget_Paged); makeConnections(pagedNewWidget); replaceToolbarAndWorldspace(pagedNewWidget, toolbar); mScene->handleDrop(data); @@ -189,7 +206,7 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI case CSVRender::WorldspaceWidget::needUnpaged: unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this); - toolbar = makeToolbar(unPagedNewWidget); + toolbar = makeToolbar(unPagedNewWidget, widget_Unpaged); makeConnections(unPagedNewWidget); replaceToolbarAndWorldspace(unPagedNewWidget, toolbar); cellSelectionChanged(*(data.begin())); diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 251ddae1f9..b9ecbe931c 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -61,7 +61,12 @@ namespace CSVWorld void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar); - SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget); + enum widgetType + { + widget_Paged, + widget_Unpaged + }; + SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type); private slots: From a469444e5301d2bbe8b7efc0a3d470cfd2221cc4 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 4 May 2014 08:05:32 -0400 Subject: [PATCH 172/545] Player can't detect self --- apps/openmw/mwmechanics/actors.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 71ccf7ff20..1d3b45b2dc 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -724,7 +724,8 @@ namespace MWMechanics void Actors::updateSneak (const MWWorld::Ptr& ptr) { const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) + if ( player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak) + && ptr != player) { const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); int radius = esmStore.get().find("fSneakUseDist")->getInt(); From f51f826dad20e3d9b9f4798f401950b8a153137c Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sun, 4 May 2014 15:13:03 +0200 Subject: [PATCH 173/545] fixed compilation --- apps/opencs/view/render/pagedworldspacewidget.cpp | 2 +- apps/opencs/view/render/unpagedworldspacewidget.cpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index c9308fbfb4..a3f34d218f 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -3,7 +3,7 @@ #include -#include +#include #include diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index de4dde9ddd..166c85f443 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -3,7 +3,7 @@ #include -#include +#include #include "../../model/doc/document.hpp" diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index c83a5a3e15..59b82bb678 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include "../world/scenetoolmode.hpp" #include From f596b698d96a07ed4916ee056f2d4a8a00884d43 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 4 May 2014 18:15:07 +0400 Subject: [PATCH 174/545] fixes to slow-down at jump startup and infinite air intertia growth --- apps/openmw/mwmechanics/character.cpp | 35 +++++++++++++++------------ apps/openmw/mwworld/physicssystem.cpp | 11 ++++++++- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 8ad2b4a67e..42ed235c57 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1006,7 +1006,16 @@ void CharacterController::update(float duration) bool flying = world->isFlying(mPtr); //Ogre::Vector3 vec = cls.getMovementVector(mPtr); Ogre::Vector3 vec(cls.getMovementSettings(mPtr).mPosition); - vec.normalise(); + if(vec.z > 0.0f) // to avoid slow-down when jumping + { + Ogre::Vector2 vecXY = Ogre::Vector2(vec.x, vec.y); + vecXY.normalise(); + vec.x = vecXY.x; + vec.y = vecXY.y; + } + else + vec.normalise(); + if(mHitState != CharState_None && mJumpState == JumpState_None) vec = Ogre::Vector3(0.0f); Ogre::Vector3 rot = cls.getRotationVector(mPtr); @@ -1107,9 +1116,12 @@ void CharacterController::update(float duration) if(cls.isNpc()) { const NpcStats &stats = cls.getNpcStats(mPtr); - mult = gmst.find("fJumpMoveBase")->getFloat() + + static const float fJumpMoveBase = gmst.find("fJumpMoveBase")->getFloat(); + static const float fJumpMoveMult = gmst.find("fJumpMoveMult")->getFloat(); + + mult = fJumpMoveBase + (stats.getSkill(ESM::Skill::Acrobatics).getModified()/100.0f * - gmst.find("fJumpMoveMult")->getFloat()); + fJumpMoveMult); } vec.x *= mult; @@ -1119,14 +1131,7 @@ void CharacterController::update(float duration) else if(vec.z > 0.0f && mJumpState == JumpState_None) { // Started a jump. - float z = cls.getJump(mPtr); - if(vec.x == 0 && vec.y == 0) - vec = Ogre::Vector3(0.0f, 0.0f, z); - else - { - Ogre::Vector3 lat = Ogre::Vector3(vec.x, vec.y, 0.0f).normalisedCopy(); - vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f; - } + vec.z = cls.getJump(mPtr); // advance acrobatics if (mPtr.getRefData().getHandle() == "player") @@ -1438,14 +1443,14 @@ void CharacterController::updateVisibility() void CharacterController::determineAttackType() { - float * move = mPtr.getClass().getMovementSettings(mPtr).mPosition; + float *move = mPtr.getClass().getMovementSettings(mPtr).mPosition; if(mPtr.getClass().hasInventoryStore(mPtr)) { - if (move[0] && !move[1]) //sideway - mAttackType = "slash"; - else if (move[1]) //forward + if (move[1]) // forward-backward mAttackType = "thrust"; + else if (move[0]) //sideway + mAttackType = "slash"; else mAttackType = "chop"; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 247c0d4bdf..5b85e203c9 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -246,6 +246,15 @@ namespace MWWorld // If falling, add part of the incoming velocity with the current inertia // TODO: but we could be jumping up? velocity = velocity * time + physicActor->getInertialForce(); + + // avoid getting infinite inertia in air + float actorSpeed = ptr.getClass().getSpeed(ptr); + float speedXY = Ogre::Vector2(velocity.x, velocity.y).length(); + if (speedXY > actorSpeed) + { + velocity.x *= actorSpeed / speedXY; + velocity.y *= actorSpeed / speedXY; + } } inertia = velocity; // NOTE: velocity is for z axis only in this code block @@ -314,7 +323,7 @@ namespace MWWorld if(stepMove(colobj, newPosition, velocity, remainingTime, engine)) { // don't let pure water creatures move out of water after stepMove - if((ptr.getClass().canSwim(ptr) && !ptr.getClass().canWalk(ptr)) + if((ptr.getClass().canSwim(ptr) && !canWalk) && newPosition.z > (waterlevel - halfExtents.z * 0.5)) newPosition = oldPosition; else // Only on the ground if there's gravity From 7d5dab214c4a9911f8d1f1e3ea12de80c3eabce5 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 4 May 2014 16:20:09 -0400 Subject: [PATCH 175/545] #58 - Sneak Skill: functional sneaking Removed sneak checking from individual actor update. Added sneak checking to Actors::update() --- apps/openmw/mwmechanics/actors.cpp | 68 ++++++++++++++++-------------- apps/openmw/mwmechanics/actors.hpp | 2 - apps/openmw/mwworld/player.cpp | 3 -- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index bf02a8c307..3693d70b01 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -226,7 +226,6 @@ namespace MWMechanics updateDrowning(ptr, duration); calculateNpcStatModifiers(ptr); updateEquippedLight(ptr, duration); - updateSneak(ptr); } } @@ -711,27 +710,6 @@ namespace MWMechanics } } - void Actors::updateSneak (const MWWorld::Ptr& ptr) - { - const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if ( player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak) - && ptr != player) - { - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - int radius = esmStore.get().find("fSneakUseDist")->getInt(); - bool seen = false; - - // am I close enough and can I see the player? - if ( (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius) - && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr) - && MWBase::Environment::get().getWorld()->getLOS(player, ptr)) - - seen = true; - - MWBase::Environment::get().getWindowManager()->setSneakVisibility(seen); - } - } - void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -872,12 +850,12 @@ namespace MWMechanics } // AI and magic effects update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); - if(iter->first.getTypeName() == typeid(ESM::NPC).name()) + if (iter->first.getTypeName() == typeid(ESM::NPC).name()) updateNpc(iter->first, duration, paused); } } @@ -887,11 +865,11 @@ namespace MWMechanics // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), // so updating VFX immediately after that would just remove the particle effects instantly. // There needs to be a magic effect update in between. - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) iter->second->updateContinuousVfx(); // Animation/movement update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).mMagnitude > 0) @@ -900,7 +878,7 @@ namespace MWMechanics } // Kill dead actors, update some variables - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); @@ -908,7 +886,7 @@ namespace MWMechanics //KnockedOutOneFrameLogic //Used for "OnKnockedOut" command //Put here to ensure that it's run for PRECISELY one frame. - if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary + if (stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary stats.setKnockedDownOneFrame(true); } else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe @@ -926,7 +904,7 @@ namespace MWMechanics } // If it's the player and God Mode is turned on, keep it alive - if(iter->first.getRefData().getHandle()=="player" && + if (iter->first.getRefData().getHandle()=="player" && MWBase::Environment::get().getWorld()->getGodModeState()) { MWMechanics::DynamicStat stat (stats.getHealth()); @@ -942,7 +920,7 @@ namespace MWMechanics // Make sure spell effects with CasterLinked flag are removed // TODO: would be nice not to do this all the time... - for(PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) + for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) { MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); spells.purge(iter->first.getRefData().getHandle()); @@ -967,10 +945,38 @@ namespace MWMechanics stats.setMagicEffects(MWMechanics::MagicEffects()); calculateCreatureStatModifiers(iter->first, 0); - if(cls.isEssential(iter->first)) + if (cls.isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } } + + // if player is in sneak state see if anyone detects him + const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) + { + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + const int radius = esmStore.get().find("fSneakUseDist")->getInt(); + bool detected = false; + + for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + { + if (iter->first == player) // not the player + continue; + + // is the player in range and can they be detected + if ( (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius) + && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first) + && MWBase::Environment::get().getWorld()->getLOS(player, iter->first)) + { + detected = true; + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + break; + } + } + + if (!detected) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + } } } void Actors::restoreDynamicStats(bool sleep) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index ddd7a47d30..f7dff1058b 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -44,8 +44,6 @@ namespace MWMechanics void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration); - void updateSneak (const MWWorld::Ptr& ptr); - public: Actors(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 1ad43e360c..1f994d013d 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -131,9 +131,6 @@ namespace MWWorld { MWWorld::Ptr ptr = getPlayer(); ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - - if(!sneak) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } void Player::yaw(float yaw) From 78f76842a6a413a96245d9fe1f1812005cb5ff07 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 4 May 2014 16:56:30 -0400 Subject: [PATCH 176/545] Added else statement Its still dodgy though --- apps/openmw/mwmechanics/actors.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3693d70b01..8f6ac52742 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -976,6 +976,8 @@ namespace MWMechanics if (!detected) MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + else + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } } } From d4812c3af988dabe189576c24dff212fc960c733 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sun, 4 May 2014 17:54:33 -0400 Subject: [PATCH 177/545] fixed placement of else statement --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8f6ac52742..4f291c36ec 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -976,9 +976,9 @@ namespace MWMechanics if (!detected) MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); - else - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } + else + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } } void Actors::restoreDynamicStats(bool sleep) From 475214ab627f4a77d6e73566799fc0bb3e32de62 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Mon, 5 May 2014 05:56:03 -0500 Subject: [PATCH 178/545] Implmented QSettings for loading / saving file definitions. Also renamed opencs.cfg to opencs.ini to follow Ini format standards --- CMakeLists.txt | 2 +- apps/opencs/editor.cpp | 2 +- apps/opencs/model/settings/setting.cpp | 4 +- apps/opencs/model/settings/settingmanager.cpp | 232 ++---------------- apps/opencs/model/settings/settingmanager.hpp | 21 +- apps/opencs/model/settings/usersettings.cpp | 52 ++-- apps/opencs/model/settings/usersettings.hpp | 3 + apps/opencs/view/settings/settingwindow.cpp | 2 +- apps/opencs/view/settings/view.cpp | 2 +- apps/opencs/view/settings/view.hpp | 2 + files/{opencs.cfg => opencs.conf} | 0 11 files changed, 63 insertions(+), 259 deletions(-) rename files/{opencs.cfg => opencs.conf} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd45a207c9..3d59236473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -368,7 +368,7 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg.install") -configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg +configure_file(${OpenMW_SOURCE_DIR}/files/opencs.conf "${OpenMW_BINARY_DIR}/opencs.cfg") configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index f6370ac51f..480e91e301 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -27,7 +27,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) setupDataFiles (config.first); - CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); + CSMSettings::UserSettings::instance().loadSettings ("opencs.ini"); mSettings.setModel (CSMSettings::UserSettings::instance()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index fe15cf7f63..2ef829f865 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -45,7 +45,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting, foreach (const QString &val, vals) list << (QStringList() << val); - mProxies [setting->page() + '.' + setting->name()] = list; + mProxies [setting->page() + '/' + setting->name()] = list; } void CSMSettings::Setting::addProxy (const Setting *setting, @@ -54,7 +54,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting, if (serializable()) setProperty (Property_Serializable, false); - mProxies [setting->page() + '.' + setting->name()] = list; + mProxies [setting->page() + '/' + setting->name()] = list; } void CSMSettings::Setting::setColumnSpan (int value) diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index 36ca1ae03a..e48dd6e26e 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "setting.hpp" #include "settingmanager.hpp" @@ -20,15 +21,6 @@ CSMSettings::SettingManager::SettingManager(QObject *parent) : } -void CSMSettings::SettingManager::dumpModel() -{ - foreach (Setting *setting, mSettings) - { - if (setting->proxyLists().isEmpty()) - continue; - } -} - CSMSettings::Setting *CSMSettings::SettingManager::createSetting (CSMSettings::SettingType typ, const QString &page, const QString &name) { @@ -36,7 +28,7 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting if (findSetting (page, name)) { qWarning() << "Duplicate declaration encountered: " - << (name + '.' + page); + << (name + '/' + page); return 0; } @@ -49,182 +41,6 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting return setting; } -CSMSettings::DefinitionPageMap - CSMSettings::SettingManager::readFilestream (QTextStream *stream) -{ - //regEx's for page names and keys / values - QRegExp pageRegEx ("^\\[([^]]+)\\]"); - QRegExp keyRegEx ("^([^=]+)\\s*=\\s*(.+)$"); - - QString currPage = "Unassigned"; - - DefinitionPageMap pageMap; - - if (!stream) - { - displayFileErrorMessage(mReadWriteMessage, false); - return pageMap; - } - - if (stream->atEnd()) - return pageMap; - - DefinitionMap *settingMap = new DefinitionMap(); - pageMap[currPage] = settingMap; - - while (!stream->atEnd()) - { - QString line = stream->readLine().simplified(); - - if (line.isEmpty() || line.startsWith("#")) - continue; - - //page name found - if (pageRegEx.exactMatch(line)) - { - currPage = pageRegEx.cap(1).simplified().trimmed(); - settingMap = new DefinitionMap(); - pageMap[currPage] = settingMap; - continue; - } - - //setting definition found - if ( (keyRegEx.indexIn(line) != -1)) - { - QString settingName = keyRegEx.cap(1).simplified(); - QString settingValue = keyRegEx.cap(2).simplified(); - - if (!settingMap->contains (settingName)) - settingMap->insert (settingName, new QStringList()); - - settingMap->value(settingName)->append(settingValue); - } - } - - //return empty map if no settings were ever added to - if (pageMap.size() == 1) - { - QString pageKey = pageMap.keys().at(0); - if (pageMap[pageKey]->size() == 0) - pageMap.clear(); - } - - return pageMap; -} - -bool CSMSettings::SettingManager::writeFilestream(QTextStream *stream, - const QMap &settingListMap) -{ - if (!stream) - { - displayFileErrorMessage(mReadWriteMessage, false); - return false; - } - //disabled after rolling selector class into view. Need to - //iterate views to get setting definitions before writing to file - - QStringList sectionKeys; - - foreach (const QString &key, settingListMap.keys()) - { - QStringList names = key.split('.'); - QString section = names.at(0); - - if (!sectionKeys.contains(section)) - if (!settingListMap.value(key).isEmpty()) - sectionKeys.append (section); - } - - foreach (const QString §ion, sectionKeys) - { - *stream << '[' << section << "]\n"; - foreach (const QString &key, settingListMap.keys()) - { - QStringList names = key.split('.'); - - if (names.at(0) != section) - continue; - - QStringList list = settingListMap.value(key); - - if (list.isEmpty()) - continue; - - QString name = names.at(1); - - foreach (const QString value, list) - { - if (value.isEmpty()) - continue; - - *stream << name << " = " << value << '\n'; - } - } - } - - destroyStream (stream); - return true; -} - -void CSMSettings::SettingManager::mergeSettings(DefinitionPageMap &destMap, DefinitionPageMap &srcMap) -{ - if (srcMap.isEmpty()) - return; - - foreach (const QString &pageKey, srcMap.keys()) - { - DefinitionMap *srcSetting = srcMap.value(pageKey); - //Unique Page: - //insertfrom the source map - if (!destMap.keys().contains (pageKey)) - { - destMap.insert (pageKey, srcSetting); - continue; - } - - DefinitionMap *destSetting = destMap.value(pageKey); - - //Duplicate Page: - //iterate the settings in the source and check for duplicates in the - //destination - foreach (const QString &srcKey, srcSetting->keys()) - { - //insert into destination if unique - if (!destSetting->keys().contains (srcKey)) - destSetting->insert(srcKey, srcSetting->value (srcKey)); - } - } -} - -QTextStream *CSMSettings::SettingManager::openFilestream (const QString &filePath, - bool isReadOnly) const -{ - QIODevice::OpenMode openFlags = QIODevice::Text; - - if (isReadOnly) - openFlags = QIODevice::ReadOnly | openFlags; - else - openFlags = QIODevice::ReadWrite | QIODevice::Truncate | openFlags; - - QFile *file = new QFile(filePath); - QTextStream *stream = 0; - - if (file->open(openFlags)) - stream = new QTextStream(file); - - if (stream) - stream->setCodec(QTextCodec::codecForName("UTF-8")); - - return stream; -} - -void CSMSettings::SettingManager::destroyStream(QTextStream *stream) const -{ - stream->device()->close(); - - delete stream; -} - void CSMSettings::SettingManager::displayFileErrorMessage(const QString &message, bool isReadOnly) const { @@ -242,29 +58,29 @@ void CSMSettings::SettingManager::displayFileErrorMessage(const QString &message msgBox.exec(); } -void CSMSettings::SettingManager::addDefinitions (DefinitionPageMap &pageMap) +void CSMSettings::SettingManager::addDefinitions (const QSettings *settings) { - foreach (QString pageName, pageMap.keys()) + foreach (const QString &key, settings->allKeys()) { - DefinitionMap *settingMap = pageMap.value (pageName); + QStringList names = key.split('/'); - foreach (QString settingName, (*settingMap).keys()) + Setting *setting = findSetting (names.at(0), names.at(1)); + + if (!setting) { - QStringList *values = settingMap->value (settingName); - Setting *setting = findSetting (pageName, settingName); - - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << pageName << "." << settingName; - continue; - } - - if (values->size() == 0) - values->append (setting->defaultValues()); - - setting->setDefinedValues (*values); + qWarning() << "Found definitions for undeclared setting " + << names.at(0) << "." << names.at(1); + continue; } + + QStringList values = settings->value (key).toStringList(); + + if (values.isEmpty()) + values.append (setting->defaultValues()); + + setting->setDefinedValues (values); + + qDebug() << "added definitons " << values; } } @@ -297,7 +113,7 @@ CSMSettings::Setting *CSMSettings::SettingManager::findSetting { foreach (Setting *setting, mSettings) { - if (setting->name() == settingName) + if (settingName.isEmpty() || (setting->name() == settingName)) { if (setting->page() == pageName) return setting; @@ -305,7 +121,7 @@ CSMSettings::Setting *CSMSettings::SettingManager::findSetting } return 0; } - +/* QList CSMSettings::SettingManager::findSettings (const QString &pageName) { @@ -318,7 +134,7 @@ QList CSMSettings::SettingManager::findSettings } return settings; } - +*/ CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const { SettingPageMap pageMap; @@ -332,7 +148,7 @@ CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, const QStringList &list) { - QStringList names = settingKey.split('.'); + QStringList names = settingKey.split('/'); Setting *setting = findSetting (names.at(0), names.at(1)); diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp index 2efc2929f8..9342c66e43 100644 --- a/apps/opencs/model/settings/settingmanager.hpp +++ b/apps/opencs/model/settings/settingmanager.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "support.hpp" #include "setting.hpp" @@ -30,7 +31,7 @@ namespace CSMSettings ///retrieve a setting object from a given page and setting name Setting *findSetting - (const QString &pageName, const QString &settingName); + (const QString &pageName, const QString &settingName = QString()); ///retrieve all settings for a specified page QList findSettings (const QString &pageName); @@ -49,28 +50,12 @@ namespace CSMSettings const QString &page, const QString &name); ///add definitions to the settings specified in the page map - void addDefinitions (DefinitionPageMap &pageMap); - - ///read setting definitions from file - DefinitionPageMap readFilestream(QTextStream *stream); - - ///write setting definitions to file - bool writeFilestream (QTextStream *stream, - const QMap &settingMap); - - ///merge PageMaps of settings when loading from multiple files - void mergeSettings (DefinitionPageMap &destMap, DefinitionPageMap &srcMap); - - QTextStream *openFilestream (const QString &filePath, - bool isReadOnly) const; - - void destroyStream(QTextStream *stream) const; + void addDefinitions (const QSettings *settings); void displayFileErrorMessage(const QString &message, bool isReadOnly) const; QList settings() const { return mSettings; } - void dumpModel(); signals: diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index a8fd752e3e..bd24b7df04 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,7 @@ #include "setting.hpp" #include "support.hpp" +#include /** * Workaround for problems with whitespaces in paths in older versions of Boost library @@ -40,6 +42,8 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; + mSettings = 0; + buildSettingModelDefaults(); } @@ -293,16 +297,16 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) (mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8(); //open user and global streams - QTextStream *userStream = openFilestream (mUserFilePath, true); - QTextStream *otherStream = openFilestream (global, true); + //QTextStream *userStream = openFilestream (mUserFilePath, true); + // QTextStream *otherStream = openFilestream (global, true); //failed stream, try for local - if (!otherStream) - otherStream = openFilestream (local, true); + // if (!otherStream) + // otherStream = openFilestream (local, true); //error condition - notify and return - if (!otherStream || !userStream) - { + // if (!otherStream || !userStream) + /* { QString message = QObject::tr("
An error was encountered loading \ user settings files.

One or several files could not \ be read. This may be caused by a missing configuration file, \ @@ -316,40 +320,34 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) displayFileErrorMessage ( message, true); return; } +*/ + //QSETTINGS TEST + qDebug() << mCfgMgr.getUserConfigPath().string().c_str() << ',' << mCfgMgr.getGlobalPath().string().c_str(); - //success condition - merge the two streams into a single map and save - DefinitionPageMap totalMap = readFilestream (userStream); - DefinitionPageMap otherMap = readFilestream(otherStream); + QSettings::setPath (QSettings::IniFormat, QSettings::UserScope, mCfgMgr.getUserConfigPath().string().c_str()); + QSettings::setPath (QSettings::IniFormat, QSettings::SystemScope, mCfgMgr.getGlobalPath().string().c_str()); - //merging other settings file in and ignore duplicate settings to - //avoid overwriting user-level settings - mergeSettings (totalMap, otherMap); + if (mSettings) + delete mSettings; - if (!totalMap.isEmpty()) - addDefinitions (totalMap); + mSettings = new QSettings + (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); + + addDefinitions (mSettings); } void CSMSettings::UserSettings::saveSettings (const QMap &settingMap) { - for (int i = 0; i < settings().size(); i++) - { - Setting* setting = settings().at(i); + foreach (const QString &key, settingMap.keys()) + mSettings->setValue (key, settingMap.value (key)); - QString key = setting->page() + '.' + setting->name(); - - if (!settingMap.keys().contains(key)) - continue; - - setting->setDefinedValues (settingMap.value(key)); - } - - writeFilestream (openFilestream (mUserFilePath, false), settingMap); + delete mSettings; } QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { - QStringList names = settingKey.split('.'); + QStringList names = settingKey.split('/'); Setting *setting = findSetting(names.at(0), names.at(1)); diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index f0ed7af41a..ade14c50c5 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -18,6 +18,7 @@ namespace Files { typedef std::vector PathContainer; struct ConfigurationManager;} class QFile; +class QSettings; namespace CSMSettings { @@ -32,6 +33,8 @@ namespace CSMSettings { QString mReadOnlyMessage; QString mReadWriteMessage; + QSettings *mSettings; + public: diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index 7bd0b228e4..aeb652b3b4 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -57,7 +57,7 @@ void CSVSettings::SettingWindow::createConnections foreach (const QString &key, proxyMap.keys()) { - QStringList keyPair = key.split('.'); + QStringList keyPair = key.split('/'); if (keyPair.size() != 2) continue; diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 2a70152c2d..9e595478d7 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -14,7 +14,7 @@ CSVSettings::View::View(CSMSettings::Setting *setting, : mDataModel(0), mParentPage (parent), mHasFixedValues (!setting->declaredValues().isEmpty()), mIsMultiValue (setting->isMultiValue()), - mViewKey (setting->page() + '.' + setting->name()), + mViewKey (setting->page() + '/' + setting->name()), mSerializable (setting->serializable()), Frame(true, setting->name(), parent) { diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp index 23357e45fb..4f3af9ae58 100644 --- a/apps/opencs/view/settings/view.hpp +++ b/apps/opencs/view/settings/view.hpp @@ -42,8 +42,10 @@ namespace CSVSettings ///State indicating whether the view will allow multiple values bool mIsMultiValue; + ///'pagename.settingname' form of the view's id QString mViewKey; + ///indicates whether or not the setting is written to file bool mSerializable; public: diff --git a/files/opencs.cfg b/files/opencs.conf similarity index 100% rename from files/opencs.cfg rename to files/opencs.conf From 74fa115d205b320f2d259efcd5bc54416bc18153 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Mon, 5 May 2014 06:07:41 -0500 Subject: [PATCH 179/545] fixed check for missing ini files --- apps/opencs/model/settings/settingmanager.cpp | 7 +-- apps/opencs/model/settings/usersettings.cpp | 44 ++++++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index e48dd6e26e..afb80c2069 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -21,6 +21,7 @@ CSMSettings::SettingManager::SettingManager(QObject *parent) : } + CSMSettings::Setting *CSMSettings::SettingManager::createSetting (CSMSettings::SettingType typ, const QString &page, const QString &name) { @@ -113,7 +114,7 @@ CSMSettings::Setting *CSMSettings::SettingManager::findSetting { foreach (Setting *setting, mSettings) { - if (settingName.isEmpty() || (setting->name() == settingName)) + if (setting->name() == settingName) { if (setting->page() == pageName) return setting; @@ -121,7 +122,7 @@ CSMSettings::Setting *CSMSettings::SettingManager::findSetting } return 0; } -/* + QList CSMSettings::SettingManager::findSettings (const QString &pageName) { @@ -134,7 +135,7 @@ QList CSMSettings::SettingManager::findSettings } return settings; } -*/ + CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const { SettingPageMap pageMap; diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index bd24b7df04..7764cc2c28 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -288,44 +288,48 @@ CSMSettings::UserSettings::~UserSettings() void CSMSettings::UserSettings::loadSettings (const QString &fileName) { mUserFilePath = QString::fromUtf8 - (mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8(); + (mCfgMgr.getUserConfigPath().string().c_str()); - QString global = QString::fromUtf8 - (mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8(); + QString globalFilePath = QString::fromUtf8 + (mCfgMgr.getGlobalPath().string().c_str()); - QString local = QString::fromUtf8 - (mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8(); + QString localFilePath = QString::fromUtf8 + (mCfgMgr.getLocalPath().string().c_str()); - //open user and global streams - //QTextStream *userStream = openFilestream (mUserFilePath, true); - // QTextStream *otherStream = openFilestream (global, true); + bool isUser = QFile (mUserFilePath + fileName).exists(); + bool isSystem = QFile (globalFilePath + fileName).exists(); - //failed stream, try for local - // if (!otherStream) - // otherStream = openFilestream (local, true); + QString otherFilePath = globalFilePath; + + //test for local only if global fails (uninstalled copy) + if (!isSystem) + { + isSystem = QFile (localFilePath + fileName).exists(); + otherFilePath = localFilePath; + } //error condition - notify and return - // if (!otherStream || !userStream) - /* { + if (!isUser || !isSystem) + { QString message = QObject::tr("
An error was encountered loading \ user settings files.

One or several files could not \ be read. This may be caused by a missing configuration file, \ incorrect file permissions or a corrupted installation of \ OpenCS.
"); - message += QObject::tr("
Global filepath: ") + global; - message += QObject::tr("
Local filepath: ") + local; + message += QObject::tr("
Global filepath: ") + globalFilePath; + message += QObject::tr("
Local filepath: ") + localFilePath; message += QObject::tr("
User filepath: ") + mUserFilePath; displayFileErrorMessage ( message, true); return; } -*/ - //QSETTINGS TEST - qDebug() << mCfgMgr.getUserConfigPath().string().c_str() << ',' << mCfgMgr.getGlobalPath().string().c_str(); - QSettings::setPath (QSettings::IniFormat, QSettings::UserScope, mCfgMgr.getUserConfigPath().string().c_str()); - QSettings::setPath (QSettings::IniFormat, QSettings::SystemScope, mCfgMgr.getGlobalPath().string().c_str()); + QSettings::setPath + (QSettings::IniFormat, QSettings::UserScope, mUserFilePath); + + QSettings::setPath + (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); if (mSettings) delete mSettings; From 5cba828cc9e496d00f547c6e4475b7d1b8c5e910 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Mon, 5 May 2014 06:26:00 -0500 Subject: [PATCH 180/545] Removed unneeded code from setting manager. Moved some code to user settings --- apps/opencs/model/settings/settingmanager.cpp | 68 +------------------ apps/opencs/model/settings/settingmanager.hpp | 14 ---- apps/opencs/model/settings/usersettings.cpp | 56 ++++++++++----- apps/opencs/model/settings/usersettings.hpp | 9 ++- 4 files changed, 45 insertions(+), 102 deletions(-) diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp index afb80c2069..b0e5cba98f 100644 --- a/apps/opencs/model/settings/settingmanager.cpp +++ b/apps/opencs/model/settings/settingmanager.cpp @@ -10,17 +10,7 @@ CSMSettings::SettingManager::SettingManager(QObject *parent) : QObject(parent) -{ - mReadWriteMessage = QObject::tr("
Could not open or create file for \ - writing

Please make sure you have the right\ - permissions and try again.
"); - - mReadOnlyMessage = QObject::tr("
Could not open file for \ - reading

Please make sure you have the \ - right permissions and try again.
"); - -} - +{} CSMSettings::Setting *CSMSettings::SettingManager::createSetting (CSMSettings::SettingType typ, const QString &page, const QString &name) @@ -42,23 +32,6 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting return setting; } -void CSMSettings::SettingManager::displayFileErrorMessage(const QString &message, - bool isReadOnly) const -{ - // File cannot be opened or created - QMessageBox msgBox; - msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - - if (!isReadOnly) - msgBox.setText (mReadWriteMessage + message); - else - msgBox.setText (message); - - msgBox.exec(); -} - void CSMSettings::SettingManager::addDefinitions (const QSettings *settings) { foreach (const QString &key, settings->allKeys()) @@ -80,35 +53,9 @@ void CSMSettings::SettingManager::addDefinitions (const QSettings *settings) values.append (setting->defaultValues()); setting->setDefinedValues (values); - - qDebug() << "added definitons " << values; } } -QList CSMSettings::SettingManager::findSettings - (const QStringList &list) -{ - QList settings; - - foreach (const QString &value, list) - { - QStringList names = value.split(".", QString::SkipEmptyParts); - - if (names.size() != 2) - continue; - - Setting *setting = findSetting (names.at(0), names.at(1)); - - if (!setting) - continue; - - settings.append (setting); - } - - return settings; -} - - CSMSettings::Setting *CSMSettings::SettingManager::findSetting (const QString &pageName, const QString &settingName) { @@ -123,19 +70,6 @@ CSMSettings::Setting *CSMSettings::SettingManager::findSetting return 0; } -QList CSMSettings::SettingManager::findSettings - (const QString &pageName) -{ - QList settings; - - foreach (Setting *setting, mSettings) - { - if (setting->page() == pageName) - settings.append (setting); - } - return settings; -} - CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const { SettingPageMap pageMap; diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp index 9342c66e43..95f55106e2 100644 --- a/apps/opencs/model/settings/settingmanager.hpp +++ b/apps/opencs/model/settings/settingmanager.hpp @@ -22,8 +22,6 @@ namespace CSMSettings { Q_OBJECT - QString mReadOnlyMessage; - QString mReadWriteMessage; QList mSettings; public: @@ -33,13 +31,6 @@ namespace CSMSettings Setting *findSetting (const QString &pageName, const QString &settingName = QString()); - ///retrieve all settings for a specified page - QList findSettings (const QString &pageName); - - ///retrieve all settings named in the attached list. - ///Setting names are specified in "PageName.SettingName" format. - QList findSettings (const QStringList &list); - ///Retreive a map of the settings, keyed by page name SettingPageMap settingPageMap() const; @@ -52,11 +43,6 @@ namespace CSMSettings ///add definitions to the settings specified in the page map void addDefinitions (const QSettings *settings); - void displayFileErrorMessage(const QString &message, - bool isReadOnly) const; - - QList settings() const { return mSettings; } - signals: void userSettingUpdated (const QString &, const QStringList &); diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 7764cc2c28..178104982a 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -44,6 +44,14 @@ CSMSettings::UserSettings::UserSettings() mSettings = 0; + mReadWriteMessage = QObject::tr("
Could not open or create file for \ + writing

Please make sure you have the right\ + permissions and try again.
"); + + mReadOnlyMessage = QObject::tr("
Could not open file for \ + reading

Please make sure you have the \ + right permissions and try again.
"); + buildSettingModelDefaults(); } @@ -131,10 +139,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * proxy slave settings, but must match any declared values the proxy * slave has, if any. *******************************************************************/ - +/* //create setting objects, specifying the basic widget type, //the page name, and the view name -/* + Setting *masterBoolean = createSetting (Type_RadioButton, section, "Master Proxy"); @@ -234,6 +242,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveIntegerSpinbox->setSerializable (false); slaveDoubleSpinbox->setSerializable (false); slaveSlider->setSerializable (false); + slaveDial->setSerializable (false); slaveBoolean->setDefaultValues (QStringList() << "One" << "Three" << "Five"); @@ -285,9 +294,34 @@ CSMSettings::UserSettings::~UserSettings() mUserSettingsInstance = 0; } +void CSMSettings::UserSettings::displayFileErrorMessage + (const QString &userpath, + const QString &globalpath, + const QString &localpath) const +{ + QString message = QObject::tr("
An error was encountered loading \ + user settings files.

One or several files could not \ + be read. This may be caused by a missing configuration file, \ + incorrect file permissions or a corrupted installation of \ + OpenCS.
"); + + message += QObject::tr("
Global filepath: ") + globalpath; + message += QObject::tr("
Local filepath: ") + localpath; + message += QObject::tr("
User filepath: ") + userpath; + + QMessageBox msgBox; + + msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + + msgBox.setText (mReadWriteMessage + message); + msgBox.exec(); +} + void CSMSettings::UserSettings::loadSettings (const QString &fileName) { - mUserFilePath = QString::fromUtf8 + QString userFilePath = QString::fromUtf8 (mCfgMgr.getUserConfigPath().string().c_str()); QString globalFilePath = QString::fromUtf8 @@ -296,7 +330,7 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) QString localFilePath = QString::fromUtf8 (mCfgMgr.getLocalPath().string().c_str()); - bool isUser = QFile (mUserFilePath + fileName).exists(); + bool isUser = QFile (userFilePath + fileName).exists(); bool isSystem = QFile (globalFilePath + fileName).exists(); QString otherFilePath = globalFilePath; @@ -311,22 +345,12 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) //error condition - notify and return if (!isUser || !isSystem) { - QString message = QObject::tr("
An error was encountered loading \ - user settings files.

One or several files could not \ - be read. This may be caused by a missing configuration file, \ - incorrect file permissions or a corrupted installation of \ - OpenCS.
"); - - message += QObject::tr("
Global filepath: ") + globalFilePath; - message += QObject::tr("
Local filepath: ") + localFilePath; - message += QObject::tr("
User filepath: ") + mUserFilePath; - - displayFileErrorMessage ( message, true); + displayFileErrorMessage (userFilePath, globalFilePath, localFilePath); return; } QSettings::setPath - (QSettings::IniFormat, QSettings::UserScope, mUserFilePath); + (QSettings::IniFormat, QSettings::UserScope, userFilePath); QSettings::setPath (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index ade14c50c5..826bb6d6b5 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -28,14 +28,12 @@ namespace CSMSettings { Q_OBJECT static UserSettings *mUserSettingsInstance; - QString mUserFilePath; Files::ConfigurationManager mCfgMgr; QString mReadOnlyMessage; QString mReadWriteMessage; QSettings *mSettings; - public: /// Singleton implementation @@ -47,9 +45,6 @@ namespace CSMSettings { UserSettings (UserSettings const &); //not implemented void operator= (UserSettings const &); //not implemented - /// Writes settings to the last loaded settings file - bool writeSettings(); - /// Retrieves the settings file at all three levels (global, local and user). void loadSettings (const QString &fileName); @@ -61,6 +56,10 @@ namespace CSMSettings { private: void buildSettingModelDefaults(); + void displayFileErrorMessage(const QString &userpath, + const QString &globalpath, + const QString &localpath) const; + }; } #endif // USERSETTINGS_HPP From 536fc5e1928f00329a55e61e74a8affcdc46ba24 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 4 May 2014 18:25:41 +0200 Subject: [PATCH 181/545] Fix autosaves --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index d2a31e8d15..6a15c8e33e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1447,7 +1447,7 @@ namespace MWGui { return !MyGUI::InputManager::getInstance().isModalAny() // TODO: remove this, once we have properly serialized the state of open windows - && (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu)); + && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest || getMode() == GM_RestBed))); } void WindowManager::playVideo(const std::string &name, bool allowSkipping) From d4492b56dbe106d824a902d2a37a568a6919c1b9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 5 May 2014 23:52:09 +0200 Subject: [PATCH 182/545] Added header file missing from CMakeLists --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 89e40c9b19..7a52831251 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,7 +48,7 @@ add_openmw_dir (mwscript ) add_openmw_dir (mwsound - soundmanagerimp openal_output ffmpeg_decoder + soundmanagerimp openal_output ffmpeg_decoder sound ) add_openmw_dir (mwworld From dd9117809de91d32ca49a9aacf2a44c27b590089 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 6 May 2014 00:13:31 +0200 Subject: [PATCH 183/545] Say an attack phrase when combat starts Move combat start to a helper method Added some todo comments --- apps/openmw/mwbase/mechanicsmanager.hpp | 3 +++ apps/openmw/mwmechanics/actors.cpp | 14 ++++++++------ apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 10 ++++++++++ apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 3 +++ apps/openmw/mwscript/aiextensions.cpp | 9 ++------- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index d5f9e30cd7..f31241bdb4 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -96,6 +96,9 @@ namespace MWBase /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0; + /// Makes \a ptr fight \a target. Also shouts a combat taunt. + virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0; + enum OffenseType { OT_Theft, // Taking items owned by an NPC or a faction you are not a member of diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index bf02a8c307..c3957f72f2 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -206,8 +206,7 @@ namespace MWMechanics if (LOS) { - creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr); - creatureStats.setHostile(true); + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); } } } @@ -784,15 +783,16 @@ namespace MWMechanics if (ptr.getClass().isClass(ptr, "Guard")) creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); else - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); + { + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); + } } } // if I didn't report a crime was I attacked? + // TODO: this is incorrect, getAttacked also triggers if attacked by other non-player actors. else if (creatureStats.getAttacked() && !creatureStats.isHostile()) { - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); } } } @@ -1073,6 +1073,8 @@ namespace MWMechanics if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) { MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); + // TODO: This is wrong! It's comparing Ref IDs with Ogre handles. The only case where this (coincidentally) works is the player. + // possibly applies to other code using getTargetId. if(package->getTargetId() == actor.getCellRef().mRefID) list.push_front(*iter); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 396e710bed..e69f39a194 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -13,6 +13,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" +#include "../mwmechanics/aicombat.hpp" + #include #include "spellcasting.hpp" @@ -1007,6 +1009,14 @@ namespace MWMechanics return (roll >= target); } + void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) + { + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); + if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) + ptr.getClass().getCreatureStats(ptr).setHostile(true); + } + void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) { mActors.getObjectsInRange(position, radius, objects); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 1c9bab25ed..dcd12ee140 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -105,6 +105,9 @@ namespace MWMechanics /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer); + /// Makes \a ptr fight \a target. Also shouts a combat taunt. + virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target); + /** * @brief Commit a crime. If any actors witness the crime and report it, * reportCrime will be called automatically. diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 43da111bf4..e53b53e58f 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -16,7 +16,6 @@ #include "../mwmechanics/aifollow.hpp" #include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/aiwander.hpp" -#include "../mwmechanics/aicombat.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -435,12 +434,8 @@ namespace MWScript std::string targetID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); - - - creatureStats.setHostile(true); - creatureStats.getAiSequence().stack( - MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(targetID, true); + MWBase::Environment::get().getMechanicsManager()->startCombat(actor, target); } }; From 492620c8cf0f4436d31f46061bd6f37c82391b91 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 6 May 2014 09:39:39 +0200 Subject: [PATCH 184/545] handle exceptions thrown during loading and report them to the user --- apps/opencs/model/doc/documentmanager.cpp | 8 +-- apps/opencs/model/doc/documentmanager.hpp | 8 +-- apps/opencs/view/doc/loader.cpp | 63 +++++++++++++++++------ apps/opencs/view/doc/loader.hpp | 12 +++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++ 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index d44da15c5c..fe6aaef279 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -59,7 +59,7 @@ void CSMDoc::DocumentManager::addDocument (const std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); @@ -86,6 +86,8 @@ void CSMDoc::DocumentManager::documentLoaded (Document *document) void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error) { -// emit loadingStopped (document, false, error); - removeDocument (document); + emit loadingStopped (document, false, error); + + if (error.empty()) // do not remove the document yet, if we have an error + removeDocument (document); } \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index d834d85d47..de4a5e94be 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -43,9 +43,6 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. - void removeDocument (Document *document); - ///< Emits the lastDocumentDeleted signal, if applicable. - void setResourceDir (const boost::filesystem::path& parResDir); private: @@ -61,6 +58,11 @@ namespace CSMDoc ///< Document load has been interrupted either because of a call to abortLoading /// or a problem during loading). In the former case error will be an empty string. + public slots: + + void removeDocument (CSMDoc::Document *document); + ///< Emits the lastDocumentDeleted signal, if applicable. + signals: void documentAdded (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 3b58904793..1b2ca8ad5d 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -13,11 +13,11 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) { event->ignore(); - emit cancel (mDocument); + cancel(); } CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) -: mDocument (document) +: mDocument (document), mAborted (false) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); @@ -52,10 +52,16 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mRecordProgress->setTextVisible (true); mRecordProgress->setValue (0); - QDialogButtonBox *buttonBox = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, - this); + // error message + mError = new QLabel (this); + mError->setWordWrap (true); - layout->addWidget (buttonBox); + layout->addWidget (mError); + + // buttons + mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); + + layout->addWidget (mButtons); setLayout (layout); @@ -63,7 +69,7 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) show(); - connect (buttonBox, SIGNAL (rejected()), this, SLOT (cancel())); + connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel())); } void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) @@ -73,10 +79,9 @@ void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps) mFileProgress->setValue (mFileProgress->value()+1); mRecordProgress->setValue (0); - mRecordProgress->setMaximum (steps); + mRecordProgress->setMaximum (steps>0 ? steps : 1); } - void CSVDoc::LoadingDocument::nextRecord() { int value = mRecordProgress->value()+1; @@ -85,9 +90,22 @@ void CSVDoc::LoadingDocument::nextRecord() mRecordProgress->setValue (value); } +void CSVDoc::LoadingDocument::abort (const std::string& error) +{ + mAborted = true; + mError->setText (QString::fromUtf8 (("Loading failed: " + error).c_str())); + mButtons->setStandardButtons (QDialogButtonBox::Close); +} + void CSVDoc::LoadingDocument::cancel() { - emit cancel (mDocument); + if (!mAborted) + emit cancel (mDocument); + else + { + emit close (mDocument); + deleteLater(); + } } @@ -107,21 +125,32 @@ void CSVDoc::Loader::add (CSMDoc::Document *document) connect (loading, SIGNAL (cancel (CSMDoc::Document *)), this, SIGNAL (cancel (CSMDoc::Document *))); + connect (loading, SIGNAL (close (CSMDoc::Document *)), + this, SIGNAL (close (CSMDoc::Document *))); } void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed, const std::string& error) { + std::map::iterator iter = mDocuments.begin(); + + for (; iter!=mDocuments.end(); ++iter) + if (iter->first==document) + break; + + if (iter==mDocuments.end()) + return; + if (completed || error.empty()) { - for (std::map::iterator iter (mDocuments.begin()); - iter!=mDocuments.end(); ++iter) - if (iter->first==document) - { - delete iter->second; - mDocuments.erase (iter); - break; - } + delete iter->second; + mDocuments.erase (iter); + } + else if (!completed && !error.empty()) + { + iter->second->abort (error); + // Leave the window open for now (wait for the user to close it) + mDocuments.erase (iter); } } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index d1c740011d..ece071755d 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -9,6 +9,7 @@ class QLabel; class QProgressBar; +class QDialogButtonBox; namespace CSMDoc { @@ -25,6 +26,9 @@ namespace CSVDoc QLabel *mFile; QProgressBar *mFileProgress; QProgressBar *mRecordProgress; + bool mAborted; + QDialogButtonBox *mButtons; + QLabel *mError; private: @@ -38,6 +42,8 @@ namespace CSVDoc void nextRecord(); + void abort (const std::string& error); + private slots: void cancel(); @@ -45,6 +51,10 @@ namespace CSVDoc signals: void cancel (CSMDoc::Document *document); + ///< Stop loading process. + + void close (CSMDoc::Document *document); + ///< Close stopped loading process. }; class Loader : public QObject @@ -63,6 +73,8 @@ namespace CSVDoc void cancel (CSMDoc::Document *document); + void close (CSMDoc::Document *document); + public slots: void add (CSMDoc::Document *document); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b8971a296a..816eff7917 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -103,6 +103,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) connect ( &mLoader, SIGNAL (cancel (CSMDoc::Document *)), &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); + + connect ( + &mLoader, SIGNAL (close (CSMDoc::Document *)), + &mDocumentManager, SLOT (removeDocument (CSMDoc::Document *))); } CSVDoc::ViewManager::~ViewManager() From a30d816982f7f8e700661c888c1879bad1adb618 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 6 May 2014 11:44:20 +0200 Subject: [PATCH 185/545] fixed a mixup in CSMTools::Tools constructor/destructor --- apps/opencs/model/tools/tools.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index d3d8f5fadd..8104cc3e66 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -87,13 +87,14 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { - for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) - delete iter->second; } CSMTools::Tools::~Tools() { delete mVerifier; + + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) + delete iter->second; } CSMWorld::UniversalId CSMTools::Tools::runVerifier() From 79b13a74a36ce9a0214d43a9d7c7777124902e81 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 6 May 2014 07:33:32 -0500 Subject: [PATCH 186/545] Incorporated SettingManager into UserSettings class. Other minor code changes to support QSettings integration --- apps/opencs/CMakeLists.txt | 1 - apps/opencs/editor.cpp | 5 - apps/opencs/model/settings/settingmanager.cpp | 93 -------------- apps/opencs/model/settings/settingmanager.hpp | 55 -------- apps/opencs/model/settings/usersettings.cpp | 117 ++++++++++++++++-- apps/opencs/model/settings/usersettings.hpp | 36 +++++- apps/opencs/view/doc/view.cpp | 4 +- apps/opencs/view/settings/settingwindow.hpp | 6 +- .../opencs/view/world/datadisplaydelegate.cpp | 9 +- .../opencs/view/world/datadisplaydelegate.hpp | 3 +- apps/opencs/view/world/idtypedelegate.cpp | 2 +- .../view/world/recordstatusdelegate.cpp | 2 +- 12 files changed, 155 insertions(+), 178 deletions(-) delete mode 100644 apps/opencs/model/settings/settingmanager.cpp delete mode 100644 apps/opencs/model/settings/settingmanager.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 38075ac536..22db972069 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -106,7 +106,6 @@ opencs_units_noqt (view/settings opencs_units (model/settings usersettings - settingmanager setting connector ) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 480e91e301..f6a13f4f65 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -124,11 +124,6 @@ std::pair > CS::Editor::readConfi QString path = QString::fromUtf8 (iter->string().c_str()); mFileDialog.addFiles(path); } -/* - //load the settings into the userSettings instance. - const QString settingFileName = "opencs.cfg"; - CSMSettings::UserSettings::instance().loadSettings(settingFileName); -*/ return std::make_pair (dataDirs, variables["fallback-archive"].as >()); } diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp deleted file mode 100644 index b0e5cba98f..0000000000 --- a/apps/opencs/model/settings/settingmanager.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "setting.hpp" -#include "settingmanager.hpp" - -CSMSettings::SettingManager::SettingManager(QObject *parent) : - QObject(parent) -{} - -CSMSettings::Setting *CSMSettings::SettingManager::createSetting - (CSMSettings::SettingType typ, const QString &page, const QString &name) -{ - //get list of all settings for the current setting name - if (findSetting (page, name)) - { - qWarning() << "Duplicate declaration encountered: " - << (name + '/' + page); - return 0; - } - - Setting *setting = new Setting (typ, name, page); - - - //add declaration to the model - mSettings.append (setting); - - return setting; -} - -void CSMSettings::SettingManager::addDefinitions (const QSettings *settings) -{ - foreach (const QString &key, settings->allKeys()) - { - QStringList names = key.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << names.at(0) << "." << names.at(1); - continue; - } - - QStringList values = settings->value (key).toStringList(); - - if (values.isEmpty()) - values.append (setting->defaultValues()); - - setting->setDefinedValues (values); - } -} - -CSMSettings::Setting *CSMSettings::SettingManager::findSetting - (const QString &pageName, const QString &settingName) -{ - foreach (Setting *setting, mSettings) - { - if (setting->name() == settingName) - { - if (setting->page() == pageName) - return setting; - } - } - return 0; -} - -CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const -{ - SettingPageMap pageMap; - - foreach (Setting *setting, mSettings) - pageMap[setting->page()].append (setting); - - return pageMap; -} - -void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, - const QStringList &list) -{ - QStringList names = settingKey.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - setting->setDefinedValues (list); - - emit userSettingUpdated (settingKey, list); -} diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp deleted file mode 100644 index 95f55106e2..0000000000 --- a/apps/opencs/model/settings/settingmanager.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CSMSETTINGS_SETTINGMANAGER_HPP -#define CSMSETTINGS_SETTINGMANAGER_HPP - -#include -#include -#include -#include -#include - -#include "support.hpp" -#include "setting.hpp" - -namespace CSMSettings -{ - - typedef QMap DefinitionMap; - typedef QMap DefinitionPageMap; - - typedef QMap > SettingPageMap; - - class SettingManager : public QObject - { - Q_OBJECT - - QList mSettings; - - public: - explicit SettingManager(QObject *parent = 0); - - ///retrieve a setting object from a given page and setting name - Setting *findSetting - (const QString &pageName, const QString &settingName = QString()); - - ///Retreive a map of the settings, keyed by page name - SettingPageMap settingPageMap() const; - - protected: - - ///add a new setting to the model and return it - Setting *createSetting (CSMSettings::SettingType typ, - const QString &page, const QString &name); - - ///add definitions to the settings specified in the page map - void addDefinitions (const QSettings *settings); - - signals: - - void userSettingUpdated (const QString &, const QStringList &); - - public slots: - - void updateUserSetting (const QString &, const QStringList &); - }; -} -#endif // CSMSETTINGS_SETTINGMANAGER_HPP diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 178104982a..7e65cb2702 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -42,7 +42,7 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; - mSettings = 0; + mSettingDefinitions = 0; mReadWriteMessage = QObject::tr("
Could not open or create file for \ writing

Please make sure you have the right\ @@ -55,6 +55,31 @@ CSMSettings::UserSettings::UserSettings() buildSettingModelDefaults(); } +void CSMSettings::UserSettings::addDefinitions () +{ + foreach (const QString &key, mSettingDefinitions->allKeys()) + { + QStringList names = key.split('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + if (!setting) + { + qWarning() << "Found definitions for undeclared setting " + << names.at(0) << "/" << names.at(1); + removeSetting (names.at(0), names.at(1)); + continue; + } + + QStringList values = mSettingDefinitions->value (key).toStringList(); + + if (values.isEmpty()) + values.append (setting->defaultValues()); + + setting->setDefinedValues (values); + } +} + void CSMSettings::UserSettings::buildSettingModelDefaults() { QString section = "Window Size"; @@ -355,22 +380,19 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) QSettings::setPath (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); - if (mSettings) - delete mSettings; - - mSettings = new QSettings + mSettingDefinitions = new QSettings (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); - addDefinitions (mSettings); + addDefinitions(); } void CSMSettings::UserSettings::saveSettings (const QMap &settingMap) { foreach (const QString &key, settingMap.keys()) - mSettings->setValue (key, settingMap.value (key)); + mSettingDefinitions->setValue (key, settingMap.value (key)); - delete mSettings; + mSettingDefinitions->sync(); } QString CSMSettings::UserSettings::settingValue (const QString &settingKey) @@ -392,3 +414,82 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance() assert(mUserSettingsInstance); return *mUserSettingsInstance; } + +void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey, + const QStringList &list) +{ + QStringList names = settingKey.split('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + setting->setDefinedValues (list); + + emit userSettingUpdated (settingKey, list); +} + +CSMSettings::Setting *CSMSettings::UserSettings::findSetting + (const QString &pageName, const QString &settingName) +{ + foreach (Setting *setting, mSettings) + { + if (setting->name() == settingName) + { + if (setting->page() == pageName) + return setting; + } + } + return 0; +} + +void CSMSettings::UserSettings::removeSetting + (const QString &pageName, const QString &settingName) +{ + if (mSettings.isEmpty()) + return; + + QList ::iterator removeIterator = mSettings.begin(); + + while (removeIterator != mSettings.end()) + { + if ((*removeIterator)->name() == settingName) + { + if ((*removeIterator)->page() == pageName) + { + mSettings.erase (removeIterator); + break; + } + } + removeIterator++; + } +} + + +CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const +{ + SettingPageMap pageMap; + + foreach (Setting *setting, mSettings) + pageMap[setting->page()].append (setting); + + return pageMap; +} + +CSMSettings::Setting *CSMSettings::UserSettings::createSetting + (CSMSettings::SettingType typ, const QString &page, const QString &name) +{ + //get list of all settings for the current setting name + if (findSetting (page, name)) + { + qWarning() << "Duplicate declaration encountered: " + << (name + '/' + page); + return 0; + } + + Setting *setting = new Setting (typ, name, page); + + + //add declaration to the model + mSettings.append (setting); + + return setting; +} diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 826bb6d6b5..509c06bfa6 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -7,8 +7,7 @@ #include #include - -#include "settingmanager.hpp" +#include "support.hpp" #ifndef Q_MOC_RUN #include @@ -22,7 +21,10 @@ class QSettings; namespace CSMSettings { - class UserSettings: public SettingManager + class Setting; + typedef QMap > SettingPageMap; + + class UserSettings: public QObject { Q_OBJECT @@ -32,7 +34,8 @@ namespace CSMSettings { QString mReadOnlyMessage; QString mReadWriteMessage; - QSettings *mSettings; + QSettings *mSettingDefinitions; + QList mSettings; public: @@ -53,13 +56,38 @@ namespace CSMSettings { QString settingValue (const QString &settingKey); + ///retrieve a setting object from a given page and setting name + Setting *findSetting + (const QString &pageName, const QString &settingName = QString()); + + ///remove a setting from the list + void removeSetting + (const QString &pageName, const QString &settingName); + + ///Retreive a map of the settings, keyed by page name + SettingPageMap settingPageMap() const; + private: + ///add definitions to the settings specified in the page map + void addDefinitions(); + void buildSettingModelDefaults(); void displayFileErrorMessage(const QString &userpath, const QString &globalpath, const QString &localpath) const; + ///add a new setting to the model and return it + Setting *createSetting (CSMSettings::SettingType typ, + const QString &page, const QString &name); + + signals: + + void userSettingUpdated (const QString &, const QStringList &); + + public slots: + + void updateUserSetting (const QString &, const QStringList &); }; } #endif // USERSETTINGS_HPP diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index acb272553e..95ab6ca279 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -236,10 +236,10 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mViewTotal (totalViews) { QString width = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Width"); + ("Window Size/Width"); QString height = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Height"); + ("Window Size/Height"); resize (width.toInt(), height.toInt()); diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 35ae4c068c..8354ced7f5 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -8,7 +8,7 @@ namespace CSMSettings { class Setting; - class SettingManager; + class UserSettings; } namespace CSVSettings { @@ -23,13 +23,13 @@ namespace CSVSettings { Q_OBJECT PageList mPages; - CSMSettings::SettingManager *mModel; + CSMSettings::UserSettings *mModel; public: explicit SettingWindow(QWidget *parent = 0); View *findView (const QString &pageName, const QString &setting); - void setModel (CSMSettings::SettingManager &model) { mModel = &model; } + void setModel (CSMSettings::UserSettings &model) { mModel = &model; } protected: diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index c3ec68b527..31ec18d52e 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -7,18 +7,19 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const IconList &icons, QUndoStack &undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent) : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), - mTextLeftOffset(8), mSettingKey (settingKey) + mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); buildPixmaps(); QString value = - CSMSettings::UserSettings::instance().settingValue (settingKey); + CSMSettings::UserSettings::instance().settingValue (mSettingKey); updateDisplayMode(value); } @@ -140,7 +141,7 @@ CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (Q QObject *parent) const { - return new DataDisplayDelegate (mValues, mIcons, undoStack, "", parent); + return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent); } diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f11c4a2b9e..ef453c58f2 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -41,7 +41,8 @@ namespace CSVWorld explicit DataDisplayDelegate (const ValueList & values, const IconList & icons, QUndoStack& undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent); ~DataDisplayDelegate(); diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index 485ca57ac9..6b4d442f30 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -5,7 +5,7 @@ CSVWorld::IdTypeDelegate::IdTypeDelegate (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Referenceable ID Type Display", + "Display Format", "Referenceable ID Type Display", parent) {} diff --git a/apps/opencs/view/world/recordstatusdelegate.cpp b/apps/opencs/view/world/recordstatusdelegate.cpp index 206adbdd7e..4fe7031ce2 100644 --- a/apps/opencs/view/world/recordstatusdelegate.cpp +++ b/apps/opencs/view/world/recordstatusdelegate.cpp @@ -11,7 +11,7 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values, const IconList & icons, QUndoStack &undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Record Status Display", + "Display Format", "Record Status Display", parent) {} From a17cb1f389757bfac403a16fef7c2efb5b2c7cc2 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 6 May 2014 07:33:32 -0500 Subject: [PATCH 187/545] Fixed opencs.ini formatting --- CMakeLists.txt | 4 +- apps/opencs/CMakeLists.txt | 1 - apps/opencs/editor.cpp | 5 - apps/opencs/model/settings/settingmanager.cpp | 93 -------------- apps/opencs/model/settings/settingmanager.hpp | 55 -------- apps/opencs/model/settings/usersettings.cpp | 117 ++++++++++++++++-- apps/opencs/model/settings/usersettings.hpp | 36 +++++- apps/opencs/view/doc/view.cpp | 4 +- apps/opencs/view/settings/settingwindow.hpp | 6 +- .../opencs/view/world/datadisplaydelegate.cpp | 9 +- .../opencs/view/world/datadisplaydelegate.hpp | 3 +- apps/opencs/view/world/idtypedelegate.cpp | 2 +- .../view/world/recordstatusdelegate.cpp | 2 +- files/opencs.conf | 5 - files/opencs.ini | 7 ++ 15 files changed, 164 insertions(+), 185 deletions(-) delete mode 100644 apps/opencs/model/settings/settingmanager.cpp delete mode 100644 apps/opencs/model/settings/settingmanager.hpp delete mode 100644 files/opencs.conf create mode 100644 files/opencs.ini diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d59236473..ff09160865 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -368,8 +368,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg.install") -configure_file(${OpenMW_SOURCE_DIR}/files/opencs.conf - "${OpenMW_BINARY_DIR}/opencs.cfg") +configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini + "${OpenMW_BINARY_DIR}/opencs.ini") configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 38075ac536..22db972069 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -106,7 +106,6 @@ opencs_units_noqt (view/settings opencs_units (model/settings usersettings - settingmanager setting connector ) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 480e91e301..f6a13f4f65 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -124,11 +124,6 @@ std::pair > CS::Editor::readConfi QString path = QString::fromUtf8 (iter->string().c_str()); mFileDialog.addFiles(path); } -/* - //load the settings into the userSettings instance. - const QString settingFileName = "opencs.cfg"; - CSMSettings::UserSettings::instance().loadSettings(settingFileName); -*/ return std::make_pair (dataDirs, variables["fallback-archive"].as >()); } diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp deleted file mode 100644 index b0e5cba98f..0000000000 --- a/apps/opencs/model/settings/settingmanager.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "setting.hpp" -#include "settingmanager.hpp" - -CSMSettings::SettingManager::SettingManager(QObject *parent) : - QObject(parent) -{} - -CSMSettings::Setting *CSMSettings::SettingManager::createSetting - (CSMSettings::SettingType typ, const QString &page, const QString &name) -{ - //get list of all settings for the current setting name - if (findSetting (page, name)) - { - qWarning() << "Duplicate declaration encountered: " - << (name + '/' + page); - return 0; - } - - Setting *setting = new Setting (typ, name, page); - - - //add declaration to the model - mSettings.append (setting); - - return setting; -} - -void CSMSettings::SettingManager::addDefinitions (const QSettings *settings) -{ - foreach (const QString &key, settings->allKeys()) - { - QStringList names = key.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << names.at(0) << "." << names.at(1); - continue; - } - - QStringList values = settings->value (key).toStringList(); - - if (values.isEmpty()) - values.append (setting->defaultValues()); - - setting->setDefinedValues (values); - } -} - -CSMSettings::Setting *CSMSettings::SettingManager::findSetting - (const QString &pageName, const QString &settingName) -{ - foreach (Setting *setting, mSettings) - { - if (setting->name() == settingName) - { - if (setting->page() == pageName) - return setting; - } - } - return 0; -} - -CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const -{ - SettingPageMap pageMap; - - foreach (Setting *setting, mSettings) - pageMap[setting->page()].append (setting); - - return pageMap; -} - -void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, - const QStringList &list) -{ - QStringList names = settingKey.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - setting->setDefinedValues (list); - - emit userSettingUpdated (settingKey, list); -} diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp deleted file mode 100644 index 95f55106e2..0000000000 --- a/apps/opencs/model/settings/settingmanager.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CSMSETTINGS_SETTINGMANAGER_HPP -#define CSMSETTINGS_SETTINGMANAGER_HPP - -#include -#include -#include -#include -#include - -#include "support.hpp" -#include "setting.hpp" - -namespace CSMSettings -{ - - typedef QMap DefinitionMap; - typedef QMap DefinitionPageMap; - - typedef QMap > SettingPageMap; - - class SettingManager : public QObject - { - Q_OBJECT - - QList mSettings; - - public: - explicit SettingManager(QObject *parent = 0); - - ///retrieve a setting object from a given page and setting name - Setting *findSetting - (const QString &pageName, const QString &settingName = QString()); - - ///Retreive a map of the settings, keyed by page name - SettingPageMap settingPageMap() const; - - protected: - - ///add a new setting to the model and return it - Setting *createSetting (CSMSettings::SettingType typ, - const QString &page, const QString &name); - - ///add definitions to the settings specified in the page map - void addDefinitions (const QSettings *settings); - - signals: - - void userSettingUpdated (const QString &, const QStringList &); - - public slots: - - void updateUserSetting (const QString &, const QStringList &); - }; -} -#endif // CSMSETTINGS_SETTINGMANAGER_HPP diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 178104982a..7e65cb2702 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -42,7 +42,7 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; - mSettings = 0; + mSettingDefinitions = 0; mReadWriteMessage = QObject::tr("
Could not open or create file for \ writing

Please make sure you have the right\ @@ -55,6 +55,31 @@ CSMSettings::UserSettings::UserSettings() buildSettingModelDefaults(); } +void CSMSettings::UserSettings::addDefinitions () +{ + foreach (const QString &key, mSettingDefinitions->allKeys()) + { + QStringList names = key.split('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + if (!setting) + { + qWarning() << "Found definitions for undeclared setting " + << names.at(0) << "/" << names.at(1); + removeSetting (names.at(0), names.at(1)); + continue; + } + + QStringList values = mSettingDefinitions->value (key).toStringList(); + + if (values.isEmpty()) + values.append (setting->defaultValues()); + + setting->setDefinedValues (values); + } +} + void CSMSettings::UserSettings::buildSettingModelDefaults() { QString section = "Window Size"; @@ -355,22 +380,19 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) QSettings::setPath (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); - if (mSettings) - delete mSettings; - - mSettings = new QSettings + mSettingDefinitions = new QSettings (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); - addDefinitions (mSettings); + addDefinitions(); } void CSMSettings::UserSettings::saveSettings (const QMap &settingMap) { foreach (const QString &key, settingMap.keys()) - mSettings->setValue (key, settingMap.value (key)); + mSettingDefinitions->setValue (key, settingMap.value (key)); - delete mSettings; + mSettingDefinitions->sync(); } QString CSMSettings::UserSettings::settingValue (const QString &settingKey) @@ -392,3 +414,82 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance() assert(mUserSettingsInstance); return *mUserSettingsInstance; } + +void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey, + const QStringList &list) +{ + QStringList names = settingKey.split('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + setting->setDefinedValues (list); + + emit userSettingUpdated (settingKey, list); +} + +CSMSettings::Setting *CSMSettings::UserSettings::findSetting + (const QString &pageName, const QString &settingName) +{ + foreach (Setting *setting, mSettings) + { + if (setting->name() == settingName) + { + if (setting->page() == pageName) + return setting; + } + } + return 0; +} + +void CSMSettings::UserSettings::removeSetting + (const QString &pageName, const QString &settingName) +{ + if (mSettings.isEmpty()) + return; + + QList ::iterator removeIterator = mSettings.begin(); + + while (removeIterator != mSettings.end()) + { + if ((*removeIterator)->name() == settingName) + { + if ((*removeIterator)->page() == pageName) + { + mSettings.erase (removeIterator); + break; + } + } + removeIterator++; + } +} + + +CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const +{ + SettingPageMap pageMap; + + foreach (Setting *setting, mSettings) + pageMap[setting->page()].append (setting); + + return pageMap; +} + +CSMSettings::Setting *CSMSettings::UserSettings::createSetting + (CSMSettings::SettingType typ, const QString &page, const QString &name) +{ + //get list of all settings for the current setting name + if (findSetting (page, name)) + { + qWarning() << "Duplicate declaration encountered: " + << (name + '/' + page); + return 0; + } + + Setting *setting = new Setting (typ, name, page); + + + //add declaration to the model + mSettings.append (setting); + + return setting; +} diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 826bb6d6b5..509c06bfa6 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -7,8 +7,7 @@ #include #include - -#include "settingmanager.hpp" +#include "support.hpp" #ifndef Q_MOC_RUN #include @@ -22,7 +21,10 @@ class QSettings; namespace CSMSettings { - class UserSettings: public SettingManager + class Setting; + typedef QMap > SettingPageMap; + + class UserSettings: public QObject { Q_OBJECT @@ -32,7 +34,8 @@ namespace CSMSettings { QString mReadOnlyMessage; QString mReadWriteMessage; - QSettings *mSettings; + QSettings *mSettingDefinitions; + QList mSettings; public: @@ -53,13 +56,38 @@ namespace CSMSettings { QString settingValue (const QString &settingKey); + ///retrieve a setting object from a given page and setting name + Setting *findSetting + (const QString &pageName, const QString &settingName = QString()); + + ///remove a setting from the list + void removeSetting + (const QString &pageName, const QString &settingName); + + ///Retreive a map of the settings, keyed by page name + SettingPageMap settingPageMap() const; + private: + ///add definitions to the settings specified in the page map + void addDefinitions(); + void buildSettingModelDefaults(); void displayFileErrorMessage(const QString &userpath, const QString &globalpath, const QString &localpath) const; + ///add a new setting to the model and return it + Setting *createSetting (CSMSettings::SettingType typ, + const QString &page, const QString &name); + + signals: + + void userSettingUpdated (const QString &, const QStringList &); + + public slots: + + void updateUserSetting (const QString &, const QStringList &); }; } #endif // USERSETTINGS_HPP diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index acb272553e..95ab6ca279 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -236,10 +236,10 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mViewTotal (totalViews) { QString width = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Width"); + ("Window Size/Width"); QString height = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Height"); + ("Window Size/Height"); resize (width.toInt(), height.toInt()); diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 35ae4c068c..8354ced7f5 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -8,7 +8,7 @@ namespace CSMSettings { class Setting; - class SettingManager; + class UserSettings; } namespace CSVSettings { @@ -23,13 +23,13 @@ namespace CSVSettings { Q_OBJECT PageList mPages; - CSMSettings::SettingManager *mModel; + CSMSettings::UserSettings *mModel; public: explicit SettingWindow(QWidget *parent = 0); View *findView (const QString &pageName, const QString &setting); - void setModel (CSMSettings::SettingManager &model) { mModel = &model; } + void setModel (CSMSettings::UserSettings &model) { mModel = &model; } protected: diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index c3ec68b527..31ec18d52e 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -7,18 +7,19 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const IconList &icons, QUndoStack &undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent) : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), - mTextLeftOffset(8), mSettingKey (settingKey) + mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); buildPixmaps(); QString value = - CSMSettings::UserSettings::instance().settingValue (settingKey); + CSMSettings::UserSettings::instance().settingValue (mSettingKey); updateDisplayMode(value); } @@ -140,7 +141,7 @@ CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (Q QObject *parent) const { - return new DataDisplayDelegate (mValues, mIcons, undoStack, "", parent); + return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent); } diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f11c4a2b9e..ef453c58f2 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -41,7 +41,8 @@ namespace CSVWorld explicit DataDisplayDelegate (const ValueList & values, const IconList & icons, QUndoStack& undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent); ~DataDisplayDelegate(); diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index 485ca57ac9..6b4d442f30 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -5,7 +5,7 @@ CSVWorld::IdTypeDelegate::IdTypeDelegate (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Referenceable ID Type Display", + "Display Format", "Referenceable ID Type Display", parent) {} diff --git a/apps/opencs/view/world/recordstatusdelegate.cpp b/apps/opencs/view/world/recordstatusdelegate.cpp index 206adbdd7e..4fe7031ce2 100644 --- a/apps/opencs/view/world/recordstatusdelegate.cpp +++ b/apps/opencs/view/world/recordstatusdelegate.cpp @@ -11,7 +11,7 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values, const IconList & icons, QUndoStack &undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Record Status Display", + "Display Format", "Record Status Display", parent) {} diff --git a/files/opencs.conf b/files/opencs.conf deleted file mode 100644 index 3faac7c8e8..0000000000 --- a/files/opencs.conf +++ /dev/null @@ -1,5 +0,0 @@ -[Editor] -Record Status Display = Icon and Text -[Window Size] -Width = 640 -Height = 480 diff --git a/files/opencs.ini b/files/opencs.ini new file mode 100644 index 0000000000..065f11a883 --- /dev/null +++ b/files/opencs.ini @@ -0,0 +1,7 @@ +[Display%20Format] +Record%20Status%20Display=Icon Only +Referenceable%20ID%20Type%20Display=Text Only + +[Window%20Size] +Height=900 +Width=1440 From d2beb814e75a59e7200e39888c6a008847ab69aa Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 6 May 2014 18:05:53 +0200 Subject: [PATCH 188/545] Remove superfluous attack phrases (already done by startCombat) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index e69f39a194..dc04f92d43 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -885,8 +885,6 @@ namespace MWMechanics // TODO: Add more messages if (type == OT_Theft) MWBase::Environment::get().getDialogueManager()->say(*it1, "thief"); - else if (type == OT_Assault) - MWBase::Environment::get().getDialogueManager()->say(*it1, "attack"); // Will other witnesses paticipate in crime if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm From 1c8c26072dc74d916000dafe4fd589b1158009a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 6 May 2014 18:23:17 +0200 Subject: [PATCH 189/545] Crime and self defense fixes - NPCs should still shout messages such as "thief" even if they did not report the crime - Fixed self defense for NPCs (they no longer attack the player when they were attacked by a non-player actor) - Fixed self defense for creatures (Fixes #1203) --- apps/openmw/mwclass/creature.cpp | 6 +++ apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 6 --- apps/openmw/mwmechanics/aisequence.hpp | 1 + .../mwmechanics/mechanicsmanagerimp.cpp | 37 +++++++++++++------ 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 94238e6d53..4c6ab1c75b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -337,6 +337,12 @@ namespace MWClass { // NOTE: 'object' and/or 'attacker' may be empty. + getCreatureStats(ptr).setAttacked(true); + + // Self defense + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker); + if(!successful) { // TODO: Handle HitAttemptOnMe script function diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5222eac443..6a96c955f4 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -621,7 +621,7 @@ namespace MWClass // NOTE: 'object' and/or 'attacker' may be empty. // Attacking peaceful NPCs is a crime - if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); getCreatureStats(ptr).setAttacked(true); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c3957f72f2..295f00d216 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -788,12 +788,6 @@ namespace MWMechanics } } } - // if I didn't report a crime was I attacked? - // TODO: this is incorrect, getAttacked also triggers if attacked by other non-player actors. - else if (creatureStats.getAttacked() && !creatureStats.isHostile()) - { - MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); - } } } diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 614eb4154d..37e0c7f17e 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -64,6 +64,7 @@ namespace MWMechanics void stack (const AiPackage& package, const MWWorld::Ptr& actor); ///< Add \a package to the front of the sequence (suspends current package) + /// @param actor The actor that owns this AiSequence void queue (const AiPackage& package); ///< Add \a package to the end of the sequence (executed after all other packages have been diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index dc04f92d43..5381af8da7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -854,27 +854,45 @@ namespace MWMechanics // Innocent until proven guilty bool reported = false; - // Find all the NPCs within the alarm radius + // Find all the actors within the alarm radius std::vector neighbors; mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), esmStore.get().find("fAlarmRadius")->getInt(), neighbors); - // Find an actor who witnessed the crime + int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); + + // Find actors who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - if ( *it == ptr - || !it->getClass().isNpc()) continue; // not the player and is an NPC + if (*it == ptr) continue; // not the player // Was the crime seen? - if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || - type == OT_Assault ) + if (MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) { + // TODO: Add more messages + if (type == OT_Theft) + MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); + + if (*it == victim) + { + // Self-defense + // The victim is aware of the criminal/assailant. If being assaulted, fight back now + // (regardless of whether the assault is reported or not) + // This applies to both NPCs and creatures + + // ... except if this is a guard: then the player is given a chance to pay a fine / go to jail instead + if (type == OT_Assault && !ptr.getClass().isClass(ptr, "guard")) + MWBase::Environment::get().getMechanicsManager()->startCombat(victim, ptr); + } + + // Crime reporting only applies to NPCs + if (!it->getClass().isNpc()) + continue; // Will the witness report the crime? if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) { reported = true; - int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) @@ -882,10 +900,6 @@ namespace MWMechanics if ( *it1 == ptr || !it1->getClass().isNpc()) continue; // not the player and is an NPC - // TODO: Add more messages - if (type == OT_Theft) - MWBase::Environment::get().getDialogueManager()->say(*it1, "thief"); - // Will other witnesses paticipate in crime if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm || type == OT_Assault ) @@ -896,7 +910,6 @@ namespace MWMechanics // Mark as Alarmed for dialogue it1->getClass().getCreatureStats(*it1).setAlarmed(true); } - break; // Someone saw the crime and everyone has been told } } } From 01810f24b04b60e5c38262881d8df0f85bf89045 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Tue, 6 May 2014 23:29:39 +0400 Subject: [PATCH 190/545] A* misses 1st closest node fix --- apps/openmw/mwmechanics/pathgrid.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index 82d815d681..c3fa0a662e 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -328,6 +328,12 @@ namespace MWMechanics path.push_front(pt); current = graphParent[current]; } + + // add first node to path explicitly + ESM::Pathgrid::Point pt = mPathgrid->mPoints[start]; + pt.mX += xCell; + pt.mY += yCell; + path.push_front(pt); return path; } } From 8fb96e1be32817ca506b084fe5611eb54effeb78 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 6 May 2014 19:22:45 -0500 Subject: [PATCH 191/545] Removed error code for missing opencs.ini files. --- apps/opencs/model/settings/usersettings.cpp | 8 ++++---- apps/opencs/model/settings/usersettings.hpp | 3 --- apps/opencs/view/settings/dialog.cpp | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 7e65cb2702..e26b1de5ca 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -318,7 +318,7 @@ CSMSettings::UserSettings::~UserSettings() { mUserSettingsInstance = 0; } - +/* void CSMSettings::UserSettings::displayFileErrorMessage (const QString &userpath, const QString &globalpath, @@ -343,7 +343,7 @@ void CSMSettings::UserSettings::displayFileErrorMessage msgBox.setText (mReadWriteMessage + message); msgBox.exec(); } - +*/ void CSMSettings::UserSettings::loadSettings (const QString &fileName) { QString userFilePath = QString::fromUtf8 @@ -366,14 +366,14 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) isSystem = QFile (localFilePath + fileName).exists(); otherFilePath = localFilePath; } - +/* //error condition - notify and return if (!isUser || !isSystem) { displayFileErrorMessage (userFilePath, globalFilePath, localFilePath); return; } - +*/ QSettings::setPath (QSettings::IniFormat, QSettings::UserScope, userFilePath); diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 509c06bfa6..7bb15e598e 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -73,9 +73,6 @@ namespace CSMSettings { void addDefinitions(); void buildSettingModelDefaults(); - void displayFileErrorMessage(const QString &userpath, - const QString &globalpath, - const QString &localpath) const; ///add a new setting to the model and return it Setting *createSetting (CSMSettings::SettingType typ, diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index 3ed4d3b091..32fc7a46ae 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -123,6 +123,7 @@ void CSVSettings::Dialog::show() { if (pages().isEmpty()) buildPages(); + QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); move (screenCenter - geometry().center()); From e47e3de3d2b1cf4a42feac8c85af9b8a0545114b Mon Sep 17 00:00:00 2001 From: graffy76 Date: Tue, 6 May 2014 21:58:50 -0500 Subject: [PATCH 192/545] Removed unneeded includes, cleaned up code, added comments --- apps/opencs/model/settings/connector.hpp | 18 +++++- apps/opencs/model/settings/setting.hpp | 16 +++-- apps/opencs/model/settings/support.hpp | 34 +++------- apps/opencs/model/settings/usersettings.cpp | 64 ++----------------- apps/opencs/model/settings/usersettings.hpp | 4 +- apps/opencs/view/settings/dialog.cpp | 13 ---- apps/opencs/view/settings/dialog.hpp | 1 - apps/opencs/view/settings/frame.hpp | 2 + apps/opencs/view/settings/page.hpp | 2 +- apps/opencs/view/settings/rangeview.cpp | 3 - apps/opencs/view/settings/rangeview.hpp | 6 ++ .../view/settings/resizeablestackedwidget.hpp | 2 + apps/opencs/view/settings/settingwindow.hpp | 8 +++ apps/opencs/view/settings/spinbox.cpp | 3 +- apps/opencs/view/settings/spinbox.hpp | 11 +++- apps/opencs/view/settings/textview.hpp | 1 + apps/opencs/view/settings/view.cpp | 21 +++--- apps/opencs/view/settings/view.hpp | 5 -- 18 files changed, 76 insertions(+), 138 deletions(-) diff --git a/apps/opencs/model/settings/connector.hpp b/apps/opencs/model/settings/connector.hpp index da4c36d44c..aaf9936d54 100644 --- a/apps/opencs/model/settings/connector.hpp +++ b/apps/opencs/model/settings/connector.hpp @@ -20,34 +20,46 @@ namespace CSMSettings { CSVSettings::View *mMasterView; - //map using the view pointer as a key to it's index value + ///map using the view pointer as a key to it's index value QList mSlaveViews; - //list of proxy values for each master value. - //value list order is indexed to the master value index. + ///list of proxy values for each master value. + ///value list order is indexed to the master value index. QMap < QString, QList > mProxyListMap; public: explicit Connector(CSVSettings::View *master, QObject *parent = 0); + ///Set the view which acts as a proxy for other setting views void setMasterView (CSVSettings::View *view); + + ///Add a view to be updated / update to the master void addSlaveView (CSVSettings::View *view, QList &masterProxyValues); private: + ///loosely matches lists of proxy values across registered slaves + ///against a proxy value list for a given master value bool proxyListsMatch (const QList &list1, const QList &list2) const; + ///loosely matches two string lists bool stringListsMatch (const QStringList &list1, const QStringList &list2) const; + ///retrieves current values of registered slave views QList getSlaveViewValues() const; public slots: + ///updates slave views with proxy values associated with current + ///master value void slotUpdateSlaves() const; + + ///updates master value associated with the currently selected + ///slave values, if applicable. void slotUpdateMaster() const; }; } diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index cf5dd2a06c..89d6cc2c48 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -7,11 +7,17 @@ namespace CSMSettings { - //Maps setting id ("page.name") to a list of corresponding proxy values. - //Order of proxy value stringlists corresponds to order of master proxy's - //values in it's declared value list + //QString is the setting id in the form of "page/name" + //QList is a list of stringlists of proxy values. + //Order is important! Proxy stringlists are matched against + //master values by their position in the QList. typedef QMap > ProxyValueMap; + ///Setting class is the interface for the User Settings. It contains + ///a great deal of boiler plate to provide the core API functions, as + ///well as the property() functions which use enumeration to be iterable. + ///This makes the Setting class capable of being manipulated by script. + ///See CSMSettings::support.hpp for enumerations / string values. class Setting { QList mProperties; @@ -19,10 +25,6 @@ namespace CSMSettings bool mIsEditorSetting; - //QString is the setting id in the form of "page.name" - //QList is a list of stringlists of proxy values. - //Order is important! Proxy stringlists are matched against - //master values by their position in the QList. ProxyValueMap mProxies; public: diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index d65de2b91a..229e293b8b 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -7,22 +7,10 @@ #include #include -//Typedefs -namespace CSMSettings -{ - // Definition / Declaration model typedefs - // "Pair" = Setting name and specific data - // "ListItem" = Page name and associated setting pair - - typedef QPair StringPair; - typedef QPair StringListPair; - typedef QList StringListPairs; - -} - //Enums namespace CSMSettings { + ///Enumerated properties for scripting enum SettingProperty { Property_Name = 0, @@ -55,6 +43,7 @@ namespace CSMSettings Property_Proxies = 25 }; + ///Basic setting widget types. enum SettingType { /* @@ -82,16 +71,11 @@ namespace CSMSettings Type_Undefined = 40 }; - enum MergeMethod - { - Merge_Accept, - Merge_Ignore, - Merge_Overwrite - }; } namespace CSVSettings { + ///Categorical view types which encompass the setting widget types enum ViewType { ViewType_Boolean = 0, @@ -100,18 +84,12 @@ namespace CSVSettings ViewType_Text = 3, ViewType_Undefined = 4 }; - - enum Alignment - { - Align_Left = Qt::AlignLeft, - Align_Center = Qt::AlignHCenter, - Align_Right = Qt::AlignRight - }; } namespace CSMSettings { + ///used to construct default settings in the Setting class struct PropertyDefaultValues { int id; @@ -119,6 +97,9 @@ namespace CSMSettings QVariant value; }; + ///strings which correspond to setting values. These strings represent + ///the script language keywords which would be used to declare setting + ///views for 3rd party addons const QString sPropertyNames[] = { "name", "page", "setting_type", "is_multi_value", @@ -129,6 +110,7 @@ namespace CSMSettings "defaults", "declarations", "definitions", "proxies" }; + ///Default values for a setting. Used in setting creation. const QString sPropertyDefaults[] = { "", //name diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index e26b1de5ca..8d71dbe822 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -1,16 +1,7 @@ #include "usersettings.hpp" -#include -#include -#include -#include -#include -#include -#include #include - #include -#include #include #include @@ -44,14 +35,6 @@ CSMSettings::UserSettings::UserSettings() mSettingDefinitions = 0; - mReadWriteMessage = QObject::tr("
Could not open or create file for \ - writing

Please make sure you have the right\ - permissions and try again.
"); - - mReadOnlyMessage = QObject::tr("
Could not open file for \ - reading

Please make sure you have the \ - right permissions and try again.
"); - buildSettingModelDefaults(); } @@ -318,32 +301,7 @@ CSMSettings::UserSettings::~UserSettings() { mUserSettingsInstance = 0; } -/* -void CSMSettings::UserSettings::displayFileErrorMessage - (const QString &userpath, - const QString &globalpath, - const QString &localpath) const -{ - QString message = QObject::tr("
An error was encountered loading \ - user settings files.

One or several files could not \ - be read. This may be caused by a missing configuration file, \ - incorrect file permissions or a corrupted installation of \ - OpenCS.
"); - message += QObject::tr("
Global filepath: ") + globalpath; - message += QObject::tr("
Local filepath: ") + localpath; - message += QObject::tr("
User filepath: ") + userpath; - - QMessageBox msgBox; - - msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - - msgBox.setText (mReadWriteMessage + message); - msgBox.exec(); -} -*/ void CSMSettings::UserSettings::loadSettings (const QString &fileName) { QString userFilePath = QString::fromUtf8 @@ -352,28 +310,16 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) QString globalFilePath = QString::fromUtf8 (mCfgMgr.getGlobalPath().string().c_str()); - QString localFilePath = QString::fromUtf8 - (mCfgMgr.getLocalPath().string().c_str()); - - bool isUser = QFile (userFilePath + fileName).exists(); - bool isSystem = QFile (globalFilePath + fileName).exists(); - QString otherFilePath = globalFilePath; //test for local only if global fails (uninstalled copy) - if (!isSystem) + if (!QFile (globalFilePath + fileName).exists()) { - isSystem = QFile (localFilePath + fileName).exists(); - otherFilePath = localFilePath; + //if global is invalid, use the local path + otherFilePath = QString::fromUtf8 + (mCfgMgr.getLocalPath().string().c_str()); } -/* - //error condition - notify and return - if (!isUser || !isSystem) - { - displayFileErrorMessage (userFilePath, globalFilePath, localFilePath); - return; - } -*/ + QSettings::setPath (QSettings::IniFormat, QSettings::UserScope, userFilePath); diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 7bb15e598e..3ac3487603 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -1,7 +1,7 @@ #ifndef USERSETTINGS_HPP #define USERSETTINGS_HPP -#include +#include #include #include #include @@ -32,8 +32,6 @@ namespace CSMSettings { static UserSettings *mUserSettingsInstance; Files::ConfigurationManager mCfgMgr; - QString mReadOnlyMessage; - QString mReadWriteMessage; QSettings *mSettingDefinitions; QList mSettings; diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index 32fc7a46ae..4e7b08aff7 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -76,22 +76,9 @@ void CSVSettings::Dialog::buildPages() mStackedWidget->addWidget (&dynamic_cast(*(page))); } - addDebugPage(); - resize (mStackedWidget->sizeHint()); } -void CSVSettings::Dialog::addDebugPage() -{ - /* - QTreeView *tree = new QTreeView(); - - //tree->setModel( &CSMSettings::UserSettings::instance().model() ); - - mStackedWidget->addWidget(tree); - new QListWidgetItem ("Standard Item Model", mPageListWidget);*/ -} - void CSVSettings::Dialog::buildPageListWidget (QWidget *centralWidget) { mPageListWidget = new QListWidget (centralWidget); diff --git a/apps/opencs/view/settings/dialog.hpp b/apps/opencs/view/settings/dialog.hpp index 0cfd415acd..b0e12c4615 100644 --- a/apps/opencs/view/settings/dialog.hpp +++ b/apps/opencs/view/settings/dialog.hpp @@ -41,7 +41,6 @@ namespace CSVSettings { void buildPages(); void buildPageListWidget (QWidget *centralWidget); void buildStackedWidget (QWidget *centralWidget); - void addDebugPage(); public slots: diff --git a/apps/opencs/view/settings/frame.hpp b/apps/opencs/view/settings/frame.hpp index 2b52dfd1f4..bbb92f34f7 100644 --- a/apps/opencs/view/settings/frame.hpp +++ b/apps/opencs/view/settings/frame.hpp @@ -44,11 +44,13 @@ namespace CSVSettings void setHLayout() { mIsHorizontal = true; } void setVLayout() { mIsHorizontal = false; } + ///show / hide widgets (when stacked widget page changes) void showWidgets(); void hideWidgets(); private: + ///functions which return the index for the next layout row / column int getNextColumn() const; int getNextRow() const; diff --git a/apps/opencs/view/settings/page.hpp b/apps/opencs/view/settings/page.hpp index 7f24f6a625..877d4bef8a 100644 --- a/apps/opencs/view/settings/page.hpp +++ b/apps/opencs/view/settings/page.hpp @@ -1,7 +1,6 @@ #ifndef CSVSETTINGS_PAGE_HPP #define CSVSETTINGS_PAGE_HPP -#include #include #include #include @@ -40,6 +39,7 @@ namespace CSVSettings ///and returns it. View *findView (const QString &page, const QString &setting) const; + ///returns the list of views associated with the page const QList &views () const { return mViews; } private: diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index b2701c7bf3..8ae6caca0b 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp index e8d6df88e3..2ab343f1f9 100644 --- a/apps/opencs/view/settings/rangeview.hpp +++ b/apps/opencs/view/settings/rangeview.hpp @@ -21,13 +21,19 @@ namespace CSVSettings Page *parent); protected: + + ///virtual function called through View void updateView (bool signalUpdate = true) const; + ///construct a slider-based view void buildSlider (CSMSettings::Setting *setting); + + ///construct a spinbox-based view void buildSpinBox (CSMSettings::Setting *setting); private slots: + ///responds to valueChanged signals void slotUpdateView (int value); void slotUpdateView (double value); diff --git a/apps/opencs/view/settings/resizeablestackedwidget.hpp b/apps/opencs/view/settings/resizeablestackedwidget.hpp index 5e894d8dfd..2d0c71a23a 100644 --- a/apps/opencs/view/settings/resizeablestackedwidget.hpp +++ b/apps/opencs/view/settings/resizeablestackedwidget.hpp @@ -14,8 +14,10 @@ namespace CSVSettings public: explicit ResizeableStackedWidget(QWidget *parent = 0); + ///add a widget to the stacked widget void addWidget(QWidget* pWidget); + ///called whenever the stacked widget page is changed void changePage (int, int); }; } diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 8354ced7f5..071f1b45ec 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -28,20 +28,28 @@ namespace CSVSettings { public: explicit SettingWindow(QWidget *parent = 0); + ///retrieve a reference to a view based on it's page and setting name View *findView (const QString &pageName, const QString &setting); + + ///set the model the view uses (instance of UserSettings) void setModel (CSMSettings::UserSettings &model) { mModel = &model; } protected: virtual void closeEvent (QCloseEvent *event); + ///construct the pages to be displayed in the dialog void createPages(); + ///return the list of constructed pages const PageList &pages() const { return mPages; } + ///save settings from the GUI to file void saveSettings(); private: + + ///create connections between settings (used for proxy settings) void createConnections (const QList &list); }; } diff --git a/apps/opencs/view/settings/spinbox.cpp b/apps/opencs/view/settings/spinbox.cpp index bfb1663709..4b1447f8f8 100644 --- a/apps/opencs/view/settings/spinbox.cpp +++ b/apps/opencs/view/settings/spinbox.cpp @@ -1,6 +1,5 @@ #include "spinbox.hpp" -#include #include CSVSettings::SpinBox::SpinBox(QWidget *parent) @@ -14,7 +13,7 @@ QString CSVSettings::SpinBox::textFromValue(int val) const if (mValueList.isEmpty()) return QVariant (val).toString(); - QString value = ""; + QString value; if (val < mValueList.size()) value = mValueList.at (val); diff --git a/apps/opencs/view/settings/spinbox.hpp b/apps/opencs/view/settings/spinbox.hpp index f8e59fa05a..e887e8c937 100644 --- a/apps/opencs/view/settings/spinbox.hpp +++ b/apps/opencs/view/settings/spinbox.hpp @@ -16,15 +16,22 @@ namespace CSVSettings public: explicit SpinBox(QWidget *parent = 0); - void setObjectName (const QString &name); - + ///set the value displayed in the spin box void setValue (const QString &value); + + ///set the stringlist that's used as a list of pre-defined values + ///to be displayed as the user scrolls void setValueList (const QStringList &list); + + ///returns the pre-defined value list. const QStringList &valueList() const { return mValueList; } protected: + ///converts an index value to corresponding text to be displayed QString textFromValue (int val) const; + + ///converts a text value to a corresponding index int valueFromText (const QString &text) const; }; } diff --git a/apps/opencs/view/settings/textview.hpp b/apps/opencs/view/settings/textview.hpp index c485e7fcf0..f4cd03d2f6 100644 --- a/apps/opencs/view/settings/textview.hpp +++ b/apps/opencs/view/settings/textview.hpp @@ -20,6 +20,7 @@ namespace CSVSettings protected: + /// virtual function called through View void updateView (bool signalUpdate = true) const; protected slots: diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 9e595478d7..c3b33cf84a 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -1,7 +1,8 @@ -#include -#include +#include #include #include +#include +#include #include "view.hpp" #include "../../model/settings/support.hpp" @@ -42,24 +43,22 @@ void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) void CSVSettings::View::buildFixedValueModel (const QStringList &values) { + //fixed value models are simple string list models, since they are read-only mDataModel = new QStringListModel (values, this); } void CSVSettings::View::buildUpdatableValueModel (const QStringList &values) { + //updateable models are standard item models because they support + //replacing entire columns QList itemList; foreach (const QString &value, values) itemList.append (new QStandardItem(value)); -// QSortFilterProxyModel *filter = new QSortFilterProxyModel (this); QStandardItemModel *model = new QStandardItemModel (this); model->appendColumn (itemList); -// filter->setSourceModel (model); - /* filter->setFilterRegExp ("*"); - filter->setFilterKeyColumn (0); - filter->setFilterRole (Qt::DisplayRole);*/ mDataModel = model; } @@ -151,9 +150,6 @@ void CSVSettings::View::setSelectedValues (const QStringList &list, } select (selection); - //push changes to model side - - //update the view if the selection was set from the model side, not by the //user if (doViewUpdate) @@ -192,7 +188,6 @@ bool CSVSettings::View::stringListsMatch ( QList CSVSettings::View::toStandardItemList (const QStringList &list) const { - QList itemList; foreach (const QString &value, list) @@ -212,12 +207,12 @@ QString CSVSettings::View::value (int row) const if (row > -1 && row < mDataModel->rowCount()) return mDataModel->data (mDataModel->index(row, 0)).toString(); - return ""; + return QString(); } int CSVSettings::View::widgetWidth(int characterCount) const { - QString widthToken = QString().fill ('P', characterCount); + QString widthToken = QString().fill ('m', characterCount); QFontMetrics fm (QApplication::font()); return (fm.width (widthToken)); diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp index 4f3af9ae58..5106d8d90f 100644 --- a/apps/opencs/view/settings/view.hpp +++ b/apps/opencs/view/settings/view.hpp @@ -11,8 +11,6 @@ class QGroupBox; class QStringList; class QStandardItem; class QItemSelection; -class QStringListModel; -class QStandardItemModel; class QAbstractItemModel; class QItemSelectionModel; @@ -52,9 +50,6 @@ namespace CSVSettings explicit View (CSMSettings::Setting *setting, Page *parent); - ///Physical frame in which the view UI is contained - void addViewWidget (QWidget *widget, int row = -1, int col = -1) const; - ///Returns the index / row of the passed value, -1 if not found. int currentIndex () const; From 224f5cf7db31532b6acf7b6467b47563de80b10c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 7 May 2014 19:14:04 +0200 Subject: [PATCH 193/545] updated changelog --- readme.txt | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/readme.txt b/readme.txt index a054626ddb..44f15fbcf8 100644 --- a/readme.txt +++ b/readme.txt @@ -96,6 +96,86 @@ Allowed options: CHANGELOG +0.30.0 + +Bug #416: Extreme shaking can occur during cell transitions while moving +Bug #1003: Province Cyrodiil: Ogre Exception in Stirk +Bug #1071: Crash when given a non-existent content file +Bug #1080: OpenMW allows resting/using a bed while in combat +Bug #1097: Wrong punishment for stealing in Census and Excise Office at the start of a new game +Bug #1098: Unlocked evidence chests should get locked after new evidence is put into them +Bug #1099: NPCs that you attacked still fight you after you went to jail/paid your fine +Bug #1100: Taking items from a corpse is considered stealing +Bug #1126: Some creatures can't get close enough to attack +Bug #1144: Killed creatures seem to die again each time player transitions indoors/outdoors +Bug #1181: loading a saved game does not reset the player control status +Bug #1185: Collision issues in Addamasartus +Bug #1187: Athyn Sarethi mission, rescuing varvur sarethi from the doesnt end the mission +Bug #1189: Crash when entering interior cell "Gnisis, Arvs-Drelen" +Bug #1191: Picking up papers without inventory in new game +Bug #1195: NPCs do not equip torches in certain interiors +Bug #1197: mouse wheel makes things scroll too fast +Bug #1200: door blocked by monsters +Bug #1201: item's magical charges are only refreshed when they are used +Bug #1203: Scribs do not defend themselves +Bug #1204: creatures life is not empty when they are dead +Bug #1205: armor experience does not progress when hits are taken +Bug #1206: blood particules always red. Undeads and mechanicals should have a different one. +Bug #1209: Tarhiel never falls +Bug #1210: journal adding script is ran again after having saved/loaded +Bug #1224: Names of custom classes are not properly handled in save games +Bug #1227: Editor: Fixed case handling for broken localised versions of Morrowind.esm +Bug #1235: Indoors walk stutter +Bug #1236: Aborting intro movie brings up the menu +Bug #1239: NPCs get stuck when walking past each other +Bug #1240: BTB - Settings 14.1 and Health Bar. +Bug #1241: BTB - Character and Khajiit Prejudice +Bug #1248: GUI Weapon icon is changed to hand-to-hand after save load +Bug #1254: Guild ranks do not show in dialogue +Bug #1255: When opening a container and selecting "Take All", the screen flashes blue +Bug #1260: Level Up menu doesn't show image when using a custom class +Bug #1265: Quit Menu Has Misaligned Buttons +Bug #1270: Active weapon icon is not updated when weapon is repaired +Bug #1271: NPC Stuck in hovering "Jumping" animation +Bug #1272: Crash when attempting to load Big City esm file. +Bug #1276: Editor: Dropping a region into the filter of a cell subview fails +Bug #1286: Dialogue topic list clips with window frame +Bug #1291: Saved game: store faction membership +Bug #1293: Pluginless Khajiit Head Pack by ashiraniir makes OpenMW close. +Bug #1294: Pasting in console adds text to end, not at cursor +Bug #1295: Conversation loop when asking about "specific place" in Vivec +Bug #1296: Caius doesn't leave at start of quest "Mehra Milo and the Lost Prophecies" +Bug #1297: Saved game: map markers +Bug #1302: ring_keley script causes vector::_M_range_check exception +Bug #1309: Bug on "You violated the law" dialog +Feature #50: Ranged Combat +Feature #58: Sneaking Skill +Feature #73: Crime and Punishment +Feature #135: Editor: OGRE integration +Feature #541: Editor: Dialogue Sub-Views +Feature #944: Editor: lighting modes +Feature #945: Editor: Camera navigation mode +Feature #953: Trader gold +Feature #1140: AI: summoned creatures +Feature #1142: AI follow: Run stance +Feature #1154: Not all NPCs get aggressive when one is attacked +Feature #1169: Terrain threading +Feature #1172: Loading screen and progress bars during saved/loading game +Feature #1173: Saved Game: include weather state +Feature #1207: Class creation form does not remember +Feature #1220: Editor: Preview Subview +Feature #1223: Saved Game: Local Variables +Feature #1229: Quicksave, quickload, autosave +Feature #1230: Deleting saves +Feature #1233: Bribe gold is placed into NPCs inventory +Feature #1252: Saved Game: quick key bindings +Feature #1273: Editor: Region Map context menu +Feature #1274: Editor: Region Map drag & drop +Feature #1275: Editor: Scene subview drop +Feature #1282: Non-faction member crime recognition. +Feature #1289: NPCs return to default position +Task #941: Remove unused cmake files + 0.29.0 Bug #556: Video soundtrack not played when music volume is set to zero From cd7983adb5f04140e72ad157b03b1eb931293259 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Wed, 7 May 2014 21:59:26 -0500 Subject: [PATCH 194/545] Decoupled setting definitions from the Setting class. QSettings implementation is now fully responsible for managing user settings. --- apps/opencs/model/settings/connector.cpp | 1 + apps/opencs/model/settings/setting.cpp | 10 --- apps/opencs/model/settings/setting.hpp | 3 - apps/opencs/model/settings/usersettings.cpp | 85 +++++++++------------ apps/opencs/model/settings/usersettings.hpp | 17 +++-- apps/opencs/view/settings/dialog.cpp | 3 + apps/opencs/view/settings/settingwindow.cpp | 31 ++++++-- apps/opencs/view/settings/settingwindow.hpp | 3 + apps/opencs/view/settings/view.cpp | 7 +- apps/opencs/view/settings/view.hpp | 2 +- 10 files changed, 83 insertions(+), 79 deletions(-) diff --git a/apps/opencs/model/settings/connector.cpp b/apps/opencs/model/settings/connector.cpp index 05a9ba8f96..5e1d64544d 100644 --- a/apps/opencs/model/settings/connector.cpp +++ b/apps/opencs/model/settings/connector.cpp @@ -81,6 +81,7 @@ void CSMSettings::Connector::slotUpdateMaster() const } QString masterValue = mMasterView->value (masterColumn); + mMasterView->setSelectedValue (masterValue); } diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index 2ef829f865..2f86d4ff83 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -77,16 +77,6 @@ QStringList CSMSettings::Setting::declaredValues() const return property (Property_DeclaredValues); } -void CSMSettings::Setting::setDefinedValues (QStringList list) -{ - setProperty (Property_DefinedValues, list); -} - -QStringList CSMSettings::Setting::definedValues() const -{ - return property (Property_DefinedValues); -} - QStringList CSMSettings::Setting::property (SettingProperty prop) const { if (prop >= mProperties.size()) diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index 89d6cc2c48..e40302f009 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -44,9 +44,6 @@ namespace CSMSettings void setDeclaredValues (QStringList list); QStringList declaredValues() const; - void setDefinedValues (QStringList list); - QStringList definedValues() const; - void setDefaultValue (int value); void setDefaultValue (double value); void setDefaultValue (const QString &value); diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 8d71dbe822..1a91254390 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -38,31 +38,6 @@ CSMSettings::UserSettings::UserSettings() buildSettingModelDefaults(); } -void CSMSettings::UserSettings::addDefinitions () -{ - foreach (const QString &key, mSettingDefinitions->allKeys()) - { - QStringList names = key.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << names.at(0) << "/" << names.at(1); - removeSetting (names.at(0), names.at(1)); - continue; - } - - QStringList values = mSettingDefinitions->value (key).toStringList(); - - if (values.isEmpty()) - values.append (setting->defaultValues()); - - setting->setDefinedValues (values); - } -} - void CSMSettings::UserSettings::buildSettingModelDefaults() { QString section = "Window Size"; @@ -139,13 +114,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * Defined values * * Values which represent the actual, current value of - * a setting. For settings with declared values, this must be one or - * several declared values, as appropriate. + * a setting. For settings with declared values, this must be one + * or several declared values, as appropriate. * - * Proxy values - values the proxy master updates the proxy slave when - * it's own definition is set / changed. These are definitions for - * proxy slave settings, but must match any declared values the proxy - * slave has, if any. + * Proxy values + * Values the proxy master updates the proxy slave when + * it's own definition is set / changed. These are definitions for + * proxy slave settings, but must match any declared values the + * proxy slave has, if any. *******************************************************************/ /* //create setting objects, specifying the basic widget type, @@ -328,31 +304,36 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) mSettingDefinitions = new QSettings (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); - - addDefinitions(); } -void CSMSettings::UserSettings::saveSettings - (const QMap &settingMap) +bool CSMSettings::UserSettings::hasSettingDefinitions + (const QString &viewKey) const { - foreach (const QString &key, settingMap.keys()) - mSettingDefinitions->setValue (key, settingMap.value (key)); + return (mSettingDefinitions->contains (viewKey)); +} +void CSMSettings::UserSettings::setDefinitions + (const QString &key, const QStringList &list) +{ + mSettingDefinitions->setValue (key, list); +} + +void CSMSettings::UserSettings::saveDefinitions() const +{ mSettingDefinitions->sync(); } QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { - QStringList names = settingKey.split('/'); + if (!mSettingDefinitions->contains (settingKey)) + return QString(); - Setting *setting = findSetting(names.at(0), names.at(1)); + QStringList defs = mSettingDefinitions->value (settingKey).toStringList(); - if (setting) - { - if (!setting->definedValues().isEmpty()) - return setting->definedValues().at(0); - } - return ""; + if (defs.isEmpty()) + return QString(); + + return defs.at(0); } CSMSettings::UserSettings& CSMSettings::UserSettings::instance() @@ -364,11 +345,7 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance() void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey, const QStringList &list) { - QStringList names = settingKey.split('/'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - setting->setDefinedValues (list); + mSettingDefinitions->setValue (settingKey ,list); emit userSettingUpdated (settingKey, list); } @@ -439,3 +416,11 @@ CSMSettings::Setting *CSMSettings::UserSettings::createSetting return setting; } + +QStringList CSMSettings::UserSettings::definitions (const QString &viewKey) const +{ + if (mSettingDefinitions->contains (viewKey)) + return mSettingDefinitions->value (viewKey).toStringList(); + + return QStringList(); +} diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 3ac3487603..830cc8c69f 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -49,8 +49,8 @@ namespace CSMSettings { /// Retrieves the settings file at all three levels (global, local and user). void loadSettings (const QString &fileName); - /// Writes settings to the user's config file path - void saveSettings (const QMap &settingMap); + /// Updates QSettings and syncs with the ini file + void setDefinitions (const QString &key, const QStringList &defs); QString settingValue (const QString &settingKey); @@ -65,10 +65,17 @@ namespace CSMSettings { ///Retreive a map of the settings, keyed by page name SettingPageMap settingPageMap() const; - private: + ///Returns a string list of defined vlaues for the specified setting + ///in "page/name" format. + QStringList definitions (const QString &viewKey) const; - ///add definitions to the settings specified in the page map - void addDefinitions(); + ///Test to indicate whether or not a setting has any definitions + bool hasSettingDefinitions (const QString &viewKey) const; + + ///Save any unsaved changes in the QSettings object + void saveDefinitions() const; + + private: void buildSettingModelDefaults(); diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index 4e7b08aff7..56bc1fdfee 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -109,7 +109,10 @@ void CSVSettings::Dialog::closeEvent (QCloseEvent *event) void CSVSettings::Dialog::show() { if (pages().isEmpty()) + { buildPages(); + setViewValues(); + } QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index aeb652b3b4..7cdf2bded9 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -82,6 +82,25 @@ void CSVSettings::SettingWindow::createConnections } } +void CSVSettings::SettingWindow::setViewValues() +{ + //iterate each page and view, setting their definintions + //if they exist in the model + foreach (const Page *page, mPages) + { + foreach (const View *view, page->views()) + { + //testing beforehand prevents overwriting a proxy setting + if (!mModel->hasSettingDefinitions (view->viewKey())) + continue; + + QStringList defs = mModel->definitions (view->viewKey()); + + view->setSelectedValues(defs); + } + } +} + CSVSettings::View *CSVSettings::SettingWindow::findView (const QString &pageName, const QString &setting) { @@ -95,17 +114,19 @@ CSVSettings::View *CSVSettings::SettingWindow::findView void CSVSettings::SettingWindow::saveSettings() { - QMap settingMap; - + //setting the definition in the model automatically syncs with the file foreach (const Page *page, mPages) { foreach (const View *view, page->views()) { - if (view->serializable()) - settingMap[view->viewKey()] = view->selectedValues(); + if (!view->serializable()) + continue; + + mModel->setDefinitions (view->viewKey(), view->selectedValues()); } } - CSMSettings::UserSettings::instance().saveSettings (settingMap); + + mModel->saveDefinitions(); } void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event) diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 071f1b45ec..2266f130df 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -47,6 +47,9 @@ namespace CSVSettings { ///save settings from the GUI to file void saveSettings(); + ///sets the defined values for the views that have been created + void setViewValues(); + private: ///create connections between settings (used for proxy settings) diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index c3b33cf84a..69109e2b31 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -26,10 +26,7 @@ CSVSettings::View::View(CSMSettings::Setting *setting, void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) { - QStringList values = setting->definedValues(); - - if (values.isEmpty()) - values.append (setting->defaultValues()); + QStringList values = setting->defaultValues(); if (mHasFixedValues) buildFixedValueModel (setting->declaredValues()); @@ -116,7 +113,7 @@ void CSVSettings::View::setSelectedValue (const QString &value, } void CSVSettings::View::setSelectedValues (const QStringList &list, - bool doViewUpdate, bool signalUpdate) + bool doViewUpdate, bool signalUpdate) const { QItemSelection selection; diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp index 5106d8d90f..84ad62759e 100644 --- a/apps/opencs/view/settings/view.hpp +++ b/apps/opencs/view/settings/view.hpp @@ -71,7 +71,7 @@ namespace CSVSettings ///or signaling the view was updatedto avoid viscious cylcing. void setSelectedValues (const QStringList &values, bool updateView = true, - bool signalUpdate = true); + bool signalUpdate = true) const; void setSelectedValue (const QString &value, bool updateView = true, From 205306ee3d9294ace22c46455c195524f447eb97 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 May 2014 12:42:29 +0200 Subject: [PATCH 195/545] changed message passing format from QString to a UniversalId/std::string pair --- apps/opencs/main.cpp | 5 + apps/opencs/model/doc/document.cpp | 10 +- apps/opencs/model/doc/document.hpp | 3 +- apps/opencs/model/doc/operation.cpp | 10 +- apps/opencs/model/doc/operation.hpp | 8 +- apps/opencs/model/doc/savingstages.cpp | 14 +- apps/opencs/model/doc/savingstages.hpp | 18 +- apps/opencs/model/doc/stage.hpp | 6 +- apps/opencs/model/tools/birthsigncheck.cpp | 8 +- apps/opencs/model/tools/birthsigncheck.hpp | 2 +- apps/opencs/model/tools/classcheck.cpp | 25 +- apps/opencs/model/tools/classcheck.hpp | 2 +- apps/opencs/model/tools/factioncheck.cpp | 19 +- apps/opencs/model/tools/factioncheck.hpp | 2 +- apps/opencs/model/tools/mandatoryid.cpp | 5 +- apps/opencs/model/tools/mandatoryid.hpp | 2 +- apps/opencs/model/tools/racecheck.cpp | 20 +- apps/opencs/model/tools/racecheck.hpp | 6 +- .../opencs/model/tools/referenceablecheck.cpp | 488 ++++++------------ .../opencs/model/tools/referenceablecheck.hpp | 75 +-- apps/opencs/model/tools/regioncheck.cpp | 4 +- apps/opencs/model/tools/regioncheck.hpp | 2 +- apps/opencs/model/tools/reportmodel.cpp | 9 +- apps/opencs/model/tools/reportmodel.hpp | 2 +- apps/opencs/model/tools/scriptcheck.cpp | 27 +- apps/opencs/model/tools/scriptcheck.hpp | 4 +- apps/opencs/model/tools/skillcheck.cpp | 8 +- apps/opencs/model/tools/skillcheck.hpp | 2 +- apps/opencs/model/tools/soundcheck.cpp | 4 +- apps/opencs/model/tools/soundcheck.hpp | 2 +- apps/opencs/model/tools/spellcheck.cpp | 6 +- apps/opencs/model/tools/spellcheck.hpp | 2 +- apps/opencs/model/tools/tools.cpp | 10 +- apps/opencs/model/tools/tools.hpp | 3 +- 34 files changed, 316 insertions(+), 497 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index eded36394a..8f5bfbc12d 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -6,11 +6,14 @@ #include #include +#include #include #include +#include "model/world/universalid.hpp" + #ifdef Q_OS_MAC #include #endif @@ -42,6 +45,8 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE (resources); + qRegisterMetaType ("CSMWorld::UniversalId"); + OgreInit::OgreInit ogreInit; std::auto_ptr shinyFactory; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3ef14ee7e5..bbce7fa3f4 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2288,8 +2288,9 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int))); - connect (&mSaving, SIGNAL (reportMessage (const QString&, int)), - this, SLOT (reportMessage (const QString&, int))); + connect ( + &mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), + this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int))); } CSMDoc::Document::~Document() @@ -2358,10 +2359,11 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } -void CSMDoc::Document::reportMessage (const QString& message, int type) +void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type) { /// \todo find a better way to get these messages to the user. - std::cout << message.toUtf8().constData() << std::endl; + std::cout << message << std::endl; } void CSMDoc::Document::operationDone (int type) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 201fb4342a..33378511bb 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -111,7 +111,8 @@ namespace CSMDoc void modificationStateChanged (bool clean); - void reportMessage (const QString& message, int type); + void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); void operationDone (int type); diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index d29cc2631b..42a432043c 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -6,6 +6,8 @@ #include +#include "../world/universalid.hpp" + #include "state.hpp" #include "stage.hpp" @@ -80,7 +82,7 @@ void CSMDoc::Operation::abort() void CSMDoc::Operation::executeStage() { - std::vector messages; + Stage::Messages messages; while (mCurrentStage!=mStages.end()) { @@ -97,7 +99,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (e.what(), mType); + emit reportMessage (CSMWorld::UniversalId(), e.what(), mType); abort(); } @@ -108,8 +110,8 @@ void CSMDoc::Operation::executeStage() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); - for (std::vector::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) - emit reportMessage (iter->c_str(), mType); + for (Stage::Messages::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) + emit reportMessage (iter->first, iter->second, mType); if (mCurrentStage==mStages.end()) exit(); diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 316eda78fd..6512838806 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -5,6 +5,11 @@ #include +namespace CSMWorld +{ + class UniversalId; +} + namespace CSMDoc { class Stage; @@ -46,7 +51,8 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const QString& message, int type); + void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); void done (int type); diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index d7df2117d0..eb93d90475 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -23,7 +23,7 @@ int CSMDoc::OpenSaveStage::setup() return 1; } -void CSMDoc::OpenSaveStage::perform (int stage, std::vector& messages) +void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages) { mState.start (mDocument, mProjectFile); @@ -43,7 +43,7 @@ int CSMDoc::WriteHeaderStage::setup() return 1; } -void CSMDoc::WriteHeaderStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) { mState.getWriter().setVersion(); @@ -96,7 +96,7 @@ int CSMDoc::WriteDialogueCollectionStage::setup() return mTopics.getSize(); } -void CSMDoc::WriteDialogueCollectionStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages) { const CSMWorld::Record& topic = mTopics.getRecord (stage); @@ -191,7 +191,7 @@ int CSMDoc::WriteRefIdCollectionStage::setup() return mDocument.getData().getReferenceables().getSize(); } -void CSMDoc::WriteRefIdCollectionStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages) { mDocument.getData().getReferenceables().save (stage, mState.getWriter()); } @@ -204,7 +204,7 @@ CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& sta mDocument (document), mScope (scope) {} -void CSMDoc::WriteFilterStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mDocument.getData().getFilters().getRecord (stage); @@ -223,7 +223,7 @@ int CSMDoc::CloseSaveStage::setup() return 1; } -void CSMDoc::CloseSaveStage::perform (int stage, std::vector& messages) +void CSMDoc::CloseSaveStage::perform (int stage, Messages& messages) { mState.getStream().close(); @@ -241,7 +241,7 @@ int CSMDoc::FinalSavingStage::setup() return 1; } -void CSMDoc::FinalSavingStage::perform (int stage, std::vector& messages) +void CSMDoc::FinalSavingStage::perform (int stage, Messages& messages) { if (mState.hasError()) { diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index b8eb0a3b30..c2f0a150a9 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -39,7 +39,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -57,7 +57,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -75,7 +75,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -92,7 +92,7 @@ namespace CSMDoc } template - void WriteCollectionStage::perform (int stage, std::vector& messages) + void WriteCollectionStage::perform (int stage, Messages& messages) { CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState; @@ -130,7 +130,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -147,7 +147,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -161,7 +161,7 @@ namespace CSMDoc WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope); - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -177,7 +177,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -193,7 +193,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/doc/stage.hpp b/apps/opencs/model/doc/stage.hpp index 1f96c60b43..ca34c22299 100644 --- a/apps/opencs/model/doc/stage.hpp +++ b/apps/opencs/model/doc/stage.hpp @@ -4,18 +4,22 @@ #include #include +#include "../world/universalid.hpp" + namespace CSMDoc { class Stage { public: + typedef std::vector > Messages; + virtual ~Stage(); virtual int setup() = 0; ///< \return number of steps - virtual void perform (int stage, std::vector& messages) = 0; + virtual void perform (int stage, Messages& messages) = 0; ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/birthsigncheck.cpp b/apps/opencs/model/tools/birthsigncheck.cpp index 59c65086ed..db20ce4bcd 100644 --- a/apps/opencs/model/tools/birthsigncheck.cpp +++ b/apps/opencs/model/tools/birthsigncheck.cpp @@ -17,7 +17,7 @@ int CSMTools::BirthsignCheckStage::setup() return mBirthsigns.getSize(); } -void CSMTools::BirthsignCheckStage::perform (int stage, std::vector& messages) +void CSMTools::BirthsignCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mBirthsigns.getRecord (stage); @@ -30,13 +30,13 @@ void CSMTools::BirthsignCheckStage::perform (int stage, std::vector // test for empty name, description and texture if (birthsign.mName.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name"); + messages.push_back (std::make_pair (id, birthsign.mId + " has an empty name")); if (birthsign.mDescription.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description"); + messages.push_back (std::make_pair (id, birthsign.mId + " has an empty description")); if (birthsign.mTexture.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture"); + messages.push_back (std::make_pair (id, birthsign.mId + " is missing a texture")); /// \todo test if the texture exists diff --git a/apps/opencs/model/tools/birthsigncheck.hpp b/apps/opencs/model/tools/birthsigncheck.hpp index bdd65b44ab..1030e5c021 100644 --- a/apps/opencs/model/tools/birthsigncheck.hpp +++ b/apps/opencs/model/tools/birthsigncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index 6923b31535..cea4f3a686 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -18,7 +18,7 @@ int CSMTools::ClassCheckStage::setup() return mClasses.getSize(); } -void CSMTools::ClassCheckStage::perform (int stage, std::vector& messages) +void CSMTools::ClassCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mClasses.getRecord (stage); @@ -31,10 +31,10 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me // test for empty name and description if (class_.mName.empty()) - messages.push_back (id.toString() + "|" + class_.mId + " has an empty name"); + messages.push_back (std::make_pair (id, class_.mId + " has an empty name")); if (class_.mDescription.empty()) - messages.push_back (id.toString() + "|" + class_.mId + " has an empty description"); + messages.push_back (std::make_pair (id, class_.mId + " has an empty description")); // test for invalid attributes for (int i=0; i<2; ++i) @@ -42,18 +42,14 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me { std::ostringstream stream; - stream << id.toString() << "|Attribute #" << i << " of " << class_.mId << " is not set"; + stream << "Attribute #" << i << " of " << class_.mId << " is not set"; - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, stream.str())); } if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1) { - std::ostringstream stream; - - stream << id.toString() << "|Class lists same attribute twice"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, "Class lists same attribute twice")); } // test for non-unique skill @@ -66,12 +62,7 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) if (iter->second>1) { - std::ostringstream stream; - - stream - << id.toString() << "|" - << ESM::Skill::indexToId (iter->first) << " is listed more than once"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + ESM::Skill::indexToId (iter->first) + " is listed more than once")); } } \ No newline at end of file diff --git a/apps/opencs/model/tools/classcheck.hpp b/apps/opencs/model/tools/classcheck.hpp index 3604b451c5..ec50ba35d1 100644 --- a/apps/opencs/model/tools/classcheck.hpp +++ b/apps/opencs/model/tools/classcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/factioncheck.cpp b/apps/opencs/model/tools/factioncheck.cpp index c219e56102..42d577163f 100644 --- a/apps/opencs/model/tools/factioncheck.cpp +++ b/apps/opencs/model/tools/factioncheck.cpp @@ -18,7 +18,7 @@ int CSMTools::FactionCheckStage::setup() return mFactions.getSize(); } -void CSMTools::FactionCheckStage::perform (int stage, std::vector& messages) +void CSMTools::FactionCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mFactions.getRecord (stage); @@ -31,16 +31,12 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector& // test for empty name if (faction.mName.empty()) - messages.push_back (id.toString() + "|" + faction.mId + " has an empty name"); + messages.push_back (std::make_pair (id, faction.mId + " has an empty name")); // test for invalid attributes if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1) { - std::ostringstream stream; - - stream << id.toString() << "|Faction lists same attribute twice"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id , "Faction lists same attribute twice")); } // test for non-unique skill @@ -53,13 +49,8 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector& for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) if (iter->second>1) { - std::ostringstream stream; - - stream - << id.toString() << "|" - << ESM::Skill::indexToId (iter->first) << " is listed more than once"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + ESM::Skill::indexToId (iter->first) + " is listed more than once")); } /// \todo check data members that can't be edited in the table view diff --git a/apps/opencs/model/tools/factioncheck.hpp b/apps/opencs/model/tools/factioncheck.hpp index 7cd80347db..ccc44e6a92 100644 --- a/apps/opencs/model/tools/factioncheck.hpp +++ b/apps/opencs/model/tools/factioncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index b99abec6d2..5f245dd4d4 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -15,9 +15,10 @@ int CSMTools::MandatoryIdStage::setup() return mIds.size(); } -void CSMTools::MandatoryIdStage::perform (int stage, std::vector& messages) +void CSMTools::MandatoryIdStage::perform (int stage, Messages& messages) { if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) - messages.push_back (mCollectionId.toString() + "|Missing mandatory record: " + mIds.at (stage)); + messages.push_back (std::make_pair (mCollectionId, + "|Missing mandatory record: " + mIds.at (stage))); } \ No newline at end of file diff --git a/apps/opencs/model/tools/mandatoryid.hpp b/apps/opencs/model/tools/mandatoryid.hpp index 5fddf08d32..a8afea62af 100644 --- a/apps/opencs/model/tools/mandatoryid.hpp +++ b/apps/opencs/model/tools/mandatoryid.hpp @@ -30,7 +30,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 413de5ef01..47aeda1e69 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -7,7 +7,7 @@ #include "../world/universalid.hpp" -void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::performPerRecord (int stage, Messages& messages) { const CSMWorld::Record& record = mRaces.getRecord (stage); @@ -20,24 +20,24 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::performFinal (Messages& messages) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races); if (!mPlayable) - messages.push_back (id.toString() + "|No playable race"); + messages.push_back (std::make_pair (id, "No playable race")); } CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection& races) @@ -64,7 +64,7 @@ int CSMTools::RaceCheckStage::setup() return mRaces.getSize()+1; } -void CSMTools::RaceCheckStage::perform (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::perform (int stage, Messages& messages) { if (stage==mRaces.getSize()) performFinal (messages); diff --git a/apps/opencs/model/tools/racecheck.hpp b/apps/opencs/model/tools/racecheck.hpp index ff9948bf6d..c68b283be4 100644 --- a/apps/opencs/model/tools/racecheck.hpp +++ b/apps/opencs/model/tools/racecheck.hpp @@ -15,9 +15,9 @@ namespace CSMTools const CSMWorld::IdCollection& mRaces; bool mPlayable; - void performPerRecord (int stage, std::vector& messages); + void performPerRecord (int stage, Messages& messages); - void performFinal (std::vector& messages); + void performFinal (Messages& messages); public: @@ -26,7 +26,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index dab61bfffa..488081f46f 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -1,7 +1,9 @@ #include "referenceablecheck.hpp" + +#include + #include "../world/record.hpp" #include "../world/universalid.hpp" -#include CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection& races, @@ -16,7 +18,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( { } -void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::perform (int stage, Messages& messages) { //Checks for books, than, when stage is above mBooksSize goes to other checks, with (stage - PrevSum) as stage. const int bookSize(mReferencables.getBooks().getSize()); @@ -206,11 +208,11 @@ void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::str staticCheck(stage, mReferencables.getStatics(), messages); return; } - + stage -= staticSize; const int creatureSize(mReferencables.getCreatures().getSize()); - + if (stage < creatureSize) { creatureCheck(stage, mReferencables.getCreatures(), messages); @@ -230,7 +232,7 @@ int CSMTools::ReferenceableCheckStage::setup() void CSMTools::ReferenceableCheckStage::bookCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -248,7 +250,7 @@ void CSMTools::ReferenceableCheckStage::bookCheck( void CSMTools::ReferenceableCheckStage::activatorCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -262,15 +264,13 @@ void CSMTools::ReferenceableCheckStage::activatorCheck( //Checking for model, IIRC all activators should have a model if (activator.mModel.empty()) - { - messages.push_back(id.toString() + "|" + activator.mId + " has no model"); - } + messages.push_back (std::make_pair (id, activator.mId + " has no model")); } void CSMTools::ReferenceableCheckStage::potionCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Potion >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -290,7 +290,7 @@ void CSMTools::ReferenceableCheckStage::potionCheck( void CSMTools::ReferenceableCheckStage::apparatusCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Apparatus >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -310,7 +310,7 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck( void CSMTools::ReferenceableCheckStage::armorCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Armor >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -326,21 +326,17 @@ void CSMTools::ReferenceableCheckStage::armorCheck( //checking for armor class, armor should have poistive armor class, but 0 is considered legal if (armor.mData.mArmor < 0) - { - messages.push_back(id.toString() + "|" + armor.mId + " has negative armor class"); - } + messages.push_back (std::make_pair (id, armor.mId + " has negative armor class")); //checking for health. Only positive numbers are allowed, or 0 is illegal if (armor.mData.mHealth <= 0) - { - messages.push_back(id.toString() + "|" + armor.mId + " has non positive health"); - } + messages.push_back (std::make_pair (id, armor.mId + " has non positive health")); } void CSMTools::ReferenceableCheckStage::clothingCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Clothing >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -357,7 +353,7 @@ void CSMTools::ReferenceableCheckStage::clothingCheck( void CSMTools::ReferenceableCheckStage::containerCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Container >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -371,153 +367,109 @@ void CSMTools::ReferenceableCheckStage::containerCheck( //Checking for model, IIRC all containers should have a model if (container.mModel.empty()) - { - messages.push_back(id.toString() + "|" + container.mId + " has no model"); - } + messages.push_back (std::make_pair (id, container.mId + " has no model")); //Checking for capacity (weight) if (container.mWeight < 0) //0 is allowed - { - messages.push_back(id.toString() + "|" + container.mId + " has negative weight (capacity)"); - } + messages.push_back (std::make_pair (id, + container.mId + " has negative weight (capacity)")); //checking for name if (container.mName.empty()) - { - messages.push_back(id.toString() + "|" + container.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, container.mId + " has an empty name")); } -void CSMTools::ReferenceableCheckStage::creatureCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Creature >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::creatureCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Creature >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Creature& creature = (dynamic_cast&>(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Creature, creature.mId); if (creature.mModel.empty()) - { - messages.push_back(id.toString() + "|" + creature.mId + " has no model"); - } + messages.push_back (std::make_pair (id, creature.mId + " has no model")); if (creature.mName.empty()) - { - messages.push_back(id.toString() + "|" + creature.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, creature.mId + " has an empty name")); //stats checks if (creature.mData.mLevel < 1) - { - messages.push_back(id.toString() + "|" + creature.mId + " has non-postive level"); - } + messages.push_back (std::make_pair (id, creature.mId + " has non-postive level")); if (creature.mData.mStrength < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative strength"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative strength")); if (creature.mData.mIntelligence < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative intelligence"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative intelligence")); if (creature.mData.mWillpower < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative willpower"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative willpower")); if (creature.mData.mAgility < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative agility"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative agility")); if (creature.mData.mSpeed < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative speed"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative speed")); if (creature.mData.mEndurance < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative endurance"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative endurance")); if (creature.mData.mPersonality < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative personality"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative personality")); if (creature.mData.mLuck < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative luck"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative luck")); if (creature.mData.mHealth < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative health"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative health")); if (creature.mData.mSoul < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative soul value"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative soul value")); for (int i = 0; i < 6; ++i) { if (creature.mData.mAttack[i] < 0) { - messages.push_back(id.toString() + "|" + creature.mId + " has negative attack strength"); + messages.push_back (std::make_pair (id, + creature.mId + " has negative attack strength")); break; } } //TODO, find meaning of other values if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative gold "); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative gold ")); } void CSMTools::ReferenceableCheckStage::doorCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Door >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Door >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Door& Door = (dynamic_cast&>(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, Door.mId); //usual, name or model if (Door.mName.empty()) - { - messages.push_back(id.toString() + "|" + Door.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, Door.mId + " has an empty name")); if (Door.mModel.empty()) - { - messages.push_back(id.toString() + "|" + Door.mId + " has no model"); - } - - //TODO, check what static unsigned int sRecordId; is for + messages.push_back (std::make_pair (id, Door.mId + " has no model")); } void CSMTools::ReferenceableCheckStage::ingredientCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Ingredient >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -535,7 +487,7 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck( void CSMTools::ReferenceableCheckStage::creaturesLevListCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::CreatureLevList >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -553,7 +505,7 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck( void CSMTools::ReferenceableCheckStage::itemLevelledListCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::ItemLevList >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -569,40 +521,33 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck( } void CSMTools::ReferenceableCheckStage::lightCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Light >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Light >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Light& light = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Light, light.mId); if (light.mData.mRadius < 0) - { - messages.push_back(id.toString() + "|" + light.mId + " has negative light radius"); - } + messages.push_back (std::make_pair (id, light.mId + " has negative light radius")); if (light.mData.mFlags & ESM::Light::Carry) { inventoryItemCheck(light, messages, id.toString()); if (light.mData.mTime == 0) - { - messages.push_back(id.toString() + "|" + light.mId + " has zero duration"); - } + messages.push_back (std::make_pair (id, light.mId + " has zero duration")); } } void CSMTools::ReferenceableCheckStage::lockpickCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Lockpick >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -622,7 +567,7 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck( void CSMTools::ReferenceableCheckStage::miscCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Miscellaneous >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -637,20 +582,17 @@ void CSMTools::ReferenceableCheckStage::miscCheck( inventoryItemCheck(miscellaneous, messages, id.toString()); } -void CSMTools::ReferenceableCheckStage::npcCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::NPC >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::npcCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::NPC >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::NPC& npc = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId); short level(npc.mNpdt52.mLevel); char disposition(npc.mNpdt52.mDisposition); @@ -661,15 +603,13 @@ void CSMTools::ReferenceableCheckStage::npcCheck( //Detect if player is present if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl? - { mPlayerPresent = true; - } if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated { if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag { - messages.push_back(id.toString() + "|" + npc.mId + " mNpdtType or flags mismatch!"); //should not happend? + messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend? return; } @@ -682,145 +622,100 @@ void CSMTools::ReferenceableCheckStage::npcCheck( else { if (npc.mNpdt52.mMana < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " mana has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " mana has negative value")); if (npc.mNpdt52.mFatigue < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " fatigue has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " fatigue has negative value")); if (npc.mNpdt52.mAgility == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " agility has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " agility has zero value")); if (npc.mNpdt52.mEndurance == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " endurance has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " endurance has zero value")); if (npc.mNpdt52.mIntelligence == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " intelligence has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " intelligence has zero value")); if (npc.mNpdt52.mLuck == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " luck has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " luck has zero value")); if (npc.mNpdt52.mPersonality == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " personality has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " personality has zero value")); if (npc.mNpdt52.mStrength == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " strength has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " strength has zero value")); if (npc.mNpdt52.mSpeed == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " speed has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " speed has zero value")); if (npc.mNpdt52.mWillpower == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " willpower has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " willpower has zero value")); } if (level < 1) - { - messages.push_back(id.toString() + "|" + npc.mId + " level is non positive"); - } + messages.push_back (std::make_pair (id, npc.mId + " level is non positive")); if (gold < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " gold has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " gold has negative value")); if (npc.mName.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty name"); - } + messages.push_back (std::make_pair (id, npc.mId + " has any empty name")); if (npc.mClass.empty()) { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty class"); + messages.push_back (std::make_pair (id, npc.mId + " has any empty class")); } - else //checking if there is such class + else if (mClasses.searchId (npc.mClass) == -1) { - if (mClasses.searchId(npc.mClass) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid class"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid class")); } if (npc.mRace.empty()) { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty race"); + messages.push_back (std::make_pair (id, npc.mId + " has any empty race")); } - else //checking if there is a such race + else if (mRaces.searchId (npc.mRace) == -1) { - if (mRaces.searchId(npc.mRace) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid race"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid race")); } if (disposition < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " has negative disposition"); - } + messages.push_back (std::make_pair (id, npc.mId + " has negative disposition")); if (reputation < 0) //It seems that no character in Morrowind.esm have negative reputation. I'm assuming that negative reputation is invalid { - messages.push_back(id.toString() + "|" + npc.mId + " has negative reputation"); + messages.push_back (std::make_pair (id, npc.mId + " has negative reputation")); } - if (npc.mFaction.empty() == false) + if (!npc.mFaction.empty()) { if (rank < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " has negative rank"); - } + messages.push_back (std::make_pair (id, npc.mId + " has negative rank")); if (mFactions.searchId(npc.mFaction) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid faction"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid faction")); } if (npc.mHead.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has no head"); - } + messages.push_back (std::make_pair (id, npc.mId + " has no head")); if (npc.mHair.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has no hair"); - } + messages.push_back (std::make_pair (id, npc.mId + " has no hair")); //TODO: reputation, Disposition, rank, everything else } void CSMTools::ReferenceableCheckStage::weaponCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Weapon >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Weapon >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Weapon& weapon = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Weapon, weapon.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Weapon, weapon.mId); //TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present if @@ -860,20 +755,17 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( weapon.mData.mType == ESM::Weapon::Bolt)) { if (weapon.mData.mSlash[0] > weapon.mData.mSlash[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum slash damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum slash damage higher than maximum")); if (weapon.mData.mThrust[0] > weapon.mData.mThrust[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum thrust damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum thrust damage higher than maximum")); } if (weapon.mData.mChop[0] > weapon.mData.mChop[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum chop damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum chop damage higher than maximum")); if (!(weapon.mData.mType == ESM::Weapon::Arrow || weapon.mData.mType == ESM::Weapon::Bolt || @@ -881,14 +773,10 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( { //checking of health if (weapon.mData.mHealth <= 0) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has non-positivie health"); - } + messages.push_back (std::make_pair (id, weapon.mId + " has non-positivie health")); if (weapon.mData.mReach < 0) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has negative reach"); - } + messages.push_back (std::make_pair (id, weapon.mId + " has negative reach")); } } } @@ -896,7 +784,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( void CSMTools::ReferenceableCheckStage::probeCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Probe >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -912,184 +800,128 @@ void CSMTools::ReferenceableCheckStage::probeCheck( toolCheck(probe, messages, id.toString(), true); } -void CSMTools::ReferenceableCheckStage::repairCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Repair >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::repairCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Repair >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Repair& repair = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Repair, repair.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Repair, repair.mId); - inventoryItemCheck(repair, messages, id.toString()); - toolCheck(repair, messages, id.toString(), true); + inventoryItemCheck (repair, messages, id.toString()); + toolCheck (repair, messages, id.toString(), true); } -void CSMTools::ReferenceableCheckStage::staticCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Static >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::staticCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Static >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Static& staticElement = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Static, staticElement.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Static, staticElement.mId); if (staticElement.mModel.empty()) - { - messages.push_back(id.toString() + "|" + staticElement.mId + " has no model"); - } + messages.push_back (std::make_pair (id, staticElement.mId + " has no model")); } //final check -void CSMTools::ReferenceableCheckStage::finalCheck(std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::finalCheck (Messages& messages) { if (!mPlayerPresent) - { - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc); - messages.push_back(id.toString() + "| There is no player record"); - } + messages.push_back (std::make_pair (CSMWorld::UniversalId::Type_Referenceables, + "There is no player record")); } //Templates begins here -template void CSMTools::ReferenceableCheckStage::inventoryItemCheck( - const ITEM& someItem, - std::vector< std::string >& messages, - const std::string& someID, bool enchantable) +template void CSMTools::ReferenceableCheckStage::inventoryItemCheck ( + const Item& someItem, Messages& messages, const std::string& someID, bool enchantable) { if (someItem.mName.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has an empty name"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name")); //Checking for weight if (someItem.mData.mWeight < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative weight"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight")); //Checking for value if (someItem.mData.mValue < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative value"); - } - -//checking for model - if (someItem.mModel.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no model"); - } - - //checking for icon - if (someItem.mIcon.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no icon"); - } - - if (enchantable) - { - if (someItem.mData.mEnchant < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative enchantment"); - } - } -} - -template void CSMTools::ReferenceableCheckStage::inventoryItemCheck( - const ITEM& someItem, - std::vector< std::string >& messages, - const std::string& someID) -{ - if (someItem.mName.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has an empty name"); - } - - //Checking for weight - if (someItem.mData.mWeight < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative weight"); - } - - //Checking for value - if (someItem.mData.mValue < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative value"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative value")); //checking for model if (someItem.mModel.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no model"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no model")); //checking for icon if (someItem.mIcon.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no icon"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no icon")); + + if (enchantable && someItem.mData.mEnchant < 0) + messages.push_back (std::make_pair (someID, someItem.mId + " has negative enchantment")); } -template void CSMTools::ReferenceableCheckStage::toolCheck( - const TOOL& someTool, - std::vector< std::string >& messages, - const std::string& someID, bool canBeBroken) +template void CSMTools::ReferenceableCheckStage::inventoryItemCheck ( + const Item& someItem, Messages& messages, const std::string& someID) +{ + if (someItem.mName.empty()) + messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name")); + + //Checking for weight + if (someItem.mData.mWeight < 0) + messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight")); + + //Checking for value + if (someItem.mData.mValue < 0) + messages.push_back (std::make_pair (someID, someItem.mId + " has negative value")); + + //checking for model + if (someItem.mModel.empty()) + messages.push_back (std::make_pair (someID, someItem.mId + " has no model")); + + //checking for icon + if (someItem.mIcon.empty()) + messages.push_back (std::make_pair (someID, someItem.mId + " has no icon")); +} + +template void CSMTools::ReferenceableCheckStage::toolCheck ( + const Tool& someTool, Messages& messages, const std::string& someID, bool canBeBroken) { if (someTool.mData.mQuality <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive quality"); - } + messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality")); - if (canBeBroken) - { - if (someTool.mData.mUses <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive uses count"); - } - } + if (canBeBroken && someTool.mData.mUses<=0) + messages.push_back (std::make_pair (someID, + someTool.mId + " has non-positive uses count")); } -template void CSMTools::ReferenceableCheckStage::toolCheck( - const TOOL& someTool, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::toolCheck ( + const Tool& someTool, Messages& messages, const std::string& someID) { if (someTool.mData.mQuality <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive quality"); - } + messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality")); } -template void CSMTools::ReferenceableCheckStage::listCheck( - const LIST& someList, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::listCheck ( + const List& someList, Messages& messages, const std::string& someID) { for (unsigned i = 0; i < someList.mList.size(); ++i) { if (mReferencables.searchId(someList.mList[i].mId).first == -1) - { - messages.push_back(someID + "|" + someList.mId + " contains item without referencable"); - } + messages.push_back (std::make_pair (someID, + someList.mId + " contains item without referencable")); if (someList.mList[i].mLevel < 1) - { - messages.push_back(someID + "|" + someList.mId + " contains item with non-positive level"); - } + messages.push_back (std::make_pair (someID, + someList.mId + " contains item with non-positive level")); } } -// kate: indent-mode cstyle; indent-width 4; replace-tabs on; diff --git a/apps/opencs/model/tools/referenceablecheck.hpp b/apps/opencs/model/tools/referenceablecheck.hpp index 338983cc70..b0129fc2a5 100644 --- a/apps/opencs/model/tools/referenceablecheck.hpp +++ b/apps/opencs/model/tools/referenceablecheck.hpp @@ -11,63 +11,64 @@ namespace CSMTools class ReferenceableCheckStage : public CSMDoc::Stage { public: - ReferenceableCheckStage(const CSMWorld::RefIdData& referenceable, - const CSMWorld::IdCollection& races, - const CSMWorld::IdCollection& classes, - const CSMWorld::IdCollection& factions); - virtual void perform(int stage, std::vector< std::string >& messages); + ReferenceableCheckStage (const CSMWorld::RefIdData& referenceable, + const CSMWorld::IdCollection& races, + const CSMWorld::IdCollection& classes, + const CSMWorld::IdCollection& factions); + + virtual void perform(int stage, Messages& messages); virtual int setup(); private: //CONCRETE CHECKS - void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, std::vector< std::string >& messages); - void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, std::vector< std::string >& messages); - void potionCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void armorCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void clothingCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void containerCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void creatureCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void doorCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void lightCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void miscCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void npcCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void weaponCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void probeCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void repairCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void staticCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - + void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, Messages& messages); + void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, Messages& messages); + void potionCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void armorCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void clothingCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void containerCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void creatureCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void doorCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void lightCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void miscCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void npcCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void weaponCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void probeCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void repairCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void staticCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + //FINAL CHECK - void finalCheck(std::vector& messages); - + void finalCheck (Messages& messages); + //TEMPLATE CHECKS template void inventoryItemCheck(const ITEM& someItem, - std::vector& messages, + Messages& messages, const std::string& someID, bool enchantable); //for all enchantable items. - + template void inventoryItemCheck(const ITEM& someItem, - std::vector& messages, + Messages& messages, const std::string& someID); //for non-enchantable items. - + template void toolCheck(const TOOL& someTool, - std::vector& messages, + Messages& messages, const std::string& someID, bool canbebroken); //for tools with uses. - + template void toolCheck(const TOOL& someTool, - std::vector& messages, + Messages& messages, const std::string& someID); //for tools without uses. template void listCheck(const LIST& someList, - std::vector< std::string >& messages, + Messages& messages, const std::string& someID); - + const CSMWorld::RefIdData& mReferencables; const CSMWorld::IdCollection& mRaces; const CSMWorld::IdCollection& mClasses; diff --git a/apps/opencs/model/tools/regioncheck.cpp b/apps/opencs/model/tools/regioncheck.cpp index 4398e00ef6..07df204701 100644 --- a/apps/opencs/model/tools/regioncheck.cpp +++ b/apps/opencs/model/tools/regioncheck.cpp @@ -17,7 +17,7 @@ int CSMTools::RegionCheckStage::setup() return mRegions.getSize(); } -void CSMTools::RegionCheckStage::perform (int stage, std::vector& messages) +void CSMTools::RegionCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mRegions.getRecord (stage); @@ -30,7 +30,7 @@ void CSMTools::RegionCheckStage::perform (int stage, std::vector& m // test for empty name if (region.mName.empty()) - messages.push_back (id.toString() + "|" + region.mId + " has an empty name"); + messages.push_back (std::make_pair (id, region.mId + " has an empty name")); /// \todo test that the ID in mSleeplist exists diff --git a/apps/opencs/model/tools/regioncheck.hpp b/apps/opencs/model/tools/regioncheck.hpp index c8c437cbd2..a12903e7d4 100644 --- a/apps/opencs/model/tools/regioncheck.hpp +++ b/apps/opencs/model/tools/regioncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index d883617464..75545a7c7a 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -51,16 +51,11 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p return true; } -void CSMTools::ReportModel::add (const std::string& row) +void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message) { - std::string::size_type index = row.find ('|'); - - if (index==std::string::npos) - throw std::logic_error ("invalid report message"); - beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); + mRows.push_back (std::make_pair (id, message)); endInsertRows(); } diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 55c25d9078..0f000245e1 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -28,7 +28,7 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - void add (const std::string& row); + void add (const CSMWorld::UniversalId& id, const std::string& message); const CSMWorld::UniversalId& getUniversalId (int row) const; }; diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index a5154d2926..b989e22a23 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -16,8 +16,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|"; - if (type==ErrorMessage) stream << "error "; else @@ -28,25 +26,15 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi << ", line " << loc.mLine << ", column " << loc.mColumn << " (" << loc.mLiteral << "): " << message; - mMessages->push_back (stream.str()); + mMessages->push_back (std::make_pair (id, stream.str())); } void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) { - std::ostringstream stream; - CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|"; - - if (type==ErrorMessage) - stream << "error: "; - else - stream << "warning: "; - - stream << message; - - mMessages->push_back (stream.str()); + mMessages->push_back (std::make_pair (id, + (type==ErrorMessage ? "error: " : "warning: ") + message)); } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data) @@ -68,7 +56,7 @@ int CSMTools::ScriptCheckStage::setup() return mData.getScripts().getSize(); } -void CSMTools::ScriptCheckStage::perform (int stage, std::vector& messages) +void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages) { mMessages = &messages; mId = mData.getScripts().getId (stage); @@ -90,13 +78,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, std::vector& m } catch (const std::exception& error) { - std::ostringstream stream; - CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|Critical compile error: " << error.what(); - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + std::string ("Critical compile error: ") + error.what())); } mMessages = 0; diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 8de8e1a667..ecf8d61b79 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -18,7 +18,7 @@ namespace CSMTools CSMWorld::ScriptContext mContext; std::string mId; std::string mFile; - std::vector *mMessages; + Messages *mMessages; virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. @@ -33,7 +33,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/skillcheck.cpp b/apps/opencs/model/tools/skillcheck.cpp index 28fc24fd39..630516c72a 100644 --- a/apps/opencs/model/tools/skillcheck.cpp +++ b/apps/opencs/model/tools/skillcheck.cpp @@ -16,7 +16,7 @@ int CSMTools::SkillCheckStage::setup() return mSkills.getSize(); } -void CSMTools::SkillCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SkillCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSkills.getRecord (stage); @@ -32,11 +32,11 @@ void CSMTools::SkillCheckStage::perform (int stage, std::vector& me { std::ostringstream stream; - stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative"; + stream << "Use value #" << i << " of " << skill.mId << " is negative"; - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, stream.str())); } if (skill.mDescription.empty()) - messages.push_back (id.toString() + "|" + skill.mId + " has an empty description"); + messages.push_back (std::make_pair (id, skill.mId + " has an empty description")); } \ No newline at end of file diff --git a/apps/opencs/model/tools/skillcheck.hpp b/apps/opencs/model/tools/skillcheck.hpp index 662bdadee1..cf5d53b5c9 100644 --- a/apps/opencs/model/tools/skillcheck.hpp +++ b/apps/opencs/model/tools/skillcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp index dce2d2b6fa..3d222e9092 100644 --- a/apps/opencs/model/tools/soundcheck.cpp +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -16,7 +16,7 @@ int CSMTools::SoundCheckStage::setup() return mSounds.getSize(); } -void CSMTools::SoundCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SoundCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSounds.getRecord (stage); @@ -28,7 +28,7 @@ void CSMTools::SoundCheckStage::perform (int stage, std::vector& me CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId); if (sound.mData.mMinRange>sound.mData.mMaxRange) - messages.push_back (id.toString() + "|Maximum range larger than minimum range"); + messages.push_back (std::make_pair (id, "Maximum range larger than minimum range")); /// \todo check, if the sound file exists } \ No newline at end of file diff --git a/apps/opencs/model/tools/soundcheck.hpp b/apps/opencs/model/tools/soundcheck.hpp index 00b45cd935..a82a0eb6d7 100644 --- a/apps/opencs/model/tools/soundcheck.hpp +++ b/apps/opencs/model/tools/soundcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/spellcheck.cpp b/apps/opencs/model/tools/spellcheck.cpp index a2cc7c8d25..3d0be46fdf 100644 --- a/apps/opencs/model/tools/spellcheck.cpp +++ b/apps/opencs/model/tools/spellcheck.cpp @@ -17,7 +17,7 @@ int CSMTools::SpellCheckStage::setup() return mSpells.getSize(); } -void CSMTools::SpellCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SpellCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSpells.getRecord (stage); @@ -30,11 +30,11 @@ void CSMTools::SpellCheckStage::perform (int stage, std::vector& me // test for empty name and description if (spell.mName.empty()) - messages.push_back (id.toString() + "|" + spell.mId + " has an empty name"); + messages.push_back (std::make_pair (id, spell.mId + " has an empty name")); // test for invalid cost values if (spell.mData.mCost<0) - messages.push_back (id.toString() + "|" + spell.mId + " has a negative spell costs"); + messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs")); /// \todo check data members that can't be edited in the table view } \ No newline at end of file diff --git a/apps/opencs/model/tools/spellcheck.hpp b/apps/opencs/model/tools/spellcheck.hpp index 880ddafcd2..182f1888b2 100644 --- a/apps/opencs/model/tools/spellcheck.hpp +++ b/apps/opencs/model/tools/spellcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index d3d8f5fadd..ea3568fe20 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -45,8 +45,9 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int))); - connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), - this, SLOT (verifierMessage (const QString&, int))); + connect (mVerifier, + SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), + this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int))); std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); @@ -138,11 +139,12 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& return mReports.at (id.getIndex()); } -void CSMTools::Tools::verifierMessage (const QString& message, int type) +void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type) { std::map::iterator iter = mActiveReports.find (type); if (iter!=mActiveReports.end()) - mReports[iter->second]->add (message.toUtf8().constData()); + mReports[iter->second]->add (id, message); } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 0079fab34e..3394d3f626 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -61,7 +61,8 @@ namespace CSMTools private slots: - void verifierMessage (const QString& message, int type); + void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); signals: From cf90da6cd8e2254b4d7f6fe359046329c0cec556 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 May 2014 15:23:29 +0200 Subject: [PATCH 196/545] minor fix --- apps/opencs/model/tools/mandatoryid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index 5f245dd4d4..412e9f2f02 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -20,5 +20,5 @@ void CSMTools::MandatoryIdStage::perform (int stage, Messages& messages) if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) messages.push_back (std::make_pair (mCollectionId, - "|Missing mandatory record: " + mIds.at (stage))); + "Missing mandatory record: " + mIds.at (stage))); } \ No newline at end of file From 3dfd239b839fc78f21c8e234062918df3e8e7bd2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 May 2014 20:39:58 +0200 Subject: [PATCH 197/545] updated changelog --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 44f15fbcf8..7f95003afc 100644 --- a/readme.txt +++ b/readme.txt @@ -153,6 +153,7 @@ Feature #58: Sneaking Skill Feature #73: Crime and Punishment Feature #135: Editor: OGRE integration Feature #541: Editor: Dialogue Sub-Views +Feature #853: Editor: Rework User Settings Feature #944: Editor: lighting modes Feature #945: Editor: Camera navigation mode Feature #953: Trader gold From 312dc84fa4743f3a8b40725d6afa4e6b1edb0d94 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 8 May 2014 20:40:45 +0200 Subject: [PATCH 198/545] Fix a bug where the player's inventory could be opened as a container If an NPC uses AiActivate on the player (i.e. to activate dialogue) precisely in the frame where the player just died, the player's inventory would be opened as a container instead. --- apps/openmw/mwclass/npc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 6a96c955f4..b548e08446 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -797,6 +797,10 @@ namespace MWClass boost::shared_ptr Npc::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { + // player got activated by another NPC + if(ptr.getRefData().getHandle() == "player") + return boost::shared_ptr(new MWWorld::ActionTalk(actor)); + if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -814,10 +818,6 @@ namespace MWClass if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak)) return boost::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing - // player got activated by another NPC - if(ptr.getRefData().getHandle() == "player") - return boost::shared_ptr(new MWWorld::ActionTalk(actor)); - return boost::shared_ptr(new MWWorld::ActionTalk(ptr)); } From 6e9458c07617423ae6d5b2f59f705aa1dbf19e4e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 8 May 2014 21:04:11 +0200 Subject: [PATCH 199/545] Small fix for dropping items from inventory Some widgets prevented clicking through --- files/mygui/openmw_hud.layout | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index 4f93b42f84..90fa1c8a56 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -3,10 +3,8 @@ - - - - + + @@ -54,6 +52,7 @@ + @@ -101,6 +100,7 @@ + From cf23721f1b37bed581f64401689f988685915526 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 9 May 2014 20:43:24 +1000 Subject: [PATCH 200/545] Windows debug build crash fix. --- apps/openmw/mwmechanics/aicombat.cpp | 60 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index fdaec28b49..84a155225b 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -167,7 +167,7 @@ namespace MWMechanics mCombatMove = false; } } - + actor.getClass().getMovementSettings(actor) = mMovement; actor.getClass().getMovementSettings(actor).mRotation[0] = 0; actor.getClass().getMovementSettings(actor).mRotation[2] = 0; @@ -176,7 +176,7 @@ namespace MWMechanics { if(zTurn(actor, Ogre::Degree(mMovement.mRotation[2]))) mMovement.mRotation[2] = 0; } - + if(mMovement.mRotation[0] != 0) { if(smoothTurn(actor, Ogre::Degree(mMovement.mRotation[0]), 0)) mMovement.mRotation[0] = 0; @@ -193,7 +193,7 @@ namespace MWMechanics } //Update with period = tReaction - + mTimerReact = 0; bool cellChange = mCell && (actor.getCell() != mCell); @@ -282,7 +282,7 @@ namespace MWMechanics * * - Distance where attack using the actor's weapon is possible: * longer for ranged weapons (obviously?) vs. melee weapons - * - Determined by weapon's reach parameter; hardcoded value + * - Determined by weapon's reach parameter; hardcoded value * for ranged weapon and for creatures * - Once within this distance mFollowTarget is triggered * @@ -318,15 +318,15 @@ namespace MWMechanics rangeAttack = weapRange; rangeFollow = 300; } - + ESM::Position pos = actor.getRefData().getPosition(); - Ogre::Vector3 vActorPos(pos.pos); + Ogre::Vector3 vActorPos(pos.pos); Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; bool isStuck = false; float speed = 0.0f; - if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f) + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f) isStuck = true; mLastPos = pos; @@ -397,7 +397,7 @@ namespace MWMechanics if(mReadyToAttack) isStuck = false; // check if shortcut is available - if(!isStuck + if(!isStuck && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) && inLOS) @@ -454,7 +454,7 @@ namespace MWMechanics { if(!mPathFinder.getPath().empty()) mMovement.mRotation[2] = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - else + else mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); } } @@ -497,12 +497,12 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? + MWWorld::CellStore *cell = actor.getCell(); if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { // first check if we're walking into a door mDoorCheckDuration += 1.0f; // add time taken for obstacle check - MWWorld::CellStore *cell = actor.getCell(); if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL && !cell->getCell()->isExterior()) { mDoorCheckDuration = 0; @@ -542,28 +542,26 @@ namespace MWMechanics } } - MWWorld::LiveCellRef& ref = *mDoorIter; - float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility - // TODO: add reaction to checking open doors - if(mBackOffDoor && - vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + if(!cell->getCell()->isExterior() && !mDoors.mList.empty()) { - mMovement.mPosition[1] = -0.2; // back off, but slowly + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility + // TODO: add reaction to checking open doors + if(mBackOffDoor && + vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + { + mMovement.mPosition[1] = -0.2; // back off, but slowly + } + else if(mBackOffDoor && + mDoorIter != mDoors.mList.end() && + ref.mData.getLocalRotation().rot[2] >= 1) + { + mDoorIter = mDoors.mList.end(); + mBackOffDoor = false; + //std::cout<<"open door id \""<= 1) - { - mDoorIter = mDoors.mList.end(); - mBackOffDoor = false; - //std::cout<<"open door id \""< Date: Fri, 9 May 2014 08:32:52 -0500 Subject: [PATCH 201/545] Fixes for warnings when building with MSVC Most warnings are innocuous (wrong type-specifier for forward declarations, conversion of literals into unsigned integers, warnings about methods optimized out), but I believe actual bugs were revealed in vartypedelegate.cpp and combat.cpp. --- CMakeLists.txt | 1 + apps/esmtool/esmtool.cpp | 2 - apps/mwiniimporter/main.cpp | 2 +- apps/opencs/model/doc/document.cpp | 516 +++++++++--------- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/doc/documentmanager.hpp | 4 +- apps/opencs/model/world/commands.hpp | 4 +- apps/opencs/model/world/idtable.hpp | 2 +- apps/opencs/model/world/infocollection.hpp | 4 +- apps/opencs/model/world/ref.hpp | 2 +- apps/opencs/model/world/refcollection.hpp | 2 +- apps/opencs/model/world/refidadapter.hpp | 4 +- apps/opencs/view/render/lightingday.cpp | 4 +- apps/opencs/view/render/lightingnight.cpp | 6 +- apps/opencs/view/render/scenewidget.cpp | 4 +- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 4 +- apps/openmw/mwgui/companionwindow.cpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 + apps/openmw/mwmechanics/combat.cpp | 4 +- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 + .../mwscript/transformationextensions.cpp | 4 +- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 +- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +- .../contentselector/model/contentmodel.cpp | 1 - components/esm/esmreader.hpp | 2 +- components/esm/inventorystate.hpp | 2 + components/esm/loadcell.hpp | 2 +- components/ogreinit/ogreplugin.cpp | 6 +- components/terrain/material.cpp | 4 +- 37 files changed, 314 insertions(+), 311 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd437ed616..89bf75c6c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,6 +610,7 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list + 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index eef96c8c99..6b67cf7d5b 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -218,8 +218,6 @@ int main(int argc, char**argv) std::cout << "Invalid or no mode specified, dying horribly. Have a nice day." << std::endl; return 1; } - - return 0; } void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 364a6b1a4a..c2cb8117a9 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; MwIniImporter importer; - importer.setVerbose(vm.count("verbose")); + importer.setVerbose(vm.count("verbose") != 0); // Font encoding settings std::string encoding(vm["encoding"].as()); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3ef14ee7e5..72d7f5cd88 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -292,264 +292,264 @@ void CSMDoc::Document::addGmsts() static const float gmstFloatsValues[] = { - 0.3, // fAIFleeFleeMult - 7.0, // fAIFleeHealthMult - 3.0, // fAIMagicSpellMult - 1.0, // fAIMeleeArmorMult - 1.0, // fAIMeleeSummWeaponMult - 2.0, // fAIMeleeWeaponMult - 5.0, // fAIRangeMagicSpellMult - 5.0, // fAIRangeMeleeWeaponMult - 2000.0, // fAlarmRadius - 1.0, // fAthleticsRunBonus - 40.0, // fAudioDefaultMaxDistance - 5.0, // fAudioDefaultMinDistance - 50.0, // fAudioMaxDistanceMult - 20.0, // fAudioMinDistanceMult - 60.0, // fAudioVoiceDefaultMaxDistance - 10.0, // fAudioVoiceDefaultMinDistance - 50.0, // fAutoPCSpellChance - 80.0, // fAutoSpellChance - 50.0, // fBargainOfferBase - -4.0, // fBargainOfferMulti - 24.0, // fBarterGoldResetDelay - 1.75, // fBaseRunMultiplier - 1.25, // fBlockStillBonus - 150.0, // fBribe1000Mod - 75.0, // fBribe100Mod - 35.0, // fBribe10Mod - 60.0, // fCombatAngleXY - 60.0, // fCombatAngleZ - 0.25, // fCombatArmorMinMult - -90.0, // fCombatBlockLeftAngle - 30.0, // fCombatBlockRightAngle - 4.0, // fCombatCriticalStrikeMult - 0.1, // fCombatDelayCreature - 0.1, // fCombatDelayNPC - 128.0, // fCombatDistance - 0.3, // fCombatDistanceWerewolfMod - 30.0, // fCombatForceSideAngle - 0.2, // fCombatInvisoMult - 1.5, // fCombatKODamageMult - 45.0, // fCombatTorsoSideAngle - 0.3, // fCombatTorsoStartPercent - 0.8, // fCombatTorsoStopPercent - 15.0, // fConstantEffectMult - 72.0, // fCorpseClearDelay - 72.0, // fCorpseRespawnDelay - 0.5, // fCrimeGoldDiscountMult - 0.9, // fCrimeGoldTurnInMult - 1.0, // fCrimeStealing - 0.5, // fDamageStrengthBase - 0.1, // fDamageStrengthMult - 5.0, // fDifficultyMult - 2.5, // fDiseaseXferChance - -10.0, // fDispAttacking - -1.0, // fDispBargainFailMod - 1.0, // fDispBargainSuccessMod - 0.0, // fDispCrimeMod - -10.0, // fDispDiseaseMod - 3.0, // fDispFactionMod - 1.0, // fDispFactionRankBase - 0.5, // fDispFactionRankMult - 1.0, // fDispositionMod - 50.0, // fDispPersonalityBase - 0.5, // fDispPersonalityMult - -25.0, // fDispPickPocketMod - 5.0, // fDispRaceMod - -0.5, // fDispStealing - -5.0, // fDispWeaponDrawn - 0.5, // fEffectCostMult - 0.1, // fElementalShieldMult - 3.0, // fEnchantmentChanceMult - 0.5, // fEnchantmentConstantChanceMult - 100.0, // fEnchantmentConstantDurationMult - 0.1, // fEnchantmentMult - 1000.0, // fEnchantmentValueMult - 0.3, // fEncumberedMoveEffect - 5.0, // fEncumbranceStrMult - 0.04, // fEndFatigueMult - 0.25, // fFallAcroBase - 0.01, // fFallAcroMult - 400.0, // fFallDamageDistanceMin - 0.0, // fFallDistanceBase - 0.07, // fFallDistanceMult - 2.0, // fFatigueAttackBase - 0.0, // fFatigueAttackMult - 1.25, // fFatigueBase - 4.0, // fFatigueBlockBase - 0.0, // fFatigueBlockMult - 5.0, // fFatigueJumpBase - 0.0, // fFatigueJumpMult - 0.5, // fFatigueMult - 2.5, // fFatigueReturnBase - 0.02, // fFatigueReturnMult - 5.0, // fFatigueRunBase - 2.0, // fFatigueRunMult - 1.5, // fFatigueSneakBase - 1.5, // fFatigueSneakMult - 0.0, // fFatigueSpellBase - 0.0, // fFatigueSpellCostMult - 0.0, // fFatigueSpellMult - 7.0, // fFatigueSwimRunBase - 0.0, // fFatigueSwimRunMult - 2.5, // fFatigueSwimWalkBase - 0.0, // fFatigueSwimWalkMult - 0.2, // fFightDispMult - 0.005, // fFightDistanceMultiplier - 50.0, // fFightStealing - 3000.0, // fFleeDistance - 512.0, // fGreetDistanceReset - 0.1, // fHandtoHandHealthPer - 1.0, // fHandToHandReach - 0.5, // fHoldBreathEndMult - 20.0, // fHoldBreathTime - 0.75, // fIdleChanceMultiplier - 1.0, // fIngredientMult - 0.5, // fInteriorHeadTrackMult - 128.0, // fJumpAcrobaticsBase - 4.0, // fJumpAcroMultiplier - 0.5, // fJumpEncumbranceBase - 1.0, // fJumpEncumbranceMultiplier - 0.5, // fJumpMoveBase - 0.5, // fJumpMoveMult - 1.0, // fJumpRunMultiplier - 0.5, // fKnockDownMult - 5.0, // fLevelMod - 0.1, // fLevelUpHealthEndMult - 0.6, // fLightMaxMod - 10.0, // fLuckMod - 10.0, // fMagesGuildTravel - 1.5, // fMagicCreatureCastDelay - 0.0167, // fMagicDetectRefreshRate - 1.0, // fMagicItemConstantMult - 1.0, // fMagicItemCostMult - 1.0, // fMagicItemOnceMult - 1.0, // fMagicItemPriceMult - 0.05, // fMagicItemRechargePerSecond - 1.0, // fMagicItemStrikeMult - 1.0, // fMagicItemUsedMult - 3.0, // fMagicStartIconBlink - 0.5, // fMagicSunBlockedMult - 0.75, // fMajorSkillBonus - 300.0, // fMaxFlySpeed - 0.5, // fMaxHandToHandMult - 400.0, // fMaxHeadTrackDistance - 200.0, // fMaxWalkSpeed - 300.0, // fMaxWalkSpeedCreature - 0.9, // fMedMaxMod - 0.1, // fMessageTimePerChar - 5.0, // fMinFlySpeed - 0.1, // fMinHandToHandMult - 1.0, // fMinorSkillBonus - 100.0, // fMinWalkSpeed - 5.0, // fMinWalkSpeedCreature - 1.25, // fMiscSkillBonus - 2.0, // fNPCbaseMagickaMult - 0.5, // fNPCHealthBarFade - 3.0, // fNPCHealthBarTime - 1.0, // fPCbaseMagickaMult - 0.3, // fPerDieRollMult - 5.0, // fPersonalityMod - 1.0, // fPerTempMult - -1.0, // fPickLockMult - 0.3, // fPickPocketMod - 20.0, // fPotionMinUsefulDuration - 0.5, // fPotionStrengthMult - 0.5, // fPotionT1DurMult - 1.5, // fPotionT1MagMult - 20.0, // fPotionT4BaseStrengthMult - 12.0, // fPotionT4EquipStrengthMult - 3000.0, // fProjectileMaxSpeed - 400.0, // fProjectileMinSpeed - 25.0, // fProjectileThrownStoreChance - 3.0, // fRepairAmountMult - 1.0, // fRepairMult - 1.0, // fReputationMod - 0.15, // fRestMagicMult - 0.0, // fSeriousWoundMult - 0.25, // fSleepRandMod - 0.3, // fSleepRestMod - -1.0, // fSneakBootMult - 0.5, // fSneakDistanceBase - 0.002, // fSneakDistanceMultiplier - 0.5, // fSneakNoViewMult - 1.0, // fSneakSkillMult - 0.75, // fSneakSpeedMultiplier - 1.0, // fSneakUseDelay - 500.0, // fSneakUseDist - 1.5, // fSneakViewMult - 3.0, // fSoulGemMult - 0.8, // fSpecialSkillBonus - 7.0, // fSpellMakingValueMult - 2.0, // fSpellPriceMult - 10.0, // fSpellValueMult - 0.25, // fStromWalkMult - 0.7, // fStromWindSpeed - 3.0, // fSuffocationDamage - 0.9, // fSwimHeightScale - 0.1, // fSwimRunAthleticsMult - 0.5, // fSwimRunBase - 0.02, // fSwimWalkAthleticsMult - 0.5, // fSwimWalkBase - 1.0, // fSwingBlockBase - 1.0, // fSwingBlockMult - 1000.0, // fTargetSpellMaxSpeed - 1000.0, // fThrownWeaponMaxSpeed - 300.0, // fThrownWeaponMinSpeed - 0.0, // fTrapCostMult - 4000.0, // fTravelMult - 16000.0,// fTravelTimeMult - 0.1, // fUnarmoredBase1 - 0.065, // fUnarmoredBase2 - 30.0, // fVanityDelay - 10.0, // fVoiceIdleOdds - 0.0, // fWaterReflectUpdateAlways - 10.0, // fWaterReflectUpdateSeldom - 0.1, // fWeaponDamageMult - 1.0, // fWeaponFatigueBlockMult - 0.25, // fWeaponFatigueMult - 150.0, // fWereWolfAcrobatics - 150.0, // fWereWolfAgility - 1.0, // fWereWolfAlchemy - 1.0, // fWereWolfAlteration - 1.0, // fWereWolfArmorer - 150.0, // fWereWolfAthletics - 1.0, // fWereWolfAxe - 1.0, // fWereWolfBlock - 1.0, // fWereWolfBluntWeapon - 1.0, // fWereWolfConjuration - 1.0, // fWereWolfDestruction - 1.0, // fWereWolfEnchant - 150.0, // fWereWolfEndurance - 400.0, // fWereWolfFatigue - 100.0, // fWereWolfHandtoHand - 2.0, // fWereWolfHealth - 1.0, // fWereWolfHeavyArmor - 1.0, // fWereWolfIllusion - 1.0, // fWereWolfIntellegence - 1.0, // fWereWolfLightArmor - 1.0, // fWereWolfLongBlade - 1.0, // fWereWolfLuck - 100.0, // fWereWolfMagicka - 1.0, // fWereWolfMarksman - 1.0, // fWereWolfMediumArmor - 1.0, // fWereWolfMerchantile - 1.0, // fWereWolfMysticism - 1.0, // fWereWolfPersonality - 1.0, // fWereWolfRestoration - 1.5, // fWereWolfRunMult - 1.0, // fWereWolfSecurity - 1.0, // fWereWolfShortBlade - 1.5, // fWereWolfSilverWeaponDamageMult - 1.0, // fWereWolfSneak - 1.0, // fWereWolfSpear - 1.0, // fWereWolfSpeechcraft - 150.0, // fWereWolfSpeed - 150.0, // fWereWolfStrength - 100.0, // fWereWolfUnarmored - 1.0, // fWereWolfWillPower - 15.0, // fWortChanceValue + 0.3f, // fAIFleeFleeMult + 7.0f, // fAIFleeHealthMult + 3.0f, // fAIMagicSpellMult + 1.0f, // fAIMeleeArmorMult + 1.0f, // fAIMeleeSummWeaponMult + 2.0f, // fAIMeleeWeaponMult + 5.0f, // fAIRangeMagicSpellMult + 5.0f, // fAIRangeMeleeWeaponMult + 2000.0f, // fAlarmRadius + 1.0f, // fAthleticsRunBonus + 40.0f, // fAudioDefaultMaxDistance + 5.0f, // fAudioDefaultMinDistance + 50.0f, // fAudioMaxDistanceMult + 20.0f, // fAudioMinDistanceMult + 60.0f, // fAudioVoiceDefaultMaxDistance + 10.0f, // fAudioVoiceDefaultMinDistance + 50.0f, // fAutoPCSpellChance + 80.0f, // fAutoSpellChance + 50.0f, // fBargainOfferBase + -4.0f, // fBargainOfferMulti + 24.0f, // fBarterGoldResetDelay + 1.75f, // fBaseRunMultiplier + 1.25f, // fBlockStillBonus + 150.0f, // fBribe1000Mod + 75.0f, // fBribe100Mod + 35.0f, // fBribe10Mod + 60.0f, // fCombatAngleXY + 60.0f, // fCombatAngleZ + 0.25f, // fCombatArmorMinMult + -90.0f, // fCombatBlockLeftAngle + 30.0f, // fCombatBlockRightAngle + 4.0f, // fCombatCriticalStrikeMult + 0.1f, // fCombatDelayCreature + 0.1f, // fCombatDelayNPC + 128.0f, // fCombatDistance + 0.3f, // fCombatDistanceWerewolfMod + 30.0f, // fCombatForceSideAngle + 0.2f, // fCombatInvisoMult + 1.5f, // fCombatKODamageMult + 45.0f, // fCombatTorsoSideAngle + 0.3f, // fCombatTorsoStartPercent + 0.8f, // fCombatTorsoStopPercent + 15.0f, // fConstantEffectMult + 72.0f, // fCorpseClearDelay + 72.0f, // fCorpseRespawnDelay + 0.5f, // fCrimeGoldDiscountMult + 0.9f, // fCrimeGoldTurnInMult + 1.0f, // fCrimeStealing + 0.5f, // fDamageStrengthBase + 0.1f, // fDamageStrengthMult + 5.0f, // fDifficultyMult + 2.5f, // fDiseaseXferChance + -10.0f, // fDispAttacking + -1.0f, // fDispBargainFailMod + 1.0f, // fDispBargainSuccessMod + 0.0f, // fDispCrimeMod + -10.0f, // fDispDiseaseMod + 3.0f, // fDispFactionMod + 1.0f, // fDispFactionRankBase + 0.5f, // fDispFactionRankMult + 1.0f, // fDispositionMod + 50.0f, // fDispPersonalityBase + 0.5f, // fDispPersonalityMult + -25.0f, // fDispPickPocketMod + 5.0f, // fDispRaceMod + -0.5f, // fDispStealing + -5.0f, // fDispWeaponDrawn + 0.5f, // fEffectCostMult + 0.1f, // fElementalShieldMult + 3.0f, // fEnchantmentChanceMult + 0.5f, // fEnchantmentConstantChanceMult + 100.0f, // fEnchantmentConstantDurationMult + 0.1f, // fEnchantmentMult + 1000.0f, // fEnchantmentValueMult + 0.3f, // fEncumberedMoveEffect + 5.0f, // fEncumbranceStrMult + 0.04f, // fEndFatigueMult + 0.25f, // fFallAcroBase + 0.01f, // fFallAcroMult + 400.0f, // fFallDamageDistanceMin + 0.0f, // fFallDistanceBase + 0.07f, // fFallDistanceMult + 2.0f, // fFatigueAttackBase + 0.0f, // fFatigueAttackMult + 1.25f, // fFatigueBase + 4.0f, // fFatigueBlockBase + 0.0f, // fFatigueBlockMult + 5.0f, // fFatigueJumpBase + 0.0f, // fFatigueJumpMult + 0.5f, // fFatigueMult + 2.5f, // fFatigueReturnBase + 0.02f, // fFatigueReturnMult + 5.0f, // fFatigueRunBase + 2.0f, // fFatigueRunMult + 1.5f, // fFatigueSneakBase + 1.5f, // fFatigueSneakMult + 0.0f, // fFatigueSpellBase + 0.0f, // fFatigueSpellCostMult + 0.0f, // fFatigueSpellMult + 7.0f, // fFatigueSwimRunBase + 0.0f, // fFatigueSwimRunMult + 2.5f, // fFatigueSwimWalkBase + 0.0f, // fFatigueSwimWalkMult + 0.2f, // fFightDispMult + 0.005f, // fFightDistanceMultiplier + 50.0f, // fFightStealing + 3000.0f, // fFleeDistance + 512.0f, // fGreetDistanceReset + 0.1f, // fHandtoHandHealthPer + 1.0f, // fHandToHandReach + 0.5f, // fHoldBreathEndMult + 20.0f, // fHoldBreathTime + 0.75f, // fIdleChanceMultiplier + 1.0f, // fIngredientMult + 0.5f, // fInteriorHeadTrackMult + 128.0f, // fJumpAcrobaticsBase + 4.0f, // fJumpAcroMultiplier + 0.5f, // fJumpEncumbranceBase + 1.0f, // fJumpEncumbranceMultiplier + 0.5f, // fJumpMoveBase + 0.5f, // fJumpMoveMult + 1.0f, // fJumpRunMultiplier + 0.5f, // fKnockDownMult + 5.0f, // fLevelMod + 0.1f, // fLevelUpHealthEndMult + 0.6f, // fLightMaxMod + 10.0f, // fLuckMod + 10.0f, // fMagesGuildTravel + 1.5f, // fMagicCreatureCastDelay + 0.0167f, // fMagicDetectRefreshRate + 1.0f, // fMagicItemConstantMult + 1.0f, // fMagicItemCostMult + 1.0f, // fMagicItemOnceMult + 1.0f, // fMagicItemPriceMult + 0.05f, // fMagicItemRechargePerSecond + 1.0f, // fMagicItemStrikeMult + 1.0f, // fMagicItemUsedMult + 3.0f, // fMagicStartIconBlink + 0.5f, // fMagicSunBlockedMult + 0.75f, // fMajorSkillBonus + 300.0f, // fMaxFlySpeed + 0.5f, // fMaxHandToHandMult + 400.0f, // fMaxHeadTrackDistance + 200.0f, // fMaxWalkSpeed + 300.0f, // fMaxWalkSpeedCreature + 0.9f, // fMedMaxMod + 0.1f, // fMessageTimePerChar + 5.0f, // fMinFlySpeed + 0.1f, // fMinHandToHandMult + 1.0f, // fMinorSkillBonus + 100.0f, // fMinWalkSpeed + 5.0f, // fMinWalkSpeedCreature + 1.25f, // fMiscSkillBonus + 2.0f, // fNPCbaseMagickaMult + 0.5f, // fNPCHealthBarFade + 3.0f, // fNPCHealthBarTime + 1.0f, // fPCbaseMagickaMult + 0.3f, // fPerDieRollMult + 5.0f, // fPersonalityMod + 1.0f, // fPerTempMult + -1.0f, // fPickLockMult + 0.3f, // fPickPocketMod + 20.0f, // fPotionMinUsefulDuration + 0.5f, // fPotionStrengthMult + 0.5f, // fPotionT1DurMult + 1.5f, // fPotionT1MagMult + 20.0f, // fPotionT4BaseStrengthMult + 12.0f, // fPotionT4EquipStrengthMult + 3000.0f, // fProjectileMaxSpeed + 400.0f, // fProjectileMinSpeed + 25.0f, // fProjectileThrownStoreChance + 3.0f, // fRepairAmountMult + 1.0f, // fRepairMult + 1.0f, // fReputationMod + 0.15f, // fRestMagicMult + 0.0f, // fSeriousWoundMult + 0.25f, // fSleepRandMod + 0.3f, // fSleepRestMod + -1.0f, // fSneakBootMult + 0.5f, // fSneakDistanceBase + 0.002f, // fSneakDistanceMultiplier + 0.5f, // fSneakNoViewMult + 1.0f, // fSneakSkillMult + 0.75f, // fSneakSpeedMultiplier + 1.0f, // fSneakUseDelay + 500.0f, // fSneakUseDist + 1.5f, // fSneakViewMult + 3.0f, // fSoulGemMult + 0.8f, // fSpecialSkillBonus + 7.0f, // fSpellMakingValueMult + 2.0f, // fSpellPriceMult + 10.0f, // fSpellValueMult + 0.25f, // fStromWalkMult + 0.7f, // fStromWindSpeed + 3.0f, // fSuffocationDamage + 0.9f, // fSwimHeightScale + 0.1f, // fSwimRunAthleticsMult + 0.5f, // fSwimRunBase + 0.02f, // fSwimWalkAthleticsMult + 0.5f, // fSwimWalkBase + 1.0f, // fSwingBlockBase + 1.0f, // fSwingBlockMult + 1000.0f, // fTargetSpellMaxSpeed + 1000.0f, // fThrownWeaponMaxSpeed + 300.0f, // fThrownWeaponMinSpeed + 0.0f, // fTrapCostMult + 4000.0f, // fTravelMult + 16000.0f,// fTravelTimeMult + 0.1f, // fUnarmoredBase1 + 0.065f, // fUnarmoredBase2 + 30.0f, // fVanityDelay + 10.0f, // fVoiceIdleOdds + 0.0f, // fWaterReflectUpdateAlways + 10.0f, // fWaterReflectUpdateSeldom + 0.1f, // fWeaponDamageMult + 1.0f, // fWeaponFatigueBlockMult + 0.25f, // fWeaponFatigueMult + 150.0f, // fWereWolfAcrobatics + 150.0f, // fWereWolfAgility + 1.0f, // fWereWolfAlchemy + 1.0f, // fWereWolfAlteration + 1.0f, // fWereWolfArmorer + 150.0f, // fWereWolfAthletics + 1.0f, // fWereWolfAxe + 1.0f, // fWereWolfBlock + 1.0f, // fWereWolfBluntWeapon + 1.0f, // fWereWolfConjuration + 1.0f, // fWereWolfDestruction + 1.0f, // fWereWolfEnchant + 150.0f, // fWereWolfEndurance + 400.0f, // fWereWolfFatigue + 100.0f, // fWereWolfHandtoHand + 2.0f, // fWereWolfHealth + 1.0f, // fWereWolfHeavyArmor + 1.0f, // fWereWolfIllusion + 1.0f, // fWereWolfIntellegence + 1.0f, // fWereWolfLightArmor + 1.0f, // fWereWolfLongBlade + 1.0f, // fWereWolfLuck + 100.0f, // fWereWolfMagicka + 1.0f, // fWereWolfMarksman + 1.0f, // fWereWolfMediumArmor + 1.0f, // fWereWolfMerchantile + 1.0f, // fWereWolfMysticism + 1.0f, // fWereWolfPersonality + 1.0f, // fWereWolfRestoration + 1.5f, // fWereWolfRunMult + 1.0f, // fWereWolfSecurity + 1.0f, // fWereWolfShortBlade + 1.5f, // fWereWolfSilverWeaponDamageMult + 1.0f, // fWereWolfSneak + 1.0f, // fWereWolfSpear + 1.0f, // fWereWolfSpeechcraft + 150.0f, // fWereWolfSpeed + 150.0f, // fWereWolfStrength + 100.0f, // fWereWolfUnarmored + 1.0f, // fWereWolfWillPower + 15.0f, // fWortChanceValue }; static const char *gmstIntegers[] = diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 201fb4342a..9f0617eb99 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -26,7 +26,7 @@ namespace ESM namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMDoc diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index b969862e99..6c66f2c0ec 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -8,7 +8,7 @@ namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMDoc @@ -46,4 +46,4 @@ namespace CSMDoc }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index ec6350658f..bc477e26ae 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { class IdTable; class IdTable; - class RecordBase; + struct RecordBase; class ModifyCommand : public QUndoCommand { @@ -137,4 +137,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 8b54628256..c5c84eedab 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -11,7 +11,7 @@ namespace CSMWorld { class CollectionBase; - class RecordBase; + struct RecordBase; class IdTable : public QAbstractItemModel { diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index ae61f5d391..08024d45df 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -6,7 +6,7 @@ namespace ESM { - class Dialogue; + struct Dialogue; } namespace CSMWorld @@ -47,4 +47,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index fcf016ee24..4c76991856 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -10,7 +10,7 @@ namespace ESM namespace CSMWorld { - class Cell; + struct Cell; /// \brief Wrapper for CellRef sub record struct CellRef : public ESM::CellRef diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 173efba05b..be2f5e5794 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -8,7 +8,7 @@ namespace CSMWorld { struct Cell; - struct UniversalId; + class UniversalId; /// \brief References in cells class RefCollection : public Collection diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 0870a2d3e6..74c5dfe584 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -9,7 +9,7 @@ namespace CSMWorld { class RefIdColumn; class RefIdData; - class RecordBase; + struct RecordBase; class RefIdAdapter { @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/render/lightingday.cpp b/apps/opencs/view/render/lightingday.cpp index ab0257c0c7..fa2656f89c 100644 --- a/apps/opencs/view/render/lightingday.cpp +++ b/apps/opencs/view/render/lightingday.cpp @@ -13,7 +13,7 @@ void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.7f, 0.7f, 0.7f, 1.0f)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); @@ -33,4 +33,4 @@ void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/lightingnight.cpp b/apps/opencs/view/render/lightingnight.cpp index 516bb3f408..f491717757 100644 --- a/apps/opencs/view/render/lightingnight.cpp +++ b/apps/opencs/view/render/lightingnight.cpp @@ -13,12 +13,12 @@ void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.2f, 0.2f, 0.2f, 1.0f)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); mLight->setDirection (Ogre::Vector3 (0, 0, -1)); - mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2)); + mLight->setDiffuseColour (Ogre::ColourValue (0.2f, 0.2f, 0.2f)); } void CSVRender::LightingNight::deactivate() @@ -33,4 +33,4 @@ void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 8a58b7d328..f56ba82ec9 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -42,7 +42,7 @@ namespace CSVRender mCamera->setPosition (300, 0, 0); mCamera->lookAt (0, 0, 0); - mCamera->setNearClipDistance (0.1); + mCamera->setNearClipDistance (0.1f); mCamera->setFarClipDistance (30000); mCamera->roll (Ogre::Degree (90)); @@ -104,7 +104,7 @@ namespace CSVRender #endif mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms); - mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1)); + mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3f,0.3f,0.3f,1.0f)); Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); mCamera->setAspectRatio(aspectRatio); diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 15ce2dbaf2..fc00f44919 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (type<0 && type>=enums.size()) + if (static_cast(type) >= enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 52682342f7..b797a77420 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -767,7 +767,7 @@ public: PageDisplay () { - mPage = -1; + mPage = static_cast(-1); mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -917,7 +917,7 @@ public: else { mBook.reset (); - mPage = -1; + mPage = static_cast(-1); mViewTop = 0; mViewBottom = 0; } diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index a0a34108eb..0044583db7 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -23,7 +23,7 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma : WindowBase("openmw_companion_window.layout") , mDragAndDrop(dragAndDrop) , mMessageBoxManager(manager) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mModel(NULL) , mSortModel(NULL) { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5856473388..8b287a10d7 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -111,7 +111,7 @@ namespace MWGui ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window.layout") , mDragAndDrop(dragAndDrop) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mModel(NULL) , mSortModel(NULL) , mPickpocketDetected(false) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6c43f47b4b..3c6f99e68f 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0,-pos); + mHistory->setPosition(0, (~pos) + 1); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2bea088e32..af631a2fe3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -38,7 +38,7 @@ namespace MWGui , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) - , mSelectedItem(-1) + , mSelectedItem(static_cast(-1)) , mGuiMode(GM_Inventory) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4c..82d8b1f2dc 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,6 +42,8 @@ namespace MWGui std::map > mEffectSources; + virtual ~EffectSourceVisitor() {} + virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index cdc12e210e..5ffa7a547f 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver - & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) + && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 120616f9fe..6888d88a68 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error& e) + catch (std::logic_error&) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0f6d782a65..4486559ba0 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 67bc75e02d..92a49acc01 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception& e) + catch (Ogre::Exception&) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index c09aa65d98..cbe910c716 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,6 +33,7 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} + virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 1efc796436..7051937989 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index c595de5aec..75f7ccae4c 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception &e) + catch(std::exception&) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 9a3dd73422..b245b92414 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception &e) + catch(std::exception&) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception &e) { + catch(std::exception&) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException &e) + catch(Ogre::FileNotFoundException&) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 8ce87a25e0..6854358f59 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception &e) + catch(std::exception&) { //std::cout <<"Sound Error: "< &getGameFiles() const { return mHeader.mMaster; } diff --git a/components/esm/inventorystate.hpp b/components/esm/inventorystate.hpp index 3cfffbccc9..21776f683e 100644 --- a/components/esm/inventorystate.hpp +++ b/components/esm/inventorystate.hpp @@ -14,6 +14,8 @@ namespace ESM /// \brief State for inventories and containers struct InventoryState { + virtual ~InventoryState() {} + // anything but lights (type, slot) std::vector > > mItems; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index f01c88c65d..b5eede9f5a 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -129,7 +129,7 @@ struct Cell bool hasWater() const { - return (mData.mFlags&HasWater); + return (mData.mFlags & HasWater) != 0; } // Restore the given reader to the stored position. Will try to open diff --git a/components/ogreinit/ogreplugin.cpp b/components/ogreinit/ogreplugin.cpp index 6070c43a87..91f3fce95a 100644 --- a/components/ogreinit/ogreplugin.cpp +++ b/components/ogreinit/ogreplugin.cpp @@ -30,8 +30,7 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: return false; #endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32 } -#endif //defined(DEBUG) - +#else //!defined(DEBUG) pluginPath = pluginDir + "/" + pluginName + pluginExt; if (boost::filesystem::exists(pluginPath)) { ogreRoot.loadPlugin(pluginPath); @@ -40,6 +39,7 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: else { return false; } +#endif } -} \ No newline at end of file +} diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index faa73a9864..a65b6b3b1e 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From 199f030d3819692f1c60ee4d7953548f796a38dc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 May 2014 17:19:44 +0200 Subject: [PATCH 202/545] adjusted cmake file for opencs user settings file rename --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd437ed616..0c5c156dbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,7 +427,7 @@ IF(NOT WIN32 AND NOT APPLE) INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") IF(BUILD_OPENCS) - INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") + INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") ENDIF(BUILD_OPENCS) # Install resources @@ -456,7 +456,7 @@ if(WIN32) ENDIF(BUILD_MWINIIMPORTER) IF(BUILD_OPENCS) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".") - INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION ".") + INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".") ENDIF(BUILD_OPENCS) INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") @@ -663,7 +663,7 @@ if (APPLE) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) set(CPACK_GENERATOR "DragNDrop") set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) From 731bc9c27563a73cc8fc4712d87efb908ae42d44 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 May 2014 18:45:49 +0200 Subject: [PATCH 203/545] Fix broken isClass check and renamed variable for clarity --- .../openmw/mwmechanics/mechanicsmanagerimp.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5381af8da7..eb51ddfc56 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -825,13 +825,13 @@ namespace MWMechanics commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); } - bool MechanicsManager::commitCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg) + bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg) { // NOTE: int arg can be from itemTaken() so DON'T modify it, since it is // passed to reportCrime later on in this function. // Only player can commit crime - if (ptr.getRefData().getHandle() != "player") + if (player.getRefData().getHandle() != "player") return false; const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -856,7 +856,7 @@ namespace MWMechanics // Find all the actors within the alarm radius std::vector neighbors; - mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), + mActors.getObjectsInRange(Ogre::Vector3(player.getRefData().getPosition().pos), esmStore.get().find("fAlarmRadius")->getInt(), neighbors); int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); @@ -864,10 +864,10 @@ namespace MWMechanics // Find actors who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - if (*it == ptr) continue; // not the player + if (*it == player) continue; // not the player // Was the crime seen? - if (MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) + if (MWBase::Environment::get().getWorld()->getLOS(player, *it) && awarenessCheck(player, *it) ) { // TODO: Add more messages if (type == OT_Theft) @@ -881,8 +881,8 @@ namespace MWMechanics // This applies to both NPCs and creatures // ... except if this is a guard: then the player is given a chance to pay a fine / go to jail instead - if (type == OT_Assault && !ptr.getClass().isClass(ptr, "guard")) - MWBase::Environment::get().getMechanicsManager()->startCombat(victim, ptr); + if (type == OT_Assault && !it->getClass().isClass(*it, "guard")) + MWBase::Environment::get().getMechanicsManager()->startCombat(victim, player); } // Crime reporting only applies to NPCs @@ -897,7 +897,7 @@ namespace MWMechanics // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if ( *it1 == ptr + if ( *it1 == player || !it1->getClass().isNpc()) continue; // not the player and is an NPC // Will other witnesses paticipate in crime @@ -914,7 +914,7 @@ namespace MWMechanics } } if (reported) - reportCrime(ptr, victim, type, arg); + reportCrime(player, victim, type, arg); return reported; } From 872d9be1b4ca78e0324d37015c3dee04aec54e6e Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 May 2014 19:19:21 +0200 Subject: [PATCH 204/545] Fix potential issue with dialogue globals Make sure they are updated throughout the conversation --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index caaf7c91f4..8c425caa01 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -144,7 +144,6 @@ namespace MWDialogue //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI updateTopics(); - updateGlobals(); //greeting const MWWorld::Store &dialogs = @@ -392,6 +391,8 @@ namespace MWDialogue win->setKeywords(keywordList); mChoice = choice; + + updateGlobals(); } void DialogueManager::keywordSelected (const std::string& keyword) From e7a004824c841ccce19acb1748c50543beadce2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 May 2014 23:58:24 +0200 Subject: [PATCH 205/545] Fix a search that should have been find --- apps/openmw/mwworld/livecellref.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index 0fbb26c845..f312c2159c 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -22,7 +22,7 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state) std::string scriptId = mClass->getScript (ptr); mData.setLocals (*MWBase::Environment::get().getWorld()->getStore(). - get().search (scriptId)); + get().find (scriptId)); mData.getLocals().read (state.mLocals, scriptId); } @@ -44,4 +44,4 @@ void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const bool MWWorld::LiveCellRefBase::checkStateImp (const ESM::ObjectState& state) { return true; -} \ No newline at end of file +} From 136813a882cbf8fabcf12d2c28c8f7a97126f5f6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 00:00:36 +0200 Subject: [PATCH 206/545] Bug #1319: Fix references not coming from a content file incorrectly overwriting each other --- apps/openmw/mwworld/cellstore.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index e5f0c4b88a..1c39d2c079 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -92,14 +92,17 @@ namespace if (!record) return; - for (typename MWWorld::CellRefList::List::iterator iter (collection.mList.begin()); - iter!=collection.mList.end(); ++iter) - if (iter->mRef.mRefNum==state.mRef.mRefNum) - { - // overwrite existing reference - iter->load (state); - return; - } + if (state.mRef.mRefNum.mContentFile != -1) + { + for (typename MWWorld::CellRefList::List::iterator iter (collection.mList.begin()); + iter!=collection.mList.end(); ++iter) + if (iter->mRef.mRefNum==state.mRef.mRefNum) + { + // overwrite existing reference + iter->load (state); + return; + } + } // new reference MWWorld::LiveCellRef ref (record); From 1444cd9051cc37e789f5eb816adb310b33a4291d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 00:37:36 +0200 Subject: [PATCH 207/545] Fix AiCombat exception when actor has a lockpick/probe equipped. Don't make NPCs autoEquip lockpicks/probes, since they can't use them. --- apps/openmw/mwmechanics/aicombat.cpp | 6 +++++- apps/openmw/mwworld/inventorystore.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index fdaec28b49..08d087069a 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -250,6 +250,9 @@ namespace MWMechanics if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) actorCls.getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon); + // TODO: Check equipped weapon and equip a different one if we can't attack with it + // (e.g. no ammunition, or wrong type of ammunition equipped, etc. autoEquip is not very smart in this regard)) + //Get weapon speed and range MWWorld::ContainerStoreIterator weaponSlot = MWMechanics::getActiveWeapon(actorCls.getCreatureStats(actor), actorCls.getInventoryStore(actor), &weaptype); @@ -260,8 +263,9 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->getStore().get(); weapRange = gmst.find("fHandToHandReach")->getFloat(); } - else + else if (weaptype != WeapType_PickProbe && weaptype != WeapType_Spell) { + // All other WeapTypes are actually weapons, so get is safe. weapon = weaponSlot->get()->mBase; weapRange = weapon->mData.mReach; weapSpeed = weapon->mData.mSpeed; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 9610171b23..b18bda5e33 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -192,12 +192,17 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { Ptr test = *iter; - // Don't autoEquip lights + // Don't autoEquip lights. Handled in Actors::updateEquippedLight based on environment light. if (test.getTypeName() == typeid(ESM::Light).name()) { continue; } + // Don't auto-equip probes or lockpicks. NPCs can't use them (yet). And AiCombat would attempt to "attack" with them. + // NOTE: In the future AiCombat should handle equipping appropriate weapons + if (test.getTypeName() == typeid(ESM::Lockpick).name() || test.getTypeName() == typeid(ESM::Probe).name()) + 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. From d86585b153d1c48ffee82c5ad5425be86e7960a6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 01:06:08 +0200 Subject: [PATCH 208/545] Fix clearing of local map markers destroyWidget changes the child count, so the for loop is flawed. --- apps/openmw/mwgui/mapwindow.cpp | 30 +++++++++++++++--------------- apps/openmw/mwgui/mapwindow.hpp | 11 ++++++++--- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 284e5c4e2e..6a2228c33f 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -86,6 +86,11 @@ namespace MWGui { mFogOfWar = !mFogOfWar; applyFogOfWar(); + + // clear all previous door markers + for (std::vector::iterator it = mDoorMarkerWidgets.begin(); it != mDoorMarkerWidgets.end(); ++it) + MyGUI::Gui::getInstance().destroyWidget(*it); + mDoorMarkerWidgets.clear(); } void LocalMapBase::applyFogOfWar() @@ -172,14 +177,10 @@ namespace MWGui mInterior = interior; mChanged = false; - // clear all previous markers - for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i) - { - if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door") - { - MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i)); - } - } + // clear all previous door markers + for (std::vector::iterator it = mDoorMarkerWidgets.begin(); it != mDoorMarkerWidgets.end(); ++it) + MyGUI::Gui::getInstance().destroyWidget(*it); + mDoorMarkerWidgets.clear(); // Update the map textures for (int mx=0; mx<3; ++mx) @@ -243,6 +244,8 @@ namespace MWGui // Used by tooltips to not show the tooltip if marker is hidden by fog of war markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserData(markerPos); + + mDoorMarkerWidgets.push_back(markerWidget); } updateMarkers(); @@ -344,13 +347,9 @@ namespace MWGui void LocalMapBase::updateMarkers() { // clear all previous markers - for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i) - { - if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker") - { - MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i)); - } - } + for (std::vector::iterator it = mMarkerWidgets.begin(); it != mMarkerWidgets.end(); ++it) + MyGUI::Gui::getInstance().destroyWidget(*it); + mMarkerWidgets.clear(); addDetectionMarkers(MWBase::World::Detect_Creature); addDetectionMarkers(MWBase::World::Detect_Key); @@ -373,6 +372,7 @@ namespace MWGui markerWidget->setImageTexture("textures\\menu_map_smark.dds"); markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserData(markerPos); + mMarkerWidgets.push_back(markerWidget); } } diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 7f4f18893c..a28c71ac93 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -55,12 +55,13 @@ namespace MWGui bool mChanged; bool mFogOfWar; - typedef std::pair CellId; - std::vector mMarkers; - std::vector mMapWidgets; std::vector mFogWidgets; + // Keep track of created marker widgets, just to easily remove them later. + std::vector mDoorMarkerWidgets; // Doors + std::vector mMarkerWidgets; // Other markers + void applyFogOfWar(); void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2); @@ -127,6 +128,10 @@ namespace MWGui MyGUI::IntPoint mLastDragPos; bool mGlobal; + // Markers on global map + typedef std::pair CellId; + std::vector mMarkers; + MyGUI::Button* mEventBoxGlobal; MyGUI::Button* mEventBoxLocal; From 516335847879db3c1e3db3e0005bfa69b980e625 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 01:14:12 +0200 Subject: [PATCH 209/545] Fix a crash when exiting OpenMW while the mouse cursor is over a local map marker --- apps/openmw/mwgui/mapwindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 6a2228c33f..89517d7d10 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -41,6 +41,13 @@ namespace MWGui LocalMapBase::~LocalMapBase() { + // Clear our "lost focus" delegate for marker widgets first, otherwise it will + // fire when the widget is about to be destroyed and the mouse cursor is over it. + // At that point, other widgets may already be destroyed, so applyFogOfWar (which is called by the delegate) would crash. + for (std::vector::iterator it = mDoorMarkerWidgets.begin(); it != mDoorMarkerWidgets.end(); ++it) + (*it)->eventMouseLostFocus.clear(); + for (std::vector::iterator it = mMarkerWidgets.begin(); it != mMarkerWidgets.end(); ++it) + (*it)->eventMouseLostFocus.clear(); } void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) From 242e19a136e44a6f913846224b9136fb92c61367 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 01:37:34 +0200 Subject: [PATCH 210/545] Fix crash when exiting OpenMW while dialogue/journal is opened and mouse cursor on a topic (Fixes #1300) --- apps/openmw/mwgui/bookpage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 52682342f7..6545b5d45e 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -783,7 +783,8 @@ public: ActiveTextFormats::iterator i = mActiveTextFormats.find (Font); - mNode->outOfDate (i->second->mRenderItem); + if (mNode) + mNode->outOfDate (i->second->mRenderItem); } } @@ -1125,6 +1126,8 @@ public: protected: void onMouseLostFocus(Widget* _new) { + // NOTE: MyGUI also fires eventMouseLostFocus for widgets that are about to be destroyed (if they had focus). + // Child widgets may already be destroyed! So be careful. if (PageDisplay* pd = dynamic_cast (getSubWidgetText ())) { pd->onMouseLostFocus (); From 7500895519d63264b98fcede265450170b574c78 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 10:52:23 +0200 Subject: [PATCH 211/545] updated changelog --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 7f95003afc..4db9425b6d 100644 --- a/readme.txt +++ b/readme.txt @@ -148,6 +148,7 @@ Bug #1296: Caius doesn't leave at start of quest "Mehra Milo and the Lost Prophe Bug #1297: Saved game: map markers Bug #1302: ring_keley script causes vector::_M_range_check exception Bug #1309: Bug on "You violated the law" dialog +Bug #1319: Creatures sometimes rendered incorrectly Feature #50: Ranged Combat Feature #58: Sneaking Skill Feature #73: Crime and Punishment From aadaf7827ddfe0be49a9e4ca2afe5646b2c1c723 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 12:04:36 +0200 Subject: [PATCH 212/545] added load error log --- apps/opencs/model/doc/loader.cpp | 12 +++++++++++- apps/opencs/model/doc/state.hpp | 21 +++++++++++---------- apps/opencs/model/tools/tools.cpp | 6 +++++- apps/opencs/model/world/data.cpp | 2 +- apps/opencs/model/world/data.hpp | 4 +++- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 5 +++-- apps/opencs/view/doc/view.cpp | 16 ++++++++++++++-- apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/tools/subviews.cpp | 2 ++ 10 files changed, 53 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 2ef808dd60..e2427e62d3 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -3,7 +3,10 @@ #include +#include "../tools/reportmodel.hpp" + #include "document.hpp" +#include "state.hpp" CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {} @@ -48,13 +51,20 @@ void CSMDoc::Loader::load() { if (iter->second.mRecordsLeft) { + CSMDoc::Stage::Messages messages; for (int i=0; igetData().continueLoading()) + if (document->getData().continueLoading (messages)) { iter->second.mRecordsLeft = false; break; } + CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0); + + for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin()); + iter!=messages.end(); ++iter) + document->getReport (log)->add (iter->first, iter->second); + emit nextRecord (document); return; diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp index 04e6fae899..6e1a1c4f41 100644 --- a/apps/opencs/model/doc/state.hpp +++ b/apps/opencs/model/doc/state.hpp @@ -3,17 +3,18 @@ namespace CSMDoc { - enum State - { - State_Modified = 1, - State_Locked = 2, - State_Operation = 4, + enum State + { + State_Modified = 1, + State_Locked = 2, + State_Operation = 4, - State_Saving = 8, - State_Verifying = 16, - State_Compiling = 32, // not implemented yet - State_Searching = 64 // not implemented yet - }; + State_Saving = 8, + State_Verifying = 16, + State_Compiling = 32, // not implemented yet + State_Searching = 64, // not implemented yet + State_Loading = 128 // pseudo-state; can not be encountered in a loaded document + }; } #endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index a11297b45c..2f93db48ea 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -88,6 +88,9 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { + // index 0: load error log + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); + mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0)); } CSMTools::Tools::~Tools() @@ -134,7 +137,8 @@ int CSMTools::Tools::getRunningOperations() const CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) { - if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults) + if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults && + id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog) throw std::logic_error ("invalid request for report model: " + id.toString()); return mReports.at (id.getIndex()); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 885e230336..2de58675fa 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -505,7 +505,7 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base return mReader->getRecordCount(); } -bool CSMWorld::Data::continueLoading() +bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) { if (!mReader) throw std::logic_error ("can't continue loading, because no load has been started"); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 234069e3a7..4f7c624e68 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -24,6 +24,8 @@ #include "../filter/filter.hpp" +#include "../doc/stage.hpp" + #include "idcollection.hpp" #include "universalid.hpp" #include "cell.hpp" @@ -185,7 +187,7 @@ namespace CSMWorld /// ///< \return estimated number of records - bool continueLoading(); + bool continueLoading (CSMDoc::Stage::Messages& messages); ///< \return Finished? bool hasId (const std::string& id) const; diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 94b042ec5c..7471e5cec1 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -101,6 +101,7 @@ namespace static const TypeData sIndexArg[] = { { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; } diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 24fb543996..22779b2638 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -97,10 +97,11 @@ namespace CSMWorld Type_JournalInfos, Type_JournalInfo, Type_Scene, - Type_Preview + Type_Preview, + Type_LoadErrorLog }; - enum { NumberOfTypes = Type_Scene+1 }; + enum { NumberOfTypes = Type_LoadErrorLog+1 }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 95ab6ca279..e71b8435ab 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,9 +10,12 @@ #include #include "../../model/doc/document.hpp" -#include "../world/subviews.hpp" -#include "../tools/subviews.hpp" #include "../../model/settings/usersettings.hpp" + +#include "../world/subviews.hpp" + +#include "../tools/subviews.hpp" + #include "viewmanager.hpp" #include "operations.hpp" #include "subview.hpp" @@ -47,6 +50,10 @@ void CSVDoc::View::setupFileMenu() connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); file->addAction (mVerify); + QAction *loadErrors = new QAction (tr ("Load Error Log"), this); + connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); + file->addAction (loadErrors); + QAction *close = new QAction (tr ("&Close"), this); connect (close, SIGNAL (triggered()), this, SLOT (close())); file->addAction(close); @@ -502,3 +509,8 @@ void CSVDoc::View::toggleShowStatusBar (bool show) subView->setStatusBar (show); } } + +void CSVDoc::View::loadErrorLog() +{ + addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0)); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 5e6c9abc4d..686c001dc1 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -179,6 +179,8 @@ namespace CSVDoc void addJournalInfosSubView(); void toggleShowStatusBar (bool show); + + void loadErrorLog(); }; } diff --git a/apps/opencs/view/tools/subviews.cpp b/apps/opencs/view/tools/subviews.cpp index 781cf602e3..8b04aca504 100644 --- a/apps/opencs/view/tools/subviews.cpp +++ b/apps/opencs/view/tools/subviews.cpp @@ -9,4 +9,6 @@ void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { manager.add (CSMWorld::UniversalId::Type_VerificationResults, new CSVDoc::SubViewFactory); + manager.add (CSMWorld::UniversalId::Type_LoadErrorLog, + new CSVDoc::SubViewFactory); } \ No newline at end of file From 95d24492de4f630037202881fa655cb44d4c971c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:18:40 +0200 Subject: [PATCH 213/545] display load error messages in loading window --- apps/opencs/model/doc/documentmanager.cpp | 2 ++ apps/opencs/model/doc/documentmanager.hpp | 2 ++ apps/opencs/model/doc/loader.cpp | 3 +++ apps/opencs/model/doc/loader.hpp | 3 +++ apps/opencs/view/doc/loader.cpp | 19 +++++++++++++++++++ apps/opencs/view/doc/loader.hpp | 6 ++++++ apps/opencs/view/doc/viewmanager.cpp | 4 ++++ 7 files changed, 39 insertions(+) diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index fe6aaef279..d4f8eb110c 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -35,6 +35,8 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con this, SIGNAL (nextRecord (CSMDoc::Document *))); connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)), &mLoader, SLOT (abortLoading (CSMDoc::Document *))); + connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)), + this, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&))); } CSMDoc::DocumentManager::~DocumentManager() diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index de4a5e94be..7b3a811fad 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -79,6 +79,8 @@ namespace CSMDoc void nextRecord (CSMDoc::Document *document); void cancelLoading (CSMDoc::Document *document); + + void loadMessage (CSMDoc::Document *document, const std::string& message); }; } diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index e2427e62d3..c106c06e82 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -63,7 +63,10 @@ void CSMDoc::Loader::load() for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) + { document->getReport (log)->add (iter->first, iter->second); + emit loadMessage (document, iter->second); + } emit nextRecord (document); diff --git a/apps/opencs/model/doc/loader.hpp b/apps/opencs/model/doc/loader.hpp index a6bcb6b87f..c276e14ff4 100644 --- a/apps/opencs/model/doc/loader.hpp +++ b/apps/opencs/model/doc/loader.hpp @@ -62,6 +62,9 @@ namespace CSMDoc ///< \note This signal is only given once per group of records. The group size is /// approximately the total number of records divided by the steps value of the /// previous nextStage signal. + + void loadMessage (CSMDoc::Document *document, const std::string& message); + ///< Non-critical load error or warning }; } diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 1b2ca8ad5d..0a99d434a1 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" @@ -58,6 +59,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) layout->addWidget (mError); + // other messages + mMessages = new QListWidget (this); + + layout->addWidget (mMessages); + // buttons mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); @@ -97,6 +103,11 @@ void CSVDoc::LoadingDocument::abort (const std::string& error) mButtons->setStandardButtons (QDialogButtonBox::Close); } +void CSVDoc::LoadingDocument::addMessage (const std::string& message) +{ + new QListWidgetItem (QString::fromUtf8 (message.c_str()), mMessages); +} + void CSVDoc::LoadingDocument::cancel() { if (!mAborted) @@ -168,4 +179,12 @@ void CSVDoc::Loader::nextRecord (CSMDoc::Document *document) if (iter!=mDocuments.end()) iter->second->nextRecord(); +} + +void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message) +{ + std::map::iterator iter = mDocuments.find (document); + + if (iter!=mDocuments.end()) + iter->second->addMessage (message); } \ No newline at end of file diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ece071755d..ab2cec548e 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -10,6 +10,7 @@ class QLabel; class QProgressBar; class QDialogButtonBox; +class QListWidget; namespace CSMDoc { @@ -29,6 +30,7 @@ namespace CSVDoc bool mAborted; QDialogButtonBox *mButtons; QLabel *mError; + QListWidget *mMessages; private: @@ -44,6 +46,8 @@ namespace CSVDoc void abort (const std::string& error); + void addMessage (const std::string& message); + private slots: void cancel(); @@ -85,6 +89,8 @@ namespace CSVDoc void nextStage (CSMDoc::Document *document, const std::string& name, int steps); void nextRecord (CSMDoc::Document *document); + + void loadMessage (CSMDoc::Document *document, const std::string& message); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 816eff7917..02f6a54679 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -100,6 +100,10 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) &mDocumentManager, SIGNAL (nextRecord (CSMDoc::Document *)), &mLoader, SLOT (nextRecord (CSMDoc::Document *))); + connect ( + &mDocumentManager, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)), + &mLoader, SLOT (loadMessage (CSMDoc::Document *, const std::string&))); + connect ( &mLoader, SIGNAL (cancel (CSMDoc::Document *)), &mDocumentManager, SIGNAL (cancelLoading (CSMDoc::Document *))); From 79d59153c14303a14931a648722cc818731d7c40 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:29:28 +0200 Subject: [PATCH 214/545] improved layout of loading window --- apps/opencs/view/doc/loader.cpp | 31 +++++++++++++++++-------------- apps/opencs/view/doc/loader.hpp | 2 ++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 0a99d434a1..7e4754ddf8 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -18,20 +18,22 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) } CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) -: mDocument (document), mAborted (false) +: mDocument (document), mAborted (false), mMessages (0) { setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); - QVBoxLayout *layout = new QVBoxLayout (this); + setMinimumWidth (400); + + mLayout = new QVBoxLayout (this); // file progress mFile = new QLabel (this); - layout->addWidget (mFile); + mLayout->addWidget (mFile); mFileProgress = new QProgressBar (this); - layout->addWidget (mFileProgress); + mLayout->addWidget (mFileProgress); int size = static_cast (document->getContentFiles().size())+1; if (document->isNew()) @@ -43,11 +45,11 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mFileProgress->setValue (0); // record progress - layout->addWidget (new QLabel ("Records", this)); + mLayout->addWidget (new QLabel ("Records", this)); mRecordProgress = new QProgressBar (this); - layout->addWidget (mRecordProgress); + mLayout->addWidget (mRecordProgress); mRecordProgress->setMinimum (0); mRecordProgress->setTextVisible (true); @@ -57,19 +59,14 @@ CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) mError = new QLabel (this); mError->setWordWrap (true); - layout->addWidget (mError); - - // other messages - mMessages = new QListWidget (this); - - layout->addWidget (mMessages); + mLayout->addWidget (mError); // buttons mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); - layout->addWidget (mButtons); + mLayout->addWidget (mButtons); - setLayout (layout); + setLayout (mLayout); move (QCursor::pos()); @@ -105,6 +102,12 @@ void CSVDoc::LoadingDocument::abort (const std::string& error) void CSVDoc::LoadingDocument::addMessage (const std::string& message) { + if (!mMessages) + { + mMessages = new QListWidget (this); + mLayout->insertWidget (4, mMessages); + } + new QListWidgetItem (QString::fromUtf8 (message.c_str()), mMessages); } diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index ab2cec548e..69a8b48ba3 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -11,6 +11,7 @@ class QLabel; class QProgressBar; class QDialogButtonBox; class QListWidget; +class QVBoxLayout; namespace CSMDoc { @@ -31,6 +32,7 @@ namespace CSVDoc QDialogButtonBox *mButtons; QLabel *mError; QListWidget *mMessages; + QVBoxLayout *mLayout; private: From 96ca9500ca1870ee2d6a4ebea8ea19c6dea013eb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:47:22 +0200 Subject: [PATCH 215/545] generate error messages when encounting non-critical problems during load --- apps/opencs/model/world/data.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 2de58675fa..3e9fe11eb0 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -592,7 +592,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) } else { - /// \todo report deletion of non-existing record + messages.push_back (std::make_pair (UniversalId::Type_None, + "Trying to delete dialogue record " + id + " which does not exist")); } } else @@ -608,7 +609,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) { if (!mDialogue) { - /// \todo INFO record without matching DIAL record -> report to user + messages.push_back (std::make_pair (UniversalId::Type_None, + "Found info record not following a dialogue record")); + mReader->skipRecord(); break; } @@ -636,8 +639,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) default: - /// \todo throw an exception instead, once all records are implemented - /// or maybe report error and continue? + messages.push_back (std::make_pair (UniversalId::Type_None, + "Unsupported record type: " + n.toString())); + mReader->skipRecord(); } From 6fdbd4d3f9e54c0c545a89ddbd62f484c45d0f95 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 13:49:19 +0200 Subject: [PATCH 216/545] minor adjustment to UniversalId --- apps/opencs/model/world/universalid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 7471e5cec1..140a410c06 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -18,7 +18,7 @@ namespace static const TypeData sNoArg[] = { - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 }, + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 }, From 804bf523bac3be304e3a83512c8a8b8fd225d40d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 17:35:11 +0200 Subject: [PATCH 217/545] removed two unused files --- apps/opencs/view/doc/opendialog.cpp | 62 ----------------------------- apps/opencs/view/doc/opendialog.hpp | 17 -------- 2 files changed, 79 deletions(-) delete mode 100644 apps/opencs/view/doc/opendialog.cpp delete mode 100644 apps/opencs/view/doc/opendialog.hpp diff --git a/apps/opencs/view/doc/opendialog.cpp b/apps/opencs/view/doc/opendialog.cpp deleted file mode 100644 index d107b198c6..0000000000 --- a/apps/opencs/view/doc/opendialog.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -#include - -#include "opendialog.hpp" - -OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent) -{ - QVBoxLayout *layout = new QVBoxLayout(this); - mFileSelector = new DataFilesList(mCfgMgr, this); - layout->addWidget(mFileSelector); - - /// \todo move config to Editor class and add command line options. - // We use the Configuration Manager to retrieve the configuration values - boost::program_options::variables_map variables; - boost::program_options::options_description desc; - - desc.add_options() - ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) - ("data-local", boost::program_options::value()->default_value("")) - ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) - ("encoding", boost::program_options::value()->default_value("win1252")); - - boost::program_options::notify(variables); - - mCfgMgr.readConfiguration(variables, desc); - - Files::PathContainer mDataDirs, mDataLocal; - if (!variables["data"].empty()) { - mDataDirs = Files::PathContainer(variables["data"].as()); - } - - std::string local = variables["data-local"].as(); - if (!local.empty()) { - mDataLocal.push_back(Files::PathContainer::value_type(local)); - } - - mCfgMgr.processPaths(mDataDirs); - mCfgMgr.processPaths(mDataLocal); - - // Set the charset for reading the esm/esp files - QString encoding = QString::fromUtf8 (variables["encoding"].as().c_str()); - - Files::PathContainer dataDirs; - dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); - dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); - mFileSelector->setupDataFiles(dataDirs, encoding); - - buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - layout->addWidget(buttonBox); - - setLayout(layout); - setWindowTitle(tr("Open")); -} - -void OpenDialog::getFileList(std::vector& paths) -{ - mFileSelector->selectedFiles(paths); -} diff --git a/apps/opencs/view/doc/opendialog.hpp b/apps/opencs/view/doc/opendialog.hpp deleted file mode 100644 index 6355aea44f..0000000000 --- a/apps/opencs/view/doc/opendialog.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -class DataFilesList; -class QDialogButtonBox; - -class OpenDialog : public QDialog { - Q_OBJECT -public: - OpenDialog(QWidget * parent = 0); - - void getFileList(std::vector& paths); -private: - DataFilesList * mFileSelector; - QDialogButtonBox * buttonBox; - Files::ConfigurationManager mCfgMgr; -}; \ No newline at end of file From 5b5bf6f37e4573babac9dd97adfc254869791c61 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 May 2014 17:46:10 +0200 Subject: [PATCH 218/545] removed a redundant (and unsufficiently configured) copy of ConfigurationManager --- apps/opencs/editor.cpp | 2 +- apps/opencs/model/settings/usersettings.cpp | 3 ++- apps/opencs/model/settings/usersettings.hpp | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index ad6c4be3d7..57d2f4730e 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -20,7 +20,7 @@ #include "model/world/data.hpp" CS::Editor::Editor (OgreInit::OgreInit& ogreInit) -: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), +: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mIpcServerName ("org.openmw.OpenCS") { std::pair > config = readConfig(); diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 1a91254390..04f98f0d6c 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -28,7 +28,8 @@ namespace boost CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0; -CSMSettings::UserSettings::UserSettings() +CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager) +: mCfgMgr (configurationManager) { assert(!mUserSettingsInstance); mUserSettingsInstance = this; diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 830cc8c69f..7e553caf6e 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -30,7 +30,7 @@ namespace CSMSettings { Q_OBJECT static UserSettings *mUserSettingsInstance; - Files::ConfigurationManager mCfgMgr; + const Files::ConfigurationManager& mCfgMgr; QSettings *mSettingDefinitions; QList mSettings; @@ -40,11 +40,11 @@ namespace CSMSettings { /// Singleton implementation static UserSettings& instance(); - UserSettings(); + UserSettings (const Files::ConfigurationManager& configurationManager); ~UserSettings(); - UserSettings (UserSettings const &); //not implemented - void operator= (UserSettings const &); //not implemented + UserSettings (UserSettings const &); //not implemented + UserSettings& operator= (UserSettings const &); //not implemented /// Retrieves the settings file at all three levels (global, local and user). void loadSettings (const QString &fileName); From 9fb5cef287e2e518df7c6c58c73722c18721c528 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 15:40:00 +0200 Subject: [PATCH 219/545] Oops, committed debug code --- apps/openmw/mwgui/mapwindow.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 89517d7d10..a4cd61c849 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -93,11 +93,6 @@ namespace MWGui { mFogOfWar = !mFogOfWar; applyFogOfWar(); - - // clear all previous door markers - for (std::vector::iterator it = mDoorMarkerWidgets.begin(); it != mDoorMarkerWidgets.end(); ++it) - MyGUI::Gui::getInstance().destroyWidget(*it); - mDoorMarkerWidgets.clear(); } void LocalMapBase::applyFogOfWar() From b358cf24230e4438767aaae23fc914921a29ab25 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 18:14:35 +0200 Subject: [PATCH 220/545] Fix a potential crash when loading script locals from savegame --- apps/openmw/mwworld/livecellref.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index f312c2159c..4a610b45ca 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -20,10 +20,15 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state) if (state.mHasLocals) { std::string scriptId = mClass->getScript (ptr); - - mData.setLocals (*MWBase::Environment::get().getWorld()->getStore(). - get().find (scriptId)); - mData.getLocals().read (state.mLocals, scriptId); + // Make sure we still have a script. It could have been coming from a content file that is no longer active. + if (!scriptId.empty()) + { + if (const ESM::Script* script = MWBase::Environment::get().getWorld()->getStore().get().search (scriptId)) + { + mData.setLocals (*script); + mData.getLocals().read (state.mLocals, scriptId); + } + } } mClass->readAdditionalState (ptr, state); From 9095a45ba7d5280b63b89d338b9fc1911ebd72ac Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Sat, 10 May 2014 17:05:15 -0400 Subject: [PATCH 221/545] Bug 1047 Fix Dialog links can no longer be highlighted if they appear in the middle of the word. This is achieved by confirming that the character before a match is not alphabetic, so that words following hyphens can still potentially match. --- apps/openmw/mwgui/dialogue.cpp | 3 ++- apps/openmw/mwgui/keywordsearch.hpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6c43f47b4b..6ee329aa71 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -162,7 +162,8 @@ namespace MWGui { std::string::const_iterator i = text.begin (); KeywordSearchT::Match match; - while (i != text.end () && keywordSearch->search (i, text.end (), match)) + + while (i != text.end () && keywordSearch->search (i, text.end (), match, false)) { if (i != match.mBeg) addTopicLink (typesetter, 0, i - text.begin (), match.mBeg - text.begin ()); diff --git a/apps/openmw/mwgui/keywordsearch.hpp b/apps/openmw/mwgui/keywordsearch.hpp index a9fb6daaba..be118597cd 100644 --- a/apps/openmw/mwgui/keywordsearch.hpp +++ b/apps/openmw/mwgui/keywordsearch.hpp @@ -66,10 +66,19 @@ public: return false; } - bool search (Point beg, Point end, Match & match) + bool search (Point beg, Point end, Match & match, bool matchSubword = true) { + char prev = ' '; for (Point i = beg; i != end; ++i) { + // check if previous character marked start of new word + if (!matchSubword && isalpha(prev)) + { + prev = *i; + continue; + } + prev = *i; + // check first character typename Entry::childen_t::iterator candidate = mRoot.mChildren.find (std::tolower (*i, mLocale)); From dab4db87fff2866e215833c2e93751f5510de511 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 May 2014 23:47:00 +0200 Subject: [PATCH 222/545] Fix a bug in marker placement for interior maps --- apps/openmw/mwgui/mapwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index a4cd61c849..b6b1bd89af 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -160,8 +160,9 @@ namespace MWGui markerPos.cellX = cellX; markerPos.cellY = cellY; - widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512, - nY * 512 + (1+cellY-mCurY) * 512); + // Image space is -Y up, cells are Y up + widgetPos = MyGUI::IntPoint(nX * 512 + (1+(cellX-mCurX)) * 512, + nY * 512 + (1-(cellY-mCurY)) * 512); } markerPos.nX = nX; From eb5ef270baa4ad051ded63169bd1663e3f421388 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Sat, 10 May 2014 17:47:21 -0400 Subject: [PATCH 223/545] Bug 1047 update - defaults and edge case Handles edge case where it was possible to highlight adjacent sub-terms without whitespace between them. Also makes ignoring words not prefixed by whitespace the assumed behaviour. --- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/journalviewmodel.cpp | 2 +- apps/openmw/mwgui/keywordsearch.hpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6ee329aa71..e5b2257918 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -163,7 +163,7 @@ namespace MWGui std::string::const_iterator i = text.begin (); KeywordSearchT::Match match; - while (i != text.end () && keywordSearch->search (i, text.end (), match, false)) + while (i != text.end () && keywordSearch->search (i, text.end (), match, text.begin ())) { if (i != match.mBeg) addTopicLink (typesetter, 0, i - text.begin (), match.mBeg - text.begin ()); diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index c6bd6d15d2..5994c6e211 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -178,7 +178,7 @@ struct JournalViewModelImpl : JournalViewModel KeywordSearchT::Match match; - while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match)) + while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match, utf8text.begin())) { if (i != match.mBeg) visitor (0, i - utf8text.begin (), match.mBeg - utf8text.begin ()); diff --git a/apps/openmw/mwgui/keywordsearch.hpp b/apps/openmw/mwgui/keywordsearch.hpp index be118597cd..4f4459b359 100644 --- a/apps/openmw/mwgui/keywordsearch.hpp +++ b/apps/openmw/mwgui/keywordsearch.hpp @@ -66,18 +66,18 @@ public: return false; } - bool search (Point beg, Point end, Match & match, bool matchSubword = true) + bool search (Point beg, Point end, Match & match, Point start) { - char prev = ' '; for (Point i = beg; i != end; ++i) { // check if previous character marked start of new word - if (!matchSubword && isalpha(prev)) + if (i != start) { - prev = *i; - continue; + Point prev = i; + --prev; + if(isalpha(*prev)) + continue; } - prev = *i; // check first character typename Entry::childen_t::iterator candidate = mRoot.mChildren.find (std::tolower (*i, mLocale)); From 3ad28ec5aad024f2338e23e78c644ee826258b2a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 00:09:02 +0200 Subject: [PATCH 224/545] Set a proper Page size for all scrollbars. Fixes scrollbars only moving very slowly when interacting with them (as opposed to using mousewheel on the content) --- files/mygui/openmw_list.skin.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 7972527acc..4dbc3da45c 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -10,6 +10,10 @@ + + + + @@ -47,6 +51,10 @@ + + + + From 07d9845aa00a3c467c1df9d9ac114b6f45106b52 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 00:10:28 +0200 Subject: [PATCH 225/545] Fix a bug in ESMStore code that checks for duplicate record insertions --- apps/openmw/mwworld/esmstore.hpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index ea6d3d0064..c6c9c1ffe2 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -166,16 +166,17 @@ namespace MWWorld template const T *insert(const T &x) { + std::ostringstream id; + id << "$dynamic" << mDynamicCount++; + Store &store = const_cast &>(get()); - if (store.search(x.mId) != 0) { + if (store.search(id.str()) != 0) { std::ostringstream msg; - msg << "Try to override existing record '" << x.mId << "'"; + msg << "Try to override existing record '" << id.str() << "'"; throw std::runtime_error(msg.str()); } T record = x; - std::ostringstream id; - id << "$dynamic" << mDynamicCount++; record.mId = id.str(); T *ptr = store.insert(record); @@ -189,10 +190,13 @@ namespace MWWorld template const T *insertStatic(const T &x) { + std::ostringstream id; + id << "$dynamic" << mDynamicCount++; + Store &store = const_cast &>(get()); - if (store.search(x.mId) != 0) { + if (store.search(id.str()) != 0) { std::ostringstream msg; - msg << "Try to override existing record '" << x.mId << "'"; + msg << "Try to override existing record '" << id.str() << "'"; throw std::runtime_error(msg.str()); } T record = x; @@ -225,17 +229,18 @@ namespace MWWorld template <> inline const ESM::NPC *ESMStore::insert(const ESM::NPC &npc) { + std::ostringstream id; + id << "$dynamic" << mDynamicCount++; + if (Misc::StringUtils::ciEqual(npc.mId, "player")) { return mNpcs.insert(npc); - } else if (mNpcs.search(npc.mId) != 0) { + } else if (mNpcs.search(id.str()) != 0) { std::ostringstream msg; - msg << "Try to override existing record '" << npc.mId << "'"; + msg << "Try to override existing record '" << id.str() << "'"; throw std::runtime_error(msg.str()); } ESM::NPC record = npc; - std::ostringstream id; - id << "$dynamic" << mDynamicCount++; record.mId = id.str(); ESM::NPC *ptr = mNpcs.insert(record); From 041319c43e4fcf059c7bcc28976e504c08fd3820 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 00:32:22 +0200 Subject: [PATCH 226/545] Fixes #1234: Store dynamic record counter in savegame to prevent name clashes --- apps/openmw/mwstate/statemanagerimp.cpp | 1 + apps/openmw/mwworld/esmstore.cpp | 16 ++++++++++++++-- components/esm/defs.hpp | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index c718eeced7..c89041710a 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -314,6 +314,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_PLAY: case ESM::REC_CSTA: case ESM::REC_WTHR: + case ESM::REC_DYNA: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index ebe0aa08a6..a769e7f67c 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -141,8 +141,8 @@ void ESMStore::setUp() int ESMStore::countSavedGameRecords() const { - return - mPotions.getDynamicSize() + return 1 // DYNA (dynamic name counter) + +mPotions.getDynamicSize() +mArmors.getDynamicSize() +mBooks.getDynamicSize() +mClasses.getDynamicSize() @@ -155,6 +155,13 @@ void ESMStore::setUp() void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { + writer.startRecord(ESM::REC_DYNA); + writer.startSubRecord("COUN"); + writer.writeT(mDynamicCount); + writer.endRecord("COUN"); + writer.endRecord(ESM::REC_DYNA); + progress.increaseProgress(); + mPotions.write (writer, progress); mArmors.write (writer, progress); mBooks.write (writer, progress); @@ -197,6 +204,11 @@ void ESMStore::setUp() return true; + case ESM::REC_DYNA: + reader.getSubNameIs("COUN"); + reader.getHT(mDynamicCount); + return true; + default: return false; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index b2a1637f11..5a99d0c2e4 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -100,6 +100,7 @@ enum RecNameInts REC_DIAS = 0x53414944, REC_WTHR = 0x52485457, REC_KEYS = FourCC<'K','E','Y','S'>::value, + REC_DYNA = FourCC<'D','Y','N','A'>::value, // format 1 REC_FILT = 0x544C4946 From 7b46e9f914228e02c1702f785c57fdb17ea651aa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 01:05:49 +0200 Subject: [PATCH 227/545] Get rid of no longer needed widget names --- apps/openmw/mwgui/mapwindow.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index b6b1bd89af..dc22dcb226 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -65,11 +65,11 @@ namespace MWGui { MyGUI::ImageBox* map = mLocalMap->createWidget("ImageBox", MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), - MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my)); + MyGUI::Align::Top | MyGUI::Align::Left); MyGUI::ImageBox* fog = map->createWidget("ImageBox", MyGUI::IntCoord(0, 0, widgetSize, widgetSize), - MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my) + "_fog"); + MyGUI::Align::Top | MyGUI::Align::Left); if (!mMapDragAndDrop) { @@ -237,7 +237,7 @@ namespace MWGui 8, 8); ++counter; MyGUI::Button* markerWidget = mLocalMap->createWidget("ButtonImage", - widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast(counter)); + widgetCoord, MyGUI::Align::Default); markerWidget->setImageResource("DoorMarker"); markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); @@ -339,7 +339,7 @@ namespace MWGui 8, 8); ++counter; MyGUI::ImageBox* markerWidget = mLocalMap->createWidget("ImageBox", - widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(counter)); + widgetCoord, MyGUI::Align::Default); markerWidget->setImageTexture(markerTexture); markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserData(markerPos); @@ -371,7 +371,7 @@ namespace MWGui widgetPos.top - 4, 8, 8); MyGUI::ImageBox* markerWidget = mLocalMap->createWidget("ImageBox", - widgetCoord, MyGUI::Align::Default, "MarkerMarked"); + widgetCoord, MyGUI::Align::Default); markerWidget->setImageTexture("textures\\menu_map_smark.dds"); markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserData(markerPos); @@ -443,7 +443,7 @@ namespace MWGui static int _counter=0; MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget("ButtonImage", - widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast(_counter)); + widgetCoord, MyGUI::Align::Default); markerWidget->setImageResource("DoorMarker"); markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); From a4a9794417ff6c89197a2ebddb8b6012add7ecc4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 02:07:28 +0200 Subject: [PATCH 228/545] Savegame: store fog of war (Closes #1177) --- apps/openmw/mwrender/localmap.cpp | 269 ++++++++++++++++------ apps/openmw/mwrender/localmap.hpp | 31 ++- apps/openmw/mwrender/renderingmanager.cpp | 10 +- apps/openmw/mwrender/renderingmanager.hpp | 7 +- apps/openmw/mwworld/cells.cpp | 4 + apps/openmw/mwworld/cellstore.cpp | 26 +++ apps/openmw/mwworld/cellstore.hpp | 20 ++ apps/openmw/mwworld/worldimp.cpp | 10 + components/CMakeLists.txt | 2 +- components/esm/cellstate.cpp | 7 +- components/esm/cellstate.hpp | 4 +- components/esm/fogstate.cpp | 40 ++++ components/esm/fogstate.hpp | 38 +++ 13 files changed, 381 insertions(+), 87 deletions(-) create mode 100644 components/esm/fogstate.cpp create mode 100644 components/esm/fogstate.hpp diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0f6d782a65..41885da337 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" @@ -46,7 +48,6 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManag LocalMap::~LocalMap() { - deleteBuffers(); } const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle) @@ -55,59 +56,83 @@ const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Ve Math::Sin(angle) * (p.x - c.x) + Math::Cos(angle) * (p.y - c.y) + c.y); } -void LocalMap::deleteBuffers() -{ - mBuffers.clear(); -} - -void LocalMap::saveTexture(const std::string& texname, const std::string& filename) -{ - TexturePtr tex = TextureManager::getSingleton().getByName(texname); - if (tex.isNull()) return; - HardwarePixelBufferSharedPtr readbuffer = tex->getBuffer(); - readbuffer->lock(HardwareBuffer::HBL_NORMAL ); - const PixelBox &readrefpb = readbuffer->getCurrentLock(); - uchar *readrefdata = static_cast(readrefpb.data); - - Image img; - img = img.loadDynamicImage (readrefdata, tex->getWidth(), - tex->getHeight(), tex->getFormat()); - img.save("./" + filename); - - readbuffer->unlock(); -} - std::string LocalMap::coordStr(const int x, const int y) { return StringConverter::toString(x) + "_" + StringConverter::toString(y); } +void LocalMap::clear() +{ + // Not actually removing the Textures here. That doesnt appear to work properly. It seems MyGUI still keeps some pointers. + mBuffers.clear(); +} + void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) { if (!mInterior) { - /*saveTexture("Cell_"+coordStr(mCellX, mCellY)+"_fog", - "Cell_"+coordStr(mCellX, mCellY)+"_fog.png");*/ + std::string textureName = "Cell_"+coordStr(cell->getCell()->getGridX(), cell->getCell()->getGridY())+"_fog"; + std::auto_ptr fog (new ESM::FogState()); + fog->mFogTextures.push_back(ESM::FogTexture()); + + TexturePtr tex = TextureManager::getSingleton().getByName(textureName); + if (tex.isNull()) + return; + + Ogre::Image image; + tex->convertToImage(image); + + Ogre::DataStreamPtr encoded = image.encode("tga"); + fog->mFogTextures.back().mImageData.resize(encoded->size()); + encoded->read(&fog->mFogTextures.back().mImageData[0], encoded->size()); + + cell->setFog(fog.release()); } else { Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y); Vector2 length = max-min; - - // divide into segments const int segsX = std::ceil( length.x / sSize ); const int segsY = std::ceil( length.y / sSize ); + mInteriorName = cell->getCell()->mName; + + std::auto_ptr fog (new ESM::FogState()); + + fog->mBounds.mMinX = mBounds.getMinimum().x; + fog->mBounds.mMaxX = mBounds.getMaximum().x; + fog->mBounds.mMinY = mBounds.getMinimum().y; + fog->mBounds.mMaxY = mBounds.getMaximum().y; + fog->mNorthMarkerAngle = mAngle; + + fog->mFogTextures.reserve(segsX*segsY); + for (int x=0; xgetCell()->mName + "_" + coordStr(x,y) + "_fog"; + + TexturePtr tex = TextureManager::getSingleton().getByName(textureName); + if (tex.isNull()) + return; + + Ogre::Image image; + tex->convertToImage(image); + + fog->mFogTextures.push_back(ESM::FogTexture()); + + Ogre::DataStreamPtr encoded = image.encode("tga"); + fog->mFogTextures.back().mImageData.resize(encoded->size()); + encoded->read(&fog->mFogTextures.back().mImageData[0], encoded->size()); + + fog->mFogTextures.back().mX = x; + fog->mFogTextures.back().mY = y; } } + + cell->setFog(fog.release()); } } @@ -126,29 +151,34 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax) mCameraPosNode->setPosition(Vector3(0,0,0)); render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name); + + if (mBuffers.find(name) == mBuffers.end()) + { + if (cell->getFog()) + loadFogOfWar(name, cell->getFog()->mFogTextures.back()); + else + createFogOfWar(name); + } } void LocalMap::requestMap(MWWorld::CellStore* cell, AxisAlignedBox bounds) { - // if we're in an empty cell, don't bother rendering anything + // If we're in an empty cell, bail out + // The operations in this function are only valid for finite bounds if (bounds.isNull ()) return; mInterior = true; + mBounds = bounds; - float zMin = mBounds.getMinimum().z; - float zMax = mBounds.getMaximum().z; - + // Get the cell's NorthMarker rotation. This is used to rotate the entire map. const Vector2& north = MWBase::Environment::get().getWorld()->getNorthVector(cell); - Radian angle = Ogre::Math::ATan2 (north.x, north.y); + Radian angle = Ogre::Math::ATan2 (north.x, north.y) + Ogre::Degree(2); mAngle = angle.valueRadians(); - mCellCamera->setOrientation(Quaternion::IDENTITY); - mCameraRotNode->setOrientation(Quaternion(Math::Cos(mAngle/2.f), 0, 0, -Math::Sin(mAngle/2.f))); - - // rotate the cell and merge the rotated corners to the bounding box + // Rotate the cell and merge the rotated corners to the bounding box Vector2 _center(bounds.getCenter().x, bounds.getCenter().y); Vector3 _c1 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM); Vector3 _c2 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM); @@ -168,9 +198,48 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, mBounds.merge(Vector3(c3.x, c3.y, 0)); mBounds.merge(Vector3(c4.x, c4.y, 0)); - // apply a little padding - mBounds.setMinimum (mBounds.getMinimum() - Vector3(500,500,0)); - mBounds.setMaximum (mBounds.getMaximum() + Vector3(500,500,0)); + // Do NOT change padding! This will break older savegames. + // If the padding really needs to be changed, then it must be saved in the ESM::FogState and + // assume the old (500) value as default for older savegames. + const int padding = 500; + + // Apply a little padding + mBounds.setMinimum (mBounds.getMinimum() - Vector3(padding,padding,0)); + mBounds.setMaximum (mBounds.getMaximum() + Vector3(padding,padding,0)); + + float zMin = mBounds.getMinimum().z; + float zMax = mBounds.getMaximum().z; + + // If there is fog state in the CellStore (e.g. when it came from a savegame) we need to do some checks + // to see if this state is still valid. + // Both the cell bounds and the NorthMarker rotation could be changed by the content files or exchanged models. + // If they changed by too much (for bounds, < padding is considered acceptable) then parts of the interior might not + // be covered by the map anymore. + // The following code detects this, and discards the CellStore's fog state if it needs to. + if (cell->getFog()) + { + ESM::FogState* fog = cell->getFog(); + + Ogre::Vector3 newMin (fog->mBounds.mMinX, fog->mBounds.mMinY, zMin); + Ogre::Vector3 newMax (fog->mBounds.mMaxX, fog->mBounds.mMaxY, zMax); + + Ogre::Vector3 minDiff = newMin - mBounds.getMinimum(); + Ogre::Vector3 maxDiff = newMax - mBounds.getMaximum(); + + if (std::abs(minDiff.x) > 500 || std::abs(minDiff.y) > 500 + || std::abs(maxDiff.x) > 500 || std::abs(maxDiff.y) > 500 + || std::abs(mAngle - fog->mNorthMarkerAngle) > Ogre::Degree(5).valueRadians()) + { + // Nuke it + cell->setFog(NULL); + } + else + { + // Looks sane, use it + mBounds = Ogre::AxisAlignedBox(newMin, newMax); + mAngle = fog->mNorthMarkerAngle; + } + } Vector2 center(mBounds.getCenter().x, mBounds.getCenter().y); @@ -179,6 +248,9 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, Vector2 length = max-min; + mCellCamera->setOrientation(Quaternion::IDENTITY); + mCameraRotNode->setOrientation(Quaternion(Math::Cos(mAngle/2.f), 0, 0, -Math::Sin(mAngle/2.f))); + mCameraPosNode->setPosition(Vector3(center.x, center.y, 0)); // divide into segments @@ -187,19 +259,96 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, mInteriorName = cell->getCell()->mName; + int i=0; for (int x=0; xgetCell()->mName + "_" + coordStr(x,y)); + std::string texturePrefix = cell->getCell()->mName + "_" + coordStr(x,y); + + render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, sSize, sSize, texturePrefix); + + if (!cell->getFog()) + createFogOfWar(texturePrefix); + else + { + ESM::FogState* fog = cell->getFog(); + + // We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same. + assert (i < int(fog->mFogTextures.size())); + + ESM::FogTexture& esm = fog->mFogTextures[i]; + loadFogOfWar(texturePrefix, esm); + } + ++i; } } } +void LocalMap::createFogOfWar(const std::string& texturePrefix) +{ + const std::string texName = texturePrefix + "_fog"; + TexturePtr tex = createFogOfWarTexture(texName); + + // create a buffer to use for dynamic operations + std::vector buffer; + + // initialize to (0, 0, 0, 1) + buffer.resize(sFogOfWarResolution*sFogOfWarResolution, (255 << 24)); + + // upload to the texture + memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); + tex->getBuffer()->unlock(); + + mBuffers[texturePrefix] = buffer; +} + +Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName) +{ + TexturePtr tex = TextureManager::getSingleton().getByName(texName); + if (tex.isNull()) + { + tex = TextureManager::getSingleton().createManual( + texName, + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + TEX_TYPE_2D, + sFogOfWarResolution, sFogOfWarResolution, + 0, + PF_A8R8G8B8, + TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + } + else + tex->unload(); + + return tex; +} + +void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& esm) +{ + std::vector& data = esm.mImageData; + Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size())); + Ogre::Image image; + image.load(stream, "tga"); + + assert (image.getWidth() == sFogOfWarResolution && image.getHeight() == sFogOfWarResolution); + + std::string texName = texturePrefix + "_fog"; + + Ogre::TexturePtr tex = createFogOfWarTexture(texName); + + tex->loadImage(image); + + // create a buffer to use for dynamic operations + std::vector buffer; + buffer.resize(sFogOfWarResolution*sFogOfWarResolution); + memcpy(&buffer[0], image.getData(), image.getSize()); + + mBuffers[texturePrefix] = buffer; +} + void LocalMap::render(const float x, const float y, const float zlow, const float zhigh, const float xw, const float yw, const std::string& texture) @@ -249,31 +398,6 @@ void LocalMap::render(const float x, const float y, vp->setMaterialScheme("local_map"); rtt->update(); - - // create "fog of war" texture - TexturePtr tex2 = TextureManager::getSingleton().createManual( - texture + "_fog", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - TEX_TYPE_2D, - xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize, - 0, - PF_A8R8G8B8, - TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); - - // create a buffer to use for dynamic operations - std::vector buffer; - buffer.resize(sFogOfWarResolution*sFogOfWarResolution); - - // initialize to (0, 0, 0, 1) - for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); - tex2->getBuffer()->unlock(); - - mBuffers[texture] = buffer; } mRenderingManager->enableLights(true); @@ -304,6 +428,9 @@ bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interi if (mBuffers.find(texName) == mBuffers.end()) return false; + nX = std::max(0.f, std::min(1.f, nX)); + nY = std::max(0.f, std::min(1.f, nY)); + int texU = (sFogOfWarResolution-1) * nX; int texV = (sFogOfWarResolution-1) * nY; @@ -414,6 +541,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni } // copy to the texture + // NOTE: Could be optimized later. We actually only need to update the region that changed. + // Not a big deal at the moment, the FoW is only 32x32 anyway. memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &aBuffer[0], sFogOfWarResolution*sFogOfWarResolution*4); tex->getBuffer()->unlock(); } diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 638469d2d7..1d480872e0 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -11,6 +11,11 @@ namespace MWWorld class CellStore; } +namespace ESM +{ + class FogTexture; +} + namespace MWRender { class RenderingManager; @@ -24,6 +29,11 @@ namespace MWRender LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering); ~LocalMap(); + /** + * Clear all savegame-specific data (i.e. fog of war textures) + */ + void clear(); + /** * Request the local map for an exterior cell. * @remarks It will either be loaded from a disk cache, @@ -54,10 +64,8 @@ namespace MWRender void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation); /** - * Save the fog of war for the current cell to disk. - * @remarks This should be called before loading a - * new cell, as well as when the game is quit. - * @param current cell + * Save the fog of war for this cell to its CellStore. + * @remarks This should be called when unloading a cell, and for all active cells prior to saving the game. */ void saveFogOfWar(MWWorld::CellStore* cell); @@ -104,17 +112,20 @@ namespace MWRender const float xw, const float yw, const std::string& texture); - void saveTexture(const std::string& texname, const std::string& filename); + // Creates a fog of war texture and initializes it to full black + void createFogOfWar(const std::string& texturePrefix); + + // Loads a fog of war texture from its ESM struct + void loadFogOfWar(const std::string& texturePrefix, ESM::FogTexture& esm); // FogTexture not const because MemoryDataStream doesn't accept it + + Ogre::TexturePtr createFogOfWarTexture(const std::string& name); std::string coordStr(const int x, const int y); - // a buffer for the "fog of war" texture of the current cell. - // interior cells could be divided into multiple textures, - // so we store in a map. + // A buffer for the "fog of war" textures of the current cell. + // Both interior and exterior maps are possibly divided into multiple textures. std::map > mBuffers; - void deleteBuffers(); - bool mInterior; int mCellX, mCellY; Ogre::AxisAlignedBox mBounds; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 19d26a176e..948f85b5ee 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -216,13 +216,14 @@ OEngine::Render::Fader* RenderingManager::getFader() return mRendering.getFader(); } - MWRender::Camera* RenderingManager::getCamera() const +MWRender::Camera* RenderingManager::getCamera() const { return mCamera; } void RenderingManager::removeCell (MWWorld::CellStore *store) { + mLocalMap->saveFogOfWar(store); mObjects->removeCell(store); mActors->removeCell(store); mDebugging->cellRemoved(store); @@ -671,7 +672,7 @@ void RenderingManager::requestMap(MWWorld::CellStore* cell) mLocalMap->requestMap(cell, mObjects->getDimensions(cell)); } -void RenderingManager::preCellChange(MWWorld::CellStore* cell) +void RenderingManager::writeFog(MWWorld::CellStore* cell) { mLocalMap->saveFogOfWar(cell); } @@ -1057,4 +1058,9 @@ void RenderingManager::spawnEffect(const std::string &model, const std::string & mEffectManager->addEffect(model, texture, worldPosition, scale); } +void RenderingManager::clear() +{ + mLocalMap->clear(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 423a7078ab..eb68272925 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -107,12 +107,15 @@ public: void cellAdded (MWWorld::CellStore *store); void waterAdded(MWWorld::CellStore *store); + /// Clear all savegame-specific data (i.e. fog of war textures) + void clear(); + void enableTerrain(bool enable); void removeWater(); - void preCellChange (MWWorld::CellStore* store); - ///< this event is fired immediately before changing cell + /// Write current fog of war for this cell to the CellStore + void writeFog (MWWorld::CellStore* store); void addObject (const MWWorld::Ptr& ptr); void removeObject (const MWWorld::Ptr& ptr); diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 7f2a87eec4..3b758f8660 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -78,6 +78,7 @@ void MWWorld::Cells::writeCell (ESM::ESMWriter& writer, CellStore& cell) const writer.startRecord (ESM::REC_CSTA); cellState.mId.save (writer); cellState.save (writer); + cell.writeFog(writer); cell.writeReferences (writer); writer.endRecord (ESM::REC_CSTA); } @@ -319,6 +320,9 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type, state.load (reader); cellStore->loadState (state); + if (state.mHasFogOfWar) + cellStore->readFog(reader); + if (cellStore->getState()!=CellStore::State_Loaded) cellStore->load (mStore, mReader); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 1c39d2c079..39f6538bbc 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -533,6 +534,21 @@ namespace MWWorld state.mWaterLevel = mWaterLevel; state.mWaterLevel = mWaterLevel; + state.mHasFogOfWar = (mFogState.get() ? 1 : 0); + } + + void CellStore::writeFog(ESM::ESMWriter &writer) const + { + if (mFogState.get()) + { + mFogState->save(writer, mCell->mData.mFlags & ESM::Cell::Interior); + } + } + + void CellStore::readFog(ESM::ESMReader &reader) + { + mFogState.reset(new ESM::FogState()); + mFogState->load(reader); } void CellStore::writeReferences (ESM::ESMWriter& writer) const @@ -697,4 +713,14 @@ namespace MWWorld { return mPathgridGraph.aStarSearch(start, end); } + + void CellStore::setFog(ESM::FogState *fog) + { + mFogState.reset(fog); + } + + ESM::FogState* CellStore::getFog() const + { + return mFogState.get(); + } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 88b49ed1c0..cc3036647d 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -3,22 +3,28 @@ #include #include +#include #include "livecellref.hpp" #include "esmstore.hpp" #include "cellreflist.hpp" +#include + #include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld namespace ESM { struct CellState; + struct FogState; } namespace MWWorld { class Ptr; + + /// \brief Mutable state of a cell class CellStore { @@ -31,6 +37,11 @@ namespace MWWorld private: + // Even though fog actually belongs to the player and not cells, + // it makes sense to store it here since we need it once for each cell. + // Note this is NULL until the cell is explored to save some memory + boost::shared_ptr mFogState; + const ESM::Cell *mCell; State mState; bool mHasState; @@ -84,6 +95,11 @@ namespace MWWorld void setWaterLevel (float level); + void setFog (ESM::FogState* fog); + ///< \note Takes ownership of the pointer + + ESM::FogState* getFog () const; + int count() const; ///< Return total number of references, including deleted ones. @@ -134,6 +150,10 @@ namespace MWWorld void saveState (ESM::CellState& state) const; + void writeFog (ESM::ESMWriter& writer) const; + + void readFog (ESM::ESMReader& reader); + void writeReferences (ESM::ESMWriter& writer) const; void readReferences (ESM::ESMReader& reader, const std::map& contentFileMap); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index de9c8f04a6..ba36d4a869 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -231,6 +231,8 @@ namespace MWWorld void World::clear() { + mRendering->clear(); + mLocalScripts.clear(); mPlayer->clear(); @@ -277,6 +279,14 @@ namespace MWWorld void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { + // Active cells could have a dirty fog of war, sync it to the CellStore first + for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); + iter!=mWorldScene->getActiveCells().end(); ++iter) + { + CellStore* cellstore = *iter; + mRendering->writeFog(cellstore); + } + mCells.write (writer, progress); mStore.write (writer, progress); mGlobalVariables.write (writer, progress); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 1c60dfb831..3dd5df2954 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys + npcstats creaturestats weatherstate quickkeys fogstate ) add_component_dir (misc diff --git a/components/esm/cellstate.cpp b/components/esm/cellstate.cpp index 1f7e8197ec..541a359c6a 100644 --- a/components/esm/cellstate.cpp +++ b/components/esm/cellstate.cpp @@ -8,10 +8,15 @@ void ESM::CellState::load (ESMReader &esm) { mWaterLevel = 0; esm.getHNOT (mWaterLevel, "WLVL"); + + mHasFogOfWar = false; + esm.getHNOT (mHasFogOfWar, "HFOW"); } void ESM::CellState::save (ESMWriter &esm) const { if (!mId.mPaged) esm.writeHNT ("WLVL", mWaterLevel); -} \ No newline at end of file + + esm.writeHNT("HFOW", mHasFogOfWar); +} diff --git a/components/esm/cellstate.hpp b/components/esm/cellstate.hpp index cd0db30675..88918a3abf 100644 --- a/components/esm/cellstate.hpp +++ b/components/esm/cellstate.hpp @@ -17,9 +17,11 @@ namespace ESM float mWaterLevel; + int mHasFogOfWar; // Do we have fog of war state (0 or 1)? (see fogstate.hpp) + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/fogstate.cpp b/components/esm/fogstate.cpp new file mode 100644 index 0000000000..18235066d4 --- /dev/null +++ b/components/esm/fogstate.cpp @@ -0,0 +1,40 @@ +#include "fogstate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +void ESM::FogState::load (ESMReader &esm) +{ + esm.getHNOT(mBounds, "BOUN"); + esm.getHNOT(mNorthMarkerAngle, "ANGL"); + while (esm.isNextSub("FTEX")) + { + esm.getSubHeader(); + FogTexture tex; + + esm.getT(tex.mX); + esm.getT(tex.mY); + + size_t imageSize = esm.getSubSize()-sizeof(int)*2; + tex.mImageData.resize(imageSize); + esm.getExact(&tex.mImageData[0], imageSize); + mFogTextures.push_back(tex); + } +} + +void ESM::FogState::save (ESMWriter &esm, bool interiorCell) const +{ + if (interiorCell) + { + esm.writeHNT("BOUN", mBounds); + esm.writeHNT("ANGL", mNorthMarkerAngle); + } + for (std::vector::const_iterator it = mFogTextures.begin(); it != mFogTextures.end(); ++it) + { + esm.startSubRecord("FTEX"); + esm.writeT(it->mX); + esm.writeT(it->mY); + esm.write(&it->mImageData[0], it->mImageData.size()); + esm.endRecord("FTEX"); + } +} diff --git a/components/esm/fogstate.hpp b/components/esm/fogstate.hpp new file mode 100644 index 0000000000..4a5619e518 --- /dev/null +++ b/components/esm/fogstate.hpp @@ -0,0 +1,38 @@ +#ifndef OPENMW_ESM_FOGSTATE_H +#define OPENMW_ESM_FOGSTATE_H + +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct FogTexture + { + int mX, mY; // Only used for interior cells + std::vector mImageData; + }; + + // format 0, saved games only + // Fog of war state + struct FogState + { + // Only used for interior cells + float mNorthMarkerAngle; + struct Bounds + { + float mMinX; + float mMinY; + float mMaxX; + float mMaxY; + } mBounds; + + std::vector mFogTextures; + + void load (ESMReader &esm); + void save (ESMWriter &esm, bool interiorCell) const; + }; +} + +#endif From c98bea2a8807f86bfd0d802c1de54b58ff62e912 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 02:27:43 +0200 Subject: [PATCH 229/545] Moved local map update to LocalMap::updatePlayer to fix a brief desync on cell transitions due to sFogOfWarSkip --- apps/openmw/mwbase/windowmanager.hpp | 4 ++-- apps/openmw/mwgui/windowmanagerimp.cpp | 8 +++----- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ++-- apps/openmw/mwrender/localmap.cpp | 5 +---- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 9e5230af62..39cfc47eda 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -200,8 +200,8 @@ namespace MWBase virtual bool getFullHelp() const = 0; - virtual void setInteriorMapTexture(const int x, const int y) = 0; - ///< set the index of the map texture that should be used (for interiors) + virtual void setActiveMap(int x, int y, bool interior) = 0; + ///< set the indices of the map texture that should be used /// sets the visibility of the drowning bar virtual void setDrowningBarVisibility(bool visible) = 0; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 6a15c8e33e..e3baf84fb8 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -766,8 +766,6 @@ namespace MWGui mMap->setCellPrefix("Cell"); mHud->setCellPrefix("Cell"); - mMap->setActiveCell (cell->getCell()->getGridX(), cell->getCell()->getGridY()); - mHud->setActiveCell (cell->getCell()->getGridX(), cell->getCell()->getGridY()); } else { @@ -783,10 +781,10 @@ namespace MWGui } } - void WindowManager::setInteriorMapTexture(const int x, const int y) + void WindowManager::setActiveMap(int x, int y, bool interior) { - mMap->setActiveCell(x,y, true); - mHud->setActiveCell(x,y, true); + mMap->setActiveCell(x,y, interior); + mHud->setActiveCell(x,y, interior); } void WindowManager::setPlayerPos(const float x, const float y) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index e31013b451..7617a4463d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -192,8 +192,8 @@ namespace MWGui virtual void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) virtual bool getFullHelp() const; - virtual void setInteriorMapTexture(const int x, const int y); - ///< set the index of the map texture that should be used (for interiors) + virtual void setActiveMap(int x, int y, bool interior); + ///< set the indices of the map texture that should be used /// sets the visibility of the drowning bar virtual void setDrowningBarVisibility(bool visible); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 41885da337..e1694d8920 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -466,10 +466,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni mCellX = x; mCellY = y; } - else - { - MWBase::Environment::get().getWindowManager()->setInteriorMapTexture(x,y); - } + MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior); // convert from world coordinates to texture UV coordinates std::string texBaseName; From c39a0368cf4150afbe64295aadcd9ae3c2a5f041 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 02:38:39 +0200 Subject: [PATCH 230/545] Bug #618: Make local map textures static in an attempt to fix the disappearing maps with D3D. Also removed problematic DISCARDABLE flag for fog of war textures. --- apps/openmw/mwrender/localmap.cpp | 43 +++++++++++++++++++------------ apps/openmw/mwrender/localmap.hpp | 5 +++- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index e1694d8920..56b2326ecd 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -44,6 +44,24 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManag mLight->setDirection (Ogre::Vector3(0.3, 0.3, -0.7)); mLight->setVisible (false); mLight->setDiffuseColour (ColourValue(0.7,0.7,0.7)); + + mRenderTexture = TextureManager::getSingleton().createManual( + "localmap/rtt", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + TEX_TYPE_2D, + sMapResolution, sMapResolution, + 0, + PF_R8G8B8, + TU_RENDERTARGET); + + mRenderTarget = mRenderTexture->getBuffer()->getRenderTarget(); + mRenderTarget->setAutoUpdated(false); + Viewport* vp = mRenderTarget->addViewport(mCellCamera); + vp->setOverlaysEnabled(false); + vp->setShadowsEnabled(false); + vp->setBackgroundColour(ColourValue(0, 0, 0)); + vp->setVisibilityMask(RV_Map); + vp->setMaterialScheme("local_map"); } LocalMap::~LocalMap() @@ -318,7 +336,7 @@ Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName) sFogOfWarResolution, sFogOfWarResolution, 0, PF_A8R8G8B8, - TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + TU_DYNAMIC_WRITE_ONLY); } else tex->unload(); @@ -378,26 +396,17 @@ void LocalMap::render(const float x, const float y, if (tex.isNull()) { // render - tex = TextureManager::getSingleton().createManual( + mRenderTarget->update(); + + // create a new texture and blit to it + Ogre::TexturePtr tex = TextureManager::getSingleton().createManual( texture, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, - xw*sMapResolution/sSize, yw*sMapResolution/sSize, + sMapResolution, sMapResolution, 0, - PF_R8G8B8, - TU_RENDERTARGET); - - RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); - - rtt->setAutoUpdated(false); - Viewport* vp = rtt->addViewport(mCellCamera); - vp->setOverlaysEnabled(false); - vp->setShadowsEnabled(false); - vp->setBackgroundColour(ColourValue(0, 0, 0)); - vp->setVisibilityMask(RV_Map); - vp->setMaterialScheme("local_map"); - - rtt->update(); + PF_R8G8B8); + tex->getBuffer()->blit(mRenderTexture->getBuffer()); } mRenderingManager->enableLights(true); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 1d480872e0..9411715271 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -84,7 +84,6 @@ namespace MWRender OEngine::Render::OgreRenderer* mRendering; MWRender::RenderingManager* mRenderingManager; - // 1024*1024 pixels for a cell static const int sMapResolution = 512; // the dynamic texture is a bottleneck, so don't set this too high @@ -126,6 +125,10 @@ namespace MWRender // Both interior and exterior maps are possibly divided into multiple textures. std::map > mBuffers; + // The render texture we will use to create the map images + Ogre::TexturePtr mRenderTexture; + Ogre::RenderTarget* mRenderTarget; + bool mInterior; int mCellX, mCellY; Ogre::AxisAlignedBox mBounds; From ac8abd339827b2aedb792ed35569fb03cef4bffa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 14:34:55 +0200 Subject: [PATCH 231/545] assert -> exception to gracefully handle corrupted savegames --- apps/openmw/mwrender/localmap.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 56b2326ecd..78d7527f7b 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -296,7 +296,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, ESM::FogState* fog = cell->getFog(); // We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same. - assert (i < int(fog->mFogTextures.size())); + if (i >= int(fog->mFogTextures.size())) + throw std::runtime_error("fog texture count mismatch"); ESM::FogTexture& esm = fog->mFogTextures[i]; loadFogOfWar(texturePrefix, esm); @@ -351,7 +352,8 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& Ogre::Image image; image.load(stream, "tga"); - assert (image.getWidth() == sFogOfWarResolution && image.getHeight() == sFogOfWarResolution); + if (image.getWidth() != sFogOfWarResolution || image.getHeight() != sFogOfWarResolution) + throw std::runtime_error("fog texture size mismatch"); std::string texName = texturePrefix + "_fog"; From 961c4d4dc4ef07b6bf994529e492c6fefd0158f1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:17:25 +0200 Subject: [PATCH 232/545] Fixes #772: Give scripts a chance to run before updating map, so that disabled objects are not visible --- apps/openmw/mwgui/mapwindow.cpp | 13 ++++++++++++- apps/openmw/mwgui/mapwindow.hpp | 11 +++++++++-- apps/openmw/mwworld/scene.cpp | 17 +++++++++++++---- apps/openmw/mwworld/scene.hpp | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index dc22dcb226..2bd5e44cbd 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -465,7 +465,18 @@ namespace MWGui void MapWindow::cellExplored(int x, int y) { - mGlobalMapRender->exploreCell(x,y); + mQueuedToExplore.push_back(std::make_pair(x,y)); + } + + void MapWindow::onFrame(float dt) + { + for (std::vector::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it) + { + mGlobalMapRender->exploreCell(it->first, it->second); + } + mQueuedToExplore.clear(); + + NoDrop::onFrame(dt); } void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index a28c71ac93..5251fac230 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -97,14 +97,17 @@ namespace MWGui void renderGlobalMap(Loading::Listener* loadingListener); - void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map + // adds the marker to the global map + void addVisitedLocation(const std::string& name, int x, int y); + + // reveals this cell's map on the global map void cellExplored(int x, int y); void setGlobalMapPlayerPosition (float worldX, float worldY); virtual void open(); - void onFrame(float dt) { NoDrop::onFrame(dt); } + void onFrame(float dt); /// Clear all savegame-specific data void clear(); @@ -132,6 +135,10 @@ namespace MWGui typedef std::pair CellId; std::vector mMarkers; + // Cells that should be explored in the next frame (i.e. their map revealed on the global map) + // We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp) + std::vector mQueuedToExplore; + MyGUI::Button* mEventBoxGlobal; MyGUI::Button* mEventBoxLocal; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3d4413a357..49fd8cb895 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -85,7 +85,15 @@ namespace namespace MWWorld { - void Scene::update (float duration, bool paused){ + void Scene::update (float duration, bool paused) + { + if (mNeedMapUpdate) + { + for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) + mRendering.requestMap(*active); + mNeedMapUpdate = false; + } + mRendering.update (duration, paused); } @@ -197,8 +205,9 @@ namespace MWWorld mRendering.updateTerrain(); - for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) - mRendering.requestMap(*active); + // Delay the map update until scripts have been given a chance to run. + // If we don't do this, objects that should be disabled will still appear on the map. + mNeedMapUpdate = true; MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); } @@ -342,7 +351,7 @@ namespace MWWorld //We need the ogre renderer and a scene node. Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics) - : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering) + : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering), mNeedMapUpdate(false) { } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 16d4877a92..8d8765378e 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -58,6 +58,8 @@ namespace MWWorld PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; + bool mNeedMapUpdate; + void playerCellChange (CellStore *cell, const ESM::Position& position, bool adjustPlayerPos = true); From 7428511ea06145261522f7e16864555b98394ca4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:22:46 +0200 Subject: [PATCH 233/545] Bug #772: Do not show door markers for disabled doors --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ba36d4a869..d5da19dfa0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1491,6 +1491,9 @@ namespace MWWorld { MWWorld::LiveCellRef& ref = *it; + if (!ref.mData.isEnabled()) + continue; + if (ref.mRef.mTeleport) { World::DoorMarker newMarker; From 54a893994a9c708192c7d0055dbcd3ac5ffec314 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:23:44 +0200 Subject: [PATCH 234/545] Also update local map when paused, to make it update properly when teleporting via GUI/console --- apps/openmw/mwrender/renderingmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 948f85b5ee..a3c53dc444 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -380,6 +380,10 @@ void RenderingManager::update (float duration, bool paused) mCamera->update(duration, paused); + Ogre::SceneNode *node = data.getBaseNode(); + Ogre::Quaternion orient = node->_getDerivedOrientation(); + mLocalMap->updatePlayer(playerPos, orient); + if(paused) return; @@ -393,10 +397,6 @@ void RenderingManager::update (float duration, bool paused) mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); - Ogre::SceneNode *node = data.getBaseNode(); - Ogre::Quaternion orient = node->_getDerivedOrientation(); - - mLocalMap->updatePlayer(playerPos, orient); mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam)); From 2bc2684a667ee0123b806d66eeb8538ff5a23c0c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 15:36:31 +0200 Subject: [PATCH 235/545] Fixes #275: force updating exterior cell maps even if already in cache --- apps/openmw/mwrender/localmap.cpp | 12 ++++++++++-- apps/openmw/mwrender/localmap.hpp | 3 ++- apps/openmw/mwworld/scene.cpp | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 78d7527f7b..4168127df6 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -168,7 +168,10 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax) mCameraPosNode->setPosition(Vector3(0,0,0)); - render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name); + // Note: using force=true for exterior cell maps. + // They must be updated even if they were visited before, because the set of surrounding active cells might be different + // (and objects in a different cell can "bleed" into another cell's map if they cross the border) + render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name, true); if (mBuffers.find(name) == mBuffers.end()) { @@ -371,7 +374,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& void LocalMap::render(const float x, const float y, const float zlow, const float zhigh, - const float xw, const float yw, const std::string& texture) + const float xw, const float yw, const std::string& texture, bool force) { mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 ); mCellCamera->setNearClipDistance(50); @@ -410,6 +413,11 @@ void LocalMap::render(const float x, const float y, PF_R8G8B8); tex->getBuffer()->blit(mRenderTexture->getBuffer()); } + else if (force) + { + mRenderTarget->update(); + tex->getBuffer()->blit(mRenderTexture->getBuffer()); + } mRenderingManager->enableLights(true); mLight->setVisible(false); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 9411715271..babf7224ed 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -106,10 +106,11 @@ namespace MWRender float mAngle; const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle); + /// @param force Always render, even if we already have a cached map void render(const float x, const float y, const float zlow, const float zhigh, const float xw, const float yw, - const std::string& texture); + const std::string& texture, bool force=false); // Creates a fog of war texture and initializes it to full black void createFogOfWar(const std::string& texturePrefix); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 49fd8cb895..7af926dca3 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -89,6 +89,8 @@ namespace MWWorld { if (mNeedMapUpdate) { + // Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different + // (and objects in a different cell can "bleed" into another cells map if they cross the border) for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active) mRendering.requestMap(*active); mNeedMapUpdate = false; From b0fbea9d57e55c3708d487b6ddf8c95c596b903b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 11 May 2014 21:03:27 +0200 Subject: [PATCH 236/545] Removed a wrong assertion. Max drowning time is defined by GMST. --- apps/openmw/mwmechanics/npcstats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 819c2701c7..b1d2c75b16 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -432,9 +432,9 @@ float MWMechanics::NpcStats::getTimeToStartDrowning() const { return mTimeToStartDrowning; } + void MWMechanics::NpcStats::setTimeToStartDrowning(float time) { - assert(time>=0 && time<=20); mTimeToStartDrowning=time; } From 117b812fb1890c559deb3d872f3e3affa48edd60 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 02:20:56 +0200 Subject: [PATCH 237/545] Fix invisibility not breaking on certain actions --- apps/openmw/mwgui/hud.cpp | 3 +++ apps/openmw/mwgui/inventorywindow.cpp | 4 +++- apps/openmw/mwworld/actionapply.cpp | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index be4a9a14ee..ccd4489ba8 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -233,6 +233,9 @@ namespace MWGui MWBase::World* world = MWBase::Environment::get().getWorld(); + MWBase::Environment::get().getWorld()->breakInvisibility( + MWBase::Environment::get().getWorld()->getPlayerPtr()); + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); float mouseX = cursorPosition.left / float(viewSize.width); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2bea088e32..d6da3b30e3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -541,9 +541,11 @@ namespace MWGui int count = object.getRefData().getCount(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + MWBase::Environment::get().getWorld()->breakInvisibility(player); + // add to player inventory // can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player); // remove from world MWBase::Environment::get().getWorld()->deleteObject (object); diff --git a/apps/openmw/mwworld/actionapply.cpp b/apps/openmw/mwworld/actionapply.cpp index f78b8f7988..bd3e875484 100644 --- a/apps/openmw/mwworld/actionapply.cpp +++ b/apps/openmw/mwworld/actionapply.cpp @@ -3,6 +3,9 @@ #include "class.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + namespace MWWorld { ActionApply::ActionApply (const Ptr& target, const std::string& id) @@ -11,6 +14,8 @@ namespace MWWorld void ActionApply::executeImp (const Ptr& actor) { + MWBase::Environment::get().getWorld()->breakInvisibility(actor); + MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor); } @@ -22,6 +27,8 @@ namespace MWWorld void ActionApplyWithSkill::executeImp (const Ptr& actor) { + MWBase::Environment::get().getWorld()->breakInvisibility(actor); + if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1) MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType); } From 050fe9ebe1190c0ca9ac0c9b4cc8fa519b100a92 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 May 2014 08:58:55 +0200 Subject: [PATCH 238/545] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 499c55eebd..6f0561490b 100644 --- a/credits.txt +++ b/credits.txt @@ -33,6 +33,7 @@ Edmondo Tommasina (edmondo) Eduard Cot (trombonecot) Eli2 Emanuel GuĂ©vel (potatoesmaster) +Fil Krynicki (filkry) gugus/gus Jacob Essex (Yacoby) Jannik Heller (scrawl) From 8279d307c4b53a13acf339594bd3703300ee17b6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 May 2014 10:32:57 +0200 Subject: [PATCH 239/545] text encoding configuration (was using hardcoded settings before) --- apps/opencs/editor.cpp | 3 +++ apps/opencs/model/doc/document.cpp | 8 +++++--- apps/opencs/model/doc/document.hpp | 5 ++++- apps/opencs/model/doc/documentmanager.cpp | 9 +++++++-- apps/opencs/model/doc/documentmanager.hpp | 5 +++++ apps/opencs/model/doc/saving.cpp | 5 +++-- apps/opencs/model/doc/saving.hpp | 5 ++++- apps/opencs/model/doc/savingstate.cpp | 8 +++----- apps/opencs/model/doc/savingstate.hpp | 5 ++++- apps/opencs/model/world/data.cpp | 6 ++---- apps/opencs/model/world/data.hpp | 4 +++- 11 files changed, 43 insertions(+), 20 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 57d2f4730e..b003735874 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -90,6 +90,9 @@ std::pair > CS::Editor::readConfi mCfgMgr.readConfiguration(variables, desc); + mDocumentManager.setEncoding ( + ToUTF8::calculateEncoding (variables["encoding"].as())); + mDocumentManager.setResourceDir (mResources = variables["resources"].as()); mFsStrict = variables["fs-strict"].as(); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 06c4a09887..f452008ac9 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2204,11 +2204,13 @@ void CSMDoc::Document::createBase() CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, - const boost::filesystem::path& savePath, const boost::filesystem::path& resDir) -: mSavePath (savePath), mContentFiles (files), mNew (new_), mTools (mData), mResDir(resDir), + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, + ToUTF8::FromType encoding) +: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData), + mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), - mSaving (*this, mProjectPath) + mSaving (*this, mProjectPath, encoding) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 000f6761a0..a6f8aaae28 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -9,6 +9,8 @@ #include #include +#include + #include "../world/data.hpp" #include "../tools/tools.hpp" @@ -70,7 +72,8 @@ namespace CSMDoc Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, - const boost::filesystem::path& savePath, const boost::filesystem::path& resDir); + const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, + ToUTF8::FromType encoding); ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index d4f8eb110c..096864b772 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -13,7 +13,7 @@ #include "document.hpp" CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration) -: mConfiguration (configuration) +: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252) { boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects"; @@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, new_, savePath, mResDir); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding); mDocuments.push_back (document); @@ -80,6 +80,11 @@ void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& par mResDir = boost::filesystem::system_complete(parResDir); } +void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding) +{ + mEncoding = encoding; +} + void CSMDoc::DocumentManager::documentLoaded (Document *document) { emit documentAdded (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 7b3a811fad..9b675826a2 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -9,6 +9,8 @@ #include #include +#include + #include "loader.hpp" namespace Files @@ -28,6 +30,7 @@ namespace CSMDoc const Files::ConfigurationManager& mConfiguration; QThread mLoaderThread; Loader mLoader; + ToUTF8::FromType mEncoding; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -45,6 +48,8 @@ namespace CSMDoc void setResourceDir (const boost::filesystem::path& parResDir); + void setEncoding (ToUTF8::FromType encoding); + private: boost::filesystem::path mResDir; diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 73278ba975..27d21635eb 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -8,8 +8,9 @@ #include "savingstages.hpp" #include "document.hpp" -CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath) -: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath) +CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding) +: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath, encoding) { // save project file appendStage (new OpenSaveStage (mDocument, mState, true)); diff --git a/apps/opencs/model/doc/saving.hpp b/apps/opencs/model/doc/saving.hpp index cd1bbef980..44239b21b5 100644 --- a/apps/opencs/model/doc/saving.hpp +++ b/apps/opencs/model/doc/saving.hpp @@ -3,6 +3,8 @@ #include +#include + #include "operation.hpp" #include "savingstate.hpp" @@ -19,7 +21,8 @@ namespace CSMDoc public: - Saving (Document& document, const boost::filesystem::path& projectPath); + Saving (Document& document, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding); }; } diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 4a1abb8883..8742148226 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -4,11 +4,9 @@ #include "operation.hpp" #include "document.hpp" -CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath) -: mOperation (operation), - /// \todo set encoding properly, once config implementation has been fixed. - mEncoder (ToUTF8::calculateEncoding ("win1252")), - mProjectPath (projectPath), mProjectFile (false) +CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding) +: mOperation (operation), mEncoder (encoding), mProjectPath (projectPath), mProjectFile (false) { mWriter.setEncoder (&mEncoder); } diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 8cf7883e50..6b45655846 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -7,6 +7,8 @@ #include +#include + namespace CSMDoc { class Operation; @@ -25,7 +27,8 @@ namespace CSMDoc public: - SavingState (Operation& operation, const boost::filesystem::path& projectPath); + SavingState (Operation& operation, const boost::filesystem::path& projectPath, + ToUTF8::FromType encoding); bool hasError() const; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 3e9fe11eb0..ff33b46655 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -55,10 +55,8 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec return number; } -CSMWorld::Data::Data() -/// \todo set encoding properly, once config implementation has been fixed. -: mEncoder (ToUTF8::calculateEncoding ("win1252")), - mRefs (mCells), mReader (0), mDialogue (0) +CSMWorld::Data::Data (ToUTF8::FromType encoding) +: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0) { mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 4f7c624e68..ab247b6a34 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -22,6 +22,8 @@ #include #include +#include + #include "../filter/filter.hpp" #include "../doc/stage.hpp" @@ -91,7 +93,7 @@ namespace CSMWorld public: - Data(); + Data (ToUTF8::FromType encoding); virtual ~Data(); From 6cc691115bcbc4fc04e0f80a2373cb3e8736851c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 21:04:02 +0200 Subject: [PATCH 240/545] Savegame: store most of CreatureStats --- apps/openmw/mwclass/npc.cpp | 3 - apps/openmw/mwgui/windowmanagerimp.cpp | 19 ++- apps/openmw/mwmechanics/creaturestats.cpp | 79 ++++++++--- apps/openmw/mwmechanics/creaturestats.hpp | 7 +- apps/openmw/mwmechanics/drawstate.hpp | 6 +- .../mwmechanics/mechanicsmanagerimp.cpp | 4 +- apps/openmw/mwmechanics/npcstats.cpp | 21 ++- apps/openmw/mwmechanics/npcstats.hpp | 5 +- apps/openmw/mwmechanics/spells.cpp | 77 +++++++++- apps/openmw/mwmechanics/spells.hpp | 19 ++- apps/openmw/mwrender/localmap.cpp | 3 +- apps/openmw/mwstate/statemanagerimp.cpp | 2 + apps/openmw/mwworld/esmstore.cpp | 2 +- apps/openmw/mwworld/inventorystore.hpp | 1 + apps/openmw/mwworld/timestamp.cpp | 18 ++- apps/openmw/mwworld/timestamp.hpp | 10 +- apps/openmw/mwworld/worldimp.cpp | 4 +- components/CMakeLists.txt | 2 +- components/esm/creaturestats.cpp | 132 +++++++++++++++++- components/esm/creaturestats.hpp | 34 ++++- components/esm/defs.hpp | 7 + components/esm/esmwriter.cpp | 3 + components/esm/esmwriter.hpp | 1 + components/esm/npcstats.cpp | 29 +++- components/esm/npcstats.hpp | 6 +- components/esm/quickkeys.cpp | 17 ++- components/esm/spellstate.cpp | 66 +++++++++ components/esm/spellstate.hpp | 29 ++++ 28 files changed, 526 insertions(+), 80 deletions(-) create mode 100644 components/esm/spellstate.cpp create mode 100644 components/esm/spellstate.hpp diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b548e08446..4c9b683a42 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -357,9 +357,6 @@ namespace MWClass data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", MWBase::Environment::get().getWorld()->getStore()); - // Relates to NPC gold reset delay - data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0)); - data->mNpcStats.setGoldPool(gold); // store diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e3baf84fb8..ed6910221b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1326,9 +1326,6 @@ namespace MWGui void WindowManager::updatePlayer() { - unsetSelectedSpell(); - unsetSelectedWeapon(); - mInventoryWindow->updatePlayer(); } @@ -1425,6 +1422,14 @@ namespace MWGui mQuickKeysMenu->write(writer); progress.increaseProgress(); + + if (!mSelectedSpell.empty()) + { + writer.startRecord(ESM::REC_ASPL); + writer.writeHNString("ID__", mSelectedSpell); + writer.endRecord(ESM::REC_ASPL); + progress.increaseProgress(); + } } void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type) @@ -1433,12 +1438,18 @@ namespace MWGui mMap->readRecord(reader, type); else if (type == ESM::REC_KEYS) mQuickKeysMenu->readRecord(reader, type); + else if (type == ESM::REC_ASPL) + { + reader.getSubNameIs("ID__"); + mSelectedSpell = reader.getHString(); + } } int WindowManager::countSavedGameRecords() const { return 1 // Global map - + 1; // QuickKeysMenu + + 1 // QuickKeysMenu + + (!mSelectedSpell.empty() ? 1 : 0); } bool WindowManager::isSavingAllowed() const diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 40ac92251d..1482ee24e6 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -17,8 +17,10 @@ namespace MWMechanics mAttacked (false), mHostile (false), mAttackingOrSpell(false), mIsWerewolf(false), - mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), - mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f) + mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), + mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), + mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), + mTradeTime(0,0), mGoldPool(0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -348,20 +350,6 @@ namespace MWMechanics return mLastHitObject; } - bool CreatureStats::canUsePower(const std::string &power) const - { - std::map::const_iterator it = mUsedPowers.find(power); - if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) - return true; - else - return false; - } - - void CreatureStats::usePower(const std::string &power) - { - mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); - } - void CreatureStats::addToFallHeight(float height) { mFallHeight += height; @@ -481,20 +469,75 @@ namespace MWMechanics void CreatureStats::writeState (ESM::CreatureStats& state) const { - for (int i=0; i<8; ++i) + for (int i=0; i mUsedPowers; - MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay int mGoldPool; // the pool of merchant gold not in inventory protected: + // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. bool mIsWerewolf; AttributeValue mWerewolfAttributes[8]; + int mLevel; public: @@ -84,9 +84,6 @@ namespace MWMechanics /// @return total fall height float land(); - bool canUsePower (const std::string& power) const; - void usePower (const std::string& power); - const AttributeValue & getAttribute(int index) const; const DynamicStat & getHealth() const; diff --git a/apps/openmw/mwmechanics/drawstate.hpp b/apps/openmw/mwmechanics/drawstate.hpp index 5be00505c2..7f59d8d782 100644 --- a/apps/openmw/mwmechanics/drawstate.hpp +++ b/apps/openmw/mwmechanics/drawstate.hpp @@ -6,9 +6,9 @@ namespace MWMechanics /// \note The _ suffix is required to avoid a collision with a Windoze macro. Die, Microsoft! Die! enum DrawState_ { - DrawState_Weapon = 0, - DrawState_Spell = 1, - DrawState_Nothing = 2 + DrawState_Nothing = 0, + DrawState_Weapon = 1, + DrawState_Spell = 2 }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index eb51ddfc56..2b1f82b926 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -342,7 +342,9 @@ namespace MWMechanics MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); if (enchantItem != inv.end()) winMgr->setSelectedEnchantItem(*enchantItem); - else if (winMgr->getSelectedSpell() == "") + else if (!winMgr->getSelectedSpell().empty()) + winMgr->setSelectedSpell(winMgr->getSelectedSpell(), int(MWMechanics::getSpellSuccessChance(winMgr->getSelectedSpell(), mWatched))); + else winMgr->unsetSelectedSpell(); } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index b1d2c75b16..24e758e32e 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -446,11 +446,16 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const state.mDisposition = mDisposition; - for (int i=0; i<27; ++i) + for (int i=0; i::const_iterator iter (state.mUsedIds.begin()); diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 0ae596a54d..185a58b947 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -31,8 +31,8 @@ namespace MWMechanics std::map mFactionRank; int mDisposition; - SkillValue mSkill[27]; - SkillValue mWerewolfSkill[27]; + SkillValue mSkill[ESM::Skill::Length]; + SkillValue mWerewolfSkill[ESM::Skill::Length]; int mBounty; std::set mExpelled; std::map mFactionReputation; @@ -40,7 +40,6 @@ namespace MWMechanics int mCrimeId; int mWerewolfKills; int mProfit; - float mAttackStrength; int mLevelProgress; // 0-10 diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index c2bf794f19..a326b7a6d1 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -30,10 +31,19 @@ namespace MWMechanics { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId); - std::vector random; - random.resize(spell->mEffects.mList.size()); - for (unsigned int i=0; i (std::rand()) / RAND_MAX; + std::map random; + + // Determine the random magnitudes (unless this is a castable spell, in which case + // they will be determined when the spell is cast) + if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell) + { + for (unsigned int i=0; imEffects.mList.size();++i) + { + if (spell->mEffects.mList[i].mMagnMin != spell->mEffects.mList[i].mMagnMax) + random[i] = static_cast (std::rand()) / RAND_MAX; + } + } + mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random)); } } @@ -67,7 +77,11 @@ namespace MWMechanics int i=0; for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) { - effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * iter->second[i]); + float random = 1.f; + if (iter->second.find(i) != iter->second.end()) + random = iter->second.at(i); + + effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random); ++i; } } @@ -192,9 +206,60 @@ namespace MWMechanics for (std::vector::const_iterator effectIt = list.mList.begin(); effectIt != list.mList.end(); ++effectIt, ++i) { - float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i]; + float random = 1.f; + if (it->second.find(i) != it->second.end()) + random = it->second.at(i); + + float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude); } } } + + bool Spells::canUsePower(const std::string &power) const + { + std::map::const_iterator it = mUsedPowers.find(power); + if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) + return true; + else + return false; + } + + void Spells::usePower(const std::string &power) + { + mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); + } + + void Spells::readState(const ESM::SpellState &state) + { + mSpells = state.mSpells; + mSelectedSpell = state.mSelectedSpell; + + // Discard spells that are no longer available due to changed content files + for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(iter->first); + if (!spell) + { + if (iter->first == mSelectedSpell) + mSelectedSpell = ""; + mSpells.erase(iter++); + } + else + ++iter; + } + + // No need to discard spells here (doesn't really matter if non existent ids are kept) + for (std::map::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) + mUsedPowers[it->first] = MWWorld::TimeStamp(it->second); + } + + void Spells::writeState(ESM::SpellState &state) const + { + state.mSpells = mSpells; + state.mSelectedSpell = mSelectedSpell; + + for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) + state.mUsedPowers[it->first] = it->second.toEsm(); + } } diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index 354b1fd0bd..6997a9d7ab 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -7,12 +7,16 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/timestamp.hpp" #include "magiceffects.hpp" + namespace ESM { struct Spell; + + struct SpellState; } namespace MWMechanics @@ -22,21 +26,29 @@ namespace MWMechanics /// \brief Spell list /// /// This class manages known spells as well as abilities, powers and permanent negative effects like - /// diseases. + /// diseases. It also keeps track of used powers (which can only be used every 24h). class Spells { public: - typedef std::map > TContainer; // ID, normalised magnitudes + + typedef std::map > TContainer; // ID, typedef TContainer::const_iterator TIterator; private: TContainer mSpells; + + // Note: this is the spell that's about to be cast, *not* the spell selected in the GUI (which may be different) std::string mSelectedSpell; + std::map mUsedPowers; + public: + bool canUsePower (const std::string& power) const; + void usePower (const std::string& power); + void purgeCommonDisease(); void purgeBlightDisease(); void purgeCorprusDisease(); @@ -72,6 +84,9 @@ namespace MWMechanics bool hasBlightDisease() const; void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const; + + void readState (const ESM::SpellState& state); + void writeState (ESM::SpellState& state) const; }; } diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 4168127df6..0d32dd0ef0 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -342,8 +342,6 @@ Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName) PF_A8R8G8B8, TU_DYNAMIC_WRITE_ONLY); } - else - tex->unload(); return tex; } @@ -362,6 +360,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& Ogre::TexturePtr tex = createFogOfWarTexture(texName); + tex->unload(); tex->loadImage(image); // create a buffer to use for dynamic operations diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index c89041710a..153da1f30b 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -326,6 +326,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_GMAP: case ESM::REC_KEYS: + case ESM::REC_ASPL: + MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index a769e7f67c..ed140434b5 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -199,7 +199,7 @@ void ESMStore::setUp() if (!mRaces.find (player->mRace) || !mClasses.find (player->mClass)) - throw std::runtime_error ("Invalid player record (race or class unavilable"); + throw std::runtime_error ("Invalid player record (race or class unavailable"); } return true; diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index b4b275b6ad..95b956907c 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -87,6 +87,7 @@ namespace MWWorld float mMultiplier; }; + // TODO: store in savegame typedef std::map > TEffectMagnitudes; TEffectMagnitudes mPermanentMagicEffectMagnitudes; diff --git a/apps/openmw/mwworld/timestamp.cpp b/apps/openmw/mwworld/timestamp.cpp index 126d5490c5..a73ed7ca59 100644 --- a/apps/openmw/mwworld/timestamp.cpp +++ b/apps/openmw/mwworld/timestamp.cpp @@ -1,10 +1,10 @@ - #include "timestamp.hpp" #include - #include +#include + namespace MWWorld { TimeStamp::TimeStamp (float hour, int day) @@ -105,4 +105,18 @@ namespace MWWorld return hours + 24*days; } + + ESM::TimeStamp TimeStamp::toEsm() const + { + ESM::TimeStamp ret; + ret.mDay = mDay; + ret.mHour = mHour; + return ret; + } + + TimeStamp::TimeStamp(const ESM::TimeStamp &esm) + { + mDay = esm.mDay; + mHour = esm.mHour; + } } diff --git a/apps/openmw/mwworld/timestamp.hpp b/apps/openmw/mwworld/timestamp.hpp index e2d8b242ae..54cd40baf7 100644 --- a/apps/openmw/mwworld/timestamp.hpp +++ b/apps/openmw/mwworld/timestamp.hpp @@ -1,6 +1,11 @@ #ifndef GAME_MWWORLD_TIMESTAMP_H #define GAME_MWWORLD_TIMESTAMP_H +namespace ESM +{ + class TimeStamp; +} + namespace MWWorld { /// \brief In-game time stamp @@ -14,9 +19,12 @@ namespace MWWorld public: explicit TimeStamp (float hour = 0, int day = 0); - ///< \oaram hour [0, 23) + ///< \param hour [0, 23) /// \param day >=0 + explicit TimeStamp (const ESM::TimeStamp& esm); + ESM::TimeStamp toEsm () const; + float getHour() const; int getDay() const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d5da19dfa0..b9a8f8dda7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2164,8 +2164,8 @@ namespace MWWorld // If this is a power, check if it was already used in the last 24h if (!fail && spell->mData.mType == ESM::Spell::ST_Power) { - if (stats.canUsePower(spell->mId)) - stats.usePower(spell->mId); + if (stats.getSpells().canUsePower(spell->mId)) + stats.getSpells().usePower(spell->mId); else { message = "#{sPowerAlreadyUsed}"; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 3dd5df2954..5332880485 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate + npcstats creaturestats weatherstate quickkeys fogstate spellstate ) add_component_dir (misc diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index fe250089aa..5bb6de6626 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -8,13 +8,143 @@ void ESM::CreatureStats::load (ESMReader &esm) for (int i=0; i<3; ++i) mDynamic[i].load (esm); + + mGoldPool = 0; + esm.getHNOT (mGoldPool, "GOLD"); + + mTradeTime.mDay = 0; + mTradeTime.mHour = 0; + esm.getHNOT (mTradeTime, "TIME"); + + mDead = false; + esm.getHNOT (mDead, "DEAD"); + + mDied = false; + esm.getHNOT (mDied, "DIED"); + + mFriendlyHits = 0; + esm.getHNOT (mFriendlyHits, "FRHT"); + + mTalkedTo = false; + esm.getHNOT (mTalkedTo, "TALK"); + + mAlarmed = false; + esm.getHNOT (mAlarmed, "ALRM"); + + mHostile = false; + esm.getHNOT (mHostile, "HOST"); + + mAttackingOrSpell = false; + esm.getHNOT (mAttackingOrSpell, "ATCK"); + + mKnockdown = false; + esm.getHNOT (mKnockdown, "KNCK"); + + mKnockdownOneFrame = false; + esm.getHNOT (mKnockdownOneFrame, "KNC1"); + + mKnockdownOverOneFrame = false; + esm.getHNOT (mKnockdownOverOneFrame, "KNCO"); + + mHitRecovery = false; + esm.getHNOT (mHitRecovery, "HITR"); + + mBlock = false; + esm.getHNOT (mBlock, "BLCK"); + + mMovementFlags = 0; + esm.getHNOT (mMovementFlags, "MOVE"); + + mAttackStrength = 0; + esm.getHNOT (mAttackStrength, "ASTR"); + + mFallHeight = 0; + esm.getHNOT (mFallHeight, "FALL"); + + mLastHitObject = esm.getHNOString ("LHIT"); + + mRecalcDynamicStats = false; + esm.getHNOT (mRecalcDynamicStats, "CALC"); + + mDrawState = 0; + esm.getHNOT (mDrawState, "DRAW"); + + mLevel = 1; + esm.getHNOT (mLevel, "LEVL"); + + mSpells.load(esm); } void ESM::CreatureStats::save (ESMWriter &esm) const { + for (int i=0; i<8; ++i) mAttributes[i].save (esm); for (int i=0; i<3; ++i) mDynamic[i].save (esm); -} \ No newline at end of file + + if (mGoldPool) + esm.writeHNT ("GOLD", mGoldPool); + + esm.writeHNT ("TIME", mTradeTime); + + if (mDead) + esm.writeHNT ("DEAD", mDead); + + if (mDied) + esm.writeHNT ("DIED", mDied); + + if (mFriendlyHits) + esm.writeHNT ("FRHT", mFriendlyHits); + + if (mTalkedTo) + esm.writeHNT ("TALK", mTalkedTo); + + if (mAlarmed) + esm.writeHNT ("ALRM", mAlarmed); + + if (mHostile) + esm.writeHNT ("HOST", mHostile); + + if (mAttackingOrSpell) + esm.writeHNT ("ATCK", mAttackingOrSpell); + + if (mKnockdown) + esm.writeHNT ("KNCK", mKnockdown); + + if (mKnockdownOneFrame) + esm.writeHNT ("KNC1", mKnockdownOneFrame); + + if (mKnockdownOverOneFrame) + esm.writeHNT ("KNCO", mKnockdownOverOneFrame); + + if (mHitRecovery) + esm.writeHNT ("HITR", mHitRecovery); + + if (mBlock) + esm.writeHNT ("BLCK", mBlock); + + if (mMovementFlags) + esm.writeHNT ("MOVE", mMovementFlags); + + if (mAttackStrength) + esm.writeHNT ("ASTR", mAttackStrength); + + if (mFallHeight) + esm.writeHNT ("FALL", mFallHeight); + + if (!mLastHitObject.empty()) + esm.writeHNString ("LHIT", mLastHitObject); + + if (mRecalcDynamicStats) + esm.writeHNT ("CALC", mRecalcDynamicStats); + + if (mDrawState) + esm.writeHNT ("DRAW", mDrawState); + + if (mLevel != 1) + esm.writeHNT ("LEVL", mLevel); + + mSpells.save(esm); +} diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 540044f389..2cf2c5b4f8 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -7,21 +7,51 @@ #include "statstate.hpp" +#include "defs.hpp" + +#include "spellstate.hpp" + namespace ESM { class ESMReader; class ESMWriter; // format 0, saved games only - struct CreatureStats { StatState mAttributes[8]; StatState mDynamic[3]; + ESM::TimeStamp mTradeTime; + int mGoldPool; + + bool mDead; + bool mDied; + int mFriendlyHits; + bool mTalkedTo; + bool mAlarmed; + bool mAttacked; + bool mHostile; + bool mAttackingOrSpell; + bool mKnockdown; + bool mKnockdownOneFrame; + bool mKnockdownOverOneFrame; + bool mHitRecovery; + bool mBlock; + unsigned int mMovementFlags; + float mAttackStrength; + float mFallHeight; + std::string mLastHitObject; + bool mRecalcDynamicStats; + int mDrawState; + + int mLevel; + + SpellState mSpells; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 5a99d0c2e4..9ef4dabd21 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -6,6 +6,12 @@ namespace ESM { +struct TimeStamp +{ + float mHour; + int mDay; +}; + // Pixel color value. Standard four-byte rr,gg,bb,aa format. typedef int32_t Color; @@ -101,6 +107,7 @@ enum RecNameInts REC_WTHR = 0x52485457, REC_KEYS = FourCC<'K','E','Y','S'>::value, REC_DYNA = FourCC<'D','Y','N','A'>::value, + REC_ASPL = FourCC<'A','S','P','L'>::value, // format 1 REC_FILT = 0x544C4946 diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index 91f123eb71..9d8d943d97 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -100,6 +100,9 @@ namespace ESM void ESMWriter::startSubRecord(const std::string& name) { + // Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later. + assert (mRecords.size() <= 1); + writeName(name); RecordData rec; rec.name = name; diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index b385ac0671..57faefdf4e 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -96,6 +96,7 @@ class ESMWriter void startRecord(const std::string& name, uint32_t flags = 0); void startRecord(uint32_t name, uint32_t flags = 0); + /// @note Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later. void startSubRecord(const std::string& name); void endRecord(const std::string& name); void endRecord(uint32_t name); diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 80238ad684..21f573bc74 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -36,6 +36,18 @@ void ESM::NpcStats::load (ESMReader &esm) mSkills[i].mWerewolf.load (esm); } + bool hasWerewolfAttributes = false; + esm.getHNOT (hasWerewolfAttributes, "HWAT"); + + if (hasWerewolfAttributes) + { + for (int i=0; i<8; ++i) + mWerewolfAttributes[i].load (esm); + } + + mIsWerewolf = false; + esm.getHNOT (mIsWerewolf, "WOLF"); + mBounty = 0; esm.getHNOT (mBounty, "BOUN"); @@ -48,8 +60,9 @@ void ESM::NpcStats::load (ESMReader &esm) mProfit = 0; esm.getHNOT (mProfit, "PROF"); - mAttackStrength = 0; - esm.getHNOT (mAttackStrength, "ASTR"); + // No longer used. Now part of CreatureStats. + float attackStrength = 0; + esm.getHNOT (attackStrength, "ASTR"); mLevelProgress = 0; esm.getHNOT (mLevelProgress, "LPRO"); @@ -101,6 +114,13 @@ void ESM::NpcStats::save (ESMWriter &esm) const mSkills[i].mWerewolf.save (esm); } + esm.writeHNT ("HWAT", true); + for (int i=0; i<8; ++i) + mWerewolfAttributes[i].save (esm); + + if (mIsWerewolf) + esm.writeHNT ("WOLF", mIsWerewolf); + if (mBounty) esm.writeHNT ("BOUN", mBounty); @@ -113,9 +133,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mProfit) esm.writeHNT ("PROF", mProfit); - if (mAttackStrength) - esm.writeHNT ("ASTR", mAttackStrength); - if (mLevelProgress) esm.writeHNT ("LPRO", mLevelProgress); @@ -136,4 +153,4 @@ void ESM::NpcStats::save (ESMWriter &esm) const if (mCrimeId != -1) esm.writeHNT ("CRID", mCrimeId); -} \ No newline at end of file +} diff --git a/components/esm/npcstats.hpp b/components/esm/npcstats.hpp index 504cd0163c..ce7c75d2ae 100644 --- a/components/esm/npcstats.hpp +++ b/components/esm/npcstats.hpp @@ -31,6 +31,9 @@ namespace ESM Faction(); }; + StatState mWerewolfAttributes[8]; + bool mIsWerewolf; + std::map mFactions; int mDisposition; Skill mSkills[27]; @@ -38,7 +41,6 @@ namespace ESM int mReputation; int mWerewolfKills; int mProfit; - float mAttackStrength; int mLevelProgress; int mSkillIncrease[8]; std::vector mUsedIds; @@ -52,4 +54,4 @@ namespace ESM }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/quickkeys.cpp b/components/esm/quickkeys.cpp index ad2b671aab..42cd91c5bc 100644 --- a/components/esm/quickkeys.cpp +++ b/components/esm/quickkeys.cpp @@ -8,11 +8,13 @@ namespace ESM void QuickKeys::load(ESMReader &esm) { - while (esm.isNextSub("KEY_")) + if (esm.isNextSub("KEY_")) + esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader + + while (esm.isNextSub("TYPE")) { - esm.getSubHeader(); int keyType; - esm.getHNT(keyType, "TYPE"); + esm.getHT(keyType); std::string id; id = esm.getHNString("ID__"); @@ -21,21 +23,18 @@ namespace ESM key.mId = id; mKeys.push_back(key); + + if (esm.isNextSub("KEY_")) + esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader } } void QuickKeys::save(ESMWriter &esm) const { - const std::string recKey = "KEY_"; - for (std::vector::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) { - esm.startSubRecord(recKey); - esm.writeHNT("TYPE", it->mType); esm.writeHNString("ID__", it->mId); - - esm.endRecord(recKey); } } diff --git a/components/esm/spellstate.cpp b/components/esm/spellstate.cpp new file mode 100644 index 0000000000..2dca2dcecc --- /dev/null +++ b/components/esm/spellstate.cpp @@ -0,0 +1,66 @@ +#include "spellstate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void SpellState::load(ESMReader &esm) + { + while (esm.isNextSub("SPEL")) + { + std::string id = esm.getHString(); + + std::map random; + while (esm.isNextSub("INDX")) + { + int index; + esm.getHT(index); + + float magnitude; + esm.getHNT(magnitude, "RAND"); + + random[index] = magnitude; + } + + mSpells[id] = random; + } + + while (esm.isNextSub("USED")) + { + std::string id = esm.getHString(); + TimeStamp time; + esm.getHNT(time, "TIME"); + + mUsedPowers[id] = time; + } + + mSelectedSpell = esm.getHNOString("SLCT"); + } + + void SpellState::save(ESMWriter &esm) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + esm.writeHNString("SPEL", it->first); + + const std::map& random = it->second; + for (std::map::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt) + { + esm.writeHNT("INDX", rIt->first); + esm.writeHNT("RAND", rIt->second); + } + } + + for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) + { + esm.writeHNString("USED", it->first); + esm.writeHNT("TIME", it->second); + } + + if (!mSelectedSpell.empty()) + esm.writeHNString("SLCT", mSelectedSpell); + } + +} diff --git a/components/esm/spellstate.hpp b/components/esm/spellstate.hpp new file mode 100644 index 0000000000..cb5c0ff0db --- /dev/null +++ b/components/esm/spellstate.hpp @@ -0,0 +1,29 @@ +#ifndef OPENMW_ESM_SPELLSTATE_H +#define OPENMW_ESM_SPELLSTATE_H + +#include +#include + +#include "defs.hpp" + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct SpellState + { + typedef std::map > TContainer; + TContainer mSpells; + + std::map mUsedPowers; + + std::string mSelectedSpell; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + +} + +#endif From 725f6cac5e5c54fc1c41ddce88fd303663f62eb4 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Tue, 13 May 2014 00:05:30 +0400 Subject: [PATCH 241/545] AiPursue infinite package updating bug resolved --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- apps/openmw/mwmechanics/aipursue.cpp | 16 +++++++++------- apps/openmw/mwmechanics/aipursue.hpp | 10 +++++++--- apps/openmw/mwmechanics/aisequence.cpp | 8 +++++++- apps/openmw/mwworld/physicssystem.cpp | 2 +- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6375bdd1b8..6ec2f64d08 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -730,7 +730,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -759,7 +759,7 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); else { MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 0c10bd81dd..8b71c80723 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -1,6 +1,5 @@ #include "aipursue.hpp" -#include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" @@ -11,8 +10,8 @@ #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPursue::AiPursue(const std::string &objectId) - : mObjectId(objectId) +MWMechanics::AiPursue::AiPursue(const MWWorld::Ptr target) + : mTarget(target) { } MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const @@ -54,8 +53,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) // Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code) - MWWorld::Ptr target = world->getPtr(mObjectId,false); - ESM::Position targetPos = target.getRefData().getPosition(); + ESM::Position targetPos = mTarget.getRefData().getPosition(); bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) @@ -81,8 +79,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100) { movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); + MWWorld::Class::get(mTarget).activate(mTarget,actor).get()->execute(actor); return true; } @@ -98,3 +95,8 @@ int MWMechanics::AiPursue::getTypeId() const { return TypeIdPursue; } + +MWWorld::Ptr MWMechanics::AiPursue::getTarget() const +{ + return mTarget; +} diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 86750acca6..4cac6c0088 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -2,7 +2,8 @@ #define GAME_MWMECHANICS_AIPURSUE_H #include "aipackage.hpp" -#include + +#include "../mwbase/world.hpp" #include "pathfinding.hpp" @@ -12,14 +13,17 @@ namespace MWMechanics class AiPursue : public AiPackage { public: - AiPursue(const std::string &objectId); + AiPursue(const MWWorld::Ptr target); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; + virtual MWWorld::Ptr getTarget() const; + private: - std::string mObjectId; + + MWWorld::Ptr mTarget; PathFinder mPathFinder; int mCellX; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 0b1da180d7..2134b7bba4 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -9,6 +9,7 @@ #include "aifollow.hpp" #include "aiactivate.hpp" #include "aicombat.hpp" +#include "aipursue.hpp" #include "../mwworld/class.hpp" #include "creaturestats.hpp" @@ -128,7 +129,12 @@ void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Pt // Notify AiWander of our current position so we can return to it after combat finished for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) { - if ((*iter)->getTypeId() == AiPackage::TypeIdWander) + if((*iter)->getTypeId() == AiPackage::TypeIdPursue && package.getTypeId() == AiPackage::TypeIdPursue + && static_cast(*iter)->getTarget() == static_cast(&package)->getTarget()) + { + return; // target is already pursued + } + else if ((*iter)->getTypeId() == AiPackage::TypeIdWander) static_cast(*iter)->setReturnPosition(Ogre::Vector3(actor.getRefData().getPosition().pos)); } } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 17f118b119..787653f117 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -316,7 +316,7 @@ namespace MWWorld if(stepMove(colobj, newPosition, velocity, remainingTime, engine)) { // don't let pure water creatures move out of water after stepMove - if((ptr.getClass().canSwim(ptr) && !canWalk) + if((ptr.getClass().canSwim(ptr) && !ptr.getClass().canWalk(ptr)) && newPosition.z > (waterlevel - halfExtents.z * 0.5)) newPosition = oldPosition; else // Only on the ground if there's gravity From f11079f1e4a42d28dcb1a04f172d87ef397d60a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 12 May 2014 23:01:21 +0200 Subject: [PATCH 242/545] Fix findGround (off by 2 units) --- libs/openengine/bullet/trace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index afda52448e..6eab43a606 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -116,7 +116,7 @@ void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &star mFraction = newTraceCallback.m_closestHitFraction; mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); mEndPos = (end-start)*mFraction + start; - mEndPos[2] -= 1.0f; + mEndPos[2] += 1.0f; } else { From 386604bc9dd859f4b11c3f2117b8cfd2888457e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 01:43:52 +0200 Subject: [PATCH 243/545] Fixes #869: Added methods to control external and internal collision modes separately When an actor dies, we should only disable external collisions, i.e. prevent other actors from colliding with the dead body. The dead actor, however, should still have gravity and collision applied. Also moved disableCollision to when the death animation finishes, not as soon as the actor's health is 0. --- apps/openmw/mwmechanics/actors.cpp | 5 ++--- apps/openmw/mwworld/physicssystem.cpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 2 +- libs/openengine/bullet/physic.cpp | 9 ++++++--- libs/openengine/bullet/physic.hpp | 10 +++++++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6375bdd1b8..b935284d38 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -920,9 +920,6 @@ namespace MWMechanics spells.purge(iter->first.getRefData().getHandle()); } - // FIXME: see http://bugs.openmw.org/issues/869 - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); - if (iter->second->kill()) { ++mDeathCount[cls.getId(iter->first)]; @@ -939,6 +936,8 @@ namespace MWMechanics stats.setMagicEffects(MWMechanics::MagicEffects()); calculateCreatureStatModifiers(iter->first, 0); + MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); + if (cls.isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e30a2bbc17..cf2ff87c64 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -626,12 +626,12 @@ namespace MWWorld bool cmode = act->getCollisionMode(); if(cmode) { - act->enableCollisions(false); + act->enableCollisionMode(false); return false; } else { - act->enableCollisions(true); + act->enableCollisionMode(true); return true; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b9a8f8dda7..538cd17df5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1957,7 +1957,7 @@ namespace MWWorld { OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); - physicActor->enableCollisions(enable); + physicActor->enableCollisionBody(enable); } bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 4484d98625..c10892e52c 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -41,15 +41,18 @@ namespace Physic } } - void PhysicActor::enableCollisions(bool collision) + void PhysicActor::enableCollisionMode(bool collision) + { + mCollisionMode = collision; + } + + void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); if(collision && !mCollisionMode) enableCollisionBody(); if(!collision && mCollisionMode) disableCollisionBody(); - mCollisionMode = collision; } - void PhysicActor::setPosition(const Ogre::Vector3 &pos) { assert(mBody); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 4ef611dc87..4e035446ee 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -99,7 +99,15 @@ namespace Physic */ void setRotation(const Ogre::Quaternion &quat); - void enableCollisions(bool collision); + /** + * Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry. + */ + void enableCollisionMode(bool collision); + + /** + * Enables or disables the *external* collision body. If disabled, other actors will not collide with this actor. + */ + void enableCollisionBody(bool collision); bool getCollisionMode() const { From 2c74ea381e1bf290ac67fe062f085dc77f0c7d75 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 12 May 2014 21:05:32 -0400 Subject: [PATCH 244/545] Moved pathfinding code to aiPackage, implemented it's use with aiFollow and aiPursue --- apps/openmw/mwmechanics/aifollow.cpp | 81 ++++------------------ apps/openmw/mwmechanics/aifollow.hpp | 8 --- apps/openmw/mwmechanics/aipackage.cpp | 91 +++++++++++++++++++++++++ apps/openmw/mwmechanics/aipackage.hpp | 18 ++++- apps/openmw/mwmechanics/aipursue.cpp | 75 ++++---------------- apps/openmw/mwmechanics/aipursue.hpp | 12 +--- apps/openmw/mwmechanics/pathfinding.cpp | 48 ++++++------- apps/openmw/mwmechanics/pathfinding.hpp | 2 + components/esm/loadpgrd.cpp | 14 ++++ components/esm/loadpgrd.hpp | 3 + 10 files changed, 181 insertions(+), 171 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 161c9700f1..98ac5ee149 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -12,17 +12,23 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") { + mTimer = 0; + mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) { + mTimer = 0; + mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), mTimer(0), mStuckTimer(0) +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") { + mTimer = 0; + mStuckTimer = 0; } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) @@ -31,10 +37,6 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) if(target == MWWorld::Ptr()) return true; //Target doesn't exist - mTimer = mTimer + duration; //Update timer - mStuckTimer = mStuckTimer + duration; //Update stuck timer - mTotalTime = mTotalTime + duration; //Update total time following - ESM::Position pos = actor.getRefData().getPosition(); //position of the actor if(!mAlwaysFollow) //Update if you only follow for a bit @@ -60,74 +62,19 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) } //Set the target desition from the actor - ESM::Pathgrid::Point dest; - dest.mX = target.getRefData().getPosition().pos[0]; - dest.mY = target.getRefData().getPosition().pos[1]; - dest.mZ = target.getRefData().getPosition().pos[2]; + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - //Current position, for pathfilding stuff - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + pathTo(actor, dest, duration); //Go to the destination - //Build the path to get to the destination - if(mPathFinder.getPath().empty()) - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - //*********************** - // Checks if you can't get to the end position at all - //*********************** - if(mTimer > 0.25) - { - if(!mPathFinder.getPath().empty()) //Path has points in it - { - ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path - - if((dest.mX - lastPos.mX)*(dest.mX - lastPos.mX) - +(dest.mY - lastPos.mY)*(dest.mY - lastPos.mY) - +(dest.mZ - lastPos.mZ)*(dest.mZ - lastPos.mZ) - > 100*100) //End of the path is far from the destination - mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go - } - - mTimer = 0; - } - - //************************ - // Checks if you aren't moving; you're stuck - //************************ - if(mStuckTimer>0.5) //Checks every half of a second - { - if((mStuckPos.pos[0] - pos.pos[0])*(mStuckPos.pos[0] - pos.pos[0]) - +(mStuckPos.pos[1] - pos.pos[1])*(mStuckPos.pos[1] - pos.pos[1]) - +(mStuckPos.pos[2] - pos.pos[2])*(mStuckPos.pos[2] - pos.pos[2]) < 100) //NPC is stuck - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - mStuckTimer = 0; - mStuckPos = pos; - } - - //Checks if the path isn't over, turn tomards the direction that you're going - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - } - - if((dest.mX - pos.pos[0])*(dest.mX - pos.pos[0])+(dest.mY - pos.pos[1])*(dest.mY - pos.pos[1])+(dest.mZ - pos.pos[2])*(dest.mZ - pos.pos[2]) - < 100*100) + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; else actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Check if you're far away - if((dest.mX - start.mX)*(dest.mX - start.mX) - +(dest.mY - start.mY)*(dest.mY - start.mY) - +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) > 1000*1000) + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) > 1000) actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run - else if((dest.mX - start.mX)*(dest.mX - start.mX) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold - +(dest.mY - start.mY)*(dest.mY - start.mY) - +(dest.mZ - start.mZ)*(dest.mZ - start.mZ) < 800*800) + else if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 800) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk return false; diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 4eb3e3757a..531082357a 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -40,14 +40,6 @@ namespace MWMechanics float mZ; std::string mActorId; std::string mCellId; - - float mTimer; - float mStuckTimer; - float mTotalTime; - - ESM::Position mStuckPos; - - PathFinder mPathFinder; }; } #endif diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 8193a670be..afe99e2c0b 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -1,4 +1,95 @@ #include "aipackage.hpp" +#include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" +#include "creaturestats.hpp" +#include "movement.hpp" + +#include + +#include "steering.hpp" + MWMechanics::AiPackage::~AiPackage() {} + + +bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration) +{ + //Update various Timers + mTimer = mTimer + duration; //Update timer + mStuckTimer = mStuckTimer + duration; //Update stuck timer + mTotalTime = mTotalTime + duration; //Update total time following + + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + + /// Stops the actor when it gets too close to a unloaded cell + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + const ESM::Cell *cell = actor.getCell()->getCell(); + Movement &movement = actor.getClass().getMovementSettings(actor); + + //Ensure pursuer doesn't leave loaded cells + if(cell->mData.mX != player.getCell()->getCell()->mData.mX) + { + int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); + //check if actor is near the border of an inactive cell. If so, stop walking. + if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) + { + movement.mPosition[1] = 0; + return false; + } + } + if(cell->mData.mY != player.getCell()->getCell()->mData.mY) + { + int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); + //check if actor is near the border of an inactive cell. If so, stop walking. + if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) + { + movement.mPosition[1] = 0; + return false; + } + } + } + + //Start position + ESM::Pathgrid::Point start = pos.pos; + + //*********************** + /// Checks if you can't get to the end position at all, adds end position to end of path + /// Rebuilds path every quarter of a second, in case the target has moved + //*********************** + if(mTimer > 0.25) + { + mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + if(!mPathFinder.getPath().empty()) //Path has points in it + { + ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path + + if(distance(dest, lastPos) > 100) //End of the path is far from the destination + mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go + } + + mTimer = 0; + } + + //************************ + /// Checks if you aren't moving; attempts to unstick you + //************************ + if(mStuckTimer>0.5) //Checks every half of a second + { + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) //NPC hasn't moved much is half a second, he's stuck + mPathFinder.buildPath(start, dest, actor.getCell(), true); + + mStuckTimer = 0; + mStuckPos = pos; + } + + //Checks if the path isn't over, turn tomards the direction that you're going + if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) + { + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + } +} diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index b3a7facee2..e36b51f691 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -1,6 +1,9 @@ #ifndef GAME_MWMECHANICS_AIPACKAGE_H #define GAME_MWMECHANICS_AIPACKAGE_H +#include "pathfinding.hpp" +#include "../../../components/esm/defs.hpp" + namespace MWWorld { class Ptr; @@ -38,8 +41,21 @@ namespace MWMechanics /// \see enum TypeId virtual int getTypeId() const = 0; - /// Higher number is higher priority (0 beeing the lowest) + /// Higher number is higher priority (0 being the lowest) virtual unsigned int getPriority() const {return 0;} + + protected: + /// Causes the actor to attempt to walk to the specified location + /** \return If the actor has arrived at his destination **/ + bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); + + PathFinder mPathFinder; + + float mTimer; + float mStuckTimer; + float mTotalTime; + + ESM::Position mStuckPos; }; } diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 0c10bd81dd..4e0bc71046 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -21,75 +21,28 @@ MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const } bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { - MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); - actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist - // Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code) + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - ESM::Position targetPos = target.getRefData().getPosition(); + pathTo(actor, dest, duration); //Go to the destination - bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - mCellX = cell->mData.mX; - mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = targetPos.pos[0]; - dest.mY = targetPos.pos[1]; - dest.mZ = targetPos.pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ - (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } + else + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - movement.mPosition[1] = 1; + actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run return false; } diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 8a471228ed..7d1ea5bb9d 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -9,18 +9,12 @@ namespace MWMechanics { /// \brief Makes the actor very closely follow the actor - /** Used for getting closer to fight, or to arrest (I think?) **/ - class AiPersue : public AiPackage + /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. **/ + class AiPursue : public AiPackage { public: ///Constructor /** \param objectId Actor to pursue **/ - AiPersue(const std::string &objectId); - virtual AiPersue *clone() const; - - class AiPursue : public AiPackage - { - public: AiPursue(const std::string &objectId); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); @@ -28,8 +22,6 @@ namespace MWMechanics private: std::string mObjectId; - - PathFinder mPathFinder; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index cd03939bd0..d77a35ea48 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -11,30 +11,6 @@ namespace { - float distanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) - { - x -= point.mX; - y -= point.mY; - z -= point.mZ; - return sqrt(x * x + y * y + 0.1 * z * z); - } - - float distance(ESM::Pathgrid::Point point, float x, float y, float z) - { - x -= point.mX; - y -= point.mY; - z -= point.mZ; - return sqrt(x * x + y * y + z * z); - } - - float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b) - { - float x = a.mX - b.mX; - float y = a.mY - b.mY; - float z = a.mZ - b.mZ; - return sqrt(x * x + y * y + z * z); - } - // Slightly cheaper version for comparisons. // Caller needs to be careful for very short distances (i.e. less than 1) // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 @@ -114,6 +90,30 @@ namespace namespace MWMechanics { + float distanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) + { + x -= point.mX; + y -= point.mY; + z -= point.mZ; + return sqrt(x * x + y * y + 0.1 * z * z); + } + + float distance(ESM::Pathgrid::Point point, float x, float y, float z) + { + x -= point.mX; + y -= point.mY; + z -= point.mZ; + return sqrt(x * x + y * y + z * z); + } + + float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b) + { + float x = a.mX - b.mX; + float y = a.mY - b.mY; + float z = a.mZ - b.mZ; + return sqrt(x * x + y * y + z * z); + } + PathFinder::PathFinder() : mIsPathConstructed(false), mPathgrid(NULL), diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 29577542e6..603a04f8c5 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -13,6 +13,8 @@ namespace MWWorld namespace MWMechanics { + float distance(ESM::Pathgrid::Point point, float x, float y, float); + float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b); class PathFinder { public: diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 3b5330e9fd..5b8ce3eb2c 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -8,6 +8,20 @@ namespace ESM { unsigned int Pathgrid::sRecordId = REC_PGRD; + Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[]) { + mX = rhs[0]; + mY = rhs[1]; + mZ = rhs[2]; + return *this; + } + Pathgrid::Point::Point(const float rhs[]) { + mX = rhs[0]; + mY = rhs[1]; + mZ = rhs[2]; + } + Pathgrid::Point::Point():mX(0),mY(0),mZ(0) { + } + void Pathgrid::load(ESMReader &esm) { esm.getHNT(mData, "DATA", 12); diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 9ee49552db..b940c27e60 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -31,6 +31,9 @@ struct Pathgrid unsigned char mAutogenerated; // autogenerated vs. user coloring flag? unsigned char mConnectionNum; // number of connections for this point short mUnknown; + Point& operator=(const float[]); + Point(const float[]); + Point(); }; // 16 bytes struct Edge // path grid edge From cbfa282f8d04932eaf01f20fa108c9094da1b1c3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 03:58:32 -0400 Subject: [PATCH 245/545] Changed implementations of aifollow/pursue/activate slightly, added ability for NPCs to go through unlocked doors (They even try locked ones), and step back from opening doors (Although it still needs some work) Notes - When the door hits them while it's about to finish closing they will try to walk through the door. - Considerably more works is needed in making the NPC work out troublesome areas where they get stuck --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 8 ++- apps/openmw/mwmechanics/aiactivate.cpp | 98 ++++++-------------------- apps/openmw/mwmechanics/aiactivate.hpp | 5 +- apps/openmw/mwmechanics/aifollow.cpp | 12 +--- apps/openmw/mwmechanics/aifollow.hpp | 4 +- apps/openmw/mwmechanics/aipackage.cpp | 61 ++++++++++++---- apps/openmw/mwmechanics/aipackage.hpp | 14 +++- apps/openmw/mwmechanics/aipursue.cpp | 7 +- apps/openmw/mwmechanics/aipursue.hpp | 4 +- apps/openmw/mwmechanics/obstacle.cpp | 22 ++++-- apps/openmw/mwmechanics/obstacle.hpp | 14 +++- apps/openmw/mwworld/worldimp.cpp | 19 ++++- apps/openmw/mwworld/worldimp.hpp | 7 +- 14 files changed, 149 insertions(+), 128 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7a52831251..aee5cbeacc 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -67,7 +67,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects - drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow + drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle ) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96bed..2dfa34ba32 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -390,10 +390,14 @@ namespace MWBase virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door) = 0; - ///< activate (open or close) an non-teleport door + + /// Is door currently opening/closing? + virtual bool getIsMovingDoor(const MWWorld::Ptr& door) = 0; virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index eeedc0d7aa..1463dff7ee 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -19,83 +19,27 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const return new AiActivate(*this); } bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) -{ - MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); - - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - - MWWorld::Ptr target = world->searchPtr(mObjectId,false); - if(target == MWWorld::Ptr()) return true; - - ESM::Position targetPos = target.getRefData().getPosition(); - - bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) - { - mCellX = cell->mData.mX; - mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = targetPos.pos[0]; - dest.mY = targetPos.pos[1]; - dest.mZ = targetPos.pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ - (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - movement.mPosition[1] = 1; - +{ + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist + + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; + + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { //Stop when you get close + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + return true; + } + else { + pathTo(actor, dest, duration); //Go to the destination + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + } + return false; } diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index b6ce9f85d9..f684388727 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -8,7 +8,8 @@ namespace MWMechanics { - /// \brief Causes actor to walk to activatable object and activate it + /// \brief Causes actor to walk to activatable object and activate it + /** Will actiavte when close to object or path grid complete **/ class AiActivate : public AiPackage { public: @@ -21,8 +22,6 @@ namespace MWMechanics private: std::string mObjectId; - - PathFinder mPathFinder; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 98ac5ee149..8d9e019394 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -12,23 +12,17 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 531082357a..43681c1634 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_AIFALLOW_H -#define GAME_MWMECHANICS_AIFALLOW_H +#ifndef GAME_MWMECHANICS_AIFOLLOW_H +#define GAME_MWMECHANICS_AIFOLLOW_H #include "aipackage.hpp" #include diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index afe99e2c0b..90f0505a4d 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -8,6 +8,7 @@ #include "../mwworld/cellstore.hpp" #include "creaturestats.hpp" #include "movement.hpp" +#include "../mwworld/action.hpp" #include @@ -15,13 +16,18 @@ MWMechanics::AiPackage::~AiPackage() {} +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(NULL), mTimer(0), mStuckTimer(0) { + +} + bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration) { //Update various Timers - mTimer = mTimer + duration; //Update timer - mStuckTimer = mStuckTimer + duration; //Update stuck timer - mTotalTime = mTotalTime + duration; //Update total time following + mTimer += duration; //Update timer + mStuckTimer += duration; //Update stuck timer + mTotalTime += duration; //Update total time following + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor @@ -78,18 +84,45 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //************************ /// Checks if you aren't moving; attempts to unstick you //************************ - if(mStuckTimer>0.5) //Checks every half of a second + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished? + return true; + else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something { - if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) //NPC hasn't moved much is half a second, he's stuck - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - mStuckTimer = 0; - mStuckPos = pos; +/// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason + //if(mObstacleCheck.check(actor, duration)) { + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //Actually stuck + // first check if we're walking into a door + MWWorld::LiveCellRef* door = getNearbyDoor(actor); + if(door != NULL) // NOTE: checks interior cells only + { + if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped + door->mClass->activate(MWBase::Environment::get().getWorld()->getPtr(door->mRef.mRefID,false), actor).get()->execute(actor); + mLastDoorChecked = door; + } + } + else // probably walking into another NPC + { + // TODO: diagonal should have same animation as walk forward + // but doesn't seem to do that? + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f; + // change the angle a bit, too + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); + } + /*else if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //NPC hasn't moved much is half a second, he's stuck + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + }*/ + } + else { + mStuckTimer = 0; + mStuckPos = pos; + mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again + } + } + else { + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; } - //Checks if the path isn't over, turn tomards the direction that you're going - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - } + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); } diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index e36b51f691..37de32d8d9 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,6 +4,8 @@ #include "pathfinding.hpp" #include "../../../components/esm/defs.hpp" +#include "obstacle.hpp" + namespace MWWorld { class Ptr; @@ -24,9 +26,13 @@ namespace MWMechanics TypeIdFollow = 3, TypeIdActivate = 4, TypeIdCombat = 5, - TypeIdPursue = 6 + TypeIdPursue = 6, + TypeIdAvoidDoor = 7 }; + ///Default constructor + AiPackage(); + ///Default Deconstructor virtual ~AiPackage(); @@ -50,10 +56,14 @@ namespace MWMechanics bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); PathFinder mPathFinder; + ObstacleCheck mObstacleCheck; + float mDoorCheckDuration; float mTimer; float mStuckTimer; - float mTotalTime; + float mTotalTime; + + MWWorld::LiveCellRef* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; }; diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 4e0bc71046..6e91ccb719 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -31,16 +31,15 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - pathTo(actor, dest, duration); //Go to the destination - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } - else - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + else { + pathTo(actor, dest, duration); //Go to the destination + } actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 7d1ea5bb9d..2eb533d625 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -9,7 +9,9 @@ namespace MWMechanics { /// \brief Makes the actor very closely follow the actor - /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. **/ + /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. + Note that while very similar to AiActivate, it will ONLY activate when evry close to target (Not also when the + path is completed). **/ class AiPursue : public AiPackage { public: diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 1815609357..7cd85685b2 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -19,11 +19,19 @@ namespace MWMechanics // Limitation: there can be false detections, and does not test whether the // actor is facing the door. bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) + { + if(getNearbyDoor(actor, minSqr, closed)!=NULL) + return true; + else + return false; + } + + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { MWWorld::CellStore *cell = actor.getCell(); if(cell->getCell()->isExterior()) - return false; // check interior cells only + return NULL; // check interior cells only // Check all the doors in this cell MWWorld::CellRefList& doors = cell->get(); @@ -31,14 +39,14 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator it = refList.begin(); Ogre::Vector3 pos(actor.getRefData().getPosition().pos); - // TODO: How to check whether the actor is facing a door? Below code is for - // the player, perhaps it can be adapted. + /// TODO: How to check whether the actor is facing a door? Below code is for + /// the player, perhaps it can be adapted. //MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject(); //if(!ptr.isEmpty()) //std::cout << "faced door " << ptr.getClass().getName(ptr) << std::endl; - // TODO: The in-game observation of rot[2] value seems to be the - // opposite of the code in World::activateDoor() ::confused:: + /// TODO: The in-game observation of rot[2] value seems to be the + /// opposite of the code in World::activateDoor() ::confused:: for (; it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; @@ -46,10 +54,10 @@ namespace MWMechanics if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { - return true; // found, stop searching + return &ref; // found, stop searching } } - return false; // none found + return NULL; // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index 12030b2bee..e737ef9cfd 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -1,6 +1,10 @@ #ifndef OPENMW_MECHANICS_OBSTACLE_H #define OPENMW_MECHANICS_OBSTACLE_H +//#include "../mwbase/world.hpp" +//#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" + namespace MWWorld { class Ptr; @@ -8,14 +12,20 @@ namespace MWWorld namespace MWMechanics { - // NOTE: determined empirically based on in-game behaviour + /// NOTE: determined empirically based on in-game behaviour static const float MIN_DIST_TO_DOOR_SQUARED = 128*128; - // tests actor's proximity to a closed door by default + /// tests actor's proximity to a closed door by default bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr = MIN_DIST_TO_DOOR_SQUARED, bool closed = true); + /// Returns door pointer within range. No guarentee is given as too which one + /** \return Pointer to the door, or NULL if none exists **/ + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, + float minSqr = MIN_DIST_TO_DOOR_SQUARED, + bool closed = true); + class ObstacleCheck { public: diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ba36d4a869..5d1657a348 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -30,6 +30,7 @@ #include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/levelledlist.hpp" #include "../mwmechanics/combat.hpp" +#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors #include "../mwrender/sky.hpp" #include "../mwrender/animation.hpp" @@ -1210,7 +1211,11 @@ namespace MWWorld MWWorld::Ptr ptr = getPtrViaHandle(*cit); if (MWWorld::Class::get(ptr).isActor()) { - // we collided with an actor, we need to undo the rotation + // Collided with actor, ask actor to try to avoid door + MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); break; } @@ -1853,6 +1858,16 @@ namespace MWWorld return door.getRefData().getLocalRotation().rot[2] == 0; } + bool World::getIsMovingDoor(const Ptr& door) + { + //This more expensive comparison is needed for some reason + // TODO (tluppi#1#): Figure out why comparing Ptr isn't working + for(std::map::iterator it = mDoorStates.begin(); it != mDoorStates.end(); it++) + if(it->first.getCellRef().mRefID == door.getCellRef().mRefID) + return true; + return false; + } + bool World::getPlayerStandingOn (const MWWorld::Ptr& object) { MWWorld::Ptr player = mPlayer->getPlayer(); @@ -1919,7 +1934,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 645330683b..d111d00083 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -493,10 +493,13 @@ namespace MWWorld virtual void setupPlayer(); virtual void renderPlayer(); + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door); - ///< activate (open or close) an non-teleport door + + virtual bool getIsMovingDoor(const MWWorld::Ptr& door); virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object From 2db3c89a9e78f2dc66a7ee5ab07d9e5c672cde49 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 04:09:21 -0400 Subject: [PATCH 246/545] Ensures destination is far enough to care about getting stuck --- apps/openmw/mwmechanics/aipackage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 90f0505a4d..872eecb62b 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -90,7 +90,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po { /// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason //if(mObstacleCheck.check(actor, duration)) { - if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //Actually stuck + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10 && distance(dest, start) > 20) { //Actually stuck, and far enough away from destination to care // first check if we're walking into a door MWWorld::LiveCellRef* door = getNearbyDoor(actor); if(door != NULL) // NOTE: checks interior cells only @@ -125,4 +125,6 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po } zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + + return false; } From e591d23880cc81c5f086c50a152ef81b5073da44 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 19:01:02 +0200 Subject: [PATCH 247/545] Fixes #894: Make sure the player's CharacterController is updated when the player is rebuilt. Necessary if the race is changed while we are still in a GUI (e.g. in the review dialog), and an update normally wouldn't occur. --- apps/openmw/mwmechanics/actors.cpp | 4 +++- apps/openmw/mwmechanics/actors.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b935284d38..91ef48c092 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -781,7 +781,7 @@ namespace MWMechanics } } - void Actors::addActor (const MWWorld::Ptr& ptr) + void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately) { // erase previous death events since we are currently only tracking them while in an active cell MWWorld::Class::get(ptr).getCreatureStats(ptr).clearHasDied(); @@ -790,6 +790,8 @@ namespace MWMechanics MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); mActors.insert(std::make_pair(ptr, new CharacterController(ptr, anim))); + if (updateImmediately) + mActors[ptr]->update(0); } void Actors::removeActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index f7dff1058b..e42672bad6 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -58,7 +58,7 @@ namespace MWMechanics /// paused we may want to do it manually (after equipping permanent enchantment) void updateMagicEffects (const MWWorld::Ptr& ptr) { adjustMagicEffects(ptr); } - void addActor (const MWWorld::Ptr& ptr); + void addActor (const MWWorld::Ptr& ptr, bool updateImmediately=false); ///< Register an actor for stats management /// /// \note Dead actors are ignored. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2b1f82b926..5c2ee30e1b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -385,7 +385,7 @@ namespace MWMechanics // have been made for them. Make sure they're properly updated. MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); mActors.removeActor(ptr); - mActors.addActor(ptr); + mActors.addActor(ptr, true); } mActors.update(duration, paused); From 598221a8e77a937ad7ff3ea144709046f5955eaf Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:07:27 -0400 Subject: [PATCH 248/545] Forgot some files --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 64 +++++++++++++++++++++++++ apps/openmw/mwmechanics/aiavoiddoor.hpp | 36 ++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 apps/openmw/mwmechanics/aiavoiddoor.cpp create mode 100644 apps/openmw/mwmechanics/aiavoiddoor.hpp diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp new file mode 100644 index 0000000000..375e8fae7f --- /dev/null +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -0,0 +1,64 @@ +#include "aiavoiddoor.hpp" +#include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" +#include "creaturestats.hpp" +#include "movement.hpp" + +#include + +#include "steering.hpp" + +MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr) +: AiPackage(), mDoorPtr(doorPtr), mDuration(1) +{ +} + +bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration) +{ + mDuration -= duration; //Update timer + + if(mDuration < 0) + return true; // We have tried backing up for more than one second, we've probably cleared it + + if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) + return true; //Door is no longer opening + + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door + float x = pos.pos[0] - tPos.pos[0]; + float y = pos.pos[1] - tPos.pos[1]; + float z = pos.pos[2] - tPos.pos[2]; + int distance = sqrt(x * x + y * y + z * z); + + if(distance > 300) //Stop backing up when you're far enough away + return true; +/// TODO: Calculate this from door size, not have it built in + + float dirToDoor = std::atan2(x,y) + pos.rot[2]; //Calculates the direction to the door, relative to the direction of the NPC + // For example, if the NPC is directly facing the door this will be pi/2 + + // Make actor move away from the door + actor.getClass().getMovementSettings(actor).mPosition[1] = -1 * std::sin(dirToDoor); //I knew I'd use trig someday + actor.getClass().getMovementSettings(actor).mPosition[0] = -1 * std::cos(dirToDoor); + + return false; +} + +std::string MWMechanics::AiAvoidDoor::getAvoidedDoor() +{ + return mDoorPtr.getCellRef().mRefID; +} + +MWMechanics::AiAvoidDoor *MWMechanics::AiAvoidDoor::clone() const +{ + return new AiAvoidDoor(*this); +} + + int MWMechanics::AiAvoidDoor::getTypeId() const +{ + return TypeIdAvoidDoor; +} + diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp new file mode 100644 index 0000000000..6c90e36d61 --- /dev/null +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -0,0 +1,36 @@ +#ifndef GAME_MWMECHANICS_AIAVOIDDOOR_H +#define GAME_MWMECHANICS_AIAVOIDDOOR_H + +#include "aipackage.hpp" +#include +#include "pathfinding.hpp" +#include "../../../components/esm/defs.hpp" +#include "../mwworld/class.hpp" + +namespace MWMechanics +{ + /// \brief AiPackage to have an actor avoid an opening door + /** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it + **/ + class AiAvoidDoor : public AiPackage + { + public: + /// Avoid door until the door is fully open + AiAvoidDoor(const MWWorld::Ptr& doorPtr); + + virtual AiAvoidDoor *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor,float duration); + + virtual int getTypeId() const; + + /// Returns the door being avoided + std::string getAvoidedDoor(); + + private: + float mDuration; + MWWorld::Ptr mDoorPtr; + }; +} +#endif + From 77d365e1963257ca08fe306e5f910c9d988b0272 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:25:22 -0400 Subject: [PATCH 249/545] Forced some function arguments to take in a specific array size --- components/esm/loadpgrd.cpp | 4 ++-- components/esm/loadpgrd.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 5b8ce3eb2c..efdbdd86be 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -8,13 +8,13 @@ namespace ESM { unsigned int Pathgrid::sRecordId = REC_PGRD; - Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[]) { + Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[3]) { mX = rhs[0]; mY = rhs[1]; mZ = rhs[2]; return *this; } - Pathgrid::Point::Point(const float rhs[]) { + Pathgrid::Point::Point(const float rhs[3]) { mX = rhs[0]; mY = rhs[1]; mZ = rhs[2]; diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index b940c27e60..9262334442 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -31,8 +31,8 @@ struct Pathgrid unsigned char mAutogenerated; // autogenerated vs. user coloring flag? unsigned char mConnectionNum; // number of connections for this point short mUnknown; - Point& operator=(const float[]); - Point(const float[]); + Point& operator=(const float[3]); + Point(const float[3]); Point(); }; // 16 bytes From f01c3e0eacfa0d42bd367892723c2be4df1441cc Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 19:38:28 +0200 Subject: [PATCH 250/545] Fixes #1037: Change default footstep volume to match vanilla --- files/settings-default.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 2b44d0f4e2..9eed2c7d92 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -150,7 +150,7 @@ device = master volume = 1.0 sfx volume = 1.0 music volume = 0.4 -footsteps volume = 0.6 +footsteps volume = 0.15 voice volume = 1.0 From ee36ace00b7f351e3525c156df80b456daaf3c5f Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:43:50 -0400 Subject: [PATCH 251/545] Undid some code clean up changes, and changed how some includes work --- apps/openmw/mwinput/inputmanagerimp.hpp | 6 +- apps/openmw/mwmechanics/aiavoiddoor.hpp | 2 +- apps/openmw/mwmechanics/aifollow.hpp | 2 +- apps/openmw/mwmechanics/aipackage.hpp | 2 +- apps/openmw/mwmechanics/alchemy.hpp | 92 ++++---- apps/openmw/mwmechanics/character.hpp | 293 ++++++++++++------------ 6 files changed, 197 insertions(+), 200 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index ace4cc6d0e..3787a9c071 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -46,7 +46,10 @@ namespace MyGUI namespace MWInput { - /// \brief Class that handles all input and key bindings for OpenMW. + + /** + * @brief Class that handles all input and key bindings for OpenMW. + */ class InputManager : public MWBase::InputManager, public SFO::KeyListener, @@ -65,7 +68,6 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); - virtual void update(float dt, bool disableControls=false, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 6c90e36d61..6e9a1bdf5b 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -4,7 +4,7 @@ #include "aipackage.hpp" #include #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include #include "../mwworld/class.hpp" namespace MWMechanics diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 43681c1634..10a381410a 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -4,7 +4,7 @@ #include "aipackage.hpp" #include #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include namespace MWMechanics { diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 37de32d8d9..c9c8504aa1 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -2,7 +2,7 @@ #define GAME_MWMECHANICS_AIPACKAGE_H #include "pathfinding.hpp" -#include "../../../components/esm/defs.hpp" +#include #include "obstacle.hpp" diff --git a/apps/openmw/mwmechanics/alchemy.hpp b/apps/openmw/mwmechanics/alchemy.hpp index b2b0fe1ee0..31cafa4dc7 100644 --- a/apps/openmw/mwmechanics/alchemy.hpp +++ b/apps/openmw/mwmechanics/alchemy.hpp @@ -31,8 +31,6 @@ namespace MWMechanics typedef std::vector TEffectsContainer; typedef TEffectsContainer::const_iterator TEffectsIterator; - /// Result of potion creation - /** Only Result_Success results in success **/ enum Result { Result_Success, @@ -44,46 +42,6 @@ namespace MWMechanics Result_RandomFailure }; - /// Set alchemist and configure alchemy setup accordingly. - /** \a npc may be empty to indicate that there is no alchemist (alchemy session has ended). **/ - void setAlchemist (const MWWorld::Ptr& npc); - - /// \attention Iterates over tool slots, not over tools. Some of the slots may be empty. - TToolsIterator beginTools() const; - - TToolsIterator endTools() const; - - /// \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. - TIngredientsIterator beginIngredients() const; - - TIngredientsIterator endIngredients() const; - - /// Remove alchemist, tools and ingredients. - void clear(); - - /// Add ingredient into the next free slot. - /// - /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being - /// listed already. - int addIngredient (const MWWorld::Ptr& ingredient); - - /// Remove ingredient from slot (calling this function on an empty slot is a no-op). - void removeIngredient (int index); - - TEffectsIterator beginEffects() const; - - TEffectsIterator endEffects() const; - - /// Return the name of the potion that would be created when calling create (if a record for such - /// a potion already exists) or return an empty string. - std::string getPotionName() const; - - /// Try to create a potion from the ingredients, place it in the inventory of the alchemist and - /// adjust the skills of the alchemist accordingly. - /// \param name must not be an empty string, unless there is already a potion record ( - /// getPotionName() does not return an empty string). - Result create (const std::string& name); - private: MWWorld::Ptr mAlchemist; @@ -92,19 +50,19 @@ namespace MWMechanics TEffectsContainer mEffects; int mValue; - /// List all effects shared by at least two ingredients. std::set listEffects() const; + ///< List all effects shared by at least two ingredients. void applyTools (int flags, float& value) const; void updateEffects(); - /// Return existing recrod for created potion (may return 0) const ESM::Potion *getRecord() const; + ///< Return existing recrod for created potion (may return 0) - /// Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and - /// update effect list accordingly. void removeIngredients(); + ///< Remove selected ingredients from alchemist's inventory, cleanup selected ingredients and + /// update effect list accordingly. void addPotion (const std::string& name); ///< Add a potion to the alchemist's inventory. @@ -116,6 +74,48 @@ namespace MWMechanics ///< Return chance of success. int countIngredients() const; + + public: + + void setAlchemist (const MWWorld::Ptr& npc); + ///< Set alchemist and configure alchemy setup accordingly. \a npc may be empty to indicate that + /// there is no alchemist (alchemy session has ended). + + TToolsIterator beginTools() const; + ///< \attention Iterates over tool slots, not over tools. Some of the slots may be empty. + + TToolsIterator endTools() const; + + TIngredientsIterator beginIngredients() const; + ///< \attention Iterates over ingredient slots, not over ingredients. Some of the slots may be empty. + + TIngredientsIterator endIngredients() const; + + void clear(); + ///< Remove alchemist, tools and ingredients. + + int addIngredient (const MWWorld::Ptr& ingredient); + ///< Add ingredient into the next free slot. + /// + /// \return Slot index or -1, if adding failed because of no free slot or the ingredient type being + /// listed already. + + void removeIngredient (int index); + ///< Remove ingredient from slot (calling this function on an empty slot is a no-op). + + TEffectsIterator beginEffects() const; + + TEffectsIterator endEffects() const; + + std::string getPotionName() const; + ///< Return the name of the potion that would be created when calling create (if a record for such + /// a potion already exists) or return an empty string. + + Result create (const std::string& name); + ///< Try to create a potion from the ingredients, place it in the inventory of the alchemist and + /// adjust the skills of the alchemist accordingly. + /// \param name must not be an empty string, unless there is already a potion record ( + /// getPotionName() does not return an empty string). }; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 09c9954288..5aea0210f2 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -21,199 +21,194 @@ namespace MWRender namespace MWMechanics { - class Movement; - class CreatureStats; +class Movement; +class CreatureStats; - ///Priority of actions - enum Priority { - Priority_Default, - Priority_Jump, - Priority_Movement, - Priority_Hit, - Priority_Weapon, - Priority_Knockdown, - Priority_Torch, +enum Priority { + Priority_Default, + Priority_Jump, + Priority_Movement, + Priority_Hit, + Priority_Weapon, + Priority_Knockdown, + Priority_Torch, - Priority_Death, + Priority_Death, - Num_Priorities - }; + Num_Priorities +}; - /// Current action of the character - enum CharacterState { - CharState_None, +enum CharacterState { + CharState_None, - CharState_SpecialIdle, - CharState_Idle, - CharState_Idle2, - CharState_Idle3, - CharState_Idle4, - CharState_Idle5, - CharState_Idle6, - CharState_Idle7, - CharState_Idle8, - CharState_Idle9, - CharState_IdleSwim, - CharState_IdleSneak, + CharState_SpecialIdle, + CharState_Idle, + CharState_Idle2, + CharState_Idle3, + CharState_Idle4, + CharState_Idle5, + CharState_Idle6, + CharState_Idle7, + CharState_Idle8, + CharState_Idle9, + CharState_IdleSwim, + CharState_IdleSneak, - CharState_WalkForward, - CharState_WalkBack, - CharState_WalkLeft, - CharState_WalkRight, + CharState_WalkForward, + CharState_WalkBack, + CharState_WalkLeft, + CharState_WalkRight, - CharState_SwimWalkForward, - CharState_SwimWalkBack, - CharState_SwimWalkLeft, - CharState_SwimWalkRight, + CharState_SwimWalkForward, + CharState_SwimWalkBack, + CharState_SwimWalkLeft, + CharState_SwimWalkRight, - CharState_RunForward, - CharState_RunBack, - CharState_RunLeft, - CharState_RunRight, + CharState_RunForward, + CharState_RunBack, + CharState_RunLeft, + CharState_RunRight, - CharState_SwimRunForward, - CharState_SwimRunBack, - CharState_SwimRunLeft, - CharState_SwimRunRight, + CharState_SwimRunForward, + CharState_SwimRunBack, + CharState_SwimRunLeft, + CharState_SwimRunRight, - CharState_SneakForward, - CharState_SneakBack, - CharState_SneakLeft, - CharState_SneakRight, + CharState_SneakForward, + CharState_SneakBack, + CharState_SneakLeft, + CharState_SneakRight, - CharState_TurnLeft, - CharState_TurnRight, + CharState_TurnLeft, + CharState_TurnRight, - CharState_Jump, + CharState_Jump, - CharState_Death1, - CharState_Death2, - CharState_Death3, - CharState_Death4, - CharState_Death5, - CharState_SwimDeath, - CharState_DeathKnockDown, - CharState_DeathKnockOut, + CharState_Death1, + CharState_Death2, + CharState_Death3, + CharState_Death4, + CharState_Death5, + CharState_SwimDeath, + CharState_DeathKnockDown, + CharState_DeathKnockOut, - CharState_Hit, - CharState_KnockDown, - CharState_KnockOut, - CharState_Block - }; + CharState_Hit, + CharState_KnockDown, + CharState_KnockOut, + CharState_Block +}; - ///Weapon type - enum WeaponType { - WeapType_None, +enum WeaponType { + WeapType_None, - WeapType_HandToHand, - WeapType_OneHand, - WeapType_TwoHand, - WeapType_TwoWide, - WeapType_BowAndArrow, - WeapType_Crossbow, - WeapType_Thrown, - WeapType_PickProbe, + WeapType_HandToHand, + WeapType_OneHand, + WeapType_TwoHand, + WeapType_TwoWide, + WeapType_BowAndArrow, + WeapType_Crossbow, + WeapType_Thrown, + WeapType_PickProbe, - WeapType_Spell - }; + WeapType_Spell +}; - ///Specific, weapon based state of the character - enum UpperBodyCharacterState { - UpperCharState_Nothing, - UpperCharState_EquipingWeap, - UpperCharState_UnEquipingWeap, - UpperCharState_WeapEquiped, - UpperCharState_StartToMinAttack, - UpperCharState_MinAttackToMaxAttack, - UpperCharState_MaxAttackToMinHit, - UpperCharState_MinHitToHit, - UpperCharState_FollowStartToFollowStop, - UpperCharState_CastingSpell - }; +enum UpperBodyCharacterState { + UpperCharState_Nothing, + UpperCharState_EquipingWeap, + UpperCharState_UnEquipingWeap, + UpperCharState_WeapEquiped, + UpperCharState_StartToMinAttack, + UpperCharState_MinAttackToMaxAttack, + UpperCharState_MaxAttackToMinHit, + UpperCharState_MinHitToHit, + UpperCharState_FollowStartToFollowStop, + UpperCharState_CastingSpell +}; - ///Current jumping state - enum JumpingState { - JumpState_None, - JumpState_Falling, - JumpState_Landing - }; +enum JumpingState { + JumpState_None, + JumpState_Falling, + JumpState_Landing +}; - class CharacterController - { - MWWorld::Ptr mPtr; - MWRender::Animation *mAnimation; +class CharacterController +{ + MWWorld::Ptr mPtr; + MWRender::Animation *mAnimation; - typedef std::deque > AnimationQueue; - AnimationQueue mAnimQueue; + typedef std::deque > AnimationQueue; + AnimationQueue mAnimQueue; - CharacterState mIdleState; - std::string mCurrentIdle; + CharacterState mIdleState; + std::string mCurrentIdle; - CharacterState mMovementState; - std::string mCurrentMovement; - float mMovementSpeed; - float mMovementAnimVelocity; + CharacterState mMovementState; + std::string mCurrentMovement; + float mMovementSpeed; + float mMovementAnimVelocity; - CharacterState mDeathState; - std::string mCurrentDeath; + CharacterState mDeathState; + std::string mCurrentDeath; - CharacterState mHitState; - std::string mCurrentHit; + CharacterState mHitState; + std::string mCurrentHit; - UpperBodyCharacterState mUpperBodyState; + UpperBodyCharacterState mUpperBodyState; - JumpingState mJumpState; - std::string mCurrentJump; + JumpingState mJumpState; + std::string mCurrentJump; - WeaponType mWeaponType; - std::string mCurrentWeapon; + WeaponType mWeaponType; + std::string mCurrentWeapon; - bool mSkipAnim; + bool mSkipAnim; - // counted for skill increase - float mSecondsOfSwimming; - float mSecondsOfRunning; + // counted for skill increase + float mSecondsOfSwimming; + float mSecondsOfRunning; - std::string mAttackType; // slash, chop or thrust - void determineAttackType(); + std::string mAttackType; // slash, chop or thrust + void determineAttackType(); - void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false); + void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false); - void clearAnimQueue(); + void clearAnimQueue(); - bool updateWeaponState(); - bool updateCreatureState(); + bool updateWeaponState(); + bool updateCreatureState(); - void updateVisibility(); + void updateVisibility(); - void playRandomDeath(float startpoint = 0.0f); + void playRandomDeath(float startpoint = 0.0f); - /// choose a random animation group with \a prefix and numeric suffix - /// @param num if non-NULL, the chosen animation number will be written here - std::string chooseRandomGroup (const std::string& prefix, int* num = NULL); + /// choose a random animation group with \a prefix and numeric suffix + /// @param num if non-NULL, the chosen animation number will be written here + std::string chooseRandomGroup (const std::string& prefix, int* num = NULL); - public: - CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); - virtual ~CharacterController(); +public: + CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); + virtual ~CharacterController(); - // Be careful when to call this, see comment in Actors - void updateContinuousVfx(); + // Be careful when to call this, see comment in Actors + void updateContinuousVfx(); - void updatePtr(const MWWorld::Ptr &ptr); + void updatePtr(const MWWorld::Ptr &ptr); - void update(float duration); + void update(float duration); - void playGroup(const std::string &groupname, int mode, int count); - void skipAnim(); - bool isAnimPlaying(const std::string &groupName); + void playGroup(const std::string &groupname, int mode, int count); + void skipAnim(); + bool isAnimPlaying(const std::string &groupName); - bool kill(); - void resurrect(); - bool isDead() const - { return mDeathState != CharState_None; } + bool kill(); + void resurrect(); + bool isDead() const + { return mDeathState != CharState_None; } - void forceStateUpdate(); - }; + void forceStateUpdate(); +}; void getWeaponGroup(WeaponType weaptype, std::string &group); MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::InventoryStore &inv, WeaponType *weaptype); From a61d804de694613874e4b8ad415cdca6c2b97b58 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 13:53:06 -0400 Subject: [PATCH 252/545] now that I've found the documentation, fixed some stuff for extensions --- components/compiler/extensions.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 5be81ac080..908165ee60 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -16,12 +16,12 @@ namespace Compiler every argument is optional.
Eg: fff/f represents 3 required floats followed by one optional float
f - Float
- c - String
+ c - String, case smashed
l - Integer
s - Short
- S - Also string (Seemed to be mostly used for Cell Names)
- x - none? - + S - String, case preserved
+ x - Optional, ignored argument + \see Compiler::ExprParser::parseArguments **/ typedef std::string ScriptArgs; From d6d4d9f75d42b60a303193f074464268b99afdc4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:08:08 -0400 Subject: [PATCH 253/545] Removed destructor documentation --- apps/openmw/mwmechanics/aisequence.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 5a4cb743aa..8196262f5b 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -40,7 +40,6 @@ namespace MWMechanics /// Assignment operator AiSequence& operator= (const AiSequence& sequence); - /// Destructor virtual ~AiSequence(); /// Returns currently executing AiPackage type From 085fb2c5a2033aa1d21e8ecbe61e537e4383fc1e Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:13:05 -0400 Subject: [PATCH 254/545] Simplified documentation a bit --- components/compiler/exprparser.hpp | 6 ++---- components/compiler/extensions.hpp | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 6a4e1be2ff..93e0d1c366 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -98,10 +98,8 @@ namespace Compiler int parseArguments (const std::string& arguments, Scanner& scanner, std::vector& code, bool invert = false); ///< Parse sequence of arguments specified by \a arguments. - /// \param arguments Each character represents one arguments ('l': integer, - /// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are - /// optional) - /// 'x': optional string that will be ignored (die in a fire, MW script compiler!) + /// \param arguments Uses ScriptArgs typedef + /// \see Compiler::ScriptArgs /// \param invert Store arguments in reverted order. /// \return number of optional arguments }; diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 908165ee60..3f91ca357d 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -21,7 +21,6 @@ namespace Compiler s - Short
S - String, case preserved
x - Optional, ignored argument - \see Compiler::ExprParser::parseArguments **/ typedef std::string ScriptArgs; From 680890c84689cb8b647b6ba55bec7b427b433266 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:21:59 -0400 Subject: [PATCH 255/545] Clarification on some documentation points --- apps/openmw/mwmechanics/aisequence.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 8196262f5b..3d524a6862 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -15,13 +15,13 @@ namespace MWMechanics class AiPackage; /// \brief Sequence of AI-packages for a single actor - /** Each package will be run in succession for an actor until completed **/ + /** The top-most AI package is run each frame. When completed, it is removed from the stack. **/ class AiSequence { ///AiPackages to run though std::list mPackages; - ///Finished with all AiPackages + ///Finished with top AIPackage, set for one frame bool mDone; ///Copy AiSequence From 6d540c4e073250fccbe09e06c9a2dcf93c7c29f6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 14:24:48 -0400 Subject: [PATCH 256/545] Removed merging error --- apps/openmw/mwmechanics/aisequence.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 3d524a6862..7ac68dd677 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -58,9 +58,6 @@ namespace MWMechanics /// Removes all combat packages until first non-combat or stack empty. void stopCombat(); - /// Removes all persue packages until first non-persue or stack empty. - void stopPersue(); - /// Has a package been completed during the last update? bool isPackageDone() const; From 365ca6c7e1b6208fc323f1fc29db8c4747bb6ee4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 21:42:27 +0200 Subject: [PATCH 257/545] Fixes #1331: Manually disable movement state for dead actors. For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. --- apps/openmw/mwmechanics/character.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 280639f714..2b8b6eccb9 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -431,6 +431,11 @@ void CharacterController::playRandomDeath(float startpoint) mDeathState = static_cast(CharState_Death1 + (selected-1)); } + // For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. + mMovementState = CharState_None; + mAnimation->disable(mCurrentMovement); + mCurrentMovement = ""; + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, false, 1.0f, "start", "stop", startpoint, 0); } From 203ef580cf3cfae01c3dcedb34842a1b71d99c14 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 20:32:29 -0400 Subject: [PATCH 258/545] Fixed moving activatable object being incorrectly activated. --- apps/openmw/mwmechanics/aiactivate.hpp | 2 +- apps/openmw/mwmechanics/aipackage.cpp | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index f684388727..0e660e967d 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -9,7 +9,7 @@ namespace MWMechanics { /// \brief Causes actor to walk to activatable object and activate it - /** Will actiavte when close to object or path grid complete **/ + /** Will activate when close to object **/ class AiActivate : public AiPackage { public: diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 872eecb62b..1bc3503832 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -109,19 +109,15 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po // change the angle a bit, too zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); } - /*else if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //NPC hasn't moved much is half a second, he's stuck - actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - actor.getClass().getMovementSettings(actor).mPosition[0] = 1; - }*/ } - else { + else { //Not stuck, so reset things mStuckTimer = 0; mStuckPos = pos; mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again } } else { - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time } zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); From 58bf7624becac34486eb6018c301de9d9f27ef04 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 21:52:05 -0400 Subject: [PATCH 259/545] Made code a bit more efficient --- apps/openmw/mwmechanics/aiactivate.cpp | 2 +- apps/openmw/mwmechanics/aiavoiddoor.hpp | 2 +- apps/openmw/mwmechanics/aipackage.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 8 ++------ 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 1463dff7ee..56c155ded0 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -29,7 +29,7 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { //Stop when you get close + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 6e9a1bdf5b..8d225655a0 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -29,7 +29,7 @@ namespace MWMechanics private: float mDuration; - MWWorld::Ptr mDoorPtr; + const MWWorld::Ptr& mDoorPtr; }; } #endif diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 1bc3503832..5ccd2c8d89 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -96,7 +96,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po if(door != NULL) // NOTE: checks interior cells only { if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped - door->mClass->activate(MWBase::Environment::get().getWorld()->getPtr(door->mRef.mRefID,false), actor).get()->execute(actor); + door->mClass->activate(MWWorld::Ptr(door, actor.getCell()), actor).get()->execute(actor); mLastDoorChecked = door; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 82489adacc..96dd91f821 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1863,12 +1863,8 @@ namespace MWWorld bool World::getIsMovingDoor(const Ptr& door) { - //This more expensive comparison is needed for some reason - // TODO (tluppi#1#): Figure out why comparing Ptr isn't working - for(std::map::iterator it = mDoorStates.begin(); it != mDoorStates.end(); it++) - if(it->first.getCellRef().mRefID == door.getCellRef().mRefID) - return true; - return false; + bool result = mDoorStates.find(door) != mDoorStates.end(); + return result; } bool World::getPlayerStandingOn (const MWWorld::Ptr& object) From 6c7b3074f5447a60d124b42e8ab6fe9114e87a72 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 05:31:19 +0200 Subject: [PATCH 260/545] Fix self-defense for creatures when attacked with a spell --- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index e6342e661a..0f5649af26 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -408,9 +408,9 @@ namespace MWMechanics target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, mSourceName, caster.getRefData().getHandle()); - if (anyHarmfulEffect && target.getClass().isActor() && target != caster - && target.getClass().getCreatureStats(target).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) - MWBase::Environment::get().getMechanicsManager()->commitCrime(caster, target, MWBase::MechanicsManager::OT_Assault); + // Notify the target actor they've been hit + if (anyHarmfulEffect && target.getClass().isActor() && target != caster) + target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true); } void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude) From 99b4bc721b5ec17ce4cf3f1e2638337b5d1440ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 05:33:18 +0200 Subject: [PATCH 261/545] Don't attempt to inflict spells on dead actors --- apps/openmw/mwmechanics/spellcasting.cpp | 3 +++ apps/openmw/mwmechanics/spellcasting.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 0f5649af26..d510373ff2 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -189,6 +189,9 @@ namespace MWMechanics void CastSpell::inflict(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const ESM::EffectList &effects, ESM::RangeType range, bool reflected, bool exploded) { + if (target.getClass().isActor() && target.getClass().getCreatureStats(target).isDead()) + return; + // If none of the effects need to apply, we can early-out bool found = false; for (std::vector::const_iterator iter (effects.mList.begin()); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 44402fe7bb..a930442fb2 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -61,6 +61,7 @@ namespace MWMechanics /// @note Auto detects if spell, ingredient or potion bool cast (const std::string& id); + /// @note \a target can be any type of object, not just actors. void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false); From 7cd4c93fa4aa7dd63a55818de533e4dd539b270b Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 23:46:00 -0400 Subject: [PATCH 262/545] Changed getNearbyDoor to use MWWorld::Ptr --- apps/openmw/mwmechanics/aipackage.cpp | 12 ++++++------ apps/openmw/mwmechanics/aipackage.hpp | 3 ++- apps/openmw/mwmechanics/obstacle.cpp | 10 +++++----- apps/openmw/mwmechanics/obstacle.hpp | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 5ccd2c8d89..c2e8385b82 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,7 +16,7 @@ MWMechanics::AiPackage::~AiPackage() {} -MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(NULL), mTimer(0), mStuckTimer(0) { +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(0), mStuckTimer(0) { } @@ -92,11 +92,11 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //if(mObstacleCheck.check(actor, duration)) { if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10 && distance(dest, start) > 20) { //Actually stuck, and far enough away from destination to care // first check if we're walking into a door - MWWorld::LiveCellRef* door = getNearbyDoor(actor); - if(door != NULL) // NOTE: checks interior cells only + MWWorld::Ptr door = getNearbyDoor(actor); + if(door != MWWorld::Ptr()) // NOTE: checks interior cells only { - if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped - door->mClass->activate(MWWorld::Ptr(door, actor.getCell()), actor).get()->execute(actor); + if(door.getCellRef().mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped + door.getClass().activate(door, actor).get()->execute(actor); mLastDoorChecked = door; } } @@ -113,7 +113,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po else { //Not stuck, so reset things mStuckTimer = 0; mStuckPos = pos; - mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again + mLastDoorChecked = MWWorld::Ptr(); //Resets it, in case he gets stuck behind the door again } } else { diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index c9c8504aa1..bb62a2543a 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -3,6 +3,7 @@ #include "pathfinding.hpp" #include +#include "../mwbase/world.hpp" #include "obstacle.hpp" @@ -63,7 +64,7 @@ namespace MWMechanics float mStuckTimer; float mTotalTime; - MWWorld::LiveCellRef* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door + MWWorld::Ptr mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; }; diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 7cd85685b2..fc781e6377 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -20,18 +20,18 @@ namespace MWMechanics // actor is facing the door. bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { - if(getNearbyDoor(actor, minSqr, closed)!=NULL) + if(getNearbyDoor(actor, minSqr, closed)!=MWWorld::Ptr()) return true; else return false; } - MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) + MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { MWWorld::CellStore *cell = actor.getCell(); if(cell->getCell()->isExterior()) - return NULL; // check interior cells only + return MWWorld::Ptr(); // check interior cells only // Check all the doors in this cell MWWorld::CellRefList& doors = cell->get(); @@ -54,10 +54,10 @@ namespace MWMechanics if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { - return &ref; // found, stop searching + return MWWorld::Ptr(&ref, actor.getCell()); // found, stop searching } } - return NULL; // none found + return MWWorld::Ptr(); // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index e737ef9cfd..76ab9d029b 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -22,7 +22,7 @@ namespace MWMechanics /// Returns door pointer within range. No guarentee is given as too which one /** \return Pointer to the door, or NULL if none exists **/ - MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, + MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minSqr = MIN_DIST_TO_DOOR_SQUARED, bool closed = true); From 7697ab37e02890d6a5bdc84dc7cfcd91be87dc9c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 06:37:31 +0200 Subject: [PATCH 263/545] Fixes #1129: Change summoned creatures to use ActorId Gracefully handles summoned creatures that are left behind in inactive cells. --- apps/openmw/mwmechanics/actors.cpp | 46 +++++++++++++++++------ apps/openmw/mwmechanics/creaturestats.hpp | 12 ++++-- apps/openmw/mwworld/actionteleport.cpp | 1 - 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 91ef48c092..22d033f408 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -38,9 +38,12 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a { if (bound) { - MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor); - MWWorld::ActionEquip action(newPtr); - action.execute(actor); + if (actor.getClass().getContainerStore(actor).count(item) == 0) + { + MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor); + MWWorld::ActionEquip action(newPtr); + action.execute(actor); + } } else { @@ -534,28 +537,49 @@ namespace MWMechanics MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1); ref.getPtr().getCellRef().mPos = ipos; - // TODO: Add AI to follow player and fight for him + MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); + + // Make the summoned creature follow its master and help in fights AiFollow package(ptr.getRefData().getHandle()); - MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr); + summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); + int creatureActorId = summonedCreatureStats.getActorId(); + + MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos); + // TODO: VFX_SummonStart, VFX_SummonEnd - creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, - MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle())); + creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, creatureActorId)); } } else { - std::string handle = creatureStats.mSummonedCreatures[it->first]; - // TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation - // plays though, which is a rather lame exploit in vanilla. - MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle); + // Summon lifetime has expired. Try to delete the creature. + int actorId = creatureStats.mSummonedCreatures[it->first]; + creatureStats.mSummonedCreatures.erase(it->first); + + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(actorId); if (!ptr.isEmpty()) { + // TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation + // plays though, which is a rather lame exploit in vanilla. MWBase::Environment::get().getWorld()->deleteObject(ptr); creatureStats.mSummonedCreatures.erase(it->first); } + else + { + // We didn't find the creature. It's probably in an inactive cell. + // Add to graveyard so we can delete it when the cell becomes active. + creatureStats.mSummonGraveyard.push_back(actorId); + } } } } + + for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ++it) + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it); + if (!ptr.isEmpty()) + MWBase::Environment::get().getWorld()->deleteObject(ptr); + } } void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 7cec26fb84..79686bb978 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -223,10 +223,16 @@ namespace MWMechanics void setLastHitObject(const std::string &objectid); const std::string &getLastHitObject() const; - // Note, this is just a cache to avoid checking the whole container store every frame TODO: Put it somewhere else? + // Note, this is just a cache to avoid checking the whole container store every frame. We don't need to store it in saves. + // TODO: Put it somewhere else? std::set mBoundItems; - // Same as above - std::map mSummonedCreatures; + + // TODO: store in savegame + // TODO: encapsulate? + // + std::map mSummonedCreatures; + // Contains summoned creatures with an expired lifetime that have not been deleted yet. + std::vector mSummonGraveyard; void writeState (ESM::CreatureStats& state) const; diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 627c05251f..4378e179d7 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -22,7 +22,6 @@ namespace MWWorld std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); for(std::list::iterator it = followers.begin();it != followers.end();++it) { - std::cout << "teleporting someone!" << (*it).getCellRef().mRefID; executeImp(*it); } From c160a04ede26f28d1f9530a7dc0c2ba890494cb1 Mon Sep 17 00:00:00 2001 From: slothlife Date: Wed, 14 May 2014 00:03:30 -0500 Subject: [PATCH 264/545] Revert "Fixes for warnings when building with MSVC" This reverts commit 46eb20b98ce990756ad1f9af5054f0a571dca43c. --- CMakeLists.txt | 1 - apps/esmtool/esmtool.cpp | 2 + apps/mwiniimporter/main.cpp | 2 +- apps/opencs/model/doc/document.cpp | 516 +++++++++--------- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/doc/documentmanager.hpp | 4 +- apps/opencs/model/world/commands.hpp | 4 +- apps/opencs/model/world/idtable.hpp | 2 +- apps/opencs/model/world/infocollection.hpp | 4 +- apps/opencs/model/world/ref.hpp | 2 +- apps/opencs/model/world/refcollection.hpp | 2 +- apps/opencs/model/world/refidadapter.hpp | 4 +- apps/opencs/view/render/lightingday.cpp | 4 +- apps/opencs/view/render/lightingnight.cpp | 6 +- apps/opencs/view/render/scenewidget.cpp | 4 +- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 4 +- apps/openmw/mwgui/companionwindow.cpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 - apps/openmw/mwmechanics/combat.cpp | 4 +- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 - .../mwscript/transformationextensions.cpp | 4 +- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 +- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +- .../contentselector/model/contentmodel.cpp | 1 + components/esm/esmreader.hpp | 2 +- components/esm/inventorystate.hpp | 2 - components/esm/loadcell.hpp | 2 +- components/ogreinit/ogreplugin.cpp | 6 +- components/terrain/material.cpp | 4 +- 37 files changed, 311 insertions(+), 314 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89bf75c6c6..bd437ed616 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,7 +610,6 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list - 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 6b67cf7d5b..eef96c8c99 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -218,6 +218,8 @@ int main(int argc, char**argv) std::cout << "Invalid or no mode specified, dying horribly. Have a nice day." << std::endl; return 1; } + + return 0; } void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index c2cb8117a9..364a6b1a4a 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; MwIniImporter importer; - importer.setVerbose(vm.count("verbose") != 0); + importer.setVerbose(vm.count("verbose")); // Font encoding settings std::string encoding(vm["encoding"].as()); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 72d7f5cd88..3ef14ee7e5 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -292,264 +292,264 @@ void CSMDoc::Document::addGmsts() static const float gmstFloatsValues[] = { - 0.3f, // fAIFleeFleeMult - 7.0f, // fAIFleeHealthMult - 3.0f, // fAIMagicSpellMult - 1.0f, // fAIMeleeArmorMult - 1.0f, // fAIMeleeSummWeaponMult - 2.0f, // fAIMeleeWeaponMult - 5.0f, // fAIRangeMagicSpellMult - 5.0f, // fAIRangeMeleeWeaponMult - 2000.0f, // fAlarmRadius - 1.0f, // fAthleticsRunBonus - 40.0f, // fAudioDefaultMaxDistance - 5.0f, // fAudioDefaultMinDistance - 50.0f, // fAudioMaxDistanceMult - 20.0f, // fAudioMinDistanceMult - 60.0f, // fAudioVoiceDefaultMaxDistance - 10.0f, // fAudioVoiceDefaultMinDistance - 50.0f, // fAutoPCSpellChance - 80.0f, // fAutoSpellChance - 50.0f, // fBargainOfferBase - -4.0f, // fBargainOfferMulti - 24.0f, // fBarterGoldResetDelay - 1.75f, // fBaseRunMultiplier - 1.25f, // fBlockStillBonus - 150.0f, // fBribe1000Mod - 75.0f, // fBribe100Mod - 35.0f, // fBribe10Mod - 60.0f, // fCombatAngleXY - 60.0f, // fCombatAngleZ - 0.25f, // fCombatArmorMinMult - -90.0f, // fCombatBlockLeftAngle - 30.0f, // fCombatBlockRightAngle - 4.0f, // fCombatCriticalStrikeMult - 0.1f, // fCombatDelayCreature - 0.1f, // fCombatDelayNPC - 128.0f, // fCombatDistance - 0.3f, // fCombatDistanceWerewolfMod - 30.0f, // fCombatForceSideAngle - 0.2f, // fCombatInvisoMult - 1.5f, // fCombatKODamageMult - 45.0f, // fCombatTorsoSideAngle - 0.3f, // fCombatTorsoStartPercent - 0.8f, // fCombatTorsoStopPercent - 15.0f, // fConstantEffectMult - 72.0f, // fCorpseClearDelay - 72.0f, // fCorpseRespawnDelay - 0.5f, // fCrimeGoldDiscountMult - 0.9f, // fCrimeGoldTurnInMult - 1.0f, // fCrimeStealing - 0.5f, // fDamageStrengthBase - 0.1f, // fDamageStrengthMult - 5.0f, // fDifficultyMult - 2.5f, // fDiseaseXferChance - -10.0f, // fDispAttacking - -1.0f, // fDispBargainFailMod - 1.0f, // fDispBargainSuccessMod - 0.0f, // fDispCrimeMod - -10.0f, // fDispDiseaseMod - 3.0f, // fDispFactionMod - 1.0f, // fDispFactionRankBase - 0.5f, // fDispFactionRankMult - 1.0f, // fDispositionMod - 50.0f, // fDispPersonalityBase - 0.5f, // fDispPersonalityMult - -25.0f, // fDispPickPocketMod - 5.0f, // fDispRaceMod - -0.5f, // fDispStealing - -5.0f, // fDispWeaponDrawn - 0.5f, // fEffectCostMult - 0.1f, // fElementalShieldMult - 3.0f, // fEnchantmentChanceMult - 0.5f, // fEnchantmentConstantChanceMult - 100.0f, // fEnchantmentConstantDurationMult - 0.1f, // fEnchantmentMult - 1000.0f, // fEnchantmentValueMult - 0.3f, // fEncumberedMoveEffect - 5.0f, // fEncumbranceStrMult - 0.04f, // fEndFatigueMult - 0.25f, // fFallAcroBase - 0.01f, // fFallAcroMult - 400.0f, // fFallDamageDistanceMin - 0.0f, // fFallDistanceBase - 0.07f, // fFallDistanceMult - 2.0f, // fFatigueAttackBase - 0.0f, // fFatigueAttackMult - 1.25f, // fFatigueBase - 4.0f, // fFatigueBlockBase - 0.0f, // fFatigueBlockMult - 5.0f, // fFatigueJumpBase - 0.0f, // fFatigueJumpMult - 0.5f, // fFatigueMult - 2.5f, // fFatigueReturnBase - 0.02f, // fFatigueReturnMult - 5.0f, // fFatigueRunBase - 2.0f, // fFatigueRunMult - 1.5f, // fFatigueSneakBase - 1.5f, // fFatigueSneakMult - 0.0f, // fFatigueSpellBase - 0.0f, // fFatigueSpellCostMult - 0.0f, // fFatigueSpellMult - 7.0f, // fFatigueSwimRunBase - 0.0f, // fFatigueSwimRunMult - 2.5f, // fFatigueSwimWalkBase - 0.0f, // fFatigueSwimWalkMult - 0.2f, // fFightDispMult - 0.005f, // fFightDistanceMultiplier - 50.0f, // fFightStealing - 3000.0f, // fFleeDistance - 512.0f, // fGreetDistanceReset - 0.1f, // fHandtoHandHealthPer - 1.0f, // fHandToHandReach - 0.5f, // fHoldBreathEndMult - 20.0f, // fHoldBreathTime - 0.75f, // fIdleChanceMultiplier - 1.0f, // fIngredientMult - 0.5f, // fInteriorHeadTrackMult - 128.0f, // fJumpAcrobaticsBase - 4.0f, // fJumpAcroMultiplier - 0.5f, // fJumpEncumbranceBase - 1.0f, // fJumpEncumbranceMultiplier - 0.5f, // fJumpMoveBase - 0.5f, // fJumpMoveMult - 1.0f, // fJumpRunMultiplier - 0.5f, // fKnockDownMult - 5.0f, // fLevelMod - 0.1f, // fLevelUpHealthEndMult - 0.6f, // fLightMaxMod - 10.0f, // fLuckMod - 10.0f, // fMagesGuildTravel - 1.5f, // fMagicCreatureCastDelay - 0.0167f, // fMagicDetectRefreshRate - 1.0f, // fMagicItemConstantMult - 1.0f, // fMagicItemCostMult - 1.0f, // fMagicItemOnceMult - 1.0f, // fMagicItemPriceMult - 0.05f, // fMagicItemRechargePerSecond - 1.0f, // fMagicItemStrikeMult - 1.0f, // fMagicItemUsedMult - 3.0f, // fMagicStartIconBlink - 0.5f, // fMagicSunBlockedMult - 0.75f, // fMajorSkillBonus - 300.0f, // fMaxFlySpeed - 0.5f, // fMaxHandToHandMult - 400.0f, // fMaxHeadTrackDistance - 200.0f, // fMaxWalkSpeed - 300.0f, // fMaxWalkSpeedCreature - 0.9f, // fMedMaxMod - 0.1f, // fMessageTimePerChar - 5.0f, // fMinFlySpeed - 0.1f, // fMinHandToHandMult - 1.0f, // fMinorSkillBonus - 100.0f, // fMinWalkSpeed - 5.0f, // fMinWalkSpeedCreature - 1.25f, // fMiscSkillBonus - 2.0f, // fNPCbaseMagickaMult - 0.5f, // fNPCHealthBarFade - 3.0f, // fNPCHealthBarTime - 1.0f, // fPCbaseMagickaMult - 0.3f, // fPerDieRollMult - 5.0f, // fPersonalityMod - 1.0f, // fPerTempMult - -1.0f, // fPickLockMult - 0.3f, // fPickPocketMod - 20.0f, // fPotionMinUsefulDuration - 0.5f, // fPotionStrengthMult - 0.5f, // fPotionT1DurMult - 1.5f, // fPotionT1MagMult - 20.0f, // fPotionT4BaseStrengthMult - 12.0f, // fPotionT4EquipStrengthMult - 3000.0f, // fProjectileMaxSpeed - 400.0f, // fProjectileMinSpeed - 25.0f, // fProjectileThrownStoreChance - 3.0f, // fRepairAmountMult - 1.0f, // fRepairMult - 1.0f, // fReputationMod - 0.15f, // fRestMagicMult - 0.0f, // fSeriousWoundMult - 0.25f, // fSleepRandMod - 0.3f, // fSleepRestMod - -1.0f, // fSneakBootMult - 0.5f, // fSneakDistanceBase - 0.002f, // fSneakDistanceMultiplier - 0.5f, // fSneakNoViewMult - 1.0f, // fSneakSkillMult - 0.75f, // fSneakSpeedMultiplier - 1.0f, // fSneakUseDelay - 500.0f, // fSneakUseDist - 1.5f, // fSneakViewMult - 3.0f, // fSoulGemMult - 0.8f, // fSpecialSkillBonus - 7.0f, // fSpellMakingValueMult - 2.0f, // fSpellPriceMult - 10.0f, // fSpellValueMult - 0.25f, // fStromWalkMult - 0.7f, // fStromWindSpeed - 3.0f, // fSuffocationDamage - 0.9f, // fSwimHeightScale - 0.1f, // fSwimRunAthleticsMult - 0.5f, // fSwimRunBase - 0.02f, // fSwimWalkAthleticsMult - 0.5f, // fSwimWalkBase - 1.0f, // fSwingBlockBase - 1.0f, // fSwingBlockMult - 1000.0f, // fTargetSpellMaxSpeed - 1000.0f, // fThrownWeaponMaxSpeed - 300.0f, // fThrownWeaponMinSpeed - 0.0f, // fTrapCostMult - 4000.0f, // fTravelMult - 16000.0f,// fTravelTimeMult - 0.1f, // fUnarmoredBase1 - 0.065f, // fUnarmoredBase2 - 30.0f, // fVanityDelay - 10.0f, // fVoiceIdleOdds - 0.0f, // fWaterReflectUpdateAlways - 10.0f, // fWaterReflectUpdateSeldom - 0.1f, // fWeaponDamageMult - 1.0f, // fWeaponFatigueBlockMult - 0.25f, // fWeaponFatigueMult - 150.0f, // fWereWolfAcrobatics - 150.0f, // fWereWolfAgility - 1.0f, // fWereWolfAlchemy - 1.0f, // fWereWolfAlteration - 1.0f, // fWereWolfArmorer - 150.0f, // fWereWolfAthletics - 1.0f, // fWereWolfAxe - 1.0f, // fWereWolfBlock - 1.0f, // fWereWolfBluntWeapon - 1.0f, // fWereWolfConjuration - 1.0f, // fWereWolfDestruction - 1.0f, // fWereWolfEnchant - 150.0f, // fWereWolfEndurance - 400.0f, // fWereWolfFatigue - 100.0f, // fWereWolfHandtoHand - 2.0f, // fWereWolfHealth - 1.0f, // fWereWolfHeavyArmor - 1.0f, // fWereWolfIllusion - 1.0f, // fWereWolfIntellegence - 1.0f, // fWereWolfLightArmor - 1.0f, // fWereWolfLongBlade - 1.0f, // fWereWolfLuck - 100.0f, // fWereWolfMagicka - 1.0f, // fWereWolfMarksman - 1.0f, // fWereWolfMediumArmor - 1.0f, // fWereWolfMerchantile - 1.0f, // fWereWolfMysticism - 1.0f, // fWereWolfPersonality - 1.0f, // fWereWolfRestoration - 1.5f, // fWereWolfRunMult - 1.0f, // fWereWolfSecurity - 1.0f, // fWereWolfShortBlade - 1.5f, // fWereWolfSilverWeaponDamageMult - 1.0f, // fWereWolfSneak - 1.0f, // fWereWolfSpear - 1.0f, // fWereWolfSpeechcraft - 150.0f, // fWereWolfSpeed - 150.0f, // fWereWolfStrength - 100.0f, // fWereWolfUnarmored - 1.0f, // fWereWolfWillPower - 15.0f, // fWortChanceValue + 0.3, // fAIFleeFleeMult + 7.0, // fAIFleeHealthMult + 3.0, // fAIMagicSpellMult + 1.0, // fAIMeleeArmorMult + 1.0, // fAIMeleeSummWeaponMult + 2.0, // fAIMeleeWeaponMult + 5.0, // fAIRangeMagicSpellMult + 5.0, // fAIRangeMeleeWeaponMult + 2000.0, // fAlarmRadius + 1.0, // fAthleticsRunBonus + 40.0, // fAudioDefaultMaxDistance + 5.0, // fAudioDefaultMinDistance + 50.0, // fAudioMaxDistanceMult + 20.0, // fAudioMinDistanceMult + 60.0, // fAudioVoiceDefaultMaxDistance + 10.0, // fAudioVoiceDefaultMinDistance + 50.0, // fAutoPCSpellChance + 80.0, // fAutoSpellChance + 50.0, // fBargainOfferBase + -4.0, // fBargainOfferMulti + 24.0, // fBarterGoldResetDelay + 1.75, // fBaseRunMultiplier + 1.25, // fBlockStillBonus + 150.0, // fBribe1000Mod + 75.0, // fBribe100Mod + 35.0, // fBribe10Mod + 60.0, // fCombatAngleXY + 60.0, // fCombatAngleZ + 0.25, // fCombatArmorMinMult + -90.0, // fCombatBlockLeftAngle + 30.0, // fCombatBlockRightAngle + 4.0, // fCombatCriticalStrikeMult + 0.1, // fCombatDelayCreature + 0.1, // fCombatDelayNPC + 128.0, // fCombatDistance + 0.3, // fCombatDistanceWerewolfMod + 30.0, // fCombatForceSideAngle + 0.2, // fCombatInvisoMult + 1.5, // fCombatKODamageMult + 45.0, // fCombatTorsoSideAngle + 0.3, // fCombatTorsoStartPercent + 0.8, // fCombatTorsoStopPercent + 15.0, // fConstantEffectMult + 72.0, // fCorpseClearDelay + 72.0, // fCorpseRespawnDelay + 0.5, // fCrimeGoldDiscountMult + 0.9, // fCrimeGoldTurnInMult + 1.0, // fCrimeStealing + 0.5, // fDamageStrengthBase + 0.1, // fDamageStrengthMult + 5.0, // fDifficultyMult + 2.5, // fDiseaseXferChance + -10.0, // fDispAttacking + -1.0, // fDispBargainFailMod + 1.0, // fDispBargainSuccessMod + 0.0, // fDispCrimeMod + -10.0, // fDispDiseaseMod + 3.0, // fDispFactionMod + 1.0, // fDispFactionRankBase + 0.5, // fDispFactionRankMult + 1.0, // fDispositionMod + 50.0, // fDispPersonalityBase + 0.5, // fDispPersonalityMult + -25.0, // fDispPickPocketMod + 5.0, // fDispRaceMod + -0.5, // fDispStealing + -5.0, // fDispWeaponDrawn + 0.5, // fEffectCostMult + 0.1, // fElementalShieldMult + 3.0, // fEnchantmentChanceMult + 0.5, // fEnchantmentConstantChanceMult + 100.0, // fEnchantmentConstantDurationMult + 0.1, // fEnchantmentMult + 1000.0, // fEnchantmentValueMult + 0.3, // fEncumberedMoveEffect + 5.0, // fEncumbranceStrMult + 0.04, // fEndFatigueMult + 0.25, // fFallAcroBase + 0.01, // fFallAcroMult + 400.0, // fFallDamageDistanceMin + 0.0, // fFallDistanceBase + 0.07, // fFallDistanceMult + 2.0, // fFatigueAttackBase + 0.0, // fFatigueAttackMult + 1.25, // fFatigueBase + 4.0, // fFatigueBlockBase + 0.0, // fFatigueBlockMult + 5.0, // fFatigueJumpBase + 0.0, // fFatigueJumpMult + 0.5, // fFatigueMult + 2.5, // fFatigueReturnBase + 0.02, // fFatigueReturnMult + 5.0, // fFatigueRunBase + 2.0, // fFatigueRunMult + 1.5, // fFatigueSneakBase + 1.5, // fFatigueSneakMult + 0.0, // fFatigueSpellBase + 0.0, // fFatigueSpellCostMult + 0.0, // fFatigueSpellMult + 7.0, // fFatigueSwimRunBase + 0.0, // fFatigueSwimRunMult + 2.5, // fFatigueSwimWalkBase + 0.0, // fFatigueSwimWalkMult + 0.2, // fFightDispMult + 0.005, // fFightDistanceMultiplier + 50.0, // fFightStealing + 3000.0, // fFleeDistance + 512.0, // fGreetDistanceReset + 0.1, // fHandtoHandHealthPer + 1.0, // fHandToHandReach + 0.5, // fHoldBreathEndMult + 20.0, // fHoldBreathTime + 0.75, // fIdleChanceMultiplier + 1.0, // fIngredientMult + 0.5, // fInteriorHeadTrackMult + 128.0, // fJumpAcrobaticsBase + 4.0, // fJumpAcroMultiplier + 0.5, // fJumpEncumbranceBase + 1.0, // fJumpEncumbranceMultiplier + 0.5, // fJumpMoveBase + 0.5, // fJumpMoveMult + 1.0, // fJumpRunMultiplier + 0.5, // fKnockDownMult + 5.0, // fLevelMod + 0.1, // fLevelUpHealthEndMult + 0.6, // fLightMaxMod + 10.0, // fLuckMod + 10.0, // fMagesGuildTravel + 1.5, // fMagicCreatureCastDelay + 0.0167, // fMagicDetectRefreshRate + 1.0, // fMagicItemConstantMult + 1.0, // fMagicItemCostMult + 1.0, // fMagicItemOnceMult + 1.0, // fMagicItemPriceMult + 0.05, // fMagicItemRechargePerSecond + 1.0, // fMagicItemStrikeMult + 1.0, // fMagicItemUsedMult + 3.0, // fMagicStartIconBlink + 0.5, // fMagicSunBlockedMult + 0.75, // fMajorSkillBonus + 300.0, // fMaxFlySpeed + 0.5, // fMaxHandToHandMult + 400.0, // fMaxHeadTrackDistance + 200.0, // fMaxWalkSpeed + 300.0, // fMaxWalkSpeedCreature + 0.9, // fMedMaxMod + 0.1, // fMessageTimePerChar + 5.0, // fMinFlySpeed + 0.1, // fMinHandToHandMult + 1.0, // fMinorSkillBonus + 100.0, // fMinWalkSpeed + 5.0, // fMinWalkSpeedCreature + 1.25, // fMiscSkillBonus + 2.0, // fNPCbaseMagickaMult + 0.5, // fNPCHealthBarFade + 3.0, // fNPCHealthBarTime + 1.0, // fPCbaseMagickaMult + 0.3, // fPerDieRollMult + 5.0, // fPersonalityMod + 1.0, // fPerTempMult + -1.0, // fPickLockMult + 0.3, // fPickPocketMod + 20.0, // fPotionMinUsefulDuration + 0.5, // fPotionStrengthMult + 0.5, // fPotionT1DurMult + 1.5, // fPotionT1MagMult + 20.0, // fPotionT4BaseStrengthMult + 12.0, // fPotionT4EquipStrengthMult + 3000.0, // fProjectileMaxSpeed + 400.0, // fProjectileMinSpeed + 25.0, // fProjectileThrownStoreChance + 3.0, // fRepairAmountMult + 1.0, // fRepairMult + 1.0, // fReputationMod + 0.15, // fRestMagicMult + 0.0, // fSeriousWoundMult + 0.25, // fSleepRandMod + 0.3, // fSleepRestMod + -1.0, // fSneakBootMult + 0.5, // fSneakDistanceBase + 0.002, // fSneakDistanceMultiplier + 0.5, // fSneakNoViewMult + 1.0, // fSneakSkillMult + 0.75, // fSneakSpeedMultiplier + 1.0, // fSneakUseDelay + 500.0, // fSneakUseDist + 1.5, // fSneakViewMult + 3.0, // fSoulGemMult + 0.8, // fSpecialSkillBonus + 7.0, // fSpellMakingValueMult + 2.0, // fSpellPriceMult + 10.0, // fSpellValueMult + 0.25, // fStromWalkMult + 0.7, // fStromWindSpeed + 3.0, // fSuffocationDamage + 0.9, // fSwimHeightScale + 0.1, // fSwimRunAthleticsMult + 0.5, // fSwimRunBase + 0.02, // fSwimWalkAthleticsMult + 0.5, // fSwimWalkBase + 1.0, // fSwingBlockBase + 1.0, // fSwingBlockMult + 1000.0, // fTargetSpellMaxSpeed + 1000.0, // fThrownWeaponMaxSpeed + 300.0, // fThrownWeaponMinSpeed + 0.0, // fTrapCostMult + 4000.0, // fTravelMult + 16000.0,// fTravelTimeMult + 0.1, // fUnarmoredBase1 + 0.065, // fUnarmoredBase2 + 30.0, // fVanityDelay + 10.0, // fVoiceIdleOdds + 0.0, // fWaterReflectUpdateAlways + 10.0, // fWaterReflectUpdateSeldom + 0.1, // fWeaponDamageMult + 1.0, // fWeaponFatigueBlockMult + 0.25, // fWeaponFatigueMult + 150.0, // fWereWolfAcrobatics + 150.0, // fWereWolfAgility + 1.0, // fWereWolfAlchemy + 1.0, // fWereWolfAlteration + 1.0, // fWereWolfArmorer + 150.0, // fWereWolfAthletics + 1.0, // fWereWolfAxe + 1.0, // fWereWolfBlock + 1.0, // fWereWolfBluntWeapon + 1.0, // fWereWolfConjuration + 1.0, // fWereWolfDestruction + 1.0, // fWereWolfEnchant + 150.0, // fWereWolfEndurance + 400.0, // fWereWolfFatigue + 100.0, // fWereWolfHandtoHand + 2.0, // fWereWolfHealth + 1.0, // fWereWolfHeavyArmor + 1.0, // fWereWolfIllusion + 1.0, // fWereWolfIntellegence + 1.0, // fWereWolfLightArmor + 1.0, // fWereWolfLongBlade + 1.0, // fWereWolfLuck + 100.0, // fWereWolfMagicka + 1.0, // fWereWolfMarksman + 1.0, // fWereWolfMediumArmor + 1.0, // fWereWolfMerchantile + 1.0, // fWereWolfMysticism + 1.0, // fWereWolfPersonality + 1.0, // fWereWolfRestoration + 1.5, // fWereWolfRunMult + 1.0, // fWereWolfSecurity + 1.0, // fWereWolfShortBlade + 1.5, // fWereWolfSilverWeaponDamageMult + 1.0, // fWereWolfSneak + 1.0, // fWereWolfSpear + 1.0, // fWereWolfSpeechcraft + 150.0, // fWereWolfSpeed + 150.0, // fWereWolfStrength + 100.0, // fWereWolfUnarmored + 1.0, // fWereWolfWillPower + 15.0, // fWortChanceValue }; static const char *gmstIntegers[] = diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 9f0617eb99..201fb4342a 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -26,7 +26,7 @@ namespace ESM namespace Files { - struct ConfigurationManager; + class ConfigurationManager; } namespace CSMDoc diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 6c66f2c0ec..b969862e99 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -8,7 +8,7 @@ namespace Files { - struct ConfigurationManager; + class ConfigurationManager; } namespace CSMDoc @@ -46,4 +46,4 @@ namespace CSMDoc }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index bc477e26ae..ec6350658f 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { class IdTable; class IdTable; - struct RecordBase; + class RecordBase; class ModifyCommand : public QUndoCommand { @@ -137,4 +137,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index c5c84eedab..8b54628256 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -11,7 +11,7 @@ namespace CSMWorld { class CollectionBase; - struct RecordBase; + class RecordBase; class IdTable : public QAbstractItemModel { diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index 08024d45df..ae61f5d391 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -6,7 +6,7 @@ namespace ESM { - struct Dialogue; + class Dialogue; } namespace CSMWorld @@ -47,4 +47,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index 4c76991856..fcf016ee24 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -10,7 +10,7 @@ namespace ESM namespace CSMWorld { - struct Cell; + class Cell; /// \brief Wrapper for CellRef sub record struct CellRef : public ESM::CellRef diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index be2f5e5794..173efba05b 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -8,7 +8,7 @@ namespace CSMWorld { struct Cell; - class UniversalId; + struct UniversalId; /// \brief References in cells class RefCollection : public Collection diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 74c5dfe584..0870a2d3e6 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -9,7 +9,7 @@ namespace CSMWorld { class RefIdColumn; class RefIdData; - struct RecordBase; + class RecordBase; class RefIdAdapter { @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/view/render/lightingday.cpp b/apps/opencs/view/render/lightingday.cpp index fa2656f89c..ab0257c0c7 100644 --- a/apps/opencs/view/render/lightingday.cpp +++ b/apps/opencs/view/render/lightingday.cpp @@ -13,7 +13,7 @@ void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.7f, 0.7f, 0.7f, 1.0f)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); @@ -33,4 +33,4 @@ void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} +} \ No newline at end of file diff --git a/apps/opencs/view/render/lightingnight.cpp b/apps/opencs/view/render/lightingnight.cpp index f491717757..516bb3f408 100644 --- a/apps/opencs/view/render/lightingnight.cpp +++ b/apps/opencs/view/render/lightingnight.cpp @@ -13,12 +13,12 @@ void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager, if (defaultAmbient) mSceneManager->setAmbientLight (*defaultAmbient); else - mSceneManager->setAmbientLight (Ogre::ColourValue (0.2f, 0.2f, 0.2f, 1.0f)); + mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1)); mLight = mSceneManager->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); mLight->setDirection (Ogre::Vector3 (0, 0, -1)); - mLight->setDiffuseColour (Ogre::ColourValue (0.2f, 0.2f, 0.2f)); + mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2)); } void CSVRender::LightingNight::deactivate() @@ -33,4 +33,4 @@ void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} +} \ No newline at end of file diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index f56ba82ec9..8a58b7d328 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -42,7 +42,7 @@ namespace CSVRender mCamera->setPosition (300, 0, 0); mCamera->lookAt (0, 0, 0); - mCamera->setNearClipDistance (0.1f); + mCamera->setNearClipDistance (0.1); mCamera->setFarClipDistance (30000); mCamera->roll (Ogre::Degree (90)); @@ -104,7 +104,7 @@ namespace CSVRender #endif mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, ¶ms); - mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3f,0.3f,0.3f,1.0f)); + mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1)); Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); mCamera->setAspectRatio(aspectRatio); diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index fc00f44919..15ce2dbaf2 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (static_cast(type) >= enums.size()) + if (type<0 && type>=enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index b797a77420..52682342f7 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -767,7 +767,7 @@ public: PageDisplay () { - mPage = static_cast(-1); + mPage = -1; mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -917,7 +917,7 @@ public: else { mBook.reset (); - mPage = static_cast(-1); + mPage = -1; mViewTop = 0; mViewBottom = 0; } diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 0044583db7..a0a34108eb 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -23,7 +23,7 @@ CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* ma : WindowBase("openmw_companion_window.layout") , mDragAndDrop(dragAndDrop) , mMessageBoxManager(manager) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mModel(NULL) , mSortModel(NULL) { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8b287a10d7..5856473388 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -111,7 +111,7 @@ namespace MWGui ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window.layout") , mDragAndDrop(dragAndDrop) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mModel(NULL) , mSortModel(NULL) , mPickpocketDetected(false) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 3c6f99e68f..6c43f47b4b 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0, (~pos) + 1); + mHistory->setPosition(0,-pos); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index af631a2fe3..2bea088e32 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -38,7 +38,7 @@ namespace MWGui , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) - , mSelectedItem(static_cast(-1)) + , mSelectedItem(-1) , mGuiMode(GM_Inventory) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 82d8b1f2dc..1bb80f3d4c 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,8 +42,6 @@ namespace MWGui std::map > mEffectSources; - virtual ~EffectSourceVisitor() {} - virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 5ffa7a547f..cdc12e210e 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) - && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver + & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 6888d88a68..120616f9fe 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error&) + catch (std::logic_error& e) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 4486559ba0..0f6d782a65 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 92a49acc01..67bc75e02d 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception&) + catch (Ogre::Exception& e) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index cbe910c716..c09aa65d98 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,7 +33,6 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} - virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 7051937989..1efc796436 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception&) + catch(std::exception &e) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception&) + catch(std::exception &e) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 75f7ccae4c..c595de5aec 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception&) + catch(std::exception &e) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index b245b92414..9a3dd73422 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception&) + catch(std::exception &e) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception&) { + catch(std::exception &e) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException&) + catch(Ogre::FileNotFoundException &e) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception&) + catch(std::exception &e) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 6854358f59..8ce87a25e0 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception&) + catch(std::exception &e) { //std::cout <<"Sound Error: "< &getGameFiles() const { return mHeader.mMaster; } diff --git a/components/esm/inventorystate.hpp b/components/esm/inventorystate.hpp index 21776f683e..3cfffbccc9 100644 --- a/components/esm/inventorystate.hpp +++ b/components/esm/inventorystate.hpp @@ -14,8 +14,6 @@ namespace ESM /// \brief State for inventories and containers struct InventoryState { - virtual ~InventoryState() {} - // anything but lights (type, slot) std::vector > > mItems; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index b5eede9f5a..f01c88c65d 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -129,7 +129,7 @@ struct Cell bool hasWater() const { - return (mData.mFlags & HasWater) != 0; + return (mData.mFlags&HasWater); } // Restore the given reader to the stored position. Will try to open diff --git a/components/ogreinit/ogreplugin.cpp b/components/ogreinit/ogreplugin.cpp index 91f3fce95a..6070c43a87 100644 --- a/components/ogreinit/ogreplugin.cpp +++ b/components/ogreinit/ogreplugin.cpp @@ -30,7 +30,8 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: return false; #endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32 } -#else //!defined(DEBUG) +#endif //defined(DEBUG) + pluginPath = pluginDir + "/" + pluginName + pluginExt; if (boost::filesystem::exists(pluginPath)) { ogreRoot.loadPlugin(pluginPath); @@ -39,7 +40,6 @@ bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre:: else { return false; } -#endif } -} +} \ No newline at end of file diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index a65b6b3b1e..faa73a9864 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3u : 1u); ++i) + for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From 67e942e733fc1410b967f7be045e2e892397e0c5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 07:13:12 +0200 Subject: [PATCH 265/545] Bug #869: Some fixes to the previous fix --- apps/openmw/mwclass/creature.cpp | 4 ++++ apps/openmw/mwclass/npc.cpp | 2 ++ libs/openengine/bullet/physic.cpp | 8 +++++--- libs/openengine/bullet/physic.hpp | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 4c6ab1c75b..dc23b63f3b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -164,7 +164,11 @@ namespace MWClass { const std::string model = getModel(ptr); if(!model.empty()) + { physics.addActor(ptr); + if (getCreatureStats(ptr).isDead()) + MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false); + } MWBase::Environment::get().getMechanicsManager()->add(ptr); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4c9b683a42..214e510090 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -388,6 +388,8 @@ namespace MWClass { physics.addActor(ptr); MWBase::Environment::get().getMechanicsManager()->add(ptr); + if (getCreatureStats(ptr).isDead()) + MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false); } bool Npc::isPersistent(const MWWorld::Ptr &actor) const diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index c10892e52c..6646ce2738 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -18,6 +18,7 @@ namespace Physic PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) : mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) , mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0) + , mCollisionBody(true) , mForce(0.0f) { mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); @@ -49,8 +50,9 @@ namespace Physic void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); - if(collision && !mCollisionMode) enableCollisionBody(); - if(!collision && mCollisionMode) disableCollisionBody(); + if(collision && !mCollisionBody) enableCollisionBody(); + if(!collision && mCollisionBody) disableCollisionBody(); + mCollisionBody = collision; } void PhysicActor::setPosition(const Ogre::Vector3 &pos) @@ -108,7 +110,7 @@ namespace Physic //Create the newly scaled rigid body mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot); mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot, 0, 0, true); - mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map + mEngine->addRigidBody(mCollisionBody ? mBody : 0, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map } Ogre::Vector3 PhysicActor::getHalfExtents() const diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 4e035446ee..16eb453068 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -175,6 +175,7 @@ namespace Physic Ogre::Vector3 mForce; bool mOnGround; bool mCollisionMode; + bool mCollisionBody; std::string mMesh; std::string mName; From dfacf8c0448710c0e64dfc83789cdd86b9fa22f4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 07:14:08 +0200 Subject: [PATCH 266/545] Change ActiveSpells to use ActorId --- apps/openmw/mwgui/spellicons.cpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 +- apps/openmw/mwmechanics/activespells.cpp | 10 +++++----- apps/openmw/mwmechanics/activespells.hpp | 11 +++++------ apps/openmw/mwmechanics/actors.cpp | 19 +++++++++---------- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/character.hpp | 2 ++ apps/openmw/mwmechanics/magiceffects.hpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 6 +++--- apps/openmw/mwmechanics/spells.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 2 +- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 0cd665a871..d5ece298b0 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -21,7 +21,7 @@ namespace MWGui { void EffectSourceVisitor::visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime) { MagicEffectInfo newEffectSource; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4c..6aed8db71d 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -43,7 +43,7 @@ namespace MWGui std::map > mEffectSources; virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1); }; diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 86db207a4a..95d455edbd 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -133,7 +133,7 @@ namespace MWMechanics } void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, - const std::string &displayName, const std::string& casterHandle) + const std::string &displayName, int casterActorId) { bool exists = false; for (TContainer::const_iterator it = begin(); it != end(); ++it) @@ -146,7 +146,7 @@ namespace MWMechanics params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp(); params.mEffects = effects; params.mDisplayName = displayName; - params.mCasterHandle = casterHandle; + params.mCasterActorId = casterActorId; if (!exists || stack) mSpells.insert (std::make_pair(id, params)); @@ -178,7 +178,7 @@ namespace MWMechanics float magnitude = effectIt->mMagnitude; if (magnitude) - visitor.visit(effectIt->mKey, name, it->second.mCasterHandle, magnitude, remainingTime); + visitor.visit(effectIt->mKey, name, it->second.mCasterActorId, magnitude, remainingTime); } } } @@ -212,7 +212,7 @@ namespace MWMechanics mSpellsChanged = true; } - void ActiveSpells::purge(const std::string &actorHandle) + void ActiveSpells::purge(int casterActorId) { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { @@ -221,7 +221,7 @@ namespace MWMechanics { const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mKey.mId); if (effect->mData.mFlags & ESM::MagicEffect::CasterLinked - && it->second.mCasterHandle == actorHandle) + && it->second.mCasterActorId == casterActorId) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 7a40afb4cb..5f36cea2c2 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -37,8 +37,8 @@ namespace MWMechanics MWWorld::TimeStamp mTimeStamp; std::string mDisplayName; - // Handle to the caster that that inflicted this spell on us - std::string mCasterHandle; + // The caster that inflicted this spell on us + int mCasterActorId; }; typedef std::multimap TContainer; @@ -76,10 +76,9 @@ namespace MWMechanics /// \param stack If false, the spell is not added if one with the same ID exists already. /// \param effects /// \param displayName Name for display in magic menu. - /// \param casterHandle /// void addSpell (const std::string& id, bool stack, std::vector effects, - const std::string& displayName, const std::string& casterHandle); + const std::string& displayName, int casterActorId); /// Removes the active effects from this spell/potion/.. with \a id void removeEffects (const std::string& id); @@ -90,8 +89,8 @@ namespace MWMechanics /// Remove all active effects, if roll succeeds (for each effect) void purgeAll (float chance); - /// Remove all effects with CASTER_LINKED flag that were cast by \a actorHandle - void purge (const std::string& actorHandle); + /// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId + void purge (int casterActorId); bool isSpellActive (std::string id) const; ///< case insensitive diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 22d033f408..e0db094d1a 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -119,7 +119,7 @@ namespace MWMechanics : mCreature(trappedCreature) {} virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1) { if (key.mId != ESM::MagicEffect::Soultrap) @@ -129,7 +129,7 @@ namespace MWMechanics MWBase::World* world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr caster = world->searchPtrViaHandle(casterHandle); + MWWorld::Ptr caster = world->searchPtrViaActorId(casterActorId); if (caster.isEmpty() || !caster.getClass().isActor()) return; @@ -938,18 +938,17 @@ namespace MWMechanics continue; } - // Make sure spell effects with CasterLinked flag are removed - // TODO: would be nice not to do this all the time... - for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) - { - MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); - spells.purge(iter->first.getRefData().getHandle()); - } - if (iter->second->kill()) { ++mDeathCount[cls.getId(iter->first)]; + // Make sure spell effects with CasterLinked flag are removed + for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) + { + MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); + spells.purge(stats.getActorId()); + } + // Apply soultrap if (iter->first.getTypeName() == typeid(ESM::Creature).name()) { diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2b8b6eccb9..bf8ce8bdc0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1372,9 +1372,9 @@ bool CharacterController::kill() { if( isDead() ) { - //player's death animation is over if( mPtr.getRefData().getHandle()=="player" && !isAnimPlaying(mCurrentDeath) ) { + //player's death animation is over MWBase::Environment::get().getStateManager()->askLoadRecent(); } return false; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 5aea0210f2..1b7caf34d7 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -202,7 +202,9 @@ public: void skipAnim(); bool isAnimPlaying(const std::string &groupName); + /// @return false if the character has already been killed before bool kill(); + void resurrect(); bool isDead() const { return mDeathState != CharState_None; } diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 45abda21d9..4fd5e159aa 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -56,7 +56,7 @@ namespace MWMechanics struct EffectSourceVisitor { virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& casterHandle, + const std::string& sourceName, int casterActorId, float magnitude, float remainingTime = -1) = 0; }; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index d510373ff2..cb02d46559 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -349,9 +349,9 @@ namespace MWMechanics ActiveSpells::Effect effect_ = effect; effect_.mMagnitude *= -1; effects.push_back(effect_); - // Also make sure to set casterHandle = target, so that the effect on the caster gets purged when the target dies + // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, - effects, mSourceName, target.getRefData().getHandle()); + effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); } } } @@ -409,7 +409,7 @@ namespace MWMechanics if (!appliedLastingEffects.empty()) target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, - mSourceName, caster.getRefData().getHandle()); + mSourceName, caster.getClass().getCreatureStats(caster).getActorId()); // Notify the target actor they've been hit if (anyHarmfulEffect && target.getClass().isActor() && target != caster) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index a326b7a6d1..dee1a1b05d 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -211,7 +211,7 @@ namespace MWMechanics random = it->second.at(i); float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; - visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude); + visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, -1, magnitude); } } } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index b18bda5e33..7127c92f3f 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -599,7 +599,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i]; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom; magnitude *= params.mMultiplier; - visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), "", magnitude); + visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), -1, magnitude); ++i; } From cbcf0f60399e5ca59513a8dcf189c3af040c7b45 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 01:44:11 -0400 Subject: [PATCH 267/545] Changed AiEScort to use new PathTo function --- apps/openmw/mwmechanics/aiescort.cpp | 57 +-------------------------- apps/openmw/mwmechanics/aipackage.cpp | 6 ++- apps/openmw/mwmechanics/aipackage.hpp | 1 + components/esm/loadpgrd.hpp | 1 + 4 files changed, 9 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index f27fada39f..0430adf06a 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -75,58 +75,6 @@ namespace MWMechanics return true; } - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - ESM::Position pos = actor.getRefData().getPosition(); - bool cellChange = actor.getCell()->getCell()->mData.mX != mCellX || actor.getCell()->getCell()->mData.mY != mCellY; - - if(actor.getCell()->getCell()->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(actor.getCell()->getCell()->mData.mX - player.getCell()->getCell()->mData.mX); - // Check if actor is near the border of an inactive cell. If so, pause walking. - if(sideX * (pos.pos[0] - actor.getCell()->getCell()->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / - 2.0 - 200)) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return false; - } - } - if(actor.getCell()->getCell()->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(actor.getCell()->getCell()->mData.mY - player.getCell()->getCell()->mData.mY); - // Check if actor is near the border of an inactive cell. If so, pause walking. - if(sideY*(pos.pos[1] - actor.getCell()->getCell()->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / - 2.0 - 200)) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return false; - } - } - - - if(!mPathFinder.isPathConstructed() || cellChange) - { - mCellX = actor.getCell()->getCell()->mData.mX; - mCellY = actor.getCell()->getCell()->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = mX; - dest.mY = mY; - dest.mZ = mZ; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return true; - } - const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); const float* const leaderPos = actor.getRefData().getPosition().pos; const float* const followerPos = follower.getRefData().getPosition().pos; @@ -141,9 +89,8 @@ namespace MWMechanics if(distanceBetweenResult <= mMaxDist * mMaxDist) { - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; + if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete + return true; mMaxDist = 470; } else diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index c2e8385b82..5e16ebdc8f 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -69,7 +69,11 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //*********************** if(mTimer > 0.25) { - mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved + mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + mPrevDest = dest; + } + if(!mPathFinder.getPath().empty()) //Path has points in it { ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index bb62a2543a..055958384a 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -67,6 +67,7 @@ namespace MWMechanics MWWorld::Ptr mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; + ESM::Pathgrid::Point mPrevDest; }; } diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 9262334442..60a7369917 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -34,6 +34,7 @@ struct Pathgrid Point& operator=(const float[3]); Point(const float[3]); Point(); + Point(int x, int y, int z) : mX(x), mY(y), mZ(z) {} }; // 16 bytes struct Edge // path grid edge From 51020fdb5fb2a95ec9339a331e68d04bc831f858 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:17:30 +0200 Subject: [PATCH 268/545] Fix a bug for NpcStats::mUsedIds in savegames, and added a compile-time guard to prevent similar errors in the future. --- components/esm/esmwriter.hpp | 12 ++++++++++++ components/esm/npcstats.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index 57faefdf4e..ca4f422172 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -74,6 +74,18 @@ class ESMWriter endRecord(name); } +private: + // Prevent using writeHNT with strings. This already happened by accident and results in + // state being discarded without any error on writing or reading it. :( + // writeHNString and friends must be used instead. + void writeHNT(const std::string &name, std::string data) + { + } + void writeT(const std::string& data) + { + } +public: + template void writeHNT(const std::string& name, const T& data, int size) { diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 21f573bc74..3fa954182c 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -140,7 +140,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const for (std::vector::const_iterator iter (mUsedIds.begin()); iter!=mUsedIds.end(); ++iter) - esm.writeHNT ("USED", *iter); + esm.writeHNString ("USED", *iter); if (mTimeToStartDrowning) esm.writeHNT ("DRTI", mTimeToStartDrowning); From 61187c2fef662a9fe0217609e6e81d3b0cfd1373 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:47:49 +0200 Subject: [PATCH 269/545] Savegame: store actorIds --- apps/openmw/mwmechanics/creaturestats.cpp | 14 ++++++++++++++ apps/openmw/mwmechanics/creaturestats.hpp | 3 +++ apps/openmw/mwstate/statemanagerimp.cpp | 1 + apps/openmw/mwworld/worldimp.cpp | 12 +++++++++++- components/esm/creaturestats.cpp | 6 ++++++ components/esm/creaturestats.hpp | 1 + components/esm/defs.hpp | 1 + 7 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 9bfea41f34..80f81ffd1d 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -501,6 +501,7 @@ namespace MWMechanics state.mRecalcDynamicStats = mRecalcDynamicStats; state.mDrawState = mDrawState; state.mLevel = mLevel; + state.mActorId = mActorId; mSpells.writeState(state.mSpells); } @@ -538,6 +539,7 @@ namespace MWMechanics mRecalcDynamicStats = state.mRecalcDynamicStats; mDrawState = DrawState_(state.mDrawState); mLevel = state.mLevel; + mActorId = state.mActorId; mSpells.readState(state.mSpells); } @@ -579,4 +581,16 @@ namespace MWMechanics { sActorId = 0; } + + void CreatureStats::writeActorIdCounter (ESM::ESMWriter& esm) + { + esm.startRecord(ESM::REC_ACTC); + esm.writeHNT("COUN", sActorId); + esm.endRecord(ESM::REC_ACTC); + } + + void CreatureStats::readActorIdCounter (ESM::ESMReader& esm) + { + esm.getHNT(sActorId, "COUN"); + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 79686bb978..7d2dc1a62a 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -238,6 +238,9 @@ namespace MWMechanics void readState (const ESM::CreatureStats& state); + static void writeActorIdCounter (ESM::ESMWriter& esm); + static void readActorIdCounter (ESM::ESMReader& esm); + // Relates to NPC gold reset delay void setTradeTime(MWWorld::TimeStamp tradeTime); MWWorld::TimeStamp getTradeTime() const; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d261fe0c0f..f2cda5a018 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -318,6 +318,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_CSTA: case ESM::REC_WTHR: case ESM::REC_DYNA: + case ESM::REC_ACTC: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e07ee9df83..e223435dd2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -274,7 +274,8 @@ namespace MWWorld +mStore.countSavedGameRecords() +mGlobalVariables.countSavedGameRecords() +1 // player record - +1; // weather record + +1 // weather record + +1; // actorId counter } void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const @@ -287,6 +288,9 @@ namespace MWWorld mRendering->writeFog(cellstore); } + MWMechanics::CreatureStats::writeActorIdCounter(writer); + progress.increaseProgress(); + mCells.write (writer, progress); mStore.write (writer, progress); mGlobalVariables.write (writer, progress); @@ -297,6 +301,12 @@ namespace MWWorld void World::readRecord (ESM::ESMReader& reader, int32_t type, const std::map& contentFileMap) { + if (type == ESM::REC_ACTC) + { + MWMechanics::CreatureStats::readActorIdCounter(reader); + return; + } + if (!mStore.readRecord (reader, type) && !mGlobalVariables.readRecord (reader, type) && !mPlayer->readRecord (reader, type) && diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 5bb6de6626..e512ca5f8d 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -72,6 +72,9 @@ void ESM::CreatureStats::load (ESMReader &esm) mLevel = 1; esm.getHNOT (mLevel, "LEVL"); + mActorId = -1; + esm.getHNOT (mActorId, "ACID"); + mSpells.load(esm); } @@ -146,5 +149,8 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (mLevel != 1) esm.writeHNT ("LEVL", mLevel); + if (mActorId != -1) + esm.writeHNT ("ACID", mActorId); + mSpells.save(esm); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 2cf2c5b4f8..4c4c44b3f0 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -24,6 +24,7 @@ namespace ESM ESM::TimeStamp mTradeTime; int mGoldPool; + int mActorId; bool mDead; bool mDied; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 9ef4dabd21..6c388de08c 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -108,6 +108,7 @@ enum RecNameInts REC_KEYS = FourCC<'K','E','Y','S'>::value, REC_DYNA = FourCC<'D','Y','N','A'>::value, REC_ASPL = FourCC<'A','S','P','L'>::value, + REC_ACTC = FourCC<'A','C','T','C'>::value, // format 1 REC_FILT = 0x544C4946 From 1141c1f3f279dea2ab446e5cc3f757d1f7ca4fe1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 09:48:16 +0200 Subject: [PATCH 270/545] Change projectiles to use actorIds --- apps/openmw/mwworld/worldimp.cpp | 10 +++++----- apps/openmw/mwworld/worldimp.hpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e223435dd2..947de0e4da 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2223,7 +2223,7 @@ namespace MWWorld const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) { ProjectileState state; - state.mActorHandle = actor.getRefData().getHandle(); + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mBow = bow; state.mVelocity = orient.yAxis() * speed; @@ -2310,7 +2310,7 @@ namespace MWWorld MagicBoltState state; state.mSourceName = sourceName; state.mId = id; - state.mActorHandle = actor.getRefData().getHandle(); + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mSpeed = speed; state.mStack = stack; @@ -2374,7 +2374,7 @@ namespace MWWorld if (obstacle == ptr) continue; - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); // Arrow intersects with player immediately after shooting :/ if (obstacle == caster) @@ -2460,7 +2460,7 @@ namespace MWWorld if (obstacle == ptr) continue; - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); if (caster.isEmpty()) caster = obstacle; @@ -2483,7 +2483,7 @@ namespace MWWorld if (explode) { - MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle); + MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); explodeSpell(Ogre::Vector3(ptr.getRefData().getPosition().pos), ptr, it->second.mEffects, caster, it->second.mId, it->second.mSourceName); deleteObject(ptr); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 2328e67a8b..953045fa2b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -96,7 +96,7 @@ namespace MWWorld std::string mId; // Actor who casted this projectile - std::string mActorHandle; + int mActorId; // Name of item to display as effect source in magic menu (in case we casted an enchantment) std::string mSourceName; @@ -111,7 +111,7 @@ namespace MWWorld struct ProjectileState { // Actor who shot this projectile - std::string mActorHandle; + int mActorId; MWWorld::Ptr mBow; // bow or crossbow the projectile was fired from From 993ef1be4340dbbc6203c75342c6d5fe629d37ef Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 04:05:18 -0400 Subject: [PATCH 271/545] Actor avoiding door asks all surrounding actors to do the same. --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 13 +++++++++++++ apps/openmw/mwworld/worldimp.cpp | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 375e8fae7f..c6ecc08bf3 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -6,6 +6,7 @@ #include "../mwworld/cellstore.hpp" #include "creaturestats.hpp" #include "movement.hpp" +#include "mechanicsmanagerimp.hpp" #include @@ -44,6 +45,18 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration actor.getClass().getMovementSettings(actor).mPosition[1] = -1 * std::sin(dirToDoor); //I knew I'd use trig someday actor.getClass().getMovementSettings(actor).mPosition[0] = -1 * std::cos(dirToDoor); + //Make all nearby actors also avoid the door + std::vector actors; + MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),50,actors); + for(std::vector::iterator it = actors.begin(); it != actors.end(); it++) { + if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player + MWMechanics::AiSequence& seq = MWWorld::Class::get(*it).getCreatureStats(*it).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr),*it); + } + } + } + return false; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 96dd91f821..99589b6101 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1209,15 +1209,16 @@ namespace MWWorld for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor()) + if (MWWorld::Class::get(ptr).isActor() && ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { // Collided with actor, ask actor to try to avoid door MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); - break; + //break; //Removed in case ultiple actors are touching } } From 343990023990af7c52132b86a1c958283315274f Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Wed, 14 May 2014 11:56:23 +0200 Subject: [PATCH 272/545] ignore all drops that will not create usefull filter --- apps/opencs/view/world/tablesubview.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a5a7e8252e..8da300aba8 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -110,13 +110,17 @@ void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::Univers { std::vector > > filterSource; - for (std::vector::iterator it = types.begin(); it != types.end(); ++it) + for (std::vector::iterator it(types.begin()); it != types.end(); ++it) { std::pair > pair( //splited long line - std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType())))); + std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType())))); - filterSource.push_back(pair); + if(!pair.second.empty()) + { + filterSource.push_back(pair); + } } + mFilterBox->createFilterRequest(filterSource, action); } From 2425d2c2abb27310452343f26bccb9e74a3138d2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 13:38:10 -0400 Subject: [PATCH 273/545] Added stuck mitigation for AiAvoidDoor --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 39 ++++++++++++++++--------- apps/openmw/mwmechanics/aiavoiddoor.hpp | 4 ++- apps/openmw/mwworld/worldimp.cpp | 12 ++++---- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index c6ecc08bf3..26865aea40 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -13,32 +13,45 @@ #include "steering.hpp" MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr) -: AiPackage(), mDoorPtr(doorPtr), mDuration(1) +: AiPackage(), mDoorPtr(doorPtr), mDuration(1), mAdjAngle(0) { + } bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration) { + + ESM::Position pos = actor.getRefData().getPosition(); + if(mDuration = 1) //If it just started, get the actor position as the stuck detection thing + mLastPos = pos; + mDuration -= duration; //Update timer - if(mDuration < 0) - return true; // We have tried backing up for more than one second, we've probably cleared it + if(mDuration < 0) { + float x = pos.pos[0] - mLastPos.pos[0]; + float y = pos.pos[1] - mLastPos.pos[1]; + float z = pos.pos[2] - mLastPos.pos[2]; + int distance = x * x + y * y + z * z; + if(distance < 10 * 10) { //Got stuck, didn't move + if(mAdjAngle == 0) //Try going in various directions + mAdjAngle = 1.57079632679f; //pi/2 + else if (mAdjAngle == 1.57079632679f) + mAdjAngle = -1.57079632679; + else + mAdjAngle = 0; + mDuration = 1; //reset timer + } + else //Not stuck + return true; // We have tried backing up for more than one second, we've probably cleared it + } if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) return true; //Door is no longer opening - ESM::Position pos = actor.getRefData().getPosition(); //position of the actor ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door float x = pos.pos[0] - tPos.pos[0]; float y = pos.pos[1] - tPos.pos[1]; - float z = pos.pos[2] - tPos.pos[2]; - int distance = sqrt(x * x + y * y + z * z); - - if(distance > 300) //Stop backing up when you're far enough away - return true; -/// TODO: Calculate this from door size, not have it built in - - float dirToDoor = std::atan2(x,y) + pos.rot[2]; //Calculates the direction to the door, relative to the direction of the NPC + float dirToDoor = std::atan2(x,y) + pos.rot[2] + mAdjAngle; //Calculates the direction to the door, relative to the direction of the NPC // For example, if the NPC is directly facing the door this will be pi/2 // Make actor move away from the door @@ -47,7 +60,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration //Make all nearby actors also avoid the door std::vector actors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),50,actors); + MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors); for(std::vector::iterator it = actors.begin(); it != actors.end(); it++) { if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player MWMechanics::AiSequence& seq = MWWorld::Class::get(*it).getCreatureStats(*it).getAiSequence(); diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 8d225655a0..85bb09fc83 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -29,7 +29,9 @@ namespace MWMechanics private: float mDuration; - const MWWorld::Ptr& mDoorPtr; + const MWWorld::Ptr& mDoorPtr; + ESM::Position mLastPos; + float mAdjAngle; }; } #endif diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 99589b6101..a3b9e64d35 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1209,16 +1209,18 @@ namespace MWWorld for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor() && ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) + if (MWWorld::Class::get(ptr).isActor()) { // Collided with actor, ask actor to try to avoid door - MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); - if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once - seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { + MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + } // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); - //break; //Removed in case ultiple actors are touching + //break; //Removed in case multiple actors are touching } } From d2aada95b44785ee41092ec37a0e4a2d8ddaeb17 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 May 2014 14:11:34 -0400 Subject: [PATCH 274/545] Fixed AiPursue by fixing underlying issue is Pathto() --- apps/openmw/mwmechanics/aiactivate.cpp | 1 - apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwmechanics/aifollow.cpp | 7 +++---- apps/openmw/mwmechanics/aipackage.cpp | 3 ++- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 56c155ded0..4b4b36ed65 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -37,7 +37,6 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) } else { pathTo(actor, dest, duration); //Go to the destination - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; } return false; diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 26865aea40..a206d27ca0 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -22,7 +22,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration { ESM::Position pos = actor.getRefData().getPosition(); - if(mDuration = 1) //If it just started, get the actor position as the stuck detection thing + if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing mLastPos = pos; mDuration -= duration; //Update timer diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 8d9e019394..f1296a9493 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -58,12 +58,11 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - pathTo(actor, dest, duration); //Go to the destination - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - else - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + else { + pathTo(actor, dest, duration); //Go to the destination + } //Check if you're far away if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) > 1000) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 5e16ebdc8f..2a2f4fdc86 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,7 +16,7 @@ MWMechanics::AiPackage::~AiPackage() {} -MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(0), mStuckTimer(0) { +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(MWWorld::Ptr()), mTimer(.26), mStuckTimer(0) { //mTimer starts at .26 to force initial pathbuild } @@ -118,6 +118,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po mStuckTimer = 0; mStuckPos = pos; mLastDoorChecked = MWWorld::Ptr(); //Resets it, in case he gets stuck behind the door again + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward } } else { From 9052cc4a57c3bddefb2a8692d149c0a2947eaeed Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 14 May 2014 22:16:39 +0200 Subject: [PATCH 275/545] Savegame: store ActiveSpells --- apps/openmw/mwclass/npc.cpp | 3 +- apps/openmw/mwmechanics/activespells.cpp | 61 ++++++++++++++++++----- apps/openmw/mwmechanics/activespells.hpp | 21 ++++---- apps/openmw/mwmechanics/actors.cpp | 1 + apps/openmw/mwmechanics/creaturestats.cpp | 4 +- apps/openmw/mwmechanics/spellcasting.cpp | 12 +++-- components/CMakeLists.txt | 2 +- components/esm/activespells.cpp | 56 +++++++++++++++++++++ components/esm/activespells.hpp | 45 +++++++++++++++++ components/esm/creaturestats.cpp | 3 +- components/esm/creaturestats.hpp | 2 + 11 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 components/esm/activespells.cpp create mode 100644 components/esm/activespells.hpp diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 214e510090..845fffbc0d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -620,7 +620,8 @@ namespace MWClass // NOTE: 'object' and/or 'attacker' may be empty. // Attacking peaceful NPCs is a crime - if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) + // anything below 80 is considered peaceful (see Actors::updateActor) + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); getCreatureStats(ptr).setAttacked(true); diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 95d455edbd..e64a736c3f 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -53,9 +53,9 @@ namespace MWMechanics { const MWWorld::TimeStamp& start = iter->second.mTimeStamp; - const std::vector& effects = iter->second.mEffects; + const std::vector& effects = iter->second.mEffects; - for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) { int duration = effectIt->mDuration; MWWorld::TimeStamp end = start; @@ -63,7 +63,7 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); if (end>now) - mEffects.add(effectIt->mKey, MWMechanics::EffectParam(effectIt->mMagnitude)); + mEffects.add(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), MWMechanics::EffectParam(effectIt->mMagnitude)); } } } @@ -91,11 +91,11 @@ namespace MWMechanics double ActiveSpells::timeToExpire (const TIterator& iterator) const { - const std::vector& effects = iterator->second.mEffects; + const std::vector& effects = iterator->second.mEffects; int duration = 0; - for (std::vector::const_iterator iter (effects.begin()); + for (std::vector::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) { if (iter->mDuration > duration) @@ -132,7 +132,7 @@ namespace MWMechanics return mSpells; } - void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, + void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, const std::string &displayName, int casterActorId) { bool exists = false; @@ -168,7 +168,7 @@ namespace MWMechanics { float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); - for (std::vector::const_iterator effectIt = it->second.mEffects.begin(); + for (std::vector::const_iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end(); ++effectIt) { std::string name = it->second.mDisplayName; @@ -178,7 +178,7 @@ namespace MWMechanics float magnitude = effectIt->mMagnitude; if (magnitude) - visitor.visit(effectIt->mKey, name, it->second.mCasterActorId, magnitude, remainingTime); + visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->second.mCasterActorId, magnitude, remainingTime); } } } @@ -200,10 +200,10 @@ namespace MWMechanics { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { - for (std::vector::iterator effectIt = it->second.mEffects.begin(); + for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - if (effectIt->mKey.mId == effectId) + if (effectIt->mEffectId == effectId) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; @@ -216,10 +216,10 @@ namespace MWMechanics { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { - for (std::vector::iterator effectIt = it->second.mEffects.begin(); + for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mKey.mId); + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mEffectId); if (effect->mData.mFlags & ESM::MagicEffect::CasterLinked && it->second.mCasterActorId == casterActorId) effectIt = it->second.mEffects.erase(effectIt); @@ -229,4 +229,41 @@ namespace MWMechanics } mSpellsChanged = true; } + + void ActiveSpells::clear() + { + mSpells.clear(); + mSpellsChanged = true; + } + + void ActiveSpells::writeState(ESM::ActiveSpells &state) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + // Stupid copying of almost identical structures. ESM::TimeStamp <-> MWWorld::TimeStamp + ESM::ActiveSpells::ActiveSpellParams params; + params.mEffects = it->second.mEffects; + params.mCasterActorId = it->second.mCasterActorId; + params.mDisplayName = it->second.mDisplayName; + params.mTimeStamp = it->second.mTimeStamp.toEsm(); + + state.mSpells.insert (std::make_pair(it->first, params)); + } + } + + void ActiveSpells::readState(const ESM::ActiveSpells &state) + { + for (ESM::ActiveSpells::TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it) + { + // Stupid copying of almost identical structures. ESM::TimeStamp <-> MWWorld::TimeStamp + ActiveSpellParams params; + params.mEffects = it->second.mEffects; + params.mCasterActorId = it->second.mCasterActorId; + params.mDisplayName = it->second.mDisplayName; + params.mTimeStamp = MWWorld::TimeStamp(it->second.mTimeStamp); + + mSpells.insert (std::make_pair(it->first, params)); + mSpellsChanged = true; + } + } } diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 5f36cea2c2..6c4c93128f 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -10,6 +10,7 @@ #include "magiceffects.hpp" #include +#include namespace MWMechanics { @@ -21,19 +22,11 @@ namespace MWMechanics { public: - // Parameters of an effect concerning lasting effects. - // Note we are not using ENAMstruct since the magnitude may be modified by magic resistance, etc. - // It could also be a negative magnitude, in case of inversing an effect, e.g. Absorb spell causes damage on target, but heals the caster. - struct Effect - { - float mMagnitude; - EffectKey mKey; - float mDuration; - }; + typedef ESM::ActiveEffect ActiveEffect; struct ActiveSpellParams { - std::vector mEffects; + std::vector mEffects; MWWorld::TimeStamp mTimeStamp; std::string mDisplayName; @@ -44,6 +37,9 @@ namespace MWMechanics typedef std::multimap TContainer; typedef TContainer::const_iterator TIterator; + void readState (const ESM::ActiveSpells& state); + void writeState (ESM::ActiveSpells& state) const; + private: mutable TContainer mSpells; @@ -77,7 +73,7 @@ namespace MWMechanics /// \param effects /// \param displayName Name for display in magic menu. /// - void addSpell (const std::string& id, bool stack, std::vector effects, + void addSpell (const std::string& id, bool stack, std::vector effects, const std::string& displayName, int casterActorId); /// Removes the active effects from this spell/potion/.. with \a id @@ -92,6 +88,9 @@ namespace MWMechanics /// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId void purge (int casterActorId); + /// Remove all spells + void clear(); + bool isSpellActive (std::string id) const; ///< case insensitive diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e0db094d1a..79a90c4d33 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -959,6 +959,7 @@ namespace MWMechanics // Reset magic effects and recalculate derived effects // One case where we need this is to make sure bound items are removed upon death stats.setMagicEffects(MWMechanics::MagicEffects()); + stats.getActiveSpells().clear(); calculateCreatureStatModifiers(iter->first, 0); MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 80f81ffd1d..57618e6e93 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -496,7 +496,7 @@ namespace MWMechanics state.mBlock = mBlock; state.mMovementFlags = mMovementFlags; state.mAttackStrength = mAttackStrength; - state.mFallHeight = mFallHeight; + state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?) state.mLastHitObject = mLastHitObject; state.mRecalcDynamicStats = mRecalcDynamicStats; state.mDrawState = mDrawState; @@ -504,6 +504,7 @@ namespace MWMechanics state.mActorId = mActorId; mSpells.writeState(state.mSpells); + mActiveSpells.writeState(state.mActiveSpells); } void CreatureStats::readState (const ESM::CreatureStats& state) @@ -542,6 +543,7 @@ namespace MWMechanics mActorId = state.mActorId; mSpells.readState(state.mSpells); + mActiveSpells.readState(state.mActiveSpells); } // Relates to NPC gold reset delay diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index cb02d46559..553674dd3d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -222,7 +222,7 @@ namespace MWMechanics } ESM::EffectList reflectedEffects; - std::vector appliedLastingEffects; + std::vector appliedLastingEffects; bool firstAppliedEffect = true; bool anyHarmfulEffect = false; @@ -332,8 +332,9 @@ namespace MWMechanics bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); if (target.getClass().isActor() && hasDuration) { - ActiveSpells::Effect effect; - effect.mKey = MWMechanics::EffectKey(*effectIt); + ActiveSpells::ActiveEffect effect; + effect.mEffectId = effectIt->mEffectID; + effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; effect.mDuration = effectIt->mDuration; effect.mMagnitude = magnitude; @@ -345,8 +346,8 @@ namespace MWMechanics { if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) { - std::vector effects; - ActiveSpells::Effect effect_ = effect; + std::vector effects; + ActiveSpells::ActiveEffect effect_ = effect; effect_.mMagnitude *= -1; effects.push_back(effect_); // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies @@ -392,6 +393,7 @@ namespace MWMechanics else castStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_DefaultHit"); + // TODO: VFX are no longer active after saving/reloading the game bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; // Note: in case of non actor, a free effect should be fine as well MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 5332880485..90570b260d 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells ) add_component_dir (misc diff --git a/components/esm/activespells.cpp b/components/esm/activespells.cpp new file mode 100644 index 0000000000..4f51a619ee --- /dev/null +++ b/components/esm/activespells.cpp @@ -0,0 +1,56 @@ +#include "activespells.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void ActiveSpells::save(ESMWriter &esm) const + { + for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + { + esm.writeHNString ("ID__", it->first); + + const ActiveSpellParams& params = it->second; + + esm.writeHNT ("CAST", params.mCasterActorId); + esm.writeHNString ("DISP", params.mDisplayName); + esm.writeHNT ("TIME", params.mTimeStamp); + + for (std::vector::const_iterator effectIt = params.mEffects.begin(); effectIt != params.mEffects.end(); ++effectIt) + { + esm.writeHNT ("MGEF", effectIt->mEffectId); + if (effectIt->mArg != -1) + esm.writeHNT ("ARG_", effectIt->mArg); + esm.writeHNT ("MAGN", effectIt->mMagnitude); + esm.writeHNT ("DURA", effectIt->mDuration); + } + } + } + + void ActiveSpells::load(ESMReader &esm) + { + while (esm.isNextSub("ID__")) + { + std::string spellId = esm.getHString(); + + ActiveSpellParams params; + esm.getHNT (params.mCasterActorId, "CAST"); + params.mDisplayName = esm.getHNString ("DISP"); + esm.getHNT (params.mTimeStamp, "TIME"); + + while (esm.isNextSub("MGEF")) + { + ActiveEffect effect; + esm.getHT(effect.mEffectId); + effect.mArg = -1; + esm.getHNOT(effect.mArg, "ARG_"); + esm.getHNT (effect.mMagnitude, "MAGN"); + esm.getHNT (effect.mDuration, "DURA"); + params.mEffects.push_back(effect); + } + mSpells.insert(std::make_pair(spellId, params)); + } + } +} diff --git a/components/esm/activespells.hpp b/components/esm/activespells.hpp new file mode 100644 index 0000000000..d9e9a8c633 --- /dev/null +++ b/components/esm/activespells.hpp @@ -0,0 +1,45 @@ +#ifndef OPENMW_ESM_ACTIVESPELLS_H +#define OPENMW_ESM_ACTIVESPELLS_H + +#include "effectlist.hpp" +#include "defs.hpp" + +#include +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + // Parameters of an effect concerning lasting effects. + // Note we are not using ENAMstruct since the magnitude may be modified by magic resistance, etc. + // It could also be a negative magnitude, in case of inversing an effect, e.g. Absorb spell causes damage on target, but heals the caster. + struct ActiveEffect + { + int mEffectId; + float mMagnitude; + int mArg; // skill or attribute + float mDuration; + }; + + // format 0, saved games only + struct ActiveSpells + { + struct ActiveSpellParams + { + std::vector mEffects; + ESM::TimeStamp mTimeStamp; + std::string mDisplayName; + int mCasterActorId; + }; + + typedef std::multimap TContainer; + TContainer mSpells; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; +} + +#endif diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index e512ca5f8d..66d8481240 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -1,4 +1,3 @@ - #include "creaturestats.hpp" void ESM::CreatureStats::load (ESMReader &esm) @@ -76,6 +75,7 @@ void ESM::CreatureStats::load (ESMReader &esm) esm.getHNOT (mActorId, "ACID"); mSpells.load(esm); + mActiveSpells.load(esm); } void ESM::CreatureStats::save (ESMWriter &esm) const @@ -153,4 +153,5 @@ void ESM::CreatureStats::save (ESMWriter &esm) const esm.writeHNT ("ACID", mActorId); mSpells.save(esm); + mActiveSpells.save(esm); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 4c4c44b3f0..7814d937ae 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -10,6 +10,7 @@ #include "defs.hpp" #include "spellstate.hpp" +#include "activespells.hpp" namespace ESM { @@ -49,6 +50,7 @@ namespace ESM int mLevel; SpellState mSpells; + ActiveSpells mActiveSpells; void load (ESMReader &esm); void save (ESMWriter &esm) const; From f33559fead33e19ad6f14e1934400ac7367e4b1a Mon Sep 17 00:00:00 2001 From: slothlife Date: Wed, 14 May 2014 20:12:52 -0500 Subject: [PATCH 276/545] Fixes for MSVC warnings, less overall changes Kept some fixes from the first round of review. Found out that several targets weren't being built with the same basic warnings disabled. Disabled a few warnings for external libraries specifically, rather than applying them to all targets. --- CMakeLists.txt | 23 +++++++++++--- apps/opencs/view/world/vartypedelegate.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 30 +++++++++++++++---- apps/openmw/mwgui/companionwindow.hpp | 2 +- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/spellicons.hpp | 2 ++ apps/openmw/mwmechanics/combat.cpp | 4 +-- apps/openmw/mwmechanics/levelledlist.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 2 +- apps/openmw/mwrender/weaponanimation.hpp | 1 + .../mwscript/transformationextensions.cpp | 4 +-- apps/openmw/mwsound/ffmpeg_decoder.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 12 ++++---- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +-- components/esm/inventorystate.hpp | 2 ++ components/terrain/material.cpp | 4 +-- 19 files changed, 71 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd437ed616..d60210b212 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -594,6 +594,7 @@ if (WIN32) 4706 # Assignment in conditional expression 4738 # Storing 32-bit float result in memory, possible loss of performance 4986 # Undocumented warning that occurs in the crtdbg.h file + 4987 # nonstandard extension used (triggered by setjmp.h) 4996 # Function was declared deprecated # cause by ogre extensivly @@ -610,7 +611,9 @@ if (WIN32) 4305 # Truncating value (double to float, for example) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list + 4505 # Unreferenced local function has been removed 4701 # Potentially uninitialized local variable used + 4702 # Unreachable code 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) @@ -618,19 +621,31 @@ if (WIN32) set(WARNINGS "${WARNINGS} /wd${d}") endforeach(d) - set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${WARNINGS}) - set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${WARNINGS}) + # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here + set(SHINY_WARNINGS "${WARNINGS} /wd4245") + set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${SHINY_WARNINGS}) + # there's an unreferenced local variable in the ogre platform, suppress it + set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101") + set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS}) + set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS}) + set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS}) if (BUILD_LAUNCHER) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_LAUNCHER) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) - if (BUILD_BSATOOL) + if (BUILD_BSATOOL) set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS}) - endif (BUILD_BSATOOL) + endif (BUILD_BSATOOL) if (BUILD_ESMTOOL) set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_ESMTOOL) + if (BUILD_OPENCS) + set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_OPENCS) + if (BUILD_MWINIIMPORTER) + set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_MWINIIMPORTER) endif(MSVC) # Same for MinGW diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 15ce2dbaf2..fc00f44919 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -79,7 +79,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) std::vector enums = CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - if (type<0 && type>=enums.size()) + if (static_cast(type) >= enums.size()) throw std::logic_error ("Unsupported variable type"); mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 52682342f7..2008accc99 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -695,6 +695,8 @@ protected: typedef TypesetBookImpl::Section Section; typedef TypesetBookImpl::Line Line; typedef TypesetBookImpl::Run Run; + bool mIsPageReset; + size_t mPage; struct TextFormat : ISubWidget { @@ -745,6 +747,23 @@ protected: void destroyDrawItem() {}; }; + void resetPage() + { + mIsPageReset = true; + mPage = 0; + } + + void setPage(size_t page) + { + mIsPageReset = false; + mPage = page; + } + + bool isPageDifferent(size_t page) + { + return mIsPageReset || (mPage != page); + } + public: typedef TypesetBookImpl::StyleImpl Style; @@ -760,14 +779,13 @@ public: boost::shared_ptr mBook; - size_t mPage; MyGUI::ILayerNode* mNode; ActiveTextFormats mActiveTextFormats; PageDisplay () { - mPage = -1; + resetPage (); mViewTop = 0; mViewBottom = 0; mFocusItem = NULL; @@ -901,7 +919,7 @@ public: createActiveFormats (newBook); mBook = newBook; - mPage = newPage; + setPage (newPage); if (newPage < mBook->mPages.size ()) { @@ -917,19 +935,19 @@ public: else { mBook.reset (); - mPage = -1; + resetPage (); mViewTop = 0; mViewBottom = 0; } } else - if (mBook && mPage != newPage) + if (mBook && isPageDifferent (newPage)) { if (mNode != NULL) for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i) mNode->outOfDate(i->second->mRenderItem); - mPage = newPage; + setPage (newPage); if (newPage < mBook->mPages.size ()) { diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 7fdfc069f3..02e3812f0b 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -25,7 +25,7 @@ namespace MWGui ItemView* mItemView; SortFilterItemModel* mSortModel; CompanionItemModel* mModel; - size_t mSelectedItem; + int mSelectedItem; DragAndDrop* mDragAndDrop; diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index ce4707af6b..3aa923a239 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -62,7 +62,7 @@ namespace MWGui MWGui::ItemView* mItemView; SortFilterItemModel* mSortModel; ItemModel* mModel; - size_t mSelectedItem; + int mSelectedItem; MyGUI::Button* mDisposeCorpseButton; MyGUI::Button* mTakeButton; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6c43f47b4b..e9c51a7f84 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -510,7 +510,7 @@ namespace MWGui void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos) { - mHistory->setPosition(0,-pos); + mHistory->setPosition(0, pos * -1); } void DialogueWindow::addResponse(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index c23a74efad..17a25e5027 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -52,7 +52,7 @@ namespace MWGui DragAndDrop* mDragAndDrop; bool mPreviewDirty; - size_t mSelectedItem; + int mSelectedItem; MWWorld::Ptr mPtr; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 1bb80f3d4c..82d8b1f2dc 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -42,6 +42,8 @@ namespace MWGui std::map > mEffectSources; + virtual ~EffectSourceVisitor() {} + virtual void visit (MWMechanics::EffectKey key, const std::string& sourceName, const std::string& casterHandle, float magnitude, float remainingTime = -1); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index cdc12e210e..5ffa7a547f 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -146,8 +146,8 @@ namespace MWMechanics || weapon.get()->mBase->mData.mFlags & ESM::Weapon::Magical)) damage *= multiplier; - if (weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver - & actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) + if ((weapon.get()->mBase->mData.mFlags & ESM::Weapon::Silver) + && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); if (damage == 0 && attacker.getRefData().getHandle() == "player") diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 120616f9fe..6888d88a68 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -70,7 +70,7 @@ namespace MWMechanics return getLevelledItem(ref.getPtr().get()->mBase, failChance); } } - catch (std::logic_error& e) + catch (std::logic_error&) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0f6d782a65..a22beff235 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -267,7 +267,7 @@ void LocalMap::render(const float x, const float y, // initialize to (0, 0, 0, 1) for (int p=0; pgetBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 67bc75e02d..92a49acc01 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -35,7 +35,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); } - catch (Ogre::Exception& e) + catch (Ogre::Exception&) { mSupported = false; } diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index c09aa65d98..cbe910c716 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -33,6 +33,7 @@ namespace MWRender { public: WeaponAnimation() : mPitchFactor(0) {} + virtual ~WeaponAnimation() {} virtual void attachArrow(MWWorld::Ptr actor); virtual void releaseArrow(MWWorld::Ptr actor); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 1efc796436..7051937989 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -295,7 +295,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) @@ -395,7 +395,7 @@ namespace MWScript { store = MWBase::Environment::get().getWorld()->getInterior(cellID); } - catch(std::exception &e) + catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); if(cell) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index c595de5aec..75f7ccae4c 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -204,7 +204,7 @@ void FFmpeg_Decoder::open(const std::string &fname) mFrame = avcodec_alloc_frame(); } - catch(std::exception &e) + catch(std::exception&) { if (mFormatCtx->pb->buffer != NULL) { diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 9a3dd73422..b245b92414 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -288,7 +288,7 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode mOutput.mActiveSounds.push_back(this); } - catch(std::exception &e) + catch(std::exception&) { alDeleteBuffers(sNumBuffers, mBuffers); alGetError(); @@ -471,7 +471,7 @@ bool OpenAL_SoundStream::process() mIsFinished = finished; } - catch(std::exception &e) { + catch(std::exception&) { std::cout<< "Error updating stream \""<getName()<<"\"" <open(fname); } - catch(Ogre::FileNotFoundException &e) + catch(Ogre::FileNotFoundException&) { std::string::size_type pos = fname.rfind('.'); if(pos == std::string::npos) @@ -859,7 +859,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f buf = getBuffer(fname); sound.reset(new OpenAL_Sound(*this, src, buf, Ogre::Vector3(0.0f), vol, basevol, pitch, 1.0f, 1000.0f, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -898,7 +898,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre buf = getBuffer(fname); sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); if(buf && alIsBuffer(buf)) @@ -940,7 +940,7 @@ MWBase::SoundPtr OpenAL_Output::streamSound(DecoderPtr decoder, float volume, fl { sound.reset(new OpenAL_SoundStream(*this, src, decoder, volume, pitch, flags)); } - catch(std::exception &e) + catch(std::exception&) { mFreeSources.push_back(src); throw; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 8ce87a25e0..6854358f59 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -321,7 +321,7 @@ namespace MWSound sound = mOutput->playSound(file, volume, basevol, pitch, mode|type, offset); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); } - catch(std::exception &e) + catch(std::exception&) { //std::cout <<"Sound Error: "< > mLights; + virtual ~InventoryState() {} + virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm) const; }; diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index faa73a9864..b56f706806 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -181,7 +181,7 @@ namespace Terrain // shadow. TODO: repeated, put in function if (mShadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (int i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); @@ -334,7 +334,7 @@ namespace Terrain // shadow if (shadows) { - for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) + for (int i = 0; i < (mSplitShadows ? 3 : 1); ++i) { sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); From 471bbd0021789c3882fc95a5069ed7ed830fcaea Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 00:23:53 +0200 Subject: [PATCH 277/545] Savegame: store levelled creature state and move to actorIds (Closes #1332) --- apps/openmw/mwclass/creaturelevlist.cpp | 59 ++++++++++++++++++------- apps/openmw/mwclass/creaturelevlist.hpp | 8 ++++ apps/openmw/mwworld/cellstore.cpp | 5 ++- components/CMakeLists.txt | 2 +- components/esm/creaturelevliststate.cpp | 25 +++++++++++ components/esm/creaturelevliststate.hpp | 19 ++++++++ 6 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 components/esm/creaturelevliststate.cpp create mode 100644 components/esm/creaturelevliststate.hpp diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 732038b2fc..be01b848a3 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -2,6 +2,7 @@ #include "creaturelevlist.hpp" #include +#include #include "../mwmechanics/levelledlist.hpp" @@ -11,7 +12,9 @@ namespace { struct CreatureLevListCustomData : public MWWorld::CustomData { - // TODO: save the creature we spawned here + // actorId of the creature we spawned + int mSpawnActorId; + virtual MWWorld::CustomData *clone() const; }; @@ -38,6 +41,25 @@ namespace MWClass void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, MWRender::RenderingInterface &renderingInterface) const { ensureCustomData(ptr); + + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + if (customData.mSpawnActorId != -1) + return; // TODO: handle respawning + + + MWWorld::LiveCellRef *ref = + ptr.get(); + + 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; + MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); + customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); + } } void CreatureLevList::ensureCustomData(const MWWorld::Ptr &ptr) const @@ -45,22 +67,29 @@ namespace MWClass if (!ptr.getRefData().getCustomData()) { std::auto_ptr data (new CreatureLevListCustomData); - - MWWorld::LiveCellRef *ref = - ptr.get(); - - 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); - } + data->mSpawnActorId = -1; ptr.getRefData().setCustomData(data.release()); } } + + void CreatureLevList::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const + { + const ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + customData.mSpawnActorId = state2.mSpawnActorId; + } + + void CreatureLevList::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) + const + { + ESM::CreatureLevListState& state2 = dynamic_cast (state); + + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + state2.mSpawnActorId = customData.mSpawnActorId; + } } diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index d2c02043eb..b67fb5523f 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -19,6 +19,14 @@ namespace MWClass virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + + 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. }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 67ab44b779..3f94a77c43 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -592,7 +593,7 @@ namespace MWWorld writeReferenceCollection (writer, mCreatures); writeReferenceCollection (writer, mDoors); writeReferenceCollection (writer, mIngreds); - writeReferenceCollection (writer, mCreatureLists); + writeReferenceCollection (writer, mCreatureLists); writeReferenceCollection (writer, mItemLists); writeReferenceCollection (writer, mLights); writeReferenceCollection (writer, mLockpicks); @@ -668,7 +669,7 @@ namespace MWWorld case ESM::REC_LEVC: - readReferenceCollection (reader, mCreatureLists, contentFileMap); + readReferenceCollection (reader, mCreatureLists, contentFileMap); break; case ESM::REC_LEVI: diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 90570b260d..0f2ef13013 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate ) add_component_dir (misc diff --git a/components/esm/creaturelevliststate.cpp b/components/esm/creaturelevliststate.cpp new file mode 100644 index 0000000000..164dae96e9 --- /dev/null +++ b/components/esm/creaturelevliststate.cpp @@ -0,0 +1,25 @@ +#include "creaturelevliststate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void CreatureLevListState::load(ESMReader &esm) + { + ObjectState::load(esm); + + mSpawnActorId = -1; + esm.getHNOT (mSpawnActorId, "SPAW"); + } + + void CreatureLevListState::save(ESMWriter &esm, bool inInventory) const + { + ObjectState::save(esm, inInventory); + + if (mSpawnActorId != -1) + esm.writeHNT ("SPAW", mSpawnActorId); + } + +} diff --git a/components/esm/creaturelevliststate.hpp b/components/esm/creaturelevliststate.hpp new file mode 100644 index 0000000000..99b5a7fa2a --- /dev/null +++ b/components/esm/creaturelevliststate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_ESM_CREATURELEVLISTSTATE_H +#define OPENMW_ESM_CREATURELEVLISTSTATE_H + +#include "objectstate.hpp" + +namespace ESM +{ + // format 0, saved games only + + struct CreatureLevListState : public ObjectState + { + int mSpawnActorId; + + virtual void load (ESMReader &esm); + virtual void save (ESMWriter &esm, bool inInventory = false) const; + }; +} + +#endif From 37b9d2fb0cac2960466554021a8f94f0942471cc Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 01:53:52 +0200 Subject: [PATCH 278/545] Fix a wrong use of reference that causes potential crash --- apps/openmw/mwmechanics/aiavoiddoor.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 85bb09fc83..c1b3261981 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -11,9 +11,9 @@ namespace MWMechanics { /// \brief AiPackage to have an actor avoid an opening door /** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it - **/ - class AiAvoidDoor : public AiPackage - { + **/ + class AiAvoidDoor : public AiPackage + { public: /// Avoid door until the door is fully open AiAvoidDoor(const MWWorld::Ptr& doorPtr); @@ -29,10 +29,10 @@ namespace MWMechanics private: float mDuration; - const MWWorld::Ptr& mDoorPtr; + MWWorld::Ptr mDoorPtr; ESM::Position mLastPos; - float mAdjAngle; - }; -} -#endif + float mAdjAngle; + }; +} +#endif From a76e391ad038c99b9e8b72c08949931c9dd3c395 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 01:58:44 +0200 Subject: [PATCH 279/545] Savegame: store door movement state (Closes #747) --- apps/openmw/mwbase/world.hpp | 10 +--- apps/openmw/mwclass/door.cpp | 78 ++++++++++++++++++++++++- apps/openmw/mwclass/door.hpp | 17 +++++- apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 5 +- apps/openmw/mwworld/class.cpp | 10 ++++ apps/openmw/mwworld/class.hpp | 5 ++ apps/openmw/mwworld/worldimp.cpp | 57 +++++++++++------- apps/openmw/mwworld/worldimp.hpp | 10 ++-- components/CMakeLists.txt | 2 +- components/esm/doorstate.cpp | 25 ++++++++ components/esm/doorstate.hpp | 19 ++++++ 12 files changed, 199 insertions(+), 41 deletions(-) create mode 100644 components/esm/doorstate.cpp create mode 100644 components/esm/doorstate.hpp diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 5c8a2d2dd6..0459d5341b 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -393,14 +393,10 @@ namespace MWBase virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; - /// if activated, should this door be opened or closed? - virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; - - /// activate (open or close) an non-teleport door + /// open or close a non-teleport door (depending on current state) virtual void activateDoor(const MWWorld::Ptr& door) = 0; - - /// Is door currently opening/closing? - virtual bool getIsMovingDoor(const MWWorld::Ptr& door) = 0; + /// open or close a non-teleport door as specified + virtual void activateDoor(const MWWorld::Ptr& door, bool open) = 0; virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 984e21e72b..06f0619cec 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -2,6 +2,7 @@ #include "door.hpp" #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -17,12 +18,28 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/actiontrap.hpp" +#include "../mwworld/customdata.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +namespace +{ + struct DoorCustomData : public MWWorld::CustomData + { + int mDoorState; // 0 = nothing, 1 = opening, 2 = closing + + virtual MWWorld::CustomData *clone() const; + }; + + MWWorld::CustomData *DoorCustomData::clone() const + { + return new DoorCustomData (*this); + } +} + namespace MWClass { void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -38,6 +55,14 @@ namespace MWClass const std::string model = getModel(ptr); if(!model.empty()) physics.addObject(ptr); + + // Resume the door's opening/closing animation if it wasn't finished + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + if (customData.mDoorState > 0) + { + MWBase::Environment::get().getWorld()->activateDoor(ptr, customData.mDoorState == 1 ? true : false); + } } std::string Door::getModel(const MWWorld::Ptr &ptr) const @@ -125,7 +150,14 @@ namespace MWClass { // animated door boost::shared_ptr action(new MWWorld::ActionDoor(ptr)); - if (MWBase::Environment::get().getWorld()->getOpenOrCloseDoor(ptr)) + int doorstate = getDoorState(ptr); + bool opening = true; + if (doorstate == 1) + opening = false; + if (doorstate == 0 && ptr.getRefData().getLocalRotation().rot[2] != 0) + opening = false; + + if (opening) { MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, closeSound, 0.5); @@ -262,4 +294,48 @@ namespace MWClass return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } + + void Door::ensureCustomData(const MWWorld::Ptr &ptr) const + { + if (!ptr.getRefData().getCustomData()) + { + std::auto_ptr data(new DoorCustomData); + + data->mDoorState = 0; + ptr.getRefData().setCustomData(data.release()); + } + } + + int Door::getDoorState (const MWWorld::Ptr &ptr) const + { + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + return customData.mDoorState; + } + + void Door::setDoorState (const MWWorld::Ptr &ptr, int state) const + { + ensureCustomData(ptr); + DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + customData.mDoorState = state; + } + + void Door::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const + { + ensureCustomData(ptr); + DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + + const ESM::DoorState& state2 = dynamic_cast(state); + customData.mDoorState = state2.mDoorState; + } + + void Door::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const + { + ensureCustomData(ptr); + const DoorCustomData& customData = dynamic_cast(*ptr.getRefData().getCustomData()); + + ESM::DoorState& state2 = dynamic_cast(state); + state2.mDoorState = customData.mDoorState; + } + } diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index bddc46728d..12b360aa8c 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -9,6 +9,8 @@ namespace MWClass { class Door : public MWWorld::Class { + void ensureCustomData (const MWWorld::Ptr& ptr) const; + virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; @@ -48,7 +50,20 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; - private: + + /// 0 = nothing, 1 = opening, 2 = closing + virtual int getDoorState (const MWWorld::Ptr &ptr) const; + /// This does not actually cause the door to move. Use World::activateDoor instead. + virtual void setDoorState (const MWWorld::Ptr &ptr, int state) 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. }; } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index a206d27ca0..44eacb0d1e 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -45,7 +45,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration return true; // We have tried backing up for more than one second, we've probably cleared it } - if(!MWBase::Environment::get().getWorld()->getIsMovingDoor(mDoorPtr)) + if (!mDoorPtr.getClass().getDoorState(mDoorPtr)) return true; //Door is no longer opening ESM::Position tPos = mDoorPtr.getRefData().getPosition(); //Position of the door diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 3f94a77c43..a5f1663744 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -591,7 +592,7 @@ namespace MWWorld writeReferenceCollection (writer, mClothes); writeReferenceCollection (writer, mContainers); writeReferenceCollection (writer, mCreatures); - writeReferenceCollection (writer, mDoors); + writeReferenceCollection (writer, mDoors); writeReferenceCollection (writer, mIngreds); writeReferenceCollection (writer, mCreatureLists); writeReferenceCollection (writer, mItemLists); @@ -659,7 +660,7 @@ namespace MWWorld case ESM::REC_DOOR: - readReferenceCollection (reader, mDoors, contentFileMap); + readReferenceCollection (reader, mDoors, contentFileMap); break; case ESM::REC_INGR: diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index f20c5f6d27..951ba7865e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -406,4 +406,14 @@ namespace MWWorld { return false; } + + int Class::getDoorState (const MWWorld::Ptr &ptr) const + { + throw std::runtime_error("this is not a door"); + } + + void Class::setDoorState (const MWWorld::Ptr &ptr, int state) const + { + throw std::runtime_error("this is not a door"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 27b8423484..057bc906ef 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -336,6 +336,11 @@ namespace MWWorld virtual int getBaseGold(const MWWorld::Ptr& ptr) const; virtual bool isClass(const MWWorld::Ptr& ptr, const std::string &className) const; + + /// 0 = nothing, 1 = opening, 2 = closing + virtual int getDoorState (const MWWorld::Ptr &ptr) const; + /// This does not actually cause the door to move. Use World::activateDoor instead. + virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4ba3e00096..97b0767faf 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1202,36 +1202,48 @@ namespace MWWorld while (it != mDoorStates.end()) { if (!mWorldScene->isCellActive(*it->first.getCell()) || !it->first.getRefData().getBaseNode()) + { + // The door is no longer in an active cell, or it was disabled. + // Erase from mDoorStates, since we no longer need to move it. + // Once we load the door's cell again (or re-enable the door), Door::insertObject will reinsert to mDoorStates. mDoorStates.erase(it++); + } else { float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees(); float diff = duration * 90; - float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second ? 1 : -1)), 90.f); + float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second == 1 ? 1 : -1)), 90.f); localRotateObject(it->first, 0, 0, targetRot); + bool reached = (targetRot == 90.f && it->second) || targetRot == 0.f; + /// \todo should use convexSweepTest here std::vector collisions = mPhysics->getCollisions(it->first); for (std::vector::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) { MWWorld::Ptr ptr = getPtrViaHandle(*cit); - if (MWWorld::Class::get(ptr).isActor()) + if (ptr.getClass().isActor()) { // Collided with actor, ask actor to try to avoid door if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr() ) { - MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); } // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); + reached = false; //break; //Removed in case multiple actors are touching } } - if ((targetRot == 90.f && it->second) || targetRot == 0.f) + if (reached) + { + // Mark as non-moving + it->first.getClass().setDoorState(it->first, 0); mDoorStates.erase(it++); + } else ++it; } @@ -1849,31 +1861,32 @@ namespace MWWorld void World::activateDoor(const MWWorld::Ptr& door) { - if (mDoorStates.find(door) != mDoorStates.end()) - { - // if currently opening, then close, if closing, then open - mDoorStates[door] = !mDoorStates[door]; - } - else + int state = door.getClass().getDoorState(door); + switch (state) { + case 0: if (door.getRefData().getLocalRotation().rot[2] == 0) - mDoorStates[door] = 1; // open + state = 1; // if closed, then open else - mDoorStates[door] = 0; // close + state = 2; // if open, then close + break; + case 2: + state = 1; // if closing, then open + break; + case 1: + default: + state = 2; // if opening, then close + break; } + door.getClass().setDoorState(door, state); + mDoorStates[door] = state; } - bool World::getOpenOrCloseDoor(const Ptr &door) + void World::activateDoor(const Ptr &door, bool open) { - if (mDoorStates.find(door) != mDoorStates.end()) - return !mDoorStates[door]; // if currently opening or closing, then do the opposite - return door.getRefData().getLocalRotation().rot[2] == 0; - } - - bool World::getIsMovingDoor(const Ptr& door) - { - bool result = mDoorStates.find(door) != mDoorStates.end(); - return result; + int state = open ? 1 : 2; + door.getClass().setDoorState(door, state); + mDoorStates[door] = state; } bool World::getPlayerStandingOn (const MWWorld::Ptr& object) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index eee69e81c4..7b85c3ed87 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -88,7 +88,7 @@ namespace MWWorld float mFacedDistance; std::map mDoorStates; - ///< only holds doors that are currently moving. 0 means closing, 1 opening + ///< only holds doors that are currently moving. 1 = opening, 2 = closing struct MagicBoltState { @@ -496,13 +496,11 @@ namespace MWWorld virtual void setupPlayer(); virtual void renderPlayer(); - /// if activated, should this door be opened or closed? - virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); - - /// activate (open or close) an non-teleport door + /// open or close a non-teleport door (depending on current state) virtual void activateDoor(const MWWorld::Ptr& door); - virtual bool getIsMovingDoor(const MWWorld::Ptr& door); + /// open or close a non-teleport door as specified + virtual void activateDoor(const MWWorld::Ptr& door, bool open); virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 0f2ef13013..d7bdaf36cd 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate ) add_component_dir (misc diff --git a/components/esm/doorstate.cpp b/components/esm/doorstate.cpp new file mode 100644 index 0000000000..0487be7a4d --- /dev/null +++ b/components/esm/doorstate.cpp @@ -0,0 +1,25 @@ +#include "doorstate.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + + void DoorState::load(ESMReader &esm) + { + ObjectState::load(esm); + + mDoorState = 0; + esm.getHNOT (mDoorState, "ANIM"); + } + + void DoorState::save(ESMWriter &esm, bool inInventory) const + { + ObjectState::save(esm, inInventory); + + if (mDoorState != 0) + esm.writeHNT ("ANIM", mDoorState); + } + +} diff --git a/components/esm/doorstate.hpp b/components/esm/doorstate.hpp new file mode 100644 index 0000000000..0df30afb00 --- /dev/null +++ b/components/esm/doorstate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_ESM_DOORSTATE_H +#define OPENMW_ESM_DOORSTATE_H + +#include "objectstate.hpp" + +namespace ESM +{ + // format 0, saved games only + + struct DoorState : public ObjectState + { + int mDoorState; + + virtual void load (ESMReader &esm); + virtual void save (ESMWriter &esm, bool inInventory = false) const; + }; +} + +#endif From a609dc56749831b2011f80c56cd8a0d319b89207 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:03:42 +0200 Subject: [PATCH 280/545] Fix exception when getting hit by a trap --- apps/openmw/mwmechanics/spellcasting.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 553674dd3d..3f6cc41030 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -410,11 +410,16 @@ namespace MWMechanics inflict(caster, target, reflectedEffects, range, true); if (!appliedLastingEffects.empty()) + { + int casterActorId = -1; + if (caster.getClass().isActor()) + casterActorId = caster.getClass().getCreatureStats(caster).getActorId(); target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, - mSourceName, caster.getClass().getCreatureStats(caster).getActorId()); + mSourceName, casterActorId); + } // Notify the target actor they've been hit - if (anyHarmfulEffect && target.getClass().isActor() && target != caster) + if (anyHarmfulEffect && target.getClass().isActor() && target != caster && caster.getClass().isActor()) target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true); } From f2c193ce3d7bcb868249322c99fece14c729ee32 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:36:30 +0200 Subject: [PATCH 281/545] Fix searching the player's actorId --- apps/openmw/mwworld/worldimp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 97b0767faf..2b1cbe4c72 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -563,6 +563,10 @@ namespace MWWorld Ptr World::searchPtrViaActorId (int actorId) { + // The player is not registered in any CellStore so must be checked manually + if (actorId == getPlayerPtr().getClass().getCreatureStats(getPlayerPtr()).getActorId()) + return getPlayerPtr(); + // Now search cells return mWorldScene->searchPtrViaActorId (actorId); } From 2f13a17a39a1c11d31b9e45dd7c37f6a993564f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 02:37:20 +0200 Subject: [PATCH 282/545] Add some more safety checks to spellcasting --- .../mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 36 +++++++++++-------- apps/openmw/mwmechanics/spellcasting.hpp | 2 ++ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5c2ee30e1b..41374c1a3a 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -29,7 +29,7 @@ namespace const std::string& faction = item.getCellRef().mFaction; bool isFactionOwned = false; - if (!faction.empty()) + if (!faction.empty() && ptr.getClass().isNpc()) { const std::map& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks(); if (factions.find(Misc::StringUtils::lowerCase(faction)) == factions.end()) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 3f6cc41030..0843e3e547 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -140,7 +140,7 @@ namespace MWMechanics float x = (willpower + 0.1 * luck) * stats.getFatigueTerm(); // This makes spells that are easy to cast harder to resist and vice versa - if (spell != NULL && caster.getClass().isActor()) + if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor()) { float castChance = getSpellSuccessChance(spell, caster); if (castChance > 0) @@ -226,6 +226,8 @@ namespace MWMechanics bool firstAppliedEffect = true; bool anyHarmfulEffect = false; + bool castByPlayer = (!caster.isEmpty() && caster.getRefData().getHandle() == "player"); + for (std::vector::const_iterator effectIt (effects.mList.begin()); effectIt!=effects.mList.end(); ++effectIt) { @@ -238,7 +240,7 @@ namespace MWMechanics if (!MWBase::Environment::get().getWorld()->isLevitationEnabled() && effectIt->mEffectID == ESM::MagicEffect::Levitate) { - if (caster.getRefData().getHandle() == "player") + if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sLevitateDisabled}"); continue; } @@ -249,13 +251,13 @@ namespace MWMechanics effectIt->mEffectID == ESM::MagicEffect::Mark || effectIt->mEffectID == ESM::MagicEffect::Recall)) { - if (caster.getRefData().getHandle() == "player") + if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sTeleportDisabled}"); continue; } // If player is healing someone, show the target's HP bar - if (caster.getRefData().getHandle() == "player" && target != caster + if (castByPlayer && target != caster && effectIt->mEffectID == ESM::MagicEffect::RestoreHealth && target.getClass().isActor()) MWBase::Environment::get().getWindowManager()->setEnemy(target); @@ -266,7 +268,7 @@ namespace MWMechanics anyHarmfulEffect = true; // If player is attempting to cast a harmful spell, show the target's HP bar - if (caster.getRefData().getHandle() == "player" && target != caster) + if (castByPlayer && target != caster) MWBase::Environment::get().getWindowManager()->setEnemy(target); // Try absorbing if it's a spell @@ -342,17 +344,20 @@ namespace MWMechanics // For absorb effects, also apply the effect to the caster - but with a negative // magnitude, since we're transfering stats from the target to the caster - for (int i=0; i<5; ++i) + if (!caster.isEmpty() && caster.getClass().isActor()) { - if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) + for (int i=0; i<5; ++i) { - std::vector effects; - ActiveSpells::ActiveEffect effect_ = effect; - effect_.mMagnitude *= -1; - effects.push_back(effect_); - // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies - caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, - effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); + if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) + { + std::vector effects; + ActiveSpells::ActiveEffect effect_ = effect; + effect_.mMagnitude *= -1; + effects.push_back(effect_); + // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies + caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, + effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); + } } } } @@ -441,7 +446,8 @@ namespace MWMechanics if (target.getCellRef().mLockLevel > 0) { MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); - MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); + if (!caster.isEmpty() && caster.getClass().isActor()) + MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); //unlocks the door } diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index a930442fb2..dce4b792e2 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -62,9 +62,11 @@ namespace MWMechanics bool cast (const std::string& id); /// @note \a target can be any type of object, not just actors. + /// @note \a caster can be any type of object, or even an empty object. void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false); + /// @note \a caster can be any type of object, or even an empty object. void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); }; From 2e9985c1a371b0e5970f3791cc6d8298a624380a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 03:01:48 +0200 Subject: [PATCH 283/545] Change all AI packages (except AiActivate) to use ActorIds More robust in case the target changes cell or there are multiple targets with the same RefId --- apps/openmw/mwmechanics/actors.cpp | 6 +++--- apps/openmw/mwmechanics/aicombat.cpp | 29 +++++++++++++++----------- apps/openmw/mwmechanics/aicombat.hpp | 6 +++--- apps/openmw/mwmechanics/aiescort.cpp | 21 +++++++++++++------ apps/openmw/mwmechanics/aiescort.hpp | 6 +++--- apps/openmw/mwmechanics/aifollow.cpp | 20 +++++++++++------- apps/openmw/mwmechanics/aifollow.hpp | 22 +++++++++---------- apps/openmw/mwmechanics/aipursue.cpp | 11 +++++----- apps/openmw/mwmechanics/aipursue.hpp | 6 +++--- apps/openmw/mwmechanics/aisequence.cpp | 6 ++++-- apps/openmw/mwscript/aiextensions.cpp | 14 ++++++++----- 11 files changed, 86 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 79a90c4d33..af6cac12fb 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -540,7 +540,7 @@ namespace MWMechanics MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); // Make the summoned creature follow its master and help in fights - AiFollow package(ptr.getRefData().getHandle()); + AiFollow package(ptr); summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); int creatureActorId = summonedCreatureStats.getActorId(); @@ -754,7 +754,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -783,7 +783,7 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); else { MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8464cc419c..72cb8f5740 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -81,7 +81,7 @@ namespace MWMechanics // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp AiCombat::AiCombat(const MWWorld::Ptr& actor) : - mTarget(actor), + mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId()), mTimerAttack(0), mTimerReact(0), mTimerCombatMove(0), @@ -153,7 +153,9 @@ namespace MWMechanics || actor.getClass().getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; - if(mTarget.getClass().getCreatureStats(mTarget).isDead()) + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + + if(target.getClass().getCreatureStats(target).isDead()) return true; //Update every frame @@ -325,7 +327,7 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); Ogre::Vector3 vActorPos(pos.pos); - Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; bool isStuck = false; @@ -396,7 +398,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); + bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); if(mReadyToAttack) isStuck = false; @@ -432,7 +434,7 @@ namespace MWMechanics mFollowTarget = false; - buildNewPath(actor); //may fail to build a path, check before use + buildNewPath(actor, target); //may fail to build a path, check before use //delete visited path node mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]); @@ -476,9 +478,9 @@ namespace MWMechanics //less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing) //then start attacking float speed1 = actorCls.getSpeed(actor); - float speed2 = mTarget.getClass().getSpeed(mTarget); - if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0 - && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) + float speed2 = target.getClass().getSpeed(target); + if(target.getClass().getMovementSettings(target).mPosition[0] == 0 + && target.getClass().getMovementSettings(target).mPosition[1] == 0) speed2 = 0; float s1 = distToTarget - weapRange; @@ -570,9 +572,9 @@ namespace MWMechanics return false; } - void AiCombat::buildNewPath(const MWWorld::Ptr& actor) + void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) { - Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); float dist; @@ -627,9 +629,12 @@ namespace MWMechanics return 1; } - const std::string &AiCombat::getTargetId() const + std::string AiCombat::getTargetId() const { - return mTarget.getRefData().getHandle(); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + if (target.isEmpty()) + return ""; + return target.getRefData().getHandle(); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 833b0063c9..9125e28325 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -31,7 +31,7 @@ namespace MWMechanics virtual unsigned int getPriority() const; ///Returns target ID - const std::string &getTargetId() const; + std::string getTargetId() const; private: PathFinder mPathFinder; @@ -53,7 +53,7 @@ namespace MWMechanics ESM::Position mLastPos; MWMechanics::Movement mMovement; - MWWorld::Ptr mTarget; + int mTargetActorId; const MWWorld::CellStore* mCell; ObstacleCheck mObstacleCheck; @@ -63,7 +63,7 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator mDoorIter; MWWorld::CellRefList& mDoors; - void buildNewPath(const MWWorld::Ptr& actor); + void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 0430adf06a..f3ce7143a4 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -8,6 +8,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/timestamp.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "steering.hpp" #include "movement.hpp" @@ -19,8 +21,8 @@ namespace MWMechanics { - AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z) - : mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const MWWorld::Ptr& actor, int duration, float x, float y, float z) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -38,8 +40,8 @@ namespace MWMechanics } } - AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z) - : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const MWWorld::Ptr& actor, const std::string &cellId,int duration, float x, float y, float z) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -75,7 +77,14 @@ namespace MWMechanics return true; } - const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); + const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); + if (follower.isEmpty()) + { + // The follower disappeared + MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + return true; + } + const float* const leaderPos = actor.getRefData().getPosition().pos; const float* const followerPos = follower.getRefData().getPosition().pos; double differenceBetween[3]; @@ -89,7 +98,7 @@ namespace MWMechanics if(distanceBetweenResult <= mMaxDist * mMaxDist) { - if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete + if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete return true; mMaxDist = 470; } diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 3771417fa2..b8dc9d6e0f 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -15,11 +15,11 @@ namespace MWMechanics /// Implementation of AiEscort /** The Actor will escort the specified actor to the world position x, y, z until they reach their position, or they run out of time \implement AiEscort **/ - AiEscort(const std::string &actorId,int duration, float x, float y, float z); + AiEscort(const MWWorld::Ptr& actor,int duration, float x, float y, float z); /// Implementation of AiEscortCell /** The Actor will escort the specified actor to the cell position x, y, z until they reach their position, or they run out of time \implement AiEscortCell **/ - AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); + AiEscort(const MWWorld::Ptr& actor,const std::string &cellId,int duration, float x, float y, float z); virtual AiEscort *clone() const; @@ -28,7 +28,7 @@ namespace MWMechanics virtual int getTypeId() const; private: - std::string mActorId; + int mActorId; std::string mCellId; float mX; float mY; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index f1296a9493..d747781a38 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -11,23 +11,26 @@ #include "steering.hpp" -MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(""), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,const std::string &cellId,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(cellId), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor) +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mCellId(""), AiPackage() { + mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -75,7 +78,8 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) std::string MWMechanics::AiFollow::getFollowedActor() { - return mActorId; + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow + return target.getCellRef().mRefID; } MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 10a381410a..91bdbdac2f 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -10,16 +10,16 @@ namespace MWMechanics { /// \brief AiPackage for an actor to follow another actor/the PC /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely - **/ - class AiFollow : public AiPackage - { + **/ + class AiFollow : public AiPackage + { public: /// Follow Actor for duration or until you arrive at a world position - AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + AiFollow(const MWWorld::Ptr& actor,float duration, float X, float Y, float Z); /// Follow Actor for duration or until you arrive at a position in a cell - AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); + AiFollow(const MWWorld::Ptr& actor,const std::string &CellId,float duration, float X, float Y, float Z); /// Follow Actor indefinitively - AiFollow(const std::string &ActorId); + AiFollow(const MWWorld::Ptr& actor); virtual AiFollow *clone() const; @@ -38,8 +38,8 @@ namespace MWMechanics float mX; float mY; float mZ; - std::string mActorId; - std::string mCellId; - }; -} -#endif + int mActorId; // The actor we should follow + std::string mCellId; + }; +} +#endif diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 6e91ccb719..aa71af4658 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -7,12 +7,14 @@ #include "../mwworld/action.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "steering.hpp" #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPursue::AiPursue(const std::string &objectId) - : mObjectId(objectId) +MWMechanics::AiPursue::AiPursue(const MWWorld::Ptr& actor) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()) { } MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const @@ -23,7 +25,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { ESM::Position pos = actor.getRefData().getPosition(); //position of the actor - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -33,8 +35,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + target.getClass().activate(target,actor).get()->execute(actor); //Arrest player return true; } else { diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 2eb533d625..90ff8df93b 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -16,14 +16,14 @@ namespace MWMechanics { public: ///Constructor - /** \param objectId Actor to pursue **/ - AiPursue(const std::string &objectId); + /** \param actor Actor to pursue **/ + AiPursue(const MWWorld::Ptr& actor); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); virtual int getTypeId() const; private: - std::string mObjectId; + int mActorId; // The actor to pursue int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 0b1da180d7..8afe8402ff 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -175,7 +175,8 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else if (it->mType == ESM::AI_Escort) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiEscort(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); + package = new MWMechanics::AiEscort(target, data.mDuration, data.mX, data.mY, data.mZ); } else if (it->mType == ESM::AI_Travel) { @@ -190,7 +191,8 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else //if (it->mType == ESM::AI_Follow) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiFollow(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); + package = new MWMechanics::AiFollow(target, data.mDuration, data.mX, data.mY, data.mZ); } mPackages.push_back(package); } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index e53b53e58f..8ed19925ec 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -91,6 +91,7 @@ namespace MWScript std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); + MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -107,7 +108,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -145,7 +147,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -297,7 +300,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -335,8 +339,8 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i Date: Thu, 15 May 2014 03:07:25 +0200 Subject: [PATCH 284/545] AiCombat: Removed obsolete door back-off code (now handled in AiAvoidDoor) --- apps/openmw/mwmechanics/aicombat.cpp | 83 +++++----------------------- apps/openmw/mwmechanics/aicombat.hpp | 6 -- 2 files changed, 13 insertions(+), 76 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 72cb8f5740..ff9c0f8c48 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -92,11 +92,7 @@ namespace MWMechanics mMovement(), mForceNoShortcut(false), mShortcutFailPos(), - mBackOffDoor(false), - mCell(NULL), - mDoorIter(actor.getCell()->get().mList.end()), - mDoors(actor.getCell()->get()), - mDoorCheckDuration(0) + mBackOffDoor(false) { } @@ -198,12 +194,6 @@ namespace MWMechanics mTimerReact = 0; - bool cellChange = mCell && (actor.getCell() != mCell); - if(!mCell || cellChange) - { - mCell = actor.getCell(); - } - //actual attacking logic //TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f float attacksPeriod = 1.0f; @@ -503,70 +493,23 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? - MWWorld::CellStore *cell = actor.getCell(); if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { - // first check if we're walking into a door - mDoorCheckDuration += 1.0f; // add time taken for obstacle check - if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL && !cell->getCell()->isExterior()) - { - mDoorCheckDuration = 0; - // Check all the doors in this cell - mDoors = cell->get(); // update - mDoorIter = mDoors.mList.begin(); - for (; mDoorIter != mDoors.mList.end(); ++mDoorIter) - { - MWWorld::LiveCellRef& ref = *mDoorIter; - float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility - if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && - ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening - { - //std::cout<<"closed door id \""<getCell()->isExterior() && !mDoors.mList.empty()) - { - MWWorld::LiveCellRef& ref = *mDoorIter; - float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility - // TODO: add reaction to checking open doors - if(mBackOffDoor && - vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) - { - mMovement.mPosition[1] = -0.2; // back off, but slowly - } - else if(mBackOffDoor && - mDoorIter != mDoors.mList.end() && - ref.mData.getLocalRotation().rot[2] >= 1) - { - mDoorIter = mDoors.mList.end(); - mBackOffDoor = false; - //std::cout<<"open door id \""<::List::iterator mDoorIter; - MWWorld::CellRefList& mDoors; void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; From bac4d875df97c0f797ba874101ceeae78a08387c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:20:40 +0200 Subject: [PATCH 285/545] Fix a potential exploit that made it possible to reset the owner of any item --- apps/openmw/mwgui/inventoryitemmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index c0847929b3..390c0768c0 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -64,7 +64,10 @@ void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel bool setNewOwner = false; // Are you dead? Then you wont need that anymore - if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead()) + if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead() + // Make sure that the item is actually owned by the dead actor + // Prevents a potential exploit for resetting the owner of any item, by placing the item in a corpse + && Misc::StringUtils::ciEqual(item.mBase.getCellRef().mOwner, mActor.getCellRef().mRefID)) setNewOwner = true; otherModel->copyItem(item, count, setNewOwner); From eb40032bde675ac3baa7634c2b6fa3cf650bf789 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:41:31 +0200 Subject: [PATCH 286/545] Fix item owner not resetting when dragging an item from a corpse to the player avatar --- apps/openmw/mwgui/companionitemmodel.cpp | 12 ++++++------ apps/openmw/mwgui/companionitemmodel.hpp | 2 +- apps/openmw/mwgui/containeritemmodel.cpp | 4 ++-- apps/openmw/mwgui/containeritemmodel.hpp | 2 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 9 +++++---- apps/openmw/mwgui/inventoryitemmodel.hpp | 4 ++-- apps/openmw/mwgui/inventorywindow.cpp | 10 ++-------- apps/openmw/mwgui/itemmodel.cpp | 10 +++++----- apps/openmw/mwgui/itemmodel.hpp | 6 +++--- 9 files changed, 27 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwgui/companionitemmodel.cpp b/apps/openmw/mwgui/companionitemmodel.cpp index 9c4ea2d291..b8be9dcb82 100644 --- a/apps/openmw/mwgui/companionitemmodel.cpp +++ b/apps/openmw/mwgui/companionitemmodel.cpp @@ -10,23 +10,23 @@ namespace MWGui { } - void CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) + MWWorld::Ptr CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) { if (mActor.getClass().isNpc()) { - MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); - stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); + MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor); + stats.modifyProfit(item.mBase.getClass().getValue(item.mBase) * count); } - InventoryItemModel::copyItem(item, count, setNewOwner); + return InventoryItemModel::copyItem(item, count, setNewOwner); } void CompanionItemModel::removeItem (const ItemStack& item, size_t count) { if (mActor.getClass().isNpc()) { - MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); - stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); + MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor); + stats.modifyProfit(-item.mBase.getClass().getValue(item.mBase) * count); } InventoryItemModel::removeItem(item, count); diff --git a/apps/openmw/mwgui/companionitemmodel.hpp b/apps/openmw/mwgui/companionitemmodel.hpp index 49c58c8963..172fa9508a 100644 --- a/apps/openmw/mwgui/companionitemmodel.hpp +++ b/apps/openmw/mwgui/companionitemmodel.hpp @@ -13,7 +13,7 @@ namespace MWGui public: CompanionItemModel (const MWWorld::Ptr& actor); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner); virtual void removeItem (const ItemStack& item, size_t count); }; diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index e702c073dd..b5b498e5e6 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -71,12 +71,12 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) return -1; } -void ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) +MWWorld::Ptr ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source)) throw std::runtime_error("Item to copy needs to be from a different container!"); - source.getClass().getContainerStore(source).add(item.mBase, count, source); + return *source.getClass().getContainerStore(source).add(item.mBase, count, source); } void ContainerItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/containeritemmodel.hpp b/apps/openmw/mwgui/containeritemmodel.hpp index 4b9b4ff991..7ced6ae343 100644 --- a/apps/openmw/mwgui/containeritemmodel.hpp +++ b/apps/openmw/mwgui/containeritemmodel.hpp @@ -21,7 +21,7 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual void update(); diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index 390c0768c0..718c6d991f 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -40,11 +40,11 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item) return -1; } -void InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) +MWWorld::Ptr InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor)) throw std::runtime_error("Item to copy needs to be from a different container!"); - mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); + return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); } @@ -59,7 +59,7 @@ void InventoryItemModel::removeItem (const ItemStack& item, size_t count) throw std::runtime_error("Not enough items in the stack to remove"); } -void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) +MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) { bool setNewOwner = false; @@ -70,8 +70,9 @@ void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel && Misc::StringUtils::ciEqual(item.mBase.getCellRef().mOwner, mActor.getCellRef().mRefID)) setNewOwner = true; - otherModel->copyItem(item, count, setNewOwner); + MWWorld::Ptr ret = otherModel->copyItem(item, count, setNewOwner); removeItem(item, count); + return ret; } void InventoryItemModel::update() diff --git a/apps/openmw/mwgui/inventoryitemmodel.hpp b/apps/openmw/mwgui/inventoryitemmodel.hpp index 78dcc9497d..f58ee29390 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.hpp +++ b/apps/openmw/mwgui/inventoryitemmodel.hpp @@ -15,11 +15,11 @@ namespace MWGui virtual ModelIndex getIndex (ItemStack item); virtual size_t getItemCount(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); /// Move items from this model to \a otherModel. - virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); virtual void update(); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index d6da3b30e3..4d52d59bb6 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -408,14 +408,8 @@ namespace MWGui if (mDragAndDrop->mSourceModel != mTradeModel) { - // add item to the player's inventory - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); - MWWorld::ContainerStoreIterator it = invStore.begin(); - - it = invStore.add(ptr, mDragAndDrop->mDraggedCount, mPtr); - - mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); - ptr = *it; + // Move item to the player's inventory + ptr = mDragAndDrop->mSourceModel->moveItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount, mTradeModel); } useItem(ptr); } diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 7b2ea4d4a3..2cdd8a2e66 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -71,10 +71,11 @@ namespace MWGui { } - void ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) + MWWorld::Ptr ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel) { - otherModel->copyItem(item, count); + MWWorld::Ptr ret = otherModel->copyItem(item, count); removeItem(item, count); + return ret; } @@ -83,10 +84,9 @@ namespace MWGui delete mSourceModel; } - void ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) + MWWorld::Ptr ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner) { - // no need to use mapToSource since itemIndex refers to an index in the sourceModel - mSourceModel->copyItem (item, count, setNewOwner); + return mSourceModel->copyItem (item, count, setNewOwner); } void ProxyItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/itemmodel.hpp b/apps/openmw/mwgui/itemmodel.hpp index 684771b86b..21c5477d0b 100644 --- a/apps/openmw/mwgui/itemmodel.hpp +++ b/apps/openmw/mwgui/itemmodel.hpp @@ -56,10 +56,10 @@ namespace MWGui virtual void update() = 0; /// Move items from this model to \a otherModel. - virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); /// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner? - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0; + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0; virtual void removeItem (const ItemStack& item, size_t count) = 0; private: @@ -73,7 +73,7 @@ namespace MWGui { public: virtual ~ProxyItemModel(); - virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false); virtual void removeItem (const ItemStack& item, size_t count); virtual ModelIndex getIndex (ItemStack item); From b6a7aee42e15e45d1a251a0b02c2ad6bf514f551 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 04:52:35 +0200 Subject: [PATCH 287/545] Fix player not being allowed to use his own items --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 41374c1a3a..bf9a11d6e5 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -25,7 +25,7 @@ namespace bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) { const std::string& owner = item.getCellRef().mOwner; - bool isOwned = !owner.empty(); + bool isOwned = !owner.empty() && owner != "player"; const std::string& faction = item.getCellRef().mFaction; bool isFactionOwned = false; From 6de7e165504981fef276a93ea6c7980b3d53ec82 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 06:08:55 +0200 Subject: [PATCH 288/545] Fix searchPtrViaActorId not skipping over deleted references Fixes an issue when an actor has moved cell: searchPtrViaActorId would randomly return the deleted Ptr from the old cell. --- apps/openmw/mwworld/cellstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index a5f1663744..5d2d8a5175 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -54,7 +54,7 @@ namespace { MWWorld::Ptr actor (&*iter, cell); - if (MWWorld::Class::get (actor).getCreatureStats (actor).matchesActorId (actorId)) + if (actor.getClass().getCreatureStats (actor).matchesActorId (actorId) && actor.getRefData().getCount() > 0) return actor; } From b16d444f0ff03f77c403a657afca58556cd0b950 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 10:05:35 +0200 Subject: [PATCH 289/545] Fix never clearing graveyard. Oops --- apps/openmw/mwmechanics/actors.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index af6cac12fb..a0616258c7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -574,11 +574,16 @@ namespace MWMechanics } } - for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ++it) + for (std::vector::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ) { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it); if (!ptr.isEmpty()) + { + it = creatureStats.mSummonGraveyard.erase(it); MWBase::Environment::get().getWorld()->deleteObject(ptr); + } + else + ++it; } } From 0bc33fa86a0dc6bb6fc59ce2092d0efdc0e42dc2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 10:14:47 +0200 Subject: [PATCH 290/545] Revert "AiCombat: Removed obsolete door back-off code (now handled in AiAvoidDoor)" Apparently not working for AiCombat due to its higher getPriority(). What should we do here? This reverts commit a6e1d7ffd6daf4af4750d1478048733428db4a5b. --- apps/openmw/mwmechanics/aicombat.cpp | 83 +++++++++++++++++++++++----- apps/openmw/mwmechanics/aicombat.hpp | 6 ++ 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index ff9c0f8c48..72cb8f5740 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -92,7 +92,11 @@ namespace MWMechanics mMovement(), mForceNoShortcut(false), mShortcutFailPos(), - mBackOffDoor(false) + mBackOffDoor(false), + mCell(NULL), + mDoorIter(actor.getCell()->get().mList.end()), + mDoors(actor.getCell()->get()), + mDoorCheckDuration(0) { } @@ -194,6 +198,12 @@ namespace MWMechanics mTimerReact = 0; + bool cellChange = mCell && (actor.getCell() != mCell); + if(!mCell || cellChange) + { + mCell = actor.getCell(); + } + //actual attacking logic //TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f float attacksPeriod = 1.0f; @@ -493,23 +503,70 @@ namespace MWMechanics // coded at 250ms or 1/4 second // // TODO: Add a parameter to vary DURATION_SAME_SPOT? + MWWorld::CellStore *cell = actor.getCell(); if((distToTarget > rangeAttack || mFollowTarget) && mObstacleCheck.check(actor, tReaction)) // check if evasive action needed { - // probably walking into another NPC TODO: untested in combat situation + // first check if we're walking into a door + mDoorCheckDuration += 1.0f; // add time taken for obstacle check + if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL && !cell->getCell()->isExterior()) + { + mDoorCheckDuration = 0; + // Check all the doors in this cell + mDoors = cell->get(); // update + mDoorIter = mDoors.mList.begin(); + for (; mDoorIter != mDoors.mList.end(); ++mDoorIter) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility + if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && + ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening + { + //std::cout<<"closed door id \""<getCell()->isExterior() && !mDoors.mList.empty()) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility + // TODO: add reaction to checking open doors + if(mBackOffDoor && + vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + { + mMovement.mPosition[1] = -0.2; // back off, but slowly + } + else if(mBackOffDoor && + mDoorIter != mDoors.mList.end() && + ref.mData.getLocalRotation().rot[2] >= 1) + { + mDoorIter = mDoors.mList.end(); + mBackOffDoor = false; + //std::cout<<"open door id \""<::List::iterator mDoorIter; + MWWorld::CellRefList& mDoors; void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; From b3735981d6fb5d9c040842c391c1643894aa7315 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 15 May 2014 21:18:09 +0200 Subject: [PATCH 291/545] Remove unused file_finder --- apps/openmw_test_suite/CMakeLists.txt | 1 - .../file_finder/test_filefinder.cpp | 66 -------- .../components/file_finder/test_search.cpp | 74 --------- components/CMakeLists.txt | 4 - components/file_finder/file_finder.hpp | 142 ------------------ components/file_finder/filename_less.hpp | 84 ----------- components/file_finder/search.cpp | 36 ----- components/file_finder/search.hpp | 20 --- 8 files changed, 427 deletions(-) delete mode 100644 apps/openmw_test_suite/components/file_finder/test_filefinder.cpp delete mode 100644 apps/openmw_test_suite/components/file_finder/test_search.cpp delete mode 100644 components/file_finder/file_finder.hpp delete mode 100644 components/file_finder/filename_less.hpp delete mode 100644 components/file_finder/search.cpp delete mode 100644 components/file_finder/search.hpp diff --git a/apps/openmw_test_suite/CMakeLists.txt b/apps/openmw_test_suite/CMakeLists.txt index 6820103402..9fe7890acc 100644 --- a/apps/openmw_test_suite/CMakeLists.txt +++ b/apps/openmw_test_suite/CMakeLists.txt @@ -12,7 +12,6 @@ if (GTEST_FOUND AND GMOCK_FOUND) file(GLOB UNITTEST_SRC_FILES components/misc/test_*.cpp - components/file_finder/test_*.cpp ) source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) diff --git a/apps/openmw_test_suite/components/file_finder/test_filefinder.cpp b/apps/openmw_test_suite/components/file_finder/test_filefinder.cpp deleted file mode 100644 index 2d151988b9..0000000000 --- a/apps/openmw_test_suite/components/file_finder/test_filefinder.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include "components/file_finder/file_finder.hpp" - -struct FileFinderTest : public ::testing::Test -{ - protected: - FileFinderTest() - : mTestDir("./filefinder_test_dir/") - , mTestFile("test.txt") - , mTestFileUppercase("TEST.TXT") - , mTestFileNotFound("foobarbaz.txt") - { - } - - virtual void SetUp() - { - boost::filesystem::create_directory(boost::filesystem::path(mTestDir)); - - std::ofstream ofs(std::string(mTestDir + mTestFile).c_str(), std::ofstream::out); - ofs << std::endl; - ofs.close(); - } - - virtual void TearDown() - { - boost::filesystem::remove_all(boost::filesystem::path(mTestDir)); - } - - std::string mTestDir; - std::string mTestFile; - std::string mTestFileUppercase; - std::string mTestFileNotFound; -}; - -TEST_F(FileFinderTest, FileFinder_has_file) -{ - FileFinder::FileFinder fileFinder(mTestDir); - ASSERT_TRUE(fileFinder.has(mTestFile)); - ASSERT_TRUE(fileFinder.has(mTestFileUppercase)); - ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile)); - ASSERT_TRUE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile)); -} - -TEST_F(FileFinderTest, FileFinder_does_not_have_file) -{ - FileFinder::FileFinder fileFinder(mTestDir); - ASSERT_FALSE(fileFinder.has(mTestFileNotFound)); - ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty()); -} - -TEST_F(FileFinderTest, FileFinderStrict_has_file) -{ - FileFinder::FileFinderStrict fileFinder(mTestDir); - ASSERT_TRUE(fileFinder.has(mTestFile)); - ASSERT_FALSE(fileFinder.has(mTestFileUppercase)); - ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile)); - ASSERT_FALSE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile)); -} - -TEST_F(FileFinderTest, FileFinderStrict_does_not_have_file) -{ - FileFinder::FileFinderStrict fileFinder(mTestDir); - ASSERT_FALSE(fileFinder.has(mTestFileNotFound)); - ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty()); -} diff --git a/apps/openmw_test_suite/components/file_finder/test_search.cpp b/apps/openmw_test_suite/components/file_finder/test_search.cpp deleted file mode 100644 index 63745b6256..0000000000 --- a/apps/openmw_test_suite/components/file_finder/test_search.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -#include "components/file_finder/search.hpp" - -struct SearchTest : public ::testing::Test -{ - protected: - SearchTest() - : mTestDir("./search_test_dir/") - { - } - - virtual void SetUp() - { - boost::filesystem::create_directory(boost::filesystem::path(mTestDir)); - - std::ofstream ofs(std::string(mTestDir + "test2.txt").c_str(), std::ofstream::out); - ofs << std::endl; - ofs.close(); - } - - virtual void TearDown() - { - boost::filesystem::remove_all(boost::filesystem::path(mTestDir)); - } - - std::string mTestDir; -}; - -TEST_F(SearchTest, file_not_found) -{ - struct Result : public FileFinder::ReturnPath - { - Result(const boost::filesystem::path& expectedPath) - : mExpectedPath(expectedPath) - { - } - - void add(const boost::filesystem::path& p) - { - ASSERT_FALSE(p == mExpectedPath); - } - - private: - boost::filesystem::path mExpectedPath; - - } r(boost::filesystem::path(mTestDir + "test.txt")); - - FileFinder::find(mTestDir, r, false); -} - -TEST_F(SearchTest, file_found) -{ - struct Result : public FileFinder::ReturnPath - { - Result(const boost::filesystem::path& expectedPath) - : mExpectedPath(expectedPath) - { - } - - void add(const boost::filesystem::path& p) - { - ASSERT_TRUE(p == mExpectedPath); - } - - private: - boost::filesystem::path mExpectedPath; - - } r(boost::filesystem::path(mTestDir + "test2.txt")); - - FileFinder::find(mTestDir, r, false); -} diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index d7bdaf36cd..c7deeadf3f 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -34,10 +34,6 @@ add_component_dir (to_utf8 to_utf8 ) -add_component_dir (file_finder - file_finder filename_less search - ) - add_component_dir (esm attr defs esmcommon esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst diff --git a/components/file_finder/file_finder.hpp b/components/file_finder/file_finder.hpp deleted file mode 100644 index 8a15af73af..0000000000 --- a/components/file_finder/file_finder.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef FILE_FINDER_MAIN_H -#define FILE_FINDER_MAIN_H - -#include - -#include "search.hpp" -#include "filename_less.hpp" -#include - -namespace FileFinder -{ - -template -class FileFinderT -{ - typedef std::map TableContainer; - TableContainer table; - - struct Inserter : ReturnPath - { - FileFinderT *owner; - int cut; - - void add(const boost::filesystem::path &pth) - { - std::string file = pth.string(); - std::string key = file.substr(cut); - owner->table[key] = file; - } - }; - - Inserter inserter; - -public: - FileFinderT(const boost::filesystem::path &path, bool recurse=true) - { - inserter.owner = this; - - // Remember the original path length, so we can cut it away from - // the relative paths used as keys - const std::string& pstring = path.string(); - inserter.cut = pstring.size(); - - // If the path does not end in a slash, then boost will add one - // later, which means one more character we have to remove. - char last = *pstring.rbegin(); - if(last != '\\' && last != '/') - inserter.cut++; - - // Fill the map - find(path, inserter, recurse); - } - - bool has(const std::string& file) const - { - return table.find(file) != table.end(); - } - - // Find the full path from a relative path. - const std::string &lookup(const std::string& file) const - { - static std::string empty; - typename TableContainer::const_iterator it = table.find(file); - return (it != table.end()) ? it->second : empty; - } -}; - -template -< - class LESS -> -struct TreeFileFinder -{ - typedef TreeFileFinder finder_t; - - TreeFileFinder(const Files::PathContainer& paths, bool recurse = true) - { - struct : ReturnPath - { - finder_t *owner; - int cut; - - void add(const boost::filesystem::path &pth) - { - std::string file = pth.string(); - std::string key = file.substr(cut); - owner->mTable[key] = file; - } - } inserter; - - inserter.owner = this; - - for (Files::PathContainer::const_iterator it = paths.begin(); it != paths.end(); ++it) - { - - // Remember the original path length, so we can cut it away from - // the relative paths used as keys - const std::string& pstring = it->string(); - inserter.cut = pstring.size(); - - // If the path does not end in a slash, then boost will add one - // later, which means one more character we have to remove. - char last = *pstring.rbegin(); - if (last != '\\' && last != '/') - { - inserter.cut++; - } - - // Fill the map - find(*it, inserter, recurse); - } - } - - bool has(const std::string& file) const - { - return mTable.find(file) != mTable.end(); - } - - const std::string& lookup(const std::string& file) const - { - static std::string empty; - typename TableContainer::const_iterator it = mTable.find(file); - return (it != mTable.end()) ? it->second : empty; - } - - private: - typedef std::map TableContainer; - TableContainer mTable; - -// Inserter inserter; -}; - - -// The default is to use path_less for equality checks -typedef FileFinderT FileFinder; -typedef FileFinderT FileFinderStrict; - -typedef TreeFileFinder LessTreeFileFinder; -typedef TreeFileFinder StrictTreeFileFinder; - -} /* namespace FileFinder */ -#endif /* FILE_FINDER_MAIN_H */ diff --git a/components/file_finder/filename_less.hpp b/components/file_finder/filename_less.hpp deleted file mode 100644 index bc3186ce98..0000000000 --- a/components/file_finder/filename_less.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef FILE_FINDER_LESS_H -#define FILE_FINDER_LESS_H - -#include -#include - -namespace FileFinder{ - -// Used for maps of file paths. Compares file paths, but ignores case -// AND treats \ and / as the same character. -struct path_less -{ - int compareChar(char a, char b) const - { - if(a>b) return 1; - else if(a= 'a' && a <= 'z') a += 'A'-'a'; - else if(a == '\\') a = '/'; - if(b >= 'a' && b <= 'z') b += 'A'-'a'; - else if(b == '\\') b = '/'; - return compareChar(a,b); - } - - int compareString(const char *a, const char *b) const - { - while(*a && *b) - { - int i = comparePathChar(*a,*b); - if(i != 0) return i; - a++; b++; - } - // At this point, one or both of the chars is a null terminator. - // Normal char comparison will get the correct final result here. - return compareChar(*a,*b); - } - - bool operator() (const std::string& a, const std::string& b) const - { - return compareString(a.c_str(), b.c_str()) < 0; - } -}; - -struct path_slash -{ - int compareChar(char a, char b) const - { - if(a>b) return 1; - else if(a - -void FileFinder::find(const boost::filesystem::path & dir_path, ReturnPath &ret, bool recurse) -{ - if (boost::filesystem::exists(dir_path)) - { - if (!recurse) - { - boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end - for (boost::filesystem::directory_iterator itr(dir_path); itr != end_itr; ++itr) - { - if (!boost::filesystem::is_directory( *itr )) - { - ret.add(*itr); - } - } - } - else - { - boost::filesystem::recursive_directory_iterator end_itr; // default construction yields past-the-end - for (boost::filesystem::recursive_directory_iterator itr(dir_path); itr != end_itr; ++itr) - { - if (!boost::filesystem::is_directory(*itr)) - { - ret.add(*itr); - } - } - } - } - else - { - std::cout << "Path " << dir_path << " not found" << std::endl; - } -} diff --git a/components/file_finder/search.hpp b/components/file_finder/search.hpp deleted file mode 100644 index 4e16fb64a0..0000000000 --- a/components/file_finder/search.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef FILE_FINDER_SEARCH_H -#define FILE_FINDER_SEARCH_H - -#include -#include - -namespace FileFinder -{ - struct ReturnPath - { - virtual void add(const boost::filesystem::path &pth) = 0; - }; - - /** Search the given path and return all file paths through 'ret'. If - recurse==true, all files in subdirectories are returned as well. - */ - void find(const boost::filesystem::path & dir_path, ReturnPath &ret, bool recurse=true); -} - -#endif From 5be37f04ef1709565dbe4138bc4e603499ed481b Mon Sep 17 00:00:00 2001 From: mrcheko Date: Fri, 16 May 2014 00:03:48 +0400 Subject: [PATCH 292/545] Feature 1314: make npc fight creatures --- apps/openmw/mwmechanics/actors.cpp | 161 +++++++++++++++++-------- apps/openmw/mwmechanics/actors.hpp | 8 +- apps/openmw/mwmechanics/aicombat.cpp | 11 +- apps/openmw/mwmechanics/aicombat.hpp | 2 +- apps/openmw/mwmechanics/aisequence.cpp | 64 +++++++++- apps/openmw/mwmechanics/aisequence.hpp | 3 + 6 files changed, 187 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6ec2f64d08..d988b97030 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -178,54 +178,65 @@ namespace MWMechanics calculateDynamicStats (ptr); calculateCreatureStatModifiers (ptr, duration); - - // AI - if(MWBase::Environment::get().getMechanicsManager()->isAIActive()) - { - CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - - //engage combat or not? - if(ptr != player && !creatureStats.isHostile()) - { - ESM::Position playerpos = player.getRefData().getPosition(); - ESM::Position actorpos = ptr.getRefData().getPosition(); - float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0]) - +(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1]) - +(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2])); - float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified(); - - if( (fight == 100 ) - || (fight >= 95 && d <= 3000) - || (fight >= 90 && d <= 2000) - || (fight >= 80 && d <= 1000) - ) - { - bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player) - && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr); - - if (LOS) - { - MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); - } - } - } - updateCrimePersuit(ptr, duration); - creatureStats.getAiSequence().execute (ptr,duration); - } - // fatigue restoration calculateRestoration(ptr, duration, false); } - void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) + void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) { - if(!paused) + CreatureStats& creatureStats = MWWorld::Class::get(actor1).getCreatureStats(actor1); + + if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player + + float fight; + + if (againstPlayer) + fight = actor1.getClass().getCreatureStats(actor1).getAiSetting(CreatureStats::AI_Fight).getModified(); + else { - updateDrowning(ptr, duration); - calculateNpcStatModifiers(ptr); - updateEquippedLight(ptr, duration); + fight = 0; + // if one of actors is creature then we should make a decision to start combat or not + // NOTE: function doesn't take into account combat between 2 creatures + if (!actor1.getClass().isNpc()) + { + // if creature is hostile then it is necessarily to start combat + if (creatureStats.isHostile()) fight = 100; + else fight = creatureStats.getAiSetting(CreatureStats::AI_Fight).getModified(); + } } + + ESM::Position actor1Pos = actor1.getRefData().getPosition(); + ESM::Position actor2Pos = actor2.getRefData().getPosition(); + float d = Ogre::Vector3(actor1Pos.pos).distance(Ogre::Vector3(actor2Pos.pos)); + + if( (fight == 100 && d <= 5000) + || (fight >= 95 && d <= 3000) + || (fight >= 90 && d <= 2000) + || (fight >= 80 && d <= 1000)) + { + if (againstPlayer || actor2.getClass().getCreatureStats(actor2).getAiSequence().canAddTarget(actor2Pos, d)) + { + bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2); + + if (againstPlayer) LOS &= MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor2, actor1); + + if (LOS) + { + MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2); + if (!againstPlayer) // start combat between each other + { + MWBase::Environment::get().getMechanicsManager()->startCombat(actor2, actor1); + } + } + } + } + } + + void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration) + { + updateDrowning(ptr, duration); + calculateNpcStatModifiers(ptr); + updateEquippedLight(ptr, duration); } void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) @@ -830,10 +841,24 @@ namespace MWMechanics } } + static Ogre::Vector3 sBasePoint; + bool comparePtrDist (const MWWorld::Ptr& ptr1, const MWWorld::Ptr& ptr2) + { + return (sBasePoint.squaredDistance(Ogre::Vector3(ptr1.getRefData().getPosition().pos)) + < sBasePoint.squaredDistance(Ogre::Vector3(ptr2.getRefData().getPosition().pos))); + } + void Actors::update (float duration, bool paused) { if(!paused) { + std::list listGuards; // at the moment only guards certainly will fight with creatures + + static float timerUpdateAITargets = 0; + + // target lists get updated once every 1.0 sec + if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0; + // Reset data from previous frame for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { @@ -841,29 +866,64 @@ namespace MWMechanics // Note, the new hit object for this frame may be set by CharacterController::update -> Animation::runAnimation // (below) iter->first.getClass().getCreatureStats(iter->first).setLastHitObject(std::string()); + + // add guards to list to later make them fight with creatures + if (timerUpdateAITargets == 0 && iter->first.getClass().isClass(iter->first, "Guard")) + listGuards.push_back(iter->first); } - // AI and magic effects update - for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + + listGuards.push_back(player); + + // AI and magic effects update + for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); - if (iter->first.getTypeName() == typeid(ESM::NPC).name()) - updateNpc(iter->first, duration, paused); + + if (MWBase::Environment::get().getMechanicsManager()->isAIActive()) + { + // make guards and creatures fight each other + if (timerUpdateAITargets == 0 && !iter->first.getClass().isNpc() && !listGuards.empty()) + { + //findNthClosest + sBasePoint = Ogre::Vector3(iter->first.getRefData().getPosition().pos); + listGuards.sort(comparePtrDist); // try to engage combat starting from the nearest creature + + for (std::list::const_iterator it = listGuards.cbegin(); it != listGuards.cend(); ++it) + { + engageCombat(iter->first, *it, false); + } + } + + if (iter->first != player) engageCombat(iter->first, player, true); + + if (iter->first.getClass().isNpc() && iter->first != player) + updateCrimePersuit(iter->first, duration); + + if (iter->first != player) + iter->first.getClass().getCreatureStats(iter->first).getAiSequence().execute(iter->first, duration); + } + + if(iter->first.getTypeName() == typeid(ESM::NPC).name()) + updateNpc(iter->first, duration); } } + timerUpdateAITargets += duration; + // Looping magic VFX update // Note: we need to do this before any of the animations are updated. // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), // so updating VFX immediately after that would just remove the particle effects instantly. // There needs to be a magic effect update in between. - for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) iter->second->updateContinuousVfx(); // Animation/movement update - for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).mMagnitude > 0) @@ -872,7 +932,7 @@ namespace MWMechanics } // Kill dead actors, update some variables - for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) + for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); @@ -945,7 +1005,6 @@ namespace MWMechanics } // if player is in sneak state see if anyone detects him - const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) { const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -1075,9 +1134,7 @@ namespace MWMechanics if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) { MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); - // TODO: This is wrong! It's comparing Ref IDs with Ogre handles. The only case where this (coincidentally) works is the player. - // possibly applies to other code using getTargetId. - if(package->getTargetId() == actor.getCellRef().mRefID) + if(package->getTarget() == actor) list.push_front(*iter); } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index f7dff1058b..c6b72c9581 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -27,7 +27,7 @@ namespace MWMechanics { std::map mDeathCount; - void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused); + void updateNpc(const MWWorld::Ptr &ptr, float duration); void adjustMagicEffects (const MWWorld::Ptr& creature); @@ -81,6 +81,12 @@ namespace MWMechanics ///< This function is normally called automatically during the update process, but it can /// also be called explicitly at any time to force an update. + /** Start combat between two actors + @Notes: If againstPlayer = true then actor2 should be the Player. + If one of the combatants is creature it should be actor1. + */ + void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer); + void restoreDynamicStats(bool sleep); ///< If the player is sleeping, this should be called every hour. diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8464cc419c..9b2e73edb8 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -149,11 +149,8 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description - if(!actor.getClass().getCreatureStats(actor).isHostile() - || actor.getClass().getCreatureStats(actor).getHealth().getCurrent() <= 0) - return true; - - if(mTarget.getClass().getCreatureStats(mTarget).isDead()) + if(actor.getClass().getCreatureStats(actor).isDead() + || mTarget.getClass().getCreatureStats(mTarget).isDead() ) return true; //Update every frame @@ -627,9 +624,9 @@ namespace MWMechanics return 1; } - const std::string &AiCombat::getTargetId() const + const MWWorld::Ptr &AiCombat::getTarget() const { - return mTarget.getRefData().getHandle(); + return mTarget; } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 30b72acd92..388e6c3484 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -28,7 +28,7 @@ namespace MWMechanics virtual unsigned int getPriority() const; - const std::string &getTargetId() const; + const MWWorld::Ptr &getTarget() const; private: PathFinder mPathFinder; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 2134b7bba4..1ed135a67f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -61,7 +61,35 @@ bool MWMechanics::AiSequence::getCombatTarget(std::string &targetActorId) const if (getTypeId() != AiPackage::TypeIdCombat) return false; const AiCombat *combat = static_cast(mPackages.front()); - targetActorId = combat->getTargetId(); + targetActorId = combat->getTarget().getRefData().getHandle(); + + return true; +} + +bool MWMechanics::AiSequence::canAddTarget(const ESM::Position& actorPos, float distToTarget) const +{ + bool firstCombatFound = false; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + + for(std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + { + if ((*it)->getTypeId() == AiPackage::TypeIdCombat) + { + firstCombatFound = true; + + const AiCombat *combat = static_cast(*it); + if (combat->getTarget() != player) return false; // only 1 non-player target allowed + else + { + // add new target only if current target (player) is farther + ESM::Position &targetPos = combat->getTarget().getRefData().getPosition(); + + float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length(); + return (distToCurrTarget > distToTarget); + } + } + else if (firstCombatFound) break; // assumes combat packages go one-by-one in packages list + } return true; } @@ -96,6 +124,40 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) { MWMechanics::AiPackage* package = mPackages.front(); mLastAiPackage = package->getTypeId(); + + // if active package is combat one, choose nearest target + if (mLastAiPackage == AiPackage::TypeIdCombat) + { + std::list::const_iterator itActualCombat; + + float nearestDist = std::numeric_limits::max(); + Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); + + const AiCombat *package; + + for(std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + { + package = static_cast(*it); + + if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; + + ESM::Position &targetPos = package->getTarget().getRefData().getPosition(); + + float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); + if (distTo < nearestDist) + { + nearestDist = distTo; + itActualCombat = it; + } + } + + if (mPackages.cbegin() != itActualCombat) + { + // move combat package with nearest target to the front + mPackages.splice(mPackages.begin(), mPackages, itActualCombat); + } + } + if (package->execute (actor,duration)) { // To account for the rare case where AiPackage::execute() queued another AI package diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 37e0c7f17e..50cd3bea8a 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -47,6 +47,9 @@ namespace MWMechanics ///< Return true and assign target if combat package is currently /// active, return false otherwise + bool canAddTarget(const ESM::Position& actorPos, float distToTarget) const; + ///< Function assumes that actor can have only 1 target apart player + void stopCombat(); ///< Removes all combat packages until first non-combat or stack empty. From d70306382eac080677ef6bf3cea7303440a931ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 00:58:12 +0200 Subject: [PATCH 293/545] Don't create the player object until the game starts Fixes a crash introduced in e591d23 when using --skip-menu=0. --- apps/openmw/engine.cpp | 44 +++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 03361408cf..66c09b6ff7 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -66,9 +66,13 @@ void OMW::Engine::executeLocalScripts() bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt) { - bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode(); - MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame, paused); - MWBase::Environment::get().getWindowManager ()->frameStarted(evt.timeSinceLastFrame); + if (MWBase::Environment::get().getStateManager()->getState()!= + MWBase::StateManager::State_NoGame) + { + bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode(); + MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame, paused); + MWBase::Environment::get().getWindowManager ()->frameStarted(evt.timeSinceLastFrame); + } return true; } @@ -110,8 +114,12 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // update actors - MWBase::Environment::get().getMechanicsManager()->update(frametime, - paused); + if (MWBase::Environment::get().getStateManager()->getState()!= + MWBase::StateManager::State_NoGame) + { + MWBase::Environment::get().getMechanicsManager()->update(frametime, + paused); + } if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_Running) @@ -122,16 +130,24 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } // update world - MWBase::Environment::get().getWorld()->update(frametime, paused); + if (MWBase::Environment::get().getStateManager()->getState()!= + MWBase::StateManager::State_NoGame) + { + MWBase::Environment::get().getWorld()->update(frametime, paused); + } // update GUI - Ogre::RenderWindow* window = mOgre->getWindow(); - unsigned int tri, batch; - MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); - MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); + if (MWBase::Environment::get().getStateManager()->getState()!= + MWBase::StateManager::State_NoGame) + { + Ogre::RenderWindow* window = mOgre->getWindow(); + unsigned int tri, batch; + MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); + MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); - MWBase::Environment::get().getWindowManager()->onFrame(frametime); - MWBase::Environment::get().getWindowManager()->update(); + MWBase::Environment::get().getWindowManager()->onFrame(frametime); + MWBase::Environment::get().getWindowManager()->update(); + } } catch (const std::exception& e) { @@ -393,10 +409,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); - mEnvironment.getWorld()->renderPlayer(); - mechanics->buildPlayer(); - window->updatePlayer(); - mOgre->getRoot()->addFrameListener (this); // scripts From 940a434479976e5dd5a48596804dbb4647a9265c Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 03:19:38 +0200 Subject: [PATCH 294/545] Use ItemModel for moving items from a container to the world Fixes owner not resetting when moving an item from a corpse to the world. --- apps/openmw/mwbase/world.hpp | 5 ++- apps/openmw/mwgui/container.cpp | 3 +- apps/openmw/mwgui/hud.cpp | 56 +++++++++++++++++++++++--------- apps/openmw/mwworld/worldimp.cpp | 9 ++--- apps/openmw/mwworld/worldimp.hpp | 5 ++- 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 0459d5341b..e16f001866 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -354,15 +354,14 @@ namespace MWBase virtual void update (float duration, bool paused) = 0; - virtual bool placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount) = 0; + virtual MWWorld::Ptr placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount) = 0; ///< copy and place an object into the gameworld at the specified cursor position /// @param object /// @param cursor X (relative 0-1) /// @param cursor Y (relative 0-1) /// @param number of objects to place - /// @return true if the object was placed, or false if it was rejected because the position is too far away - virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount) = 0; + virtual MWWorld::Ptr dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount) = 0; ///< copy and place an object into the gameworld at the given actor's position /// @param actor giving the dropped object position /// @param object diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5856473388..02c4b93560 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -91,7 +91,8 @@ namespace MWGui mSourceModel->update(); finish(); - targetView->update(); + if (targetView) + targetView->update(); // We need to update the view since an other item could be auto-equipped. mSourceView->update(); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index ccd4489ba8..dc02f9976e 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -17,9 +17,47 @@ #include "itemmodel.hpp" #include "container.hpp" +#include "itemmodel.hpp" + namespace MWGui { + /** + * Makes it possible to use ItemModel::moveItem to move an item from an inventory to the world. + */ + class WorldItemModel : public ItemModel + { + public: + WorldItemModel(float left, float top) : mLeft(left), mTop(top) {} + virtual ~WorldItemModel() {} + virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) + { + MWBase::World* world = MWBase::Environment::get().getWorld(); + + MWWorld::Ptr dropped; + if (world->canPlaceObject(mLeft, mTop)) + dropped = world->placeObject(item.mBase, mLeft, mTop, count); + else + dropped = world->dropObjectOnGround(world->getPlayerPtr(), item.mBase, count); + if (setNewOwner) + dropped.getCellRef().mOwner = ""; + + return dropped; + } + + virtual void removeItem (const ItemStack& item, size_t count) { throw std::runtime_error("removeItem not implemented"); } + virtual ModelIndex getIndex (ItemStack item) { throw std::runtime_error("getIndex not implemented"); } + virtual void update() {} + virtual size_t getItemCount() { return 0; } + virtual ItemStack getItem (ModelIndex index) { throw std::runtime_error("getItem not implemented"); } + + private: + // Where to drop the item + float mLeft; + float mTop; + }; + + HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) : Layout("openmw_hud.layout") , mHealth(NULL) @@ -229,10 +267,6 @@ namespace MWGui if (mDragAndDrop->mIsOnDragAndDrop) { // drop item into the gameworld - MWWorld::Ptr object = mDragAndDrop->mItem.mBase; - - MWBase::World* world = MWBase::Environment::get().getWorld(); - MWBase::Environment::get().getWorld()->breakInvisibility( MWBase::Environment::get().getWorld()->getPlayerPtr()); @@ -241,20 +275,10 @@ namespace MWGui float mouseX = cursorPosition.left / float(viewSize.width); float mouseY = cursorPosition.top / float(viewSize.height); - if (world->canPlaceObject(mouseX, mouseY)) - world->placeObject(object, mouseX, mouseY, mDragAndDrop->mDraggedCount); - else - world->dropObjectOnGround(world->getPlayerPtr(), object, mDragAndDrop->mDraggedCount); + WorldItemModel drop (mouseX, mouseY); + mDragAndDrop->drop(&drop, NULL); MWBase::Environment::get().getWindowManager()->changePointer("arrow"); - - std::string sound = MWWorld::Class::get(object).getDownSoundId(object); - MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - - // remove object from the container it was coming from - mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); - mDragAndDrop->finish(); - mDragAndDrop->mSourceModel->update(); } else { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2b1cbe4c72..47cb50463d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1567,12 +1567,12 @@ namespace MWWorld item.getRefData().getLocals().setVarByInt(script, "onpcdrop", 1); } - bool World::placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount) + MWWorld::Ptr World::placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount) { std::pair result = mPhysics->castRay(cursorX, cursorY); if (!result.first) - return false; + return MWWorld::Ptr(); CellStore* cell = getPlayerPtr().getCell(); @@ -1593,7 +1593,7 @@ namespace MWWorld // only the player place items in the world, so no need to check actor PCDropped(dropped); - return true; + return dropped; } bool World::canPlaceObject(float cursorX, float cursorY) @@ -1644,7 +1644,7 @@ namespace MWWorld return dropped; } - void World::dropObjectOnGround (const Ptr& actor, const Ptr& object, int amount) + MWWorld::Ptr World::dropObjectOnGround (const Ptr& actor, const Ptr& object, int amount) { MWWorld::CellStore* cell = actor.getCell(); @@ -1673,6 +1673,7 @@ namespace MWWorld if(actor == mPlayer->getPlayer()) // Only call if dropped by player PCDropped(dropped); + return dropped; } void World::processChangedSettings(const Settings::CategorySettingVector& settings) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7b85c3ed87..490fdf5a70 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -439,15 +439,14 @@ namespace MWWorld virtual void update (float duration, bool paused); - virtual bool placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount); + virtual MWWorld::Ptr placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount); ///< copy and place an object into the gameworld at the specified cursor position /// @param object /// @param cursor X (relative 0-1) /// @param cursor Y (relative 0-1) /// @param number of objects to place - /// @return true if the object was placed, or false if it was rejected because the position is too far away - virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount); + virtual MWWorld::Ptr dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount); ///< copy and place an object into the gameworld at the given actor's position /// @param actor giving the dropped object position /// @param object From 868e38a07c5e1130e1ee3ce61866d3d0a6475def Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 08:32:00 +0200 Subject: [PATCH 295/545] Fix Assault crimes being reported when striking in self-defense Last missing fix for Bug #1134. --- apps/openmw/mwclass/npc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 845fffbc0d..6d2eea6af5 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -621,7 +621,8 @@ namespace MWClass // Attacking peaceful NPCs is a crime // anything below 80 is considered peaceful (see Actors::updateActor) - if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) + if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).isHostile() && + ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); getCreatureStats(ptr).setAttacked(true); From 028e00c98f6dc5274e6a5c005878f03bb4cebc65 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 09:21:08 +0200 Subject: [PATCH 296/545] Add missing status report for some toggle commands --- apps/openmw/mwbase/windowmanager.hpp | 4 ++-- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 3 ++- apps/openmw/mwgui/mapwindow.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 3 ++- apps/openmw/mwgui/tooltips.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 8 ++++---- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ++-- apps/openmw/mwrender/renderingmanager.cpp | 4 ++-- apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwrender/water.cpp | 3 ++- apps/openmw/mwrender/water.hpp | 2 +- apps/openmw/mwscript/guiextensions.cpp | 6 ++++-- apps/openmw/mwscript/miscextensions.cpp | 3 ++- apps/openmw/mwworld/worldimp.cpp | 4 ++-- apps/openmw/mwworld/worldimp.hpp | 2 +- 16 files changed, 30 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 39cfc47eda..44ebed3e98 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -193,9 +193,9 @@ namespace MWBase virtual void setDragDrop(bool dragDrop) = 0; virtual bool getWorldMouseOver() = 0; - virtual void toggleFogOfWar() = 0; + virtual bool toggleFogOfWar() = 0; - virtual void toggleFullHelp() = 0; + virtual bool toggleFullHelp() = 0; ///< show extra info in item tooltips (owner, script) virtual bool getFullHelp() const = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index e16f001866..2ddd01ac4a 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -126,7 +126,7 @@ namespace MWBase virtual void setWaterHeight(const float height) = 0; - virtual void toggleWater() = 0; + virtual bool toggleWater() = 0; virtual void adjustSky() = 0; diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 2bd5e44cbd..29c065f3d5 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -89,10 +89,11 @@ namespace MWGui mChanged = true; } - void LocalMapBase::toggleFogOfWar() + bool LocalMapBase::toggleFogOfWar() { mFogOfWar = !mFogOfWar; applyFogOfWar(); + return mFogOfWar; } void LocalMapBase::applyFogOfWar() diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 5251fac230..d23b0c2285 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -35,7 +35,7 @@ namespace MWGui void setPlayerDir(const float x, const float y); void setPlayerPos(const float x, const float y); - void toggleFogOfWar(); + bool toggleFogOfWar(); struct MarkerPosition { diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index f941c699b4..b931966f07 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -547,9 +547,10 @@ namespace MWGui return " (" + boost::lexical_cast(value) + ")"; } - void ToolTips::toggleFullHelp() + bool ToolTips::toggleFullHelp() { mFullHelp = !mFullHelp; + return mFullHelp; } bool ToolTips::getFullHelp() const diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index be5c631913..4e73cc5551 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -45,7 +45,7 @@ namespace MWGui void setEnabled(bool enabled); - void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) + bool toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; void setDelay(float delay); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ed6910221b..3cf7379ff9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -814,10 +814,10 @@ namespace MWGui mHud->setMinimapVisible (visible); } - void WindowManager::toggleFogOfWar() + bool WindowManager::toggleFogOfWar() { mMap->toggleFogOfWar(); - mHud->toggleFogOfWar(); + return mHud->toggleFogOfWar(); } void WindowManager::setFocusObject(const MWWorld::Ptr& focus) @@ -830,9 +830,9 @@ namespace MWGui mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y); } - void WindowManager::toggleFullHelp() + bool WindowManager::toggleFullHelp() { - mToolTips->toggleFullHelp(); + return mToolTips->toggleFullHelp(); } bool WindowManager::getFullHelp() const diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 7617a4463d..c98c32c524 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -188,8 +188,8 @@ namespace MWGui virtual void setDragDrop(bool dragDrop); virtual bool getWorldMouseOver(); - virtual void toggleFogOfWar(); - virtual void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) + virtual bool toggleFogOfWar(); + virtual bool toggleFullHelp(); ///< show extra info in item tooltips (owner, script) virtual bool getFullHelp() const; virtual void setActiveMap(int x, int y, bool interior); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a3c53dc444..9398e033a1 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -234,9 +234,9 @@ void RenderingManager::removeWater () mWater->setActive(false); } -void RenderingManager::toggleWater() +bool RenderingManager::toggleWater() { - mWater->toggle(); + return mWater->toggle(); } void RenderingManager::cellAdded (MWWorld::CellStore *store) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index eb68272925..d59e1e27d4 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -127,7 +127,7 @@ public: void rotateObject (const MWWorld::Ptr& ptr); void setWaterHeight(const float height); - void toggleWater(); + bool toggleWater(); /// Updates object rendering after cell change /// \param old Object reference in previous cell diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 5368cbe687..2cbc4462c3 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -326,10 +326,11 @@ void Water::setHeight(const float height) sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); } -void Water::toggle() +bool Water::toggle() { mToggled = !mToggled; updateVisible(); + return mToggled; } void diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 481a412977..6a7b05a3aa 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -150,7 +150,7 @@ namespace MWRender { void setActive(bool active); - void toggle(); + bool toggle(); void update(float dt, Ogre::Vector3 player); void frameStarted(float dt); diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 57fc2d4707..be241a5649 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -92,7 +92,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getWindowManager()->toggleFogOfWar(); + runtime.getContext().report(MWBase::Environment::get().getWindowManager()->toggleFogOfWar() ? "Fog of war -> On" + : "Fog of war -> Off"); } }; @@ -102,7 +103,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getWindowManager()->toggleFullHelp(); + runtime.getContext().report(MWBase::Environment::get().getWindowManager()->toggleFullHelp() ? "Full help -> On" + : "Full help -> Off"); } }; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 20013493f2..620a0d0c94 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -275,7 +275,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getWorld()->toggleWater(); + runtime.getContext().report(MWBase::Environment::get().getWorld()->toggleWater() ? "Water -> On" + : "Water -> Off"); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 47cb50463d..2634788902 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1553,9 +1553,9 @@ namespace MWWorld mRendering->setWaterHeight(height); } - void World::toggleWater() + bool World::toggleWater() { - mRendering->toggleWater(); + return mRendering->toggleWater(); } void World::PCDropped (const Ptr& item) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 490fdf5a70..a86cebfd2a 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -213,7 +213,7 @@ namespace MWWorld virtual void setWaterHeight(const float height); - virtual void toggleWater(); + virtual bool toggleWater(); virtual void adjustSky(); From 36d9ae17cc07e27c9a7f4db8e8b8da24dfc09ac4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 12:11:34 +0200 Subject: [PATCH 297/545] Revert "Change all AI packages (except AiActivate) to use ActorIds" Causes potential infinite loops (AiSequence::fill -> AiPackage() -> getCreatureStats -> ensureCustomData -> ..) This reverts commit 2e9985c1a371b0e5970f3791cc6d8298a624380a. --- apps/openmw/mwmechanics/actors.cpp | 6 +++--- apps/openmw/mwmechanics/aicombat.cpp | 29 +++++++++++--------------- apps/openmw/mwmechanics/aicombat.hpp | 6 +++--- apps/openmw/mwmechanics/aiescort.cpp | 21 ++++++------------- apps/openmw/mwmechanics/aiescort.hpp | 6 +++--- apps/openmw/mwmechanics/aifollow.cpp | 20 +++++++----------- apps/openmw/mwmechanics/aifollow.hpp | 22 +++++++++---------- apps/openmw/mwmechanics/aipursue.cpp | 11 +++++----- apps/openmw/mwmechanics/aipursue.hpp | 6 +++--- apps/openmw/mwmechanics/aisequence.cpp | 6 ++---- apps/openmw/mwscript/aiextensions.cpp | 14 +++++-------- 11 files changed, 61 insertions(+), 86 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a0616258c7..108cc8cc5e 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -540,7 +540,7 @@ namespace MWMechanics MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); // Make the summoned creature follow its master and help in fights - AiFollow package(ptr); + AiFollow package(ptr.getRefData().getHandle()); summonedCreatureStats.getAiSequence().stack(package, ref.getPtr()); int creatureActorId = summonedCreatureStats.getActorId(); @@ -759,7 +759,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPursue(player), ptr); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -788,7 +788,7 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPursue(player), ptr); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); else { MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 72cb8f5740..8464cc419c 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -81,7 +81,7 @@ namespace MWMechanics // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp AiCombat::AiCombat(const MWWorld::Ptr& actor) : - mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId()), + mTarget(actor), mTimerAttack(0), mTimerReact(0), mTimerCombatMove(0), @@ -153,9 +153,7 @@ namespace MWMechanics || actor.getClass().getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); - - if(target.getClass().getCreatureStats(target).isDead()) + if(mTarget.getClass().getCreatureStats(mTarget).isDead()) return true; //Update every frame @@ -327,7 +325,7 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); Ogre::Vector3 vActorPos(pos.pos); - Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); + Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; bool isStuck = false; @@ -398,7 +396,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); + bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); if(mReadyToAttack) isStuck = false; @@ -434,7 +432,7 @@ namespace MWMechanics mFollowTarget = false; - buildNewPath(actor, target); //may fail to build a path, check before use + buildNewPath(actor); //may fail to build a path, check before use //delete visited path node mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]); @@ -478,9 +476,9 @@ namespace MWMechanics //less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing) //then start attacking float speed1 = actorCls.getSpeed(actor); - float speed2 = target.getClass().getSpeed(target); - if(target.getClass().getMovementSettings(target).mPosition[0] == 0 - && target.getClass().getMovementSettings(target).mPosition[1] == 0) + float speed2 = mTarget.getClass().getSpeed(mTarget); + if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0 + && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) speed2 = 0; float s1 = distToTarget - weapRange; @@ -572,9 +570,9 @@ namespace MWMechanics return false; } - void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) + void AiCombat::buildNewPath(const MWWorld::Ptr& actor) { - Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); + Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); float dist; @@ -629,12 +627,9 @@ namespace MWMechanics return 1; } - std::string AiCombat::getTargetId() const + const std::string &AiCombat::getTargetId() const { - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); - if (target.isEmpty()) - return ""; - return target.getRefData().getHandle(); + return mTarget.getRefData().getHandle(); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 9125e28325..833b0063c9 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -31,7 +31,7 @@ namespace MWMechanics virtual unsigned int getPriority() const; ///Returns target ID - std::string getTargetId() const; + const std::string &getTargetId() const; private: PathFinder mPathFinder; @@ -53,7 +53,7 @@ namespace MWMechanics ESM::Position mLastPos; MWMechanics::Movement mMovement; - int mTargetActorId; + MWWorld::Ptr mTarget; const MWWorld::CellStore* mCell; ObstacleCheck mObstacleCheck; @@ -63,7 +63,7 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator mDoorIter; MWWorld::CellRefList& mDoors; - void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); + void buildNewPath(const MWWorld::Ptr& actor); }; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index f3ce7143a4..0430adf06a 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -8,8 +8,6 @@ #include "../mwworld/class.hpp" #include "../mwworld/timestamp.hpp" -#include "../mwmechanics/creaturestats.hpp" - #include "steering.hpp" #include "movement.hpp" @@ -21,8 +19,8 @@ namespace MWMechanics { - AiEscort::AiEscort(const MWWorld::Ptr& actor, int duration, float x, float y, float z) - : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z) + : mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -40,8 +38,8 @@ namespace MWMechanics } } - AiEscort::AiEscort(const MWWorld::Ptr& actor, const std::string &cellId,int duration, float x, float y, float z) - : mActorId(actor.getClass().getCreatureStats(actor).getActorId()), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) + AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z) + : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -77,14 +75,7 @@ namespace MWMechanics return true; } - const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); - if (follower.isEmpty()) - { - // The follower disappeared - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; - return true; - } - + const MWWorld::Ptr follower = MWBase::Environment::get().getWorld()->getPtr(mActorId, false); const float* const leaderPos = actor.getRefData().getPosition().pos; const float* const followerPos = follower.getRefData().getPosition().pos; double differenceBetween[3]; @@ -98,7 +89,7 @@ namespace MWMechanics if(distanceBetweenResult <= mMaxDist * mMaxDist) { - if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete + if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete return true; mMaxDist = 470; } diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index b8dc9d6e0f..3771417fa2 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -15,11 +15,11 @@ namespace MWMechanics /// Implementation of AiEscort /** The Actor will escort the specified actor to the world position x, y, z until they reach their position, or they run out of time \implement AiEscort **/ - AiEscort(const MWWorld::Ptr& actor,int duration, float x, float y, float z); + AiEscort(const std::string &actorId,int duration, float x, float y, float z); /// Implementation of AiEscortCell /** The Actor will escort the specified actor to the cell position x, y, z until they reach their position, or they run out of time \implement AiEscortCell **/ - AiEscort(const MWWorld::Ptr& actor,const std::string &cellId,int duration, float x, float y, float z); + AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); virtual AiEscort *clone() const; @@ -28,7 +28,7 @@ namespace MWMechanics virtual int getTypeId() const; private: - int mActorId; + std::string mActorId; std::string mCellId; float mX; float mY; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index d747781a38..f1296a9493 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -11,26 +11,23 @@ #include "steering.hpp" -MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() { - mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mCellId(cellId), AiPackage() +MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() { - mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } -MWMechanics::AiFollow::AiFollow(const MWWorld::Ptr& actor) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mCellId(""), AiPackage() +MWMechanics::AiFollow::AiFollow(const std::string &actorId) +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() { - mActorId = actor.getClass().getCreatureStats(actor).getActorId(); } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -78,8 +75,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) std::string MWMechanics::AiFollow::getFollowedActor() { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow - return target.getCellRef().mRefID; + return mActorId; } MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 91bdbdac2f..10a381410a 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -10,16 +10,16 @@ namespace MWMechanics { /// \brief AiPackage for an actor to follow another actor/the PC /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely - **/ - class AiFollow : public AiPackage - { + **/ + class AiFollow : public AiPackage + { public: /// Follow Actor for duration or until you arrive at a world position - AiFollow(const MWWorld::Ptr& actor,float duration, float X, float Y, float Z); + AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); /// Follow Actor for duration or until you arrive at a position in a cell - AiFollow(const MWWorld::Ptr& actor,const std::string &CellId,float duration, float X, float Y, float Z); + AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); /// Follow Actor indefinitively - AiFollow(const MWWorld::Ptr& actor); + AiFollow(const std::string &ActorId); virtual AiFollow *clone() const; @@ -38,8 +38,8 @@ namespace MWMechanics float mX; float mY; float mZ; - int mActorId; // The actor we should follow - std::string mCellId; - }; -} -#endif + std::string mActorId; + std::string mCellId; + }; +} +#endif diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index aa71af4658..6e91ccb719 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -7,14 +7,12 @@ #include "../mwworld/action.hpp" #include "../mwworld/cellstore.hpp" -#include "../mwmechanics/creaturestats.hpp" - #include "steering.hpp" #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPursue::AiPursue(const MWWorld::Ptr& actor) - : mActorId(actor.getClass().getCreatureStats(actor).getActorId()) +MWMechanics::AiPursue::AiPursue(const std::string &objectId) + : mObjectId(objectId) { } MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const @@ -25,7 +23,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { ESM::Position pos = actor.getRefData().getPosition(); //position of the actor - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -35,7 +33,8 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - target.getClass().activate(target,actor).get()->execute(actor); //Arrest player + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } else { diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 90ff8df93b..2eb533d625 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -16,14 +16,14 @@ namespace MWMechanics { public: ///Constructor - /** \param actor Actor to pursue **/ - AiPursue(const MWWorld::Ptr& actor); + /** \param objectId Actor to pursue **/ + AiPursue(const std::string &objectId); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); virtual int getTypeId() const; private: - int mActorId; // The actor to pursue + std::string mObjectId; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 8afe8402ff..0b1da180d7 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -175,8 +175,7 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else if (it->mType == ESM::AI_Escort) { ESM::AITarget data = it->mTarget; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); - package = new MWMechanics::AiEscort(target, data.mDuration, data.mX, data.mY, data.mZ); + package = new MWMechanics::AiEscort(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } else if (it->mType == ESM::AI_Travel) { @@ -191,8 +190,7 @@ void MWMechanics::AiSequence::fill(const ESM::AIPackageList &list) else //if (it->mType == ESM::AI_Follow) { ESM::AITarget data = it->mTarget; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(data.mId.toString(), false); - package = new MWMechanics::AiFollow(target, data.mDuration, data.mX, data.mY, data.mZ); + package = new MWMechanics::AiFollow(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } mPackages.push_back(package); } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 8ed19925ec..e53b53e58f 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -91,7 +91,6 @@ namespace MWScript std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -108,7 +107,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -147,7 +145,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); @@ -300,7 +297,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; igetPtr(actorID, true); std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -339,8 +335,8 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i Date: Fri, 16 May 2014 12:20:36 +0200 Subject: [PATCH 298/545] Manually re-added AiCombat portion of actorid changes. This is the only one that really matters, and will not suffer from the infinite recursion because it's not included in AiSequence::fill. --- apps/openmw/mwmechanics/aicombat.cpp | 29 ++++++++++++++++------------ apps/openmw/mwmechanics/aicombat.hpp | 6 +++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8464cc419c..72cb8f5740 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -81,7 +81,7 @@ namespace MWMechanics // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp AiCombat::AiCombat(const MWWorld::Ptr& actor) : - mTarget(actor), + mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId()), mTimerAttack(0), mTimerReact(0), mTimerCombatMove(0), @@ -153,7 +153,9 @@ namespace MWMechanics || actor.getClass().getCreatureStats(actor).getHealth().getCurrent() <= 0) return true; - if(mTarget.getClass().getCreatureStats(mTarget).isDead()) + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + + if(target.getClass().getCreatureStats(target).isDead()) return true; //Update every frame @@ -325,7 +327,7 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); Ogre::Vector3 vActorPos(pos.pos); - Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; bool isStuck = false; @@ -396,7 +398,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); + bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); if(mReadyToAttack) isStuck = false; @@ -432,7 +434,7 @@ namespace MWMechanics mFollowTarget = false; - buildNewPath(actor); //may fail to build a path, check before use + buildNewPath(actor, target); //may fail to build a path, check before use //delete visited path node mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]); @@ -476,9 +478,9 @@ namespace MWMechanics //less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing) //then start attacking float speed1 = actorCls.getSpeed(actor); - float speed2 = mTarget.getClass().getSpeed(mTarget); - if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0 - && mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0) + float speed2 = target.getClass().getSpeed(target); + if(target.getClass().getMovementSettings(target).mPosition[0] == 0 + && target.getClass().getMovementSettings(target).mPosition[1] == 0) speed2 = 0; float s1 = distToTarget - weapRange; @@ -570,9 +572,9 @@ namespace MWMechanics return false; } - void AiCombat::buildNewPath(const MWWorld::Ptr& actor) + void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) { - Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); + Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); float dist; @@ -627,9 +629,12 @@ namespace MWMechanics return 1; } - const std::string &AiCombat::getTargetId() const + std::string AiCombat::getTargetId() const { - return mTarget.getRefData().getHandle(); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); + if (target.isEmpty()) + return ""; + return target.getRefData().getHandle(); } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 833b0063c9..9125e28325 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -31,7 +31,7 @@ namespace MWMechanics virtual unsigned int getPriority() const; ///Returns target ID - const std::string &getTargetId() const; + std::string getTargetId() const; private: PathFinder mPathFinder; @@ -53,7 +53,7 @@ namespace MWMechanics ESM::Position mLastPos; MWMechanics::Movement mMovement; - MWWorld::Ptr mTarget; + int mTargetActorId; const MWWorld::CellStore* mCell; ObstacleCheck mObstacleCheck; @@ -63,7 +63,7 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator mDoorIter; MWWorld::CellRefList& mDoors; - void buildNewPath(const MWWorld::Ptr& actor); + void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target); }; } From e5a21aca53ba029e901066dd04b7d65289c19ee5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 May 2014 13:09:23 +0200 Subject: [PATCH 299/545] Refactor projectiles to no longer use MW-objects --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/soundmanager.hpp | 15 +- apps/openmw/mwbase/world.hpp | 5 +- apps/openmw/mwmechanics/spellcasting.cpp | 55 +++- apps/openmw/mwrender/effectmanager.cpp | 12 - apps/openmw/mwrender/effectmanager.hpp | 14 + apps/openmw/mwsound/soundmanagerimp.cpp | 38 +++ apps/openmw/mwsound/soundmanagerimp.hpp | 10 + apps/openmw/mwworld/projectilemanager.cpp | 261 +++++++++++++++++ apps/openmw/mwworld/projectilemanager.hpp | 104 +++++++ apps/openmw/mwworld/scene.cpp | 3 - apps/openmw/mwworld/worldimp.cpp | 335 ++-------------------- apps/openmw/mwworld/worldimp.hpp | 47 +-- 13 files changed, 528 insertions(+), 373 deletions(-) create mode 100644 apps/openmw/mwworld/projectilemanager.cpp create mode 100644 apps/openmw/mwworld/projectilemanager.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index aee5cbeacc..e791ab8910 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwworld cells localscripts customdata weather inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor - contentloader esmloader omwloader actiontrap cellreflist + contentloader esmloader omwloader actiontrap cellreflist projectilemanager ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index f3973153a2..15739730ba 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -110,18 +110,25 @@ namespace MWBase ///< Play a sound, independently of 3D-position ///< @param offset Value from [0,1] meaning from which fraction the sound the playback starts. - virtual SoundPtr playSound3D(const MWWorld::Ptr &reference, const std::string& soundId, - float volume, float pitch, PlayType type=Play_TypeSfx, - PlayMode mode=Play_Normal, float offset=0) = 0; - ///< Play a sound from an object + virtual MWBase::SoundPtr playSound3D(const MWWorld::Ptr &reference, const std::string& soundId, + float volume, float pitch, PlayType type=Play_TypeSfx, + PlayMode mode=Play_Normal, float offset=0) = 0; + ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. ///< @param offset Value from [0,1] meaning from which fraction the sound the playback starts. + virtual MWBase::SoundPtr playManualSound3D(const Ogre::Vector3& initialPos, const std::string& soundId, + float volume, float pitch, PlayType type, PlayMode mode, float offset=0) = 0; + ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated manually using Sound::setPosition. + virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId) = 0; ///< Stop the given object from playing the given sound, virtual void stopSound3D(const MWWorld::Ptr &reference) = 0; ///< Stop the given object from playing all sounds. + virtual void stopSound(MWBase::SoundPtr sound) = 0; + ///< Stop the given sound handle + virtual void stopSound(const MWWorld::CellStore *cell) = 0; ///< Stop all sounds for the given cell. diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 2ddd01ac4a..d1ecd11a0e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -467,7 +467,8 @@ namespace MWBase virtual void castSpell (const MWWorld::Ptr& actor) = 0; - virtual void launchMagicBolt (const std::string& id, bool stack, const ESM::EffectList& effects, + virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId, + float speed, bool stack, const ESM::EffectList& effects, const MWWorld::Ptr& actor, const std::string& sourceName) = 0; virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) = 0; @@ -513,7 +514,7 @@ namespace MWBase /// Spawn a blood effect for \a ptr at \a worldPosition 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, + virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0; }; } diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 0843e3e547..91a81c74be 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -21,6 +21,41 @@ #include "magiceffects.hpp" #include "npcstats.hpp" +namespace +{ + + /// Get projectile properties (model, sound and speed) for a spell with the given effects + /// If \a model is empty, the spell has no ranged effects and should not spawn a projectile. + void getProjectileInfo (const ESM::EffectList& effects, std::string& model, std::string& sound, float& speed) + { + for (std::vector::const_iterator iter (effects.mList.begin()); + iter!=effects.mList.end(); ++iter) + { + if (iter->mRange != ESM::RT_Target) + continue; + + const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( + iter->mEffectID); + + model = magicEffect->mBolt; + if (model.empty()) + model = "VFX_DefaultBolt"; + + static const std::string schools[] = { + "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" + }; + if (!magicEffect->mBoltSound.empty()) + sound = magicEffect->mBoltSound; + else + sound = schools[magicEffect->mData.mSchool] + " bolt"; + + speed = magicEffect->mData.mSpeed; + break; + } + } + +} + namespace MWMechanics { @@ -409,7 +444,7 @@ namespace MWMechanics } if (!exploded) - MWBase::Environment::get().getWorld()->explodeSpell(mHitPosition, mTarget, effects, caster, mId, mSourceName); + MWBase::Environment::get().getWorld()->explodeSpell(mHitPosition, effects, caster, mId, mSourceName); if (!reflectedEffects.mList.empty()) inflict(caster, target, reflectedEffects, range, true); @@ -603,7 +638,13 @@ namespace MWMechanics inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Touch); } - MWBase::Environment::get().getWorld()->launchMagicBolt(mId, false, enchantment->mEffects, mCaster, mSourceName); + std::string projectileModel; + std::string sound; + float speed = 0; + getProjectileInfo(enchantment->mEffects, projectileModel, sound, speed); + if (!projectileModel.empty()) + MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, + false, enchantment->mEffects, mCaster, mSourceName); return true; } @@ -682,7 +723,15 @@ namespace MWMechanics } } - MWBase::Environment::get().getWorld()->launchMagicBolt(mId, false, spell->mEffects, mCaster, mSourceName); + + std::string projectileModel; + std::string sound; + float speed = 0; + getProjectileInfo(spell->mEffects, projectileModel, sound, speed); + if (!projectileModel.empty()) + MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, + false, spell->mEffects, mCaster, mSourceName); + return true; } diff --git a/apps/openmw/mwrender/effectmanager.cpp b/apps/openmw/mwrender/effectmanager.cpp index 1e6119daac..968be0f9e9 100644 --- a/apps/openmw/mwrender/effectmanager.cpp +++ b/apps/openmw/mwrender/effectmanager.cpp @@ -11,18 +11,6 @@ namespace MWRender { -class EffectAnimationTime : public Ogre::ControllerValue -{ -private: - float mTime; -public: - EffectAnimationTime() : mTime(0) { } - void addTime(float time) { mTime += time; } - - virtual Ogre::Real getValue() const { return mTime; } - virtual void setValue(Ogre::Real value) {} -}; - EffectManager::EffectManager(Ogre::SceneManager *sceneMgr) : mSceneMgr(sceneMgr) { diff --git a/apps/openmw/mwrender/effectmanager.hpp b/apps/openmw/mwrender/effectmanager.hpp index bc9e68d269..eb68636555 100644 --- a/apps/openmw/mwrender/effectmanager.hpp +++ b/apps/openmw/mwrender/effectmanager.hpp @@ -5,6 +5,20 @@ namespace MWRender { + + class EffectAnimationTime : public Ogre::ControllerValue + { + private: + float mTime; + public: + EffectAnimationTime() : mTime(0) { } + void addTime(float time) { mTime += time; } + + virtual Ogre::Real getValue() const { return mTime; } + virtual void setValue(Ogre::Real value) {} + }; + + // Note: effects attached to another object should be managed by MWRender::Animation::addEffect. // This class manages "free" effects, i.e. attached to a dedicated scene node in the world. class EffectManager diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 8ce87a25e0..dc31772c97 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -356,6 +356,44 @@ namespace MWSound return sound; } + MWBase::SoundPtr SoundManager::playManualSound3D(const Ogre::Vector3& initialPos, const std::string& soundId, + float volume, float pitch, PlayType type, PlayMode mode, float offset) + { + MWBase::SoundPtr sound; + if(!mOutput->isInitialized()) + return sound; + try + { + // Look up the sound in the ESM data + float basevol = volumeFromType(type); + float min, max; + std::string file = lookup(soundId, volume, min, max); + + sound = mOutput->playSound3D(file, initialPos, volume, basevol, pitch, min, max, mode|type, offset); + mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); + } + catch(std::exception &e) + { + //std::cout <<"Sound Error: "<first == sound) + { + snditer->first->stop(); + mActiveSounds.erase(snditer++); + } + else + ++snditer; + } + } + void SoundManager::stopSound3D(const MWWorld::Ptr &ptr, const std::string& soundId) { SoundMap::iterator snditer = mActiveSounds.begin(); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 1454240b4a..ab9dcf7345 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -115,6 +115,13 @@ namespace MWSound virtual MWBase::SoundPtr playSound3D(const MWWorld::Ptr &reference, const std::string& soundId, float volume, float pitch, PlayType type=Play_TypeSfx, PlayMode mode=Play_Normal, float offset=0); + ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. + ///< @param offset Value from [0,1] meaning from which fraction the sound the playback starts. + + virtual MWBase::SoundPtr playManualSound3D(const Ogre::Vector3& initialPos, const std::string& soundId, + float volume, float pitch, PlayType type, PlayMode mode, float offset=0); + ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated manually using Sound::setPosition. + ///< Play a sound from an object ///< @param offset value from [0,1], when to start playback. 0 is beginning, 1 is end. @@ -124,6 +131,9 @@ namespace MWSound virtual void stopSound3D(const MWWorld::Ptr &reference); ///< Stop the given object from playing all sounds. + virtual void stopSound(MWBase::SoundPtr sound); + ///< Stop the given sound handle + virtual void stopSound(const MWWorld::CellStore *cell); ///< Stop all sounds for the given cell. diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp new file mode 100644 index 0000000000..c886908f92 --- /dev/null +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -0,0 +1,261 @@ +#include "projectilemanager.hpp" + +#include + +#include + +#include "../mwworld/manualref.hpp" +#include "../mwworld/class.hpp" + +#include "../mwbase/soundmanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" + +#include "../mwmechanics/combat.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellcasting.hpp" + +#include "../mwrender/effectmanager.hpp" + +#include "../mwsound/sound.hpp" + +namespace MWWorld +{ + + ProjectileManager::ProjectileManager(Ogre::SceneManager* sceneMgr, OEngine::Physic::PhysicEngine &engine) + : mPhysEngine(engine) + , mSceneMgr(sceneMgr) + { + + } + + void ProjectileManager::createModel(State &state, const std::string &model) + { + state.mObject = NifOgre::Loader::createObjects(state.mNode, model); + for(size_t i = 0;i < state.mObject->mControllers.size();i++) + { + if(state.mObject->mControllers[i].getSource().isNull()) + state.mObject->mControllers[i].setSource(Ogre::SharedPtr (new MWRender::EffectAnimationTime())); + } + } + + void ProjectileManager::update(NifOgre::ObjectScenePtr object, float duration) + { + for(size_t i = 0; i < object->mControllers.size() ;i++) + { + MWRender::EffectAnimationTime* value = dynamic_cast(object->mControllers[i].getSource().get()); + if (value) + value->addTime(duration); + + object->mControllers[i].update(); + } + } + + void ProjectileManager::launchMagicBolt(const std::string &model, const std::string &sound, + const std::string &spellId, float speed, bool stack, + const ESM::EffectList &effects, const Ptr &actor, const std::string &sourceName) + { + // Spawn at 0.75 * ActorHeight + float height = mPhysEngine.getCharacter(actor.getRefData().getHandle())->getHalfExtents().z * 2 * 0.75; + + Ogre::Vector3 pos(actor.getRefData().getPosition().pos); + pos.z += height; + + Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * + Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X); + + MagicBoltState state; + state.mSourceName = sourceName; + state.mId = spellId; + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); + state.mSpeed = speed; + state.mStack = stack; + + // Only interested in "on target" effects + for (std::vector::const_iterator iter (effects.mList.begin()); + iter!=effects.mList.end(); ++iter) + { + if (iter->mRange == ESM::RT_Target) + state.mEffects.mList.push_back(*iter); + } + + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), model); + MWWorld::Ptr ptr = ref.getPtr(); + + state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos, orient); + createModel(state, ptr.getClass().getModel(ptr)); + + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + state.mSound = sndMgr->playManualSound3D(pos, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + + mMagicBolts.push_back(state); + } + + void ProjectileManager::launchProjectile(Ptr actor, Ptr projectile, const Ogre::Vector3 &pos, + const Ogre::Quaternion &orient, Ptr bow, float speed) + { + ProjectileState state; + state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); + state.mBow = bow; + state.mVelocity = orient.yAxis() * speed; + state.mProjectileId = projectile.getCellRef().mRefID; + + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().mRefID); + MWWorld::Ptr ptr = ref.getPtr(); + + state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos, orient); + createModel(state, ptr.getClass().getModel(ptr)); + + mProjectiles.push_back(state); + } + + void ProjectileManager::update(float dt) + { + moveProjectiles(dt); + moveMagicBolts(dt); + } + + void ProjectileManager::moveMagicBolts(float duration) + { + for (std::vector::iterator it = mMagicBolts.begin(); it != mMagicBolts.end();) + { + Ogre::Quaternion orient = it->mNode->getOrientation(); + static float fTargetSpellMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get() + .find("fTargetSpellMaxSpeed")->getFloat(); + float speed = fTargetSpellMaxSpeed * it->mSpeed; + + Ogre::Vector3 direction = orient.yAxis(); + direction.normalise(); + Ogre::Vector3 pos(it->mNode->getPosition()); + Ogre::Vector3 newPos = pos + direction * duration * speed; + + it->mSound->setPosition(newPos); + + it->mNode->setPosition(newPos); + + update(it->mObject, duration); + + // Check for impact + // TODO: use a proper btRigidBody / btGhostObject? + btVector3 from(pos.x, pos.y, pos.z); + btVector3 to(newPos.x, newPos.y, newPos.z); + std::vector > collisions = mPhysEngine.rayTest2(from, to); + bool hit=false; + + for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) + { + MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second); + + MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); + if (caster.isEmpty()) + caster = obstacle; + + if (obstacle.isEmpty()) + { + // Terrain + } + else + { + MWMechanics::CastSpell cast(caster, obstacle); + cast.mHitPosition = pos; + cast.mId = it->mId; + cast.mSourceName = it->mSourceName; + cast.mStack = it->mStack; + cast.inflict(obstacle, caster, it->mEffects, ESM::RT_Target, false, true); + } + + hit = true; + } + if (hit) + { + MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); + MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, it->mId, it->mSourceName); + + MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); + + mSceneMgr->destroySceneNode(it->mNode); + + it = mMagicBolts.erase(it); + continue; + } + else + ++it; + } + } + + void ProjectileManager::moveProjectiles(float duration) + { + for (std::vector::iterator it = mProjectiles.begin(); it != mProjectiles.end();) + { + // gravity constant - must be way lower than the gravity affecting actors, since we're not + // simulating aerodynamics at all + it->mVelocity -= Ogre::Vector3(0, 0, 627.2f * 0.1f) * duration; + + Ogre::Vector3 pos(it->mNode->getPosition()); + Ogre::Vector3 newPos = pos + it->mVelocity * duration; + + Ogre::Quaternion orient = Ogre::Vector3::UNIT_Y.getRotationTo(it->mVelocity); + it->mNode->setOrientation(orient); + it->mNode->setPosition(newPos); + + update(it->mObject, duration); + + // Check for impact + // TODO: use a proper btRigidBody / btGhostObject? + btVector3 from(pos.x, pos.y, pos.z); + btVector3 to(newPos.x, newPos.y, newPos.z); + std::vector > collisions = mPhysEngine.rayTest2(from, to); + bool hit=false; + + for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) + { + MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second); + + MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); + + // Arrow intersects with player immediately after shooting :/ + if (obstacle == caster) + continue; + + if (caster.isEmpty()) + caster = obstacle; + + if (obstacle.isEmpty()) + { + // Terrain + } + else if (obstacle.getClass().isActor()) + { + MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mProjectileId); + MWMechanics::projectileHit(caster, obstacle, it->mBow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first); + } + hit = true; + } + if (hit) + { + mSceneMgr->destroySceneNode(it->mNode); + + it = mProjectiles.erase(it); + continue; + } + else + ++it; + } + } + + void ProjectileManager::clear() + { + for (std::vector::iterator it = mProjectiles.begin(); it != mProjectiles.end(); ++it) + { + mSceneMgr->destroySceneNode(it->mNode); + } + mProjectiles.clear(); + for (std::vector::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it) + { + MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); + mSceneMgr->destroySceneNode(it->mNode); + } + mMagicBolts.clear(); + } + +} diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp new file mode 100644 index 0000000000..e934bf6aba --- /dev/null +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -0,0 +1,104 @@ +#ifndef OPENMW_MWWORLD_PROJECTILEMANAGER_H +#define OPENMW_MWWORLD_PROJECTILEMANAGER_H + +#include + +#include + +#include +#include + +#include "../mwbase/soundmanager.hpp" + +#include "ptr.hpp" + +namespace OEngine +{ +namespace Physic +{ + class PhysicEngine; +} +} + +namespace Ogre +{ + class SceneManager; +} + +namespace MWWorld +{ + + class ProjectileManager + { + public: + ProjectileManager (Ogre::SceneManager* sceneMgr, + OEngine::Physic::PhysicEngine& engine); + + void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId, + float speed, bool stack, const ESM::EffectList& effects, + const MWWorld::Ptr& actor, const std::string& sourceName); + + void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, + const Ogre::Vector3& pos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed); + + void update(float dt); + + /// Removes all current projectiles. Should be called when switching to a new worldspace. + void clear(); + + private: + OEngine::Physic::PhysicEngine& mPhysEngine; + Ogre::SceneManager* mSceneMgr; + + struct State + { + NifOgre::ObjectScenePtr mObject; + Ogre::SceneNode* mNode; + }; + + struct MagicBoltState : public State + { + // Id of spell or enchantment to apply when it hits + std::string mId; + + // Actor who casted this projectile + int mActorId; + + // Name of item to display as effect source in magic menu (in case we casted an enchantment) + std::string mSourceName; + + ESM::EffectList mEffects; + + float mSpeed; + + bool mStack; + + MWBase::SoundPtr mSound; + }; + + struct ProjectileState : public State + { + // Actor who shot this projectile + int mActorId; + + // RefID of the projectile + std::string mProjectileId; + + MWWorld::Ptr mBow; // bow or crossbow the projectile was fired from (may be empty) + + Ogre::Vector3 mVelocity; + }; + + std::vector mMagicBolts; + std::vector mProjectiles; + + void moveProjectiles(float dt); + void moveMagicBolts(float dt); + + void createModel (State& state, const std::string& model); + void update (NifOgre::ObjectScenePtr object, float duration); + }; + +} + +#endif diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 4b92a920bd..ecc8bdd022 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -344,8 +344,6 @@ namespace MWWorld // Sky system MWBase::Environment::get().getWorld()->adjustSky(); - mRendering.switchToExterior(); - mCellChanged = true; loadingListener->removeWallpaper(); @@ -439,7 +437,6 @@ namespace MWWorld mCurrentCell = cell; // adjust fog - mRendering.switchToInterior(); mRendering.configureFog(*mCurrentCell); // adjust player diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2634788902..587fb71f4d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -43,6 +43,7 @@ #include "containerstore.hpp" #include "inventorystore.hpp" #include "actionteleport.hpp" +#include "projectilemanager.hpp" #include "contentloader.hpp" #include "esmloader.hpp" @@ -136,6 +137,8 @@ namespace MWWorld mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); + mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine)); + mRendering = new MWRender::RenderingManager(renderer, resDir, cacheDir, mPhysEngine,&mFallback); mPhysEngine->setSceneManager(renderer.getScene()); @@ -255,8 +258,6 @@ namespace MWWorld mCells.clear(); - mMagicBolts.clear(); - mProjectiles.clear(); mDoorStates.clear(); mGodMode = false; @@ -807,6 +808,10 @@ namespace MWWorld void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { + // changed worldspace + mProjectileManager->clear(); + mRendering->switchToInterior(); + removeContainerScripts(getPlayerPtr()); mWorldScene->changeToInteriorCell(cellName, position); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); @@ -814,6 +819,12 @@ namespace MWWorld void World::changeToExteriorCell (const ESM::Position& position) { + if (!getPlayerPtr().getCell()->getCell()->isExterior()) + { + // changed worldspace + mProjectileManager->clear(); + mRendering->switchToExterior(); + } removeContainerScripts(getPlayerPtr()); mWorldScene->changeToExteriorCell(position); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); @@ -949,8 +960,6 @@ namespace MWWorld MWWorld::Ptr newPtr = MWWorld::Class::get(ptr) .copyToCell(ptr, *newCell); newPtr.getRefData().setBaseNode(0); - - objectLeftActiveCell(ptr, newPtr); } else { @@ -1172,8 +1181,7 @@ namespace MWWorld { processDoors(duration); - moveMagicBolts(duration); - moveProjectiles(duration); + mProjectileManager->update(duration); const PtrVelocityList &results = mPhysics->applyQueuedMovement(duration); PtrVelocityList::const_iterator player(results.end()); @@ -2254,306 +2262,14 @@ namespace MWWorld void World::launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) { - ProjectileState state; - state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); - state.mBow = bow; - state.mVelocity = orient.yAxis() * speed; - - MWWorld::ManualRef ref(getStore(), projectile.getCellRef().mRefID); - - ESM::Position pos; - pos.pos[0] = worldPos.x; - pos.pos[1] = worldPos.y; - pos.pos[2] = worldPos.z; - - // Do NOT copy actor rotation! actors use a different rotation order, and this will not produce the same facing direction. - Ogre::Matrix3 mat; - orient.ToRotationMatrix(mat); - Ogre::Radian xr,yr,zr; - mat.ToEulerAnglesXYZ(xr, yr, zr); - pos.rot[0] = -xr.valueRadians(); - pos.rot[1] = -yr.valueRadians(); - pos.rot[2] = -zr.valueRadians(); - - MWWorld::Ptr ptr = copyObjectToCell(ref.getPtr(), actor.getCell(), pos, false); - ptr.getRefData().setCount(1); - - mProjectiles[ptr] = state; + mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed); } - void World::launchMagicBolt (const std::string& id, bool stack, const ESM::EffectList& effects, + void World::launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId, + float speed, bool stack, const ESM::EffectList& effects, const MWWorld::Ptr& actor, const std::string& sourceName) { - std::string projectileModel; - std::string sound; - float speed = 0; - for (std::vector::const_iterator iter (effects.mList.begin()); - iter!=effects.mList.end(); ++iter) - { - if (iter->mRange != ESM::RT_Target) - continue; - - const ESM::MagicEffect *magicEffect = getStore().get().find ( - iter->mEffectID); - - projectileModel = magicEffect->mBolt; - if (projectileModel.empty()) - projectileModel = "VFX_DefaultBolt"; - - static const std::string schools[] = { - "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" - }; - - if (!magicEffect->mBoltSound.empty()) - sound = magicEffect->mBoltSound; - else - sound = schools[magicEffect->mData.mSchool] + " bolt"; - - speed = magicEffect->mData.mSpeed; - break; - } - if (projectileModel.empty()) - return; - - // Spawn at 0.75 * ActorHeight - float height = mPhysEngine->getCharacter(actor.getRefData().getHandle())->getHalfExtents().z * 2 * 0.75; - - MWWorld::ManualRef ref(getStore(), projectileModel); - ESM::Position pos; - pos.pos[0] = actor.getRefData().getPosition().pos[0]; - pos.pos[1] = actor.getRefData().getPosition().pos[1]; - pos.pos[2] = actor.getRefData().getPosition().pos[2] + height; - - // Do NOT copy rotation directly! actors use a different rotation order, and this will not produce the same facing direction. - Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * - Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X); - Ogre::Matrix3 mat; - orient.ToRotationMatrix(mat); - Ogre::Radian xr,yr,zr; - mat.ToEulerAnglesXYZ(xr, yr, zr); - pos.rot[0] = -xr.valueRadians(); - pos.rot[1] = -yr.valueRadians(); - pos.rot[2] = -zr.valueRadians(); - - ref.getPtr().getCellRef().mPos = pos; - CellStore* cell = actor.getCell(); - MWWorld::Ptr ptr = copyObjectToCell(ref.getPtr(), cell, pos); - - MagicBoltState state; - state.mSourceName = sourceName; - state.mId = id; - state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); - state.mSpeed = speed; - state.mStack = stack; - - // Only interested in "on target" effects - for (std::vector::const_iterator iter (effects.mList.begin()); - iter!=effects.mList.end(); ++iter) - { - if (iter->mRange == ESM::RT_Target) - state.mEffects.mList.push_back(*iter); - } - - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - sndMgr->playSound3D(ptr, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); - - mMagicBolts[ptr] = state; - } - - void World::moveProjectiles(float duration) - { - std::map moved; - for (std::map::iterator it = mProjectiles.begin(); it != mProjectiles.end();) - { - if (!mWorldScene->isCellActive(*it->first.getCell())) - { - deleteObject(it->first); - mProjectiles.erase(it++); - continue; - } - - MWWorld::Ptr ptr = it->first; - - // gravity constant - must be way lower than the gravity affecting actors, since we're not - // simulating aerodynamics at all - it->second.mVelocity -= Ogre::Vector3(0, 0, 627.2f * 0.1f) * duration; - - Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - Ogre::Vector3 newPos = pos + it->second.mVelocity * duration; - - Ogre::Quaternion orient = Ogre::Vector3::UNIT_Y.getRotationTo(it->second.mVelocity); - Ogre::Matrix3 mat; - orient.ToRotationMatrix(mat); - Ogre::Radian xr,yr,zr; - mat.ToEulerAnglesXYZ(xr, yr, zr); - rotateObject(ptr, -xr.valueDegrees(), -yr.valueDegrees(), -zr.valueDegrees()); - - // Check for impact - btVector3 from(pos.x, pos.y, pos.z); - btVector3 to(newPos.x, newPos.y, newPos.z); - std::vector > collisions = mPhysEngine->rayTest2(from, to); - bool hit=false; - - // HACK: query against the shape as well, since the ray does not take the volume into account - // really, this should be a convex cast, but the whole physics system needs a rewrite - std::vector col2 = mPhysEngine->getCollisions(ptr.getRefData().getHandle()); - for (std::vector::iterator ci = col2.begin(); ci != col2.end(); ++ci) - collisions.push_back(std::make_pair(0.f,*ci)); - - for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) - { - MWWorld::Ptr obstacle = searchPtrViaHandle(cIt->second); - if (obstacle == ptr) - continue; - - MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); - - // Arrow intersects with player immediately after shooting :/ - if (obstacle == caster) - continue; - - if (caster.isEmpty()) - caster = obstacle; - - if (obstacle.isEmpty()) - { - // Terrain - } - else if (obstacle.getClass().isActor()) - { - MWMechanics::projectileHit(caster, obstacle, it->second.mBow, ptr, pos + (newPos - pos) * cIt->first); - } - hit = true; - } - if (hit) - { - deleteObject(ptr); - mProjectiles.erase(it++); - continue; - } - - std::string handle = ptr.getRefData().getHandle(); - - moveObject(ptr, newPos.x, newPos.y, newPos.z); - - // HACK: Re-fetch Ptrs if necessary, since the cell might have changed - if (!ptr.getRefData().getCount()) - { - moved[handle] = it->second; - mProjectiles.erase(it++); - } - else - ++it; - } - - // HACK: Re-fetch Ptrs if necessary, since the cell might have changed - for (std::map::iterator it = moved.begin(); it != moved.end(); ++it) - { - MWWorld::Ptr newPtr = searchPtrViaHandle(it->first); - if (newPtr.isEmpty()) // The projectile went into an inactive cell and was deleted - continue; - mProjectiles[getPtrViaHandle(it->first)] = it->second; - } - } - - void World::moveMagicBolts(float duration) - { - std::map moved; - for (std::map::iterator it = mMagicBolts.begin(); it != mMagicBolts.end();) - { - if (!mWorldScene->isCellActive(*it->first.getCell())) - { - deleteObject(it->first); - mMagicBolts.erase(it++); - continue; - } - - MWWorld::Ptr ptr = it->first; - - Ogre::Vector3 rot(ptr.getRefData().getPosition().rot); - - Ogre::Quaternion orient = ptr.getRefData().getBaseNode()->getOrientation(); - static float fTargetSpellMaxSpeed = getStore().get().find("fTargetSpellMaxSpeed")->getFloat(); - float speed = fTargetSpellMaxSpeed * it->second.mSpeed; - - Ogre::Vector3 direction = orient.yAxis(); - direction.normalise(); - Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - Ogre::Vector3 newPos = pos + direction * duration * speed; - - // Check for impact - btVector3 from(pos.x, pos.y, pos.z); - btVector3 to(newPos.x, newPos.y, newPos.z); - std::vector > collisions = mPhysEngine->rayTest2(from, to); - bool explode = false; - for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !explode; ++cIt) - { - MWWorld::Ptr obstacle = searchPtrViaHandle(cIt->second); - if (obstacle == ptr) - continue; - - MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); - if (caster.isEmpty()) - caster = obstacle; - - if (obstacle.isEmpty()) - { - // Terrain - } - else - { - MWMechanics::CastSpell cast(caster, obstacle); - cast.mHitPosition = pos; - cast.mId = it->second.mId; - cast.mSourceName = it->second.mSourceName; - cast.mStack = it->second.mStack; - cast.inflict(obstacle, caster, it->second.mEffects, ESM::RT_Target, false, true); - } - - explode = true; - } - - if (explode) - { - MWWorld::Ptr caster = searchPtrViaActorId(it->second.mActorId); - explodeSpell(Ogre::Vector3(ptr.getRefData().getPosition().pos), ptr, it->second.mEffects, caster, it->second.mId, it->second.mSourceName); - - deleteObject(ptr); - mMagicBolts.erase(it++); - continue; - } - - std::string handle = ptr.getRefData().getHandle(); - - moveObject(ptr, newPos.x, newPos.y, newPos.z); - - // HACK: Re-fetch Ptrs if necessary, since the cell might have changed - if (!ptr.getRefData().getCount()) - { - moved[handle] = it->second; - mMagicBolts.erase(it++); - } - else - ++it; - } - - // HACK: Re-fetch Ptrs if necessary, since the cell might have changed - for (std::map::iterator it = moved.begin(); it != moved.end(); ++it) - { - MWWorld::Ptr newPtr = searchPtrViaHandle(it->first); - if (newPtr.isEmpty()) // The projectile went into an inactive cell and was deleted - continue; - mMagicBolts[getPtrViaHandle(it->first)] = it->second; - } - } - - void World::objectLeftActiveCell(Ptr object, Ptr movedPtr) - { - // For now, projectiles moved to an inactive cell are just deleted, because there's no reliable way to hold on to the meta information - if (mMagicBolts.find(object) != mMagicBolts.end()) - deleteObject(movedPtr); - if (mProjectiles.find(object) != mProjectiles.end()) - deleteObject(movedPtr); + mProjectileManager->launchMagicBolt(model, sound, spellId, speed, stack, effects, actor, sourceName); } const std::vector& World::getContentFiles() const @@ -2935,7 +2651,7 @@ namespace MWWorld mRendering->spawnEffect(model, texture, worldPosition); } - void World::explodeSpell(const Vector3 &origin, const MWWorld::Ptr& object, const ESM::EffectList &effects, const Ptr &caster, + void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, const std::string& id, const std::string& sourceName) { std::map > toApply; @@ -2960,12 +2676,13 @@ namespace MWWorld static const std::string schools[] = { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" }; - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - if(!effect->mAreaSound.empty()) - sndMgr->playSound3D(object, effect->mAreaSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); - else - sndMgr->playSound3D(object, schools[effect->mData.mSchool]+" area", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); - + { + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + if(!effect->mAreaSound.empty()) + sndMgr->playManualSound3D(origin, effect->mAreaSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); + else + sndMgr->playManualSound3D(origin, schools[effect->mData.mSchool]+" area", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); + } // Get the actors in range of the effect std::vector objects; MWBase::Environment::get().getMechanicsManager()->getObjectsInRange( diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index a86cebfd2a..8d2f3a9da1 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -3,6 +3,8 @@ #include "../mwrender/debugging.hpp" +#include + #include "ptr.hpp" #include "scene.hpp" #include "esmstore.hpp" @@ -51,6 +53,7 @@ namespace MWWorld { class WeatherManager; class Player; + class ProjectileManager; /// \brief The game world and its visual representation @@ -74,6 +77,8 @@ namespace MWWorld OEngine::Physic::PhysicEngine* mPhysEngine; + boost::shared_ptr mProjectileManager; + bool mGodMode; std::vector mContentFiles; @@ -90,37 +95,6 @@ namespace MWWorld std::map mDoorStates; ///< only holds doors that are currently moving. 1 = opening, 2 = closing - struct MagicBoltState - { - // Id of spell or enchantment to apply when it hits - std::string mId; - - // Actor who casted this projectile - int mActorId; - - // Name of item to display as effect source in magic menu (in case we casted an enchantment) - std::string mSourceName; - - ESM::EffectList mEffects; - - float mSpeed; - - bool mStack; - }; - - struct ProjectileState - { - // Actor who shot this projectile - int mActorId; - - MWWorld::Ptr mBow; // bow or crossbow the projectile was fired from - - Ogre::Vector3 mVelocity; - }; - - std::map mMagicBolts; - std::map mProjectiles; - std::string mStartCell; void updateWeather(float duration); @@ -148,9 +122,6 @@ namespace MWWorld void processDoors(float duration); ///< Run physics simulation and modify \a world accordingly. - void moveMagicBolts(float duration); - void moveProjectiles(float duration); - void doPhysics(float duration); ///< Run physics simulation and modify \a world accordingly. @@ -171,9 +142,6 @@ namespace MWWorld bool mLevitationEnabled; bool mGoToJail; - /// Called when \a object is moved to an inactive cell - void objectLeftActiveCell (MWWorld::Ptr object, MWWorld::Ptr movedPtr); - float feetToGameUnits(float feet); public: @@ -572,7 +540,8 @@ namespace MWWorld */ virtual void castSpell (const MWWorld::Ptr& actor); - virtual void launchMagicBolt (const std::string& id, bool stack, const ESM::EffectList& effects, + virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId, + float speed, bool stack, const ESM::EffectList& effects, const MWWorld::Ptr& actor, const std::string& sourceName); virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed); @@ -612,7 +581,7 @@ namespace MWWorld /// Spawn a blood effect for \a ptr at \a worldPosition virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition); - virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects, + virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName); }; } From 9adb990143b8121e8e57446a24f5f4cfecb10f4c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 02:52:10 +0200 Subject: [PATCH 300/545] Fix potentially unsafe use of MWWorld::Ptr --- apps/openmw/mwworld/projectilemanager.cpp | 24 +++++++++++++++++------ apps/openmw/mwworld/projectilemanager.hpp | 3 ++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index c886908f92..55ecdb5694 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -6,6 +6,7 @@ #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/world.hpp" @@ -96,7 +97,7 @@ namespace MWWorld { ProjectileState state; state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); - state.mBow = bow; + state.mBowId = bow.getCellRef().mRefID; state.mVelocity = orient.yAxis() * speed; state.mProjectileId = projectile.getCellRef().mRefID; @@ -217,17 +218,28 @@ namespace MWWorld if (obstacle == caster) continue; - if (caster.isEmpty()) - caster = obstacle; - if (obstacle.isEmpty()) { // Terrain } else if (obstacle.getClass().isActor()) - { + { MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mProjectileId); - MWMechanics::projectileHit(caster, obstacle, it->mBow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first); + + // Try to get a Ptr to the bow that was used. It might no longer exist. + MWWorld::Ptr bow = projectileRef.getPtr(); + if (!caster.isEmpty()) + { + MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster); + MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().mRefID, it->mBowId)) + bow = *invIt; + } + + if (caster.isEmpty()) + caster = obstacle; + + MWMechanics::projectileHit(caster, obstacle, bow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first); } hit = true; } diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index e934bf6aba..c51985a7e4 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -84,7 +84,8 @@ namespace MWWorld // RefID of the projectile std::string mProjectileId; - MWWorld::Ptr mBow; // bow or crossbow the projectile was fired from (may be empty) + // RefID of the bow or crossbow the actor was using when this projectile was fired (may be empty) + std::string mBowId; Ogre::Vector3 mVelocity; }; From 15368188dc9d55f084ee14125c8d01d71e960a91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 02:54:51 +0200 Subject: [PATCH 301/545] Fix sliders in effect editor not being precisely movable --- files/mygui/openmw_edit_effect.layout | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/mygui/openmw_edit_effect.layout b/files/mygui/openmw_edit_effect.layout index fa1e58b9d2..5dc53e5057 100644 --- a/files/mygui/openmw_edit_effect.layout +++ b/files/mygui/openmw_edit_effect.layout @@ -33,6 +33,7 @@
+ @@ -41,6 +42,7 @@ +
@@ -58,6 +60,7 @@
+
@@ -74,6 +77,7 @@
+
From e266aff5619a6280c93a2d8ecdd8e51f341b1093 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 05:21:17 +0200 Subject: [PATCH 302/545] Savegame: store projectiles --- apps/openmw/mwbase/world.hpp | 3 +- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 10 +- apps/openmw/mwrender/renderingmanager.hpp | 3 +- apps/openmw/mwstate/statemanagerimp.cpp | 8 +- apps/openmw/mwworld/projectilemanager.cpp | 137 +++++++++++++++++++++- apps/openmw/mwworld/projectilemanager.hpp | 28 +++-- apps/openmw/mwworld/worldimp.cpp | 26 ++-- apps/openmw/mwworld/worldimp.hpp | 5 +- components/CMakeLists.txt | 2 +- components/esm/defs.hpp | 2 + components/esm/projectilestate.cpp | 65 ++++++++++ components/esm/projectilestate.hpp | 90 ++++++++++++++ 13 files changed, 343 insertions(+), 38 deletions(-) create mode 100644 components/esm/projectilestate.cpp create mode 100644 components/esm/projectilestate.hpp diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index d1ecd11a0e..81bec6fe86 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -255,7 +255,8 @@ namespace MWBase virtual void changeToExteriorCell (const ESM::Position& position) = 0; ///< Move to exterior cell. - virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position) = 0; + virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true) = 0; + ///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes 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. diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 108cc8cc5e..d54805539c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -785,7 +785,7 @@ namespace MWMechanics // Update witness crime id npcStats.setCrimeId(-1); } - else if (!creatureStats.isHostile()) + else if (!creatureStats.isHostile() && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue) { if (ptr.getClass().isClass(ptr, "Guard")) creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 9398e033a1..991ca690ee 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -694,15 +694,8 @@ Shadows* RenderingManager::getShadows() return mShadows; } -void RenderingManager::switchToInterior() +void RenderingManager::notifyWorldSpaceChanged() { - // TODO: also do this when switching worldspace - mEffectManager->clear(); -} - -void RenderingManager::switchToExterior() -{ - // TODO: also do this when switching worldspace mEffectManager->clear(); } @@ -1061,6 +1054,7 @@ void RenderingManager::spawnEffect(const std::string &model, const std::string & void RenderingManager::clear() { mLocalMap->clear(); + notifyWorldSpaceChanged(); } } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d59e1e27d4..f539f9270f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -163,8 +163,7 @@ public: Shadows* getShadows(); - void switchToInterior(); - void switchToExterior(); + void notifyWorldSpaceChanged(); void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index f2cda5a018..304228010a 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -319,6 +319,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl case ESM::REC_WTHR: case ESM::REC_DYNA: case ESM::REC_ACTC: + case ESM::REC_PROJ: + case ESM::REC_MPRJ: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; @@ -361,7 +363,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl ESM::CellId cellId = ptr.getCell()->getCell()->getCellId(); - MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition()); + // Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again + MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false); + + // Do not trigger erroneous cellChanged events + MWBase::Environment::get().getWorld()->markCellAsUnchanged(); } catch (const std::exception& e) { diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 55ecdb5694..266b566f70 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -4,6 +4,8 @@ #include +#include + #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" @@ -67,10 +69,12 @@ namespace MWWorld MagicBoltState state; state.mSourceName = sourceName; - state.mId = spellId; + state.mId = model; + state.mSpellId = spellId; state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mSpeed = speed; state.mStack = stack; + state.mSoundId = sound; // Only interested in "on target" effects for (std::vector::const_iterator iter (effects.mList.begin()); @@ -99,7 +103,7 @@ namespace MWWorld state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mBowId = bow.getCellRef().mRefID; state.mVelocity = orient.yAxis() * speed; - state.mProjectileId = projectile.getCellRef().mRefID; + state.mId = projectile.getCellRef().mRefID; MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().mRefID); MWWorld::Ptr ptr = ref.getPtr(); @@ -159,7 +163,7 @@ namespace MWWorld { MWMechanics::CastSpell cast(caster, obstacle); cast.mHitPosition = pos; - cast.mId = it->mId; + cast.mId = it->mSpellId; cast.mSourceName = it->mSourceName; cast.mStack = it->mStack; cast.inflict(obstacle, caster, it->mEffects, ESM::RT_Target, false, true); @@ -170,7 +174,7 @@ namespace MWWorld if (hit) { MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); - MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, it->mId, it->mSourceName); + MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, it->mSpellId, it->mSourceName); MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); @@ -224,7 +228,7 @@ namespace MWWorld } else if (obstacle.getClass().isActor()) { - MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mProjectileId); + MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId); // Try to get a Ptr to the bow that was used. It might no longer exist. MWWorld::Ptr bow = projectileRef.getPtr(); @@ -270,4 +274,127 @@ namespace MWWorld mMagicBolts.clear(); } + void ProjectileManager::write(ESM::ESMWriter &writer, Loading::Listener &progress) const + { + for (std::vector::const_iterator it = mProjectiles.begin(); it != mProjectiles.end(); ++it) + { + writer.startRecord(ESM::REC_PROJ); + + ESM::ProjectileState state; + state.mId = it->mId; + state.mPosition = it->mNode->getPosition(); + state.mOrientation = it->mNode->getOrientation(); + state.mActorId = it->mActorId; + + state.mBowId = it->mBowId; + state.mVelocity = it->mVelocity; + + state.save(writer); + + writer.endRecord(ESM::REC_PROJ); + + progress.increaseProgress(); + } + + for (std::vector::const_iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it) + { + writer.startRecord(ESM::REC_MPRJ); + + ESM::MagicBoltState state; + state.mId = it->mId; + state.mPosition = it->mNode->getPosition(); + state.mOrientation = it->mNode->getOrientation(); + state.mActorId = it->mActorId; + + state.mSpellId = it->mSpellId; + state.mEffects = it->mEffects; + state.mSound = it->mSoundId; + state.mSourceName = it->mSourceName; + state.mSpeed = it->mSpeed; + state.mStack = it->mStack; + + state.save(writer); + + writer.endRecord(ESM::REC_MPRJ); + + progress.increaseProgress(); + } + } + + bool ProjectileManager::readRecord(ESM::ESMReader &reader, int32_t type) + { + if (type == ESM::REC_PROJ) + { + ESM::ProjectileState esm; + esm.load(reader); + + ProjectileState state; + state.mActorId = esm.mActorId; + state.mBowId = esm.mBowId; + state.mVelocity = esm.mVelocity; + state.mId = esm.mId; + + std::string model; + try + { + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId); + MWWorld::Ptr ptr = ref.getPtr(); + model = ptr.getClass().getModel(ptr); + } + catch(...) + { + return true; + } + + state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation); + createModel(state, model); + + mProjectiles.push_back(state); + return true; + } + else if (type == ESM::REC_MPRJ) + { + ESM::MagicBoltState esm; + esm.load(reader); + + MagicBoltState state; + state.mSourceName = esm.mSourceName; + state.mId = esm.mId; + state.mSpellId = esm.mSpellId; + state.mActorId = esm.mActorId; + state.mSpeed = esm.mSpeed; + state.mStack = esm.mStack; + state.mEffects = esm.mEffects; + + std::string model; + try + { + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId); + MWWorld::Ptr ptr = ref.getPtr(); + model = ptr.getClass().getModel(ptr); + } + catch(...) + { + return true; + } + + state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation); + createModel(state, model); + + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + state.mSound = sndMgr->playManualSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f, + MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + + mMagicBolts.push_back(state); + return true; + } + + return false; + } + + int ProjectileManager::countSavedGameRecords() const + { + return mMagicBolts.size() + mProjectiles.size(); + } + } diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index c51985a7e4..da965a4cff 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -20,6 +20,11 @@ namespace Physic } } +namespace Loading +{ + class Listener; +} + namespace Ogre { class SceneManager; @@ -46,6 +51,10 @@ namespace MWWorld /// Removes all current projectiles. Should be called when switching to a new worldspace. void clear(); + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; + bool readRecord (ESM::ESMReader& reader, int32_t type); + int countSavedGameRecords() const; + private: OEngine::Physic::PhysicEngine& mPhysEngine; Ogre::SceneManager* mSceneMgr; @@ -54,15 +63,17 @@ namespace MWWorld { NifOgre::ObjectScenePtr mObject; Ogre::SceneNode* mNode; + + // Actor who shot this projectile + int mActorId; + + // MW-id of this projectile + std::string mId; }; struct MagicBoltState : public State { - // Id of spell or enchantment to apply when it hits - std::string mId; - - // Actor who casted this projectile - int mActorId; + std::string mSpellId; // Name of item to display as effect source in magic menu (in case we casted an enchantment) std::string mSourceName; @@ -74,16 +85,11 @@ namespace MWWorld bool mStack; MWBase::SoundPtr mSound; + std::string mSoundId; }; struct ProjectileState : public State { - // Actor who shot this projectile - int mActorId; - - // RefID of the projectile - std::string mProjectileId; - // RefID of the bow or crossbow the actor was using when this projectile was fired (may be empty) std::string mBowId; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 587fb71f4d..1f645fd860 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -237,6 +237,8 @@ namespace MWWorld { mRendering->clear(); + mProjectileManager->clear(); + mLocalScripts.clear(); mPlayer->clear(); @@ -275,6 +277,7 @@ namespace MWWorld mCells.countSavedGameRecords() +mStore.countSavedGameRecords() +mGlobalVariables.countSavedGameRecords() + +mProjectileManager->countSavedGameRecords() +1 // player record +1 // weather record +1; // actorId counter @@ -298,6 +301,7 @@ namespace MWWorld mGlobalVariables.write (writer, progress); mPlayer->write (writer, progress); mWeatherManager->write (writer, progress); + mProjectileManager->write (writer, progress); } void World::readRecord (ESM::ESMReader& reader, int32_t type, @@ -313,7 +317,8 @@ namespace MWWorld !mGlobalVariables.readRecord (reader, type) && !mPlayer->readRecord (reader, type) && !mWeatherManager->readRecord (reader, type) && - !mCells.readRecord (reader, type, contentFileMap)) + !mCells.readRecord (reader, type, contentFileMap) && + !mProjectileManager->readRecord (reader, type)) { throw std::runtime_error ("unknown record in saved game"); } @@ -808,9 +813,13 @@ namespace MWWorld void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { - // changed worldspace - mProjectileManager->clear(); - mRendering->switchToInterior(); + if (mCurrentWorldSpace != cellName) + { + // changed worldspace + mProjectileManager->clear(); + mRendering->notifyWorldSpaceChanged(); + mCurrentWorldSpace = cellName; + } removeContainerScripts(getPlayerPtr()); mWorldScene->changeToInteriorCell(cellName, position); @@ -819,19 +828,22 @@ namespace MWWorld void World::changeToExteriorCell (const ESM::Position& position) { - if (!getPlayerPtr().getCell()->getCell()->isExterior()) + if (mCurrentWorldSpace != "sys::default") // FIXME { // changed worldspace mProjectileManager->clear(); - mRendering->switchToExterior(); + mRendering->notifyWorldSpaceChanged(); } removeContainerScripts(getPlayerPtr()); mWorldScene->changeToExteriorCell(position); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); } - void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position) + void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange) { + if (!detectWorldSpaceChange) + mCurrentWorldSpace = cellId.mWorldspace; + if (cellId.mPaged) changeToExteriorCell (position); else diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 8d2f3a9da1..285d5fef6d 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -75,6 +75,8 @@ namespace MWWorld Cells mCells; + std::string mCurrentWorldSpace; + OEngine::Physic::PhysicEngine* mPhysEngine; boost::shared_ptr mProjectileManager; @@ -311,7 +313,8 @@ namespace MWWorld virtual void changeToExteriorCell (const ESM::Position& position); ///< Move to exterior cell. - virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position); + virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true); + ///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes virtual const ESM::Cell *getExterior (const std::string& cellName) const; ///< Return a cell matching the given name or a 0-pointer, if there is no such cell. diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index c7deeadf3f..e0166138e4 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -41,7 +41,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate + npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate ) add_component_dir (misc diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 6c388de08c..bdeb95291f 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -109,6 +109,8 @@ enum RecNameInts REC_DYNA = FourCC<'D','Y','N','A'>::value, REC_ASPL = FourCC<'A','S','P','L'>::value, REC_ACTC = FourCC<'A','C','T','C'>::value, + REC_MPRJ = FourCC<'M','P','R','J'>::value, + REC_PROJ = FourCC<'P','R','O','J'>::value, // format 1 REC_FILT = 0x544C4946 diff --git a/components/esm/projectilestate.cpp b/components/esm/projectilestate.cpp new file mode 100644 index 0000000000..85c00025b6 --- /dev/null +++ b/components/esm/projectilestate.cpp @@ -0,0 +1,65 @@ +#include "projectilestate.hpp" + +#include "esmwriter.hpp" +#include "esmreader.hpp" + +namespace ESM +{ + + void BaseProjectileState::save(ESMWriter &esm) const + { + esm.writeHNString ("ID__", mId); + esm.writeHNT ("VEC3", mPosition); + esm.writeHNT ("QUAT", mOrientation); + esm.writeHNT ("ACTO", mActorId); + } + + void BaseProjectileState::load(ESMReader &esm) + { + mId = esm.getHNString("ID__"); + esm.getHNT (mPosition, "VEC3"); + esm.getHNT (mOrientation, "QUAT"); + esm.getHNT (mActorId, "ACTO"); + } + + void MagicBoltState::save(ESMWriter &esm) const + { + BaseProjectileState::save(esm); + + esm.writeHNString ("SPEL", mSpellId); + esm.writeHNString ("SRCN", mSourceName); + mEffects.save(esm); + esm.writeHNT ("SPED", mSpeed); + esm.writeHNT ("STCK", mStack); + esm.writeHNString ("SOUN", mSound); + } + + void MagicBoltState::load(ESMReader &esm) + { + BaseProjectileState::load(esm); + + mSpellId = esm.getHNString("SPEL"); + mSourceName = esm.getHNString ("SRCN"); + mEffects.load(esm); + esm.getHNT (mSpeed, "SPED"); + esm.getHNT (mStack, "STCK"); + mSound = esm.getHNString ("SOUN"); + } + + void ProjectileState::save(ESMWriter &esm) const + { + BaseProjectileState::save(esm); + + esm.writeHNString ("BOW_", mBowId); + esm.writeHNT ("VEL_", mVelocity); + } + + void ProjectileState::load(ESMReader &esm) + { + BaseProjectileState::load(esm); + + mBowId = esm.getHNString ("BOW_"); + esm.getHNT (mVelocity, "VEL_"); + } + +} diff --git a/components/esm/projectilestate.hpp b/components/esm/projectilestate.hpp new file mode 100644 index 0000000000..6e36efb5b4 --- /dev/null +++ b/components/esm/projectilestate.hpp @@ -0,0 +1,90 @@ +#ifndef OPENMW_ESM_PROJECTILESTATE_H +#define OPENMW_ESM_PROJECTILESTATE_H + +#include + +#include +#include + +#include "effectlist.hpp" + +namespace ESM +{ + + // format 0, savegames only + + struct Quaternion + { + float mValues[4]; + + Quaternion() {} + Quaternion (Ogre::Quaternion q) + { + mValues[0] = q.w; + mValues[1] = q.x; + mValues[2] = q.y; + mValues[3] = q.z; + } + + operator Ogre::Quaternion () const + { + return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]); + } + }; + + struct Vector3 + { + float mValues[3]; + + Vector3() {} + Vector3 (Ogre::Vector3 v) + { + mValues[0] = v.x; + mValues[1] = v.y; + mValues[2] = v.z; + } + + operator Ogre::Vector3 () const + { + return Ogre::Vector3(&mValues[0]); + } + }; + + struct BaseProjectileState + { + std::string mId; + + Vector3 mPosition; + Quaternion mOrientation; + + int mActorId; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + + struct MagicBoltState : public BaseProjectileState + { + std::string mSpellId; + std::string mSourceName; + ESM::EffectList mEffects; + float mSpeed; + bool mStack; + std::string mSound; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + + struct ProjectileState : public BaseProjectileState + { + std::string mBowId; + Vector3 mVelocity; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + +} + +#endif From 92c5bb56e08bd30e790f69a46eb7e01611201111 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 05:34:54 +0200 Subject: [PATCH 303/545] Un-reverted actorId for AiPursue --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- apps/openmw/mwmechanics/aipursue.cpp | 11 ++++++----- apps/openmw/mwmechanics/aipursue.hpp | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d54805539c..a3211892e6 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -759,7 +759,7 @@ namespace MWMechanics && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); creatureStats.setAlarmed(true); npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } @@ -788,7 +788,7 @@ namespace MWMechanics else if (!creatureStats.isHostile() && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player), ptr); else { MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 6e91ccb719..aa71af4658 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -7,12 +7,14 @@ #include "../mwworld/action.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "steering.hpp" #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPursue::AiPursue(const std::string &objectId) - : mObjectId(objectId) +MWMechanics::AiPursue::AiPursue(const MWWorld::Ptr& actor) + : mActorId(actor.getClass().getCreatureStats(actor).getActorId()) { } MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const @@ -23,7 +25,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { ESM::Position pos = actor.getRefData().getPosition(); //position of the actor - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); //The target to follow if(target == MWWorld::Ptr()) return true; //Target doesn't exist @@ -33,8 +35,7 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; - MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + target.getClass().activate(target,actor).get()->execute(actor); //Arrest player return true; } else { diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 2eb533d625..90ff8df93b 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -16,14 +16,14 @@ namespace MWMechanics { public: ///Constructor - /** \param objectId Actor to pursue **/ - AiPursue(const std::string &objectId); + /** \param actor Actor to pursue **/ + AiPursue(const MWWorld::Ptr& actor); virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); virtual int getTypeId() const; private: - std::string mObjectId; + int mActorId; // The actor to pursue int mCellX; int mCellY; }; From ae66d28c87d9331f0a42aca806c46232b9a6aa06 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 09:05:41 +0200 Subject: [PATCH 304/545] Feature #32: Implement respawn for containers, creatures and NPCs --- apps/openmw/mwclass/container.cpp | 10 +++++++ apps/openmw/mwclass/container.hpp | 2 ++ apps/openmw/mwclass/creature.cpp | 20 ++++++++++++++ apps/openmw/mwclass/creature.hpp | 2 ++ apps/openmw/mwclass/creaturelevlist.cpp | 27 ++++++++++++++++--- apps/openmw/mwclass/creaturelevlist.hpp | 2 ++ apps/openmw/mwclass/npc.cpp | 20 ++++++++++++++ apps/openmw/mwclass/npc.hpp | 2 ++ apps/openmw/mwworld/cellstore.cpp | 36 ++++++++++++++++++++++++- apps/openmw/mwworld/cellstore.hpp | 7 +++++ apps/openmw/mwworld/class.hpp | 2 ++ apps/openmw/mwworld/scene.cpp | 2 ++ components/esm/cellstate.cpp | 8 +++++- components/esm/cellstate.hpp | 4 +++ components/esm/creaturelevliststate.cpp | 6 +++++ components/esm/creaturelevliststate.hpp | 1 + 16 files changed, 146 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index be76bd0b41..f0c71bf536 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -60,6 +60,16 @@ namespace MWClass } } + void Container::respawn(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + if (ref->mBase->mFlags & ESM::Container::Respawn) + { + ptr.getRefData().setCustomData(NULL); + } + } + void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index f012d675c8..79a8012485 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -64,6 +64,8 @@ namespace MWClass static void registerSelf(); + virtual void respawn (const MWWorld::Ptr& ptr) const; + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index dc23b63f3b..4abc9ea713 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -822,6 +822,26 @@ namespace MWClass return ptr.get()->mBase->mData.mGold; } + void Creature::respawn(const MWWorld::Ptr &ptr) const + { + if (ptr.get()->mBase->mFlags & ESM::Creature::Respawn) + { + // Note we do not respawn moved references in the cell they were moved to. Instead they are respawned in the original cell. + // This also means we cannot respawn dynamically placed references with no content file connection. + if (ptr.getCellRef().mRefNum.mContentFile != -1) + { + if (ptr.getRefData().getCount() == 0) + ptr.getRefData().setCount(1); + + // Reset to original position + ESM::Position& pos = ptr.getRefData().getPosition(); + pos = ptr.getCellRef().mPos; + + ptr.getRefData().setCustomData(NULL); + } + } + } + const ESM::GameSetting* Creature::fMinWalkSpeedCreature; const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; const ESM::GameSetting *Creature::fEncumberedMoveEffect; diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 04c010c830..d3ffb321ef 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -143,6 +143,8 @@ namespace MWClass ///< Write additional state from \a ptr into \a state. virtual int getBaseGold(const MWWorld::Ptr& ptr) const; + + virtual void respawn (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index be01b848a3..fea30735c6 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -14,6 +14,7 @@ namespace { // actorId of the creature we spawned int mSpawnActorId; + bool mSpawn; // Should a new creature be spawned? virtual MWWorld::CustomData *clone() const; }; @@ -31,6 +32,14 @@ namespace MWClass return ""; } + void CreatureLevList::respawn(const MWWorld::Ptr &ptr) const + { + ensureCustomData(ptr); + + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + customData.mSpawn = true; + } + void CreatureLevList::registerSelf() { boost::shared_ptr instance (new CreatureLevList); @@ -43,9 +52,8 @@ namespace MWClass ensureCustomData(ptr); CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); - if (customData.mSpawnActorId != -1) - return; // TODO: handle respawning - + if (!customData.mSpawn) + return; MWWorld::LiveCellRef *ref = ptr.get(); @@ -54,11 +62,21 @@ namespace MWClass if (!id.empty()) { + // Delete the previous creature + if (customData.mSpawnActorId != -1) + { + MWWorld::Ptr creature = MWBase::Environment::get().getWorld()->searchPtrViaActorId(customData.mSpawnActorId); + if (!creature.isEmpty()) + MWBase::Environment::get().getWorld()->deleteObject(creature); + customData.mSpawnActorId = -1; + } + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); MWWorld::ManualRef ref(store, id); ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); + customData.mSpawn = false; } } @@ -68,6 +86,7 @@ namespace MWClass { std::auto_ptr data (new CreatureLevListCustomData); data->mSpawnActorId = -1; + data->mSpawn = true; ptr.getRefData().setCustomData(data.release()); } @@ -81,6 +100,7 @@ namespace MWClass ensureCustomData(ptr); CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); customData.mSpawnActorId = state2.mSpawnActorId; + customData.mSpawn = state2.mSpawn; } void CreatureLevList::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) @@ -91,5 +111,6 @@ namespace MWClass ensureCustomData(ptr); CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); state2.mSpawnActorId = customData.mSpawnActorId; + state2.mSpawn = customData.mSpawn; } } diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index b67fb5523f..6c51a31891 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -27,6 +27,8 @@ namespace MWClass virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const; ///< Write additional state from \a ptr into \a state. + + virtual void respawn (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 6d2eea6af5..5b9e26f269 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1310,6 +1310,26 @@ namespace MWClass return Misc::StringUtils::ciEqual(ptr.get()->mBase->mClass, className); } + void Npc::respawn(const MWWorld::Ptr &ptr) const + { + if (ptr.get()->mBase->mFlags & ESM::NPC::Respawn) + { + // Note we do not respawn moved references in the cell they were moved to. Instead they are respawned in the original cell. + // This also means we cannot respawn dynamically placed references with no content file connection. + if (ptr.getCellRef().mRefNum.mContentFile != -1) + { + if (ptr.getRefData().getCount() == 0) + ptr.getRefData().setCount(1); + + // Reset to original position + ESM::Position& pos = ptr.getRefData().getPosition(); + pos = ptr.getCellRef().mPos; + + ptr.getRefData().setCustomData(NULL); + } + } + } + const ESM::GameSetting *Npc::fMinWalkSpeed; const ESM::GameSetting *Npc::fMaxWalkSpeed; const ESM::GameSetting *Npc::fEncumberedMoveEffect; diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 4b9c8988ec..03c6e234a1 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -178,6 +178,8 @@ namespace MWClass virtual bool canWalk (const MWWorld::Ptr &ptr) const { return true; } + + virtual void respawn (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 5d2d8a5175..aa247f0b90 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -169,7 +169,7 @@ namespace MWWorld } CellStore::CellStore (const ESM::Cell *cell) - : mCell (cell), mState (State_Unloaded), mHasState (false) + : mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0) { mWaterLevel = cell->mWater; } @@ -555,6 +555,7 @@ namespace MWWorld mWaterLevel = state.mWaterLevel; mWaterLevel = state.mWaterLevel; + mLastRespawn = MWWorld::TimeStamp(state.mLastRespawn); } void CellStore::saveState (ESM::CellState& state) const @@ -566,6 +567,7 @@ namespace MWWorld state.mWaterLevel = mWaterLevel; state.mHasFogOfWar = (mFogState.get() ? 1 : 0); + state.mLastRespawn = mLastRespawn.toEsm(); } void CellStore::writeFog(ESM::ESMWriter &writer) const @@ -754,4 +756,36 @@ namespace MWWorld { return mFogState.get(); } + + void CellStore::respawn() + { + if (mState == State_Loaded) + { + static int iMonthsToRespawn = MWBase::Environment::get().getWorld()->getStore().get().find("iMonthsToRespawn")->getInt(); + if (MWBase::Environment::get().getWorld()->getTimeStamp() - mLastRespawn > 24*30*iMonthsToRespawn) + { + mLastRespawn = MWBase::Environment::get().getWorld()->getTimeStamp(); + for (CellRefList::List::iterator it (mContainers.mList.begin()); it!=mContainers.mList.end(); ++it) + { + Ptr ptr (&*it, this); + ptr.getClass().respawn(ptr); + } + for (CellRefList::List::iterator it (mCreatures.mList.begin()); it!=mCreatures.mList.end(); ++it) + { + Ptr ptr (&*it, this); + ptr.getClass().respawn(ptr); + } + for (CellRefList::List::iterator it (mNpcs.mList.begin()); it!=mNpcs.mList.end(); ++it) + { + Ptr ptr (&*it, this); + ptr.getClass().respawn(ptr); + } + for (CellRefList::List::iterator it (mCreatureLists.mList.begin()); it!=mCreatureLists.mList.end(); ++it) + { + Ptr ptr (&*it, this); + ptr.getClass().respawn(ptr); + } + } + } + } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 91c536b430..ba6fad7baa 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -13,6 +13,8 @@ #include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld +#include "timestamp.hpp" + namespace ESM { struct CellState; @@ -48,6 +50,8 @@ namespace MWWorld std::vector mIds; float mWaterLevel; + MWWorld::TimeStamp mLastRespawn; + CellRefList mActivators; CellRefList mPotions; CellRefList mAppas; @@ -161,6 +165,9 @@ namespace MWWorld void readReferences (ESM::ESMReader& reader, const std::map& contentFileMap); + void respawn (); + ///< Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded. + template CellRefList& get() { throw std::runtime_error ("Storage for this type not exist in cells"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 057bc906ef..f47b8ace32 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -341,6 +341,8 @@ namespace MWWorld virtual int getDoorState (const MWWorld::Ptr &ptr) const; /// This does not actually cause the door to move. Use World::activateDoor instead. virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; + + virtual void respawn (const MWWorld::Ptr& ptr) const {} }; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ecc8bdd022..25ee0c2e83 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -165,6 +165,8 @@ namespace MWWorld } } + cell->respawn(); + // ... then references. This is important for adjustPosition to work correctly. /// \todo rescale depending on the state of a new GMST insertCell (*cell, true, loadingListener); diff --git a/components/esm/cellstate.cpp b/components/esm/cellstate.cpp index 541a359c6a..4df04d0e52 100644 --- a/components/esm/cellstate.cpp +++ b/components/esm/cellstate.cpp @@ -11,6 +11,10 @@ void ESM::CellState::load (ESMReader &esm) mHasFogOfWar = false; esm.getHNOT (mHasFogOfWar, "HFOW"); + + mLastRespawn.mDay = 0; + mLastRespawn.mHour = 0; + esm.getHNOT (mLastRespawn, "RESP"); } void ESM::CellState::save (ESMWriter &esm) const @@ -18,5 +22,7 @@ void ESM::CellState::save (ESMWriter &esm) const if (!mId.mPaged) esm.writeHNT ("WLVL", mWaterLevel); - esm.writeHNT("HFOW", mHasFogOfWar); + esm.writeHNT ("HFOW", mHasFogOfWar); + + esm.writeHNT ("RESP", mLastRespawn); } diff --git a/components/esm/cellstate.hpp b/components/esm/cellstate.hpp index 88918a3abf..55c1e51550 100644 --- a/components/esm/cellstate.hpp +++ b/components/esm/cellstate.hpp @@ -3,6 +3,8 @@ #include "cellid.hpp" +#include "defs.hpp" + namespace ESM { class ESMReader; @@ -19,6 +21,8 @@ namespace ESM int mHasFogOfWar; // Do we have fog of war state (0 or 1)? (see fogstate.hpp) + ESM::TimeStamp mLastRespawn; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; diff --git a/components/esm/creaturelevliststate.cpp b/components/esm/creaturelevliststate.cpp index 164dae96e9..21cc73b89c 100644 --- a/components/esm/creaturelevliststate.cpp +++ b/components/esm/creaturelevliststate.cpp @@ -12,6 +12,9 @@ namespace ESM mSpawnActorId = -1; esm.getHNOT (mSpawnActorId, "SPAW"); + + mSpawn = false; + esm.getHNOT (mSpawn, "RESP"); } void CreatureLevListState::save(ESMWriter &esm, bool inInventory) const @@ -20,6 +23,9 @@ namespace ESM if (mSpawnActorId != -1) esm.writeHNT ("SPAW", mSpawnActorId); + + if (mSpawn) + esm.writeHNT ("RESP", mSpawn); } } diff --git a/components/esm/creaturelevliststate.hpp b/components/esm/creaturelevliststate.hpp index 99b5a7fa2a..da64cd7c2b 100644 --- a/components/esm/creaturelevliststate.hpp +++ b/components/esm/creaturelevliststate.hpp @@ -10,6 +10,7 @@ namespace ESM struct CreatureLevListState : public ObjectState { int mSpawnActorId; + bool mSpawn; virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm, bool inInventory = false) const; From b4ed828e2171f553942511ffe986832dbef9361d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 May 2014 14:30:31 +0200 Subject: [PATCH 305/545] Feature #1323: Implement restocking items (does not handle levelled lists yet) --- apps/openmw/mwclass/container.cpp | 16 +++++++++++ apps/openmw/mwclass/container.hpp | 2 ++ apps/openmw/mwclass/creature.cpp | 19 +++++++++++-- apps/openmw/mwclass/creature.hpp | 2 ++ apps/openmw/mwclass/npc.cpp | 16 +++++++++++ apps/openmw/mwclass/npc.hpp | 2 ++ apps/openmw/mwgui/tradewindow.cpp | 34 ++++++++++------------- apps/openmw/mwgui/tradewindow.hpp | 4 +-- apps/openmw/mwmechanics/creaturestats.cpp | 15 +++++----- apps/openmw/mwmechanics/creaturestats.hpp | 12 ++++---- apps/openmw/mwworld/class.hpp | 2 ++ apps/openmw/mwworld/containerstore.cpp | 3 +- 12 files changed, 87 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index f0c71bf536..fd8eeb46b9 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -70,6 +70,22 @@ namespace MWClass } } + void Container::restock(const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + const ESM::InventoryList& list = ref->mBase->mInventory; + for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) + { + if (it->mCount < 0) + { + MWWorld::ContainerStore& store = getContainerStore(ptr); + int currentCount = store.count(it->mItem.toString()); + if (currentCount < std::abs(it->mCount)) + store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); + } + } + } + void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 79a8012485..9fc013e45e 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -66,6 +66,8 @@ namespace MWClass virtual void respawn (const MWWorld::Ptr& ptr) const; + virtual void restock (const MWWorld::Ptr &ptr) const; + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 4abc9ea713..db3a70a6a6 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -123,9 +123,6 @@ namespace MWClass else data->mContainerStore = new MWWorld::ContainerStore(); - // Relates to NPC gold reset delay - data->mCreatureStats.setTradeTime(MWWorld::TimeStamp(0.0, 0)); - data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold); // store @@ -842,6 +839,22 @@ namespace MWClass } } + void Creature::restock(const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + const ESM::InventoryList& list = ref->mBase->mInventory; + for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) + { + if (it->mCount < 0) + { + MWWorld::ContainerStore& store = getContainerStore(ptr); + int currentCount = store.count(it->mItem.toString()); + if (currentCount < std::abs(it->mCount)) + store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); + } + } + } + const ESM::GameSetting* Creature::fMinWalkSpeedCreature; const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; const ESM::GameSetting *Creature::fEncumberedMoveEffect; diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index d3ffb321ef..30573cd154 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -145,6 +145,8 @@ namespace MWClass virtual int getBaseGold(const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const; + + virtual void restock (const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5b9e26f269..009559d192 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1330,6 +1330,22 @@ namespace MWClass } } + void Npc::restock(const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + const ESM::InventoryList& list = ref->mBase->mInventory; + for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) + { + if (it->mCount < 0) + { + MWWorld::ContainerStore& store = getContainerStore(ptr); + int currentCount = store.count(it->mItem.toString()); + if (currentCount < std::abs(it->mCount)) + store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); + } + } + } + const ESM::GameSetting *Npc::fMinWalkSpeed; const ESM::GameSetting *Npc::fMaxWalkSpeed; const ESM::GameSetting *Npc::fEncumberedMoveEffect; diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 03c6e234a1..356e358b9d 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -180,6 +180,8 @@ namespace MWClass } virtual void respawn (const MWWorld::Ptr& ptr) const; + + virtual void restock (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 9cabab3e8e..65ffdb9e1e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -84,7 +84,7 @@ namespace MWGui mCurrentBalance = 0; mCurrentMerchantOffer = 0; - checkTradeTime(); + restock(); std::vector itemSources; MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); @@ -364,8 +364,6 @@ namespace MWGui mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance ); } - updateTradeTime(); - MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse( MWBase::Environment::get().getWorld()->getStore().get().find("sBarterDialog5")->getString()); @@ -475,30 +473,26 @@ namespace MWGui return merchantGold; } - // Relates to NPC gold reset delay - void TradeWindow::checkTradeTime() + void TradeWindow::restock() { MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); - double delay = boost::lexical_cast(MWBase::Environment::get().getWorld()->getStore().get().find("fBarterGoldResetDelay")->getInt()); + float delay = MWBase::Environment::get().getWorld()->getStore().get().find("fBarterGoldResetDelay")->getFloat(); - // if time stamp longer than gold reset delay, reset gold. - if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() + delay) + if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getLastRestockTime() + delay) { sellerStats.setGoldPool(mPtr.getClass().getBaseGold(mPtr)); - } - } - void TradeWindow::updateTradeTime() - { - MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr); - MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); - double delay = boost::lexical_cast(MWBase::Environment::get().getWorld()->getStore().get().find("fBarterGoldResetDelay")->getInt()); + mPtr.getClass().restock(mPtr); - // If trade timestamp is within reset delay don't set - if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() && - MWBase::Environment::get().getWorld()->getTimeStamp() < sellerStats.getTradeTime() + delay) ) - { - sellerStats.setTradeTime(MWBase::Environment::get().getWorld()->getTimeStamp()); + // Also restock any containers owned by this merchant, which are also available to buy in the trade window + std::vector itemSources; + MWBase::Environment::get().getWorld()->getContainersOwnedBy(mPtr, itemSources); + for (std::vector::iterator it = itemSources.begin(); it != itemSources.end(); ++it) + { + it->getClass().restock(*it); + } + + sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp()); } } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 5c154d4259..2da58e72e1 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -101,9 +101,7 @@ namespace MWGui int getMerchantGold(); - // Relates to NPC gold reset delay - void checkTradeTime(); - void updateTradeTime(); + void restock(); }; } diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 57618e6e93..95e25cba67 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -22,7 +22,7 @@ namespace MWMechanics mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), - mTradeTime(0,0), mGoldPool(0), mActorId(-1) + mLastRestock(0,0), mGoldPool(0), mActorId(-1) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -477,7 +477,7 @@ namespace MWMechanics for (int i=0; i<3; ++i) mDynamic[i].writeState (state.mDynamic[i]); - state.mTradeTime = mTradeTime.toEsm(); + state.mTradeTime = mLastRestock.toEsm(); state.mGoldPool = mGoldPool; state.mDead = mDead; @@ -515,7 +515,7 @@ namespace MWMechanics for (int i=0; i<3; ++i) mDynamic[i].readState (state.mDynamic[i]); - mTradeTime = MWWorld::TimeStamp(state.mTradeTime); + mLastRestock = MWWorld::TimeStamp(state.mTradeTime); mGoldPool = state.mGoldPool; mFallHeight = state.mFallHeight; @@ -546,15 +546,14 @@ namespace MWMechanics mActiveSpells.readState(state.mActiveSpells); } - // Relates to NPC gold reset delay - void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime) + void CreatureStats::setLastRestockTime(MWWorld::TimeStamp tradeTime) { - mTradeTime = tradeTime; + mLastRestock = tradeTime; } - MWWorld::TimeStamp CreatureStats::getTradeTime() const + MWWorld::TimeStamp CreatureStats::getLastRestockTime() const { - return mTradeTime; + return mLastRestock; } void CreatureStats::setGoldPool(int pool) diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 7d2dc1a62a..70a86536a0 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -56,9 +56,12 @@ namespace MWMechanics // Do we need to recalculate stats derived from attributes or other factors? bool mRecalcDynamicStats; - MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay + // For merchants: the last time items were restocked and gold pool refilled. + MWWorld::TimeStamp mLastRestock; + + // The pool of merchant gold (not in inventory) + int mGoldPool; - int mGoldPool; // the pool of merchant gold not in inventory int mActorId; protected: @@ -241,9 +244,8 @@ namespace MWMechanics static void writeActorIdCounter (ESM::ESMWriter& esm); static void readActorIdCounter (ESM::ESMReader& esm); - // Relates to NPC gold reset delay - void setTradeTime(MWWorld::TimeStamp tradeTime); - MWWorld::TimeStamp getTradeTime() const; + void setLastRestockTime(MWWorld::TimeStamp tradeTime); + MWWorld::TimeStamp getLastRestockTime() const; void setGoldPool(int pool); int getGoldPool() const; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index f47b8ace32..0b1eb857c8 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -343,6 +343,8 @@ namespace MWWorld virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; virtual void respawn (const MWWorld::Ptr& ptr) const {} + + virtual void restock (const MWWorld::Ptr& ptr) const {} }; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index eb6760d14c..1cbaa349ca 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -376,7 +376,8 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std:: void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int count, bool topLevel) { - count = std::abs(count); /// \todo implement item restocking (indicated by negative count) + // A negative count indicates restocking items, but this is implemented elsewhere + count = std::abs(count); ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); From 8971db8962c0e70a430a5a696ed31dcdc46ecc4a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 17 May 2014 23:53:33 +1000 Subject: [PATCH 306/545] SceneWidget windowHandle fix for Windows. --- apps/opencs/view/render/scenewidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 8a58b7d328..52e7afefd3 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -86,8 +86,11 @@ namespace CSVRender } std::stringstream windowHandle; +#ifdef WIN32 + windowHandle << Ogre::StringConverter::toString((unsigned long)(this->winId())); +#else windowHandle << this->winId(); - +#endif std::stringstream windowTitle; static int count=0; windowTitle << ++count; From b36bb58e8c6e0d2ae5e527070f6634885bea750d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 18 May 2014 07:34:13 +1000 Subject: [PATCH 307/545] Bug #1324: Artem's solution --- components/esm/loadscpt.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index de679e8152..aee8628bd6 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -38,6 +38,8 @@ void Script::load(ESMReader &esm) char* str = &tmp[0]; for (size_t i = 0; i < mVarNames.size(); i++) { + char *termsym = strchr(str, '\r'); + if(termsym) *termsym = '\0'; mVarNames[i] = std::string(str); str += mVarNames[i].size() + 1; From 12dc5cf4ea80e2c4de3b5939d0d7f3255a67c6a6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 18 May 2014 12:05:08 +1000 Subject: [PATCH 308/545] Bug #1303 - resolves the bug by tweaking the slope constant (the value 49 was selected to mimic vanilla behaviour for a low level character exploring Seyda Neen). The feature to vary the climbable angle based on acrobatics is still to be implemented. --- apps/openmw/mwworld/physicssystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index cf2ff87c64..d5433f3286 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -33,7 +33,7 @@ using namespace Ogre; namespace MWWorld { - static const float sMaxSlope = 60.0f; + static const float sMaxSlope = 49.0f; static const float sStepSize = 32.0f; // Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared. static const int sMaxIterations = 8; From e1458453f3e04f73f915994134cb353a9a379136 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 06:49:24 +0200 Subject: [PATCH 309/545] Fix "unknown info ID" exceptions when a dialogue response is from the Info Refusal group Could be observed in TG_OverduePayments quest when talking to Trasteve about Dwemer Artifacts. Info Refusal responses are not specific to any particular topic, so they should not be added to the journal. Trying to do so anyway will cause "unknown id" exceptions because MWDialogue::Entry expects the infoId to be from the Dialogue for the supplied topic. --- apps/openmw/mwbase/journal.hpp | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 27 +++++++++++++++++-- apps/openmw/mwdialogue/filter.hpp | 1 + 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwbase/journal.hpp b/apps/openmw/mwbase/journal.hpp index 7f06320aad..a49ebb9bc4 100644 --- a/apps/openmw/mwbase/journal.hpp +++ b/apps/openmw/mwbase/journal.hpp @@ -37,7 +37,7 @@ namespace MWBase typedef std::deque TEntryContainer; typedef TEntryContainer::const_iterator TEntryIter; - typedef std::map TQuestContainer; // topc, quest + typedef std::map TQuestContainer; // topic, quest typedef TQuestContainer::const_iterator TQuestIter; typedef std::map TTopicContainer; // topic-id, topic-content typedef TTopicContainer::const_iterator TTopicIter; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 8c425caa01..323b450647 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -286,7 +286,18 @@ namespace MWDialogue MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), title); - MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor.getClass().getName(mActor)); + + // Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group, + // in which case it should not be added to the journal. + for (std::vector::const_iterator iter = dialogue.mInfo.begin(); + iter!=dialogue.mInfo.end(); ++iter) + { + if (iter->mId == info->mId) + { + MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor.getClass().getName(mActor)); + break; + } + } executeScript (info->mResultScript); @@ -453,7 +464,19 @@ namespace MWDialogue MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse (Interpreter::fixDefinesDialog(text, interpreterContext)); - MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor.getClass().getName(mActor)); + + // Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group, + // in which case it should not be added to the journal. + for (std::vector::const_iterator iter = mDialogueMap[mLastTopic].mInfo.begin(); + iter!=mDialogueMap[mLastTopic].mInfo.end(); ++iter) + { + if (iter->mId == info->mId) + { + MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor.getClass().getName(mActor)); + break; + } + } + executeScript (info->mResultScript); } } diff --git a/apps/openmw/mwdialogue/filter.hpp b/apps/openmw/mwdialogue/filter.hpp index 5c6d092ad9..7e7f2b6f54 100644 --- a/apps/openmw/mwdialogue/filter.hpp +++ b/apps/openmw/mwdialogue/filter.hpp @@ -55,6 +55,7 @@ namespace MWDialogue std::vector list (const ESM::Dialogue& dialogue, bool fallbackToInfoRefusal, bool searchAll, bool invertDisposition=false) const; + ///< \note If fallbackToInfoRefusal is used, the returned DialInfo might not be from the supplied ESM::Dialogue. const ESM::DialInfo* search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const; ///< Get a matching response for the requested dialogue. From 5fc2b1a41b1f308cb7390c80ad8e2adcd62b4dc5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 07:37:32 +0200 Subject: [PATCH 310/545] Allow setting a journal index even if there's no related journal entry This is used by the MV_SlaveMule quest. --- apps/openmw/mwdialogue/quest.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp index a5411b7479..8ecb4bd13a 100644 --- a/apps/openmw/mwdialogue/quest.cpp +++ b/apps/openmw/mwdialogue/quest.cpp @@ -45,7 +45,6 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); - bool found=false; for (std::vector::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mData.mDisposition==index && iter->mQuestStatus!=ESM::DialInfo::QS_Name) @@ -55,14 +54,11 @@ namespace MWDialogue else if (iter->mQuestStatus==ESM::DialInfo::QS_Restart) mFinished = false; - 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); + // The index must be set even if no related journal entry was found + mIndex = index; } bool Quest::isFinished() const From 150b920ef14d0708aae837faef2a5339df678d5a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 10:14:03 +0200 Subject: [PATCH 311/545] Fix long journal entries not being displayed --- apps/openmw/mwgui/bookpage.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 6545b5d45e..af2fcb46f8 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -93,7 +93,10 @@ struct TypesetBookImpl : TypesetBook typedef std::vector
Sections; + // Holds "top" and "bottom" vertical coordinates in the source text. + // A page is basically a "window" into a portion of the source text, similar to a ScrollView. typedef std::pair Page; + typedef std::vector Pages; Pages mPages; @@ -374,6 +377,29 @@ struct TypesetBookImpl::Typesetter : BookTypesetter else { //split section + int sectionHeightLeft = sectionHeight; + while (sectionHeightLeft > mPageHeight) + { + spaceLeft = mPageHeight - (curPageStop - curPageStart); + + // Adjust to the top of the first line that does not fit on the current page anymore + int splitPos = curPageStop; + for (Lines::iterator j = i->mLines.begin (); j != i->mLines.end (); ++j) + { + if (j->mRect.bottom > curPageStart + mPageHeight) + { + splitPos = j->mRect.top; + break; + } + } + + mBook->mPages.push_back (Page (curPageStart, splitPos)); + curPageStart = splitPos; + curPageStop = splitPos; + + sectionHeightLeft = (i->mRect.bottom - splitPos); + } + curPageStop = i->mRect.bottom; } } From 90ec19c3acec73e72acdbbb07636598f2443c9d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 10:30:03 +0200 Subject: [PATCH 312/545] Remove unneeded MWScrollView --- apps/openmw/mwgui/list.cpp | 26 ++++++-------------------- apps/openmw/mwgui/list.hpp | 14 +------------- apps/openmw/mwgui/windowmanagerimp.cpp | 1 - 3 files changed, 7 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index eff7aea248..19f20eeee7 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -26,7 +26,7 @@ namespace MWGui if (mClient == 0) mClient = this; - mScrollView = mClient->createWidgetReal( + mScrollView = mClient->createWidgetReal( "MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0), MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView"); } @@ -51,7 +51,7 @@ namespace MWGui const int _scrollBarWidth = 20; // fetch this from skin? const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int spacing = 3; - size_t scrollbarPosition = mScrollView->getScrollPosition(); + size_t viewPosition = -mScrollView->getViewOffset().top; while (mScrollView->getChildCount()) { @@ -96,10 +96,10 @@ namespace MWGui if (!scrollbarShown && mItemHeight > mClient->getSize().height) redraw(true); - size_t scrollbarRange = mScrollView->getScrollRange(); - if(scrollbarPosition > scrollbarRange) - scrollbarPosition = scrollbarRange; - mScrollView->setScrollPosition(scrollbarPosition); + size_t viewRange = mScrollView->getCanvasSize().height; + if(viewPosition > viewRange) + viewPosition = viewRange; + mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition)); } bool MWList::hasItem(const std::string& name) @@ -151,19 +151,5 @@ namespace MWGui return mScrollView->findWidget (getName() + "_item_" + name); } - size_t MWScrollView::getScrollPosition() - { - return getVScroll()->getScrollPosition(); - } - - void MWScrollView::setScrollPosition(size_t position) - { - getVScroll()->setScrollPosition(position); - } - size_t MWScrollView::getScrollRange() - { - return getVScroll()->getScrollRange(); - } - } } diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index 956523c0dc..dcfe7931a0 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -7,18 +7,6 @@ namespace MWGui { namespace Widgets { - /** - * \brief a custom ScrollView which has access to scrollbar properties - */ - class MWScrollView : public MyGUI::ScrollView - { - MYGUI_RTTI_DERIVED(MWScrollView) - public: - size_t getScrollPosition(); - void setScrollPosition(size_t); - size_t getScrollRange(); - }; - /** * \brief a very simple list widget that supports word-wrapping entries * \note if the width or height of the list changes, you must call adjustSize() method @@ -70,7 +58,7 @@ namespace MWGui void onItemSelected(MyGUI::Widget* _sender); private: - MWGui::Widgets::MWScrollView* mScrollView; + MyGUI::ScrollView* mScrollView; MyGUI::Widget* mClient; std::vector mItems; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 3cf7379ff9..d701e56abb 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -158,7 +158,6 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); From 69c1eb28c51ba04f50a0764fb07bd25342f11a55 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 18 May 2014 14:39:04 +0400 Subject: [PATCH 313/545] travis compile fix --- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/aisequence.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 9eb5f55cc9..2c35404626 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -922,7 +922,7 @@ namespace MWMechanics sBasePoint = Ogre::Vector3(iter->first.getRefData().getPosition().pos); listGuards.sort(comparePtrDist); // try to engage combat starting from the nearest creature - for (std::list::const_iterator it = listGuards.cbegin(); it != listGuards.cend(); ++it) + for (std::list::iterator it = listGuards.begin(); it != listGuards.end(); ++it) { engageCombat(iter->first, *it, false); } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index f93dae4d1f..b74a5da5ae 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -156,7 +156,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) } } - if (mPackages.cbegin() != itActualCombat) + if (mPackages.begin() != itActualCombat) { // move combat package with nearest target to the front mPackages.splice(mPackages.begin(), mPackages, itActualCombat); From a872c9f83ad487456b032a896ad699d590d6ad61 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 12:53:21 +0200 Subject: [PATCH 314/545] Feature #1323: handle restocking levelled items --- apps/openmw/mwclass/container.cpp | 12 +----- apps/openmw/mwclass/creature.cpp | 12 +----- apps/openmw/mwclass/npc.cpp | 12 +----- apps/openmw/mwworld/containerstore.cpp | 60 ++++++++++++++++++++++---- apps/openmw/mwworld/containerstore.hpp | 10 ++++- components/esm/inventorystate.cpp | 16 ++++++- components/esm/inventorystate.hpp | 4 ++ 7 files changed, 85 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index fd8eeb46b9..2d9695c6b9 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -74,16 +74,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; - for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) - { - if (it->mCount < 0) - { - MWWorld::ContainerStore& store = getContainerStore(ptr); - int currentCount = store.count(it->mItem.toString()); - if (currentCount < std::abs(it->mCount)) - store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); - } - } + MWWorld::ContainerStore& store = getContainerStore(ptr); + store.restock(list, ptr, ptr.getCellRef().mOwner, ptr.getCellRef().mFaction); } void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index db3a70a6a6..924021faae 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -843,16 +843,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; - for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) - { - if (it->mCount < 0) - { - MWWorld::ContainerStore& store = getContainerStore(ptr); - int currentCount = store.count(it->mItem.toString()); - if (currentCount < std::abs(it->mCount)) - store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); - } - } + MWWorld::ContainerStore& store = getContainerStore(ptr); + store.restock(list, ptr, ptr.getCellRef().mRefID, ptr.getCellRef().mFaction); } const ESM::GameSetting* Creature::fMinWalkSpeedCreature; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 009559d192..72505fa081 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1334,16 +1334,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; - for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) - { - if (it->mCount < 0) - { - MWWorld::ContainerStore& store = getContainerStore(ptr); - int currentCount = store.count(it->mItem.toString()); - if (currentCount < std::abs(it->mCount)) - store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr); - } - } + MWWorld::ContainerStore& store = getContainerStore(ptr); + store.restock(list, ptr, ptr.getCellRef().mRefID, ptr.getCellRef().mFaction); } const ESM::GameSetting *Npc::fMinWalkSpeed; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 1cbaa349ca..8f2a566461 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -366,7 +366,7 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std:: for (std::vector::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); ++iter) { - std::string id = iter->mItem.toString(); + std::string id = Misc::StringUtils::lowerCase(iter->mItem.toString()); addInitialItem(id, owner, faction, iter->mCount); } @@ -374,21 +374,18 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std:: } void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, - int count, bool topLevel) + int count, bool topLevel, const std::string& levItem) { - // A negative count indicates restocking items, but this is implemented elsewhere - count = std::abs(count); - ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) { const ESM::ItemLevList* levItem = ref.getPtr().get()->mBase; - if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each) + if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each) { - for (int i=0; i 0 ? 1 : -1, true, levItem->mId); return; } else @@ -396,17 +393,58 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: std::string id = MWMechanics::getLevelledItem(ref.getPtr().get()->mBase, false); if (id.empty()) return; - addInitialItem(id, owner, faction, count, false); + addInitialItem(id, owner, faction, count, false, levItem->mId); } } else { + // A negative count indicates restocking items + // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks + if (!levItem.empty() && count < 0) + { + if (mLevelledItemMap.find(id) == mLevelledItemMap.end()) + mLevelledItemMap[id] = 0; + mLevelledItemMap[id] += std::abs(count); + } + count = std::abs(count); + ref.getPtr().getCellRef().mOwner = owner; ref.getPtr().getCellRef().mFaction = faction; addImp (ref.getPtr(), count); } } +void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction) +{ + // Remove the items already spawned by levelled items that will restock + for (std::map::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it) + { + if (count(it->first) >= it->second) + remove(it->first, it->second, ptr); + } + mLevelledItemMap.clear(); + + for (std::vector::const_iterator it = items.mList.begin(); it != items.mList.end(); ++it) + { + if (it->mCount >= 0) + continue; + + std::string item = Misc::StringUtils::lowerCase(it->mItem.toString()); + + if (MWBase::Environment::get().getWorld()->getStore().get().search(it->mItem.toString())) + { + addInitialItem(item, owner, faction, it->mCount, true); + } + else + { + int currentCount = count(item); + if (currentCount < std::abs(it->mCount)) + add (item, std::abs(it->mCount) - currentCount, ptr); + } + } + flagAsModified(); +} + void MWWorld::ContainerStore::clear() { for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) @@ -585,6 +623,8 @@ void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const state.mLights.clear(); + state.mLevelledItemMap = mLevelledItemMap; + for (MWWorld::CellRefList::List::const_iterator iter (lights.mList.begin()); iter!=lights.mList.end(); ++iter) { @@ -628,6 +668,8 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& state) { getState (lights, iter->first); } + + mLevelledItemMap = state.mLevelledItemMap; } diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index dd0c1b0024..7c81bdb6e7 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -2,6 +2,7 @@ #define GAME_MWWORLD_CONTAINERSTORE_H #include +#include #include #include @@ -65,10 +66,15 @@ namespace MWWorld MWWorld::CellRefList probes; MWWorld::CellRefList repairs; MWWorld::CellRefList weapons; + + std::map mLevelledItemMap; + ///< Stores result of levelled item spawns. + /// This is used to remove the spawned item(s) if the levelled item is restocked. + mutable float mCachedWeight; mutable bool mWeightUpToDate; ContainerStoreIterator addImp (const Ptr& ptr, int count); - void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int count, bool topLevel=true); + void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int count, bool topLevel=true, const std::string& levItem = ""); template ContainerStoreIterator getState (CellRefList& collection, @@ -145,6 +151,8 @@ namespace MWWorld void fill (const ESM::InventoryList& items, const std::string& owner, const std::string& faction, const MWWorld::ESMStore& store); ///< Insert items into *this. + void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction); + virtual void clear(); ///< Empty container. diff --git a/components/esm/inventorystate.cpp b/components/esm/inventorystate.cpp index 4d8cbc6228..1b0bc772e9 100644 --- a/components/esm/inventorystate.cpp +++ b/components/esm/inventorystate.cpp @@ -47,6 +47,14 @@ void ESM::InventoryState::load (ESMReader &esm) mItems.push_back (std::make_pair (state, std::make_pair (id, slot))); } } + + while (esm.isNextSub("LEVM")) + { + std::string id = esm.getHString(); + int count; + esm.getHNT (count, "COUN"); + mLevelledItemMap[id] = count; + } } void ESM::InventoryState::save (ESMWriter &esm) const @@ -57,4 +65,10 @@ void ESM::InventoryState::save (ESMWriter &esm) const for (std::vector >::const_iterator iter (mLights.begin()); iter!=mLights.end(); ++iter) write (esm, iter->first, ESM::REC_LIGH, iter->second); -} \ No newline at end of file + + for (std::map::const_iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it) + { + esm.writeHNString ("LEVM", it->first); + esm.writeHNT ("COUN", it->second); + } +} diff --git a/components/esm/inventorystate.hpp b/components/esm/inventorystate.hpp index 3cfffbccc9..f754fb57aa 100644 --- a/components/esm/inventorystate.hpp +++ b/components/esm/inventorystate.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_ESM_INVENTORYSTATE_H #define OPENMW_ESM_INVENTORYSTATE_H +#include + #include "objectstate.hpp" #include "lightstate.hpp" @@ -20,6 +22,8 @@ namespace ESM // lights (slot) std::vector > mLights; + std::map mLevelledItemMap; + virtual void load (ESMReader &esm); virtual void save (ESMWriter &esm) const; }; From 584c121f33ac2f879b366ec60591aa9f6af4d604 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 14 Jan 2014 17:20:41 +0400 Subject: [PATCH 315/545] fix windows unicode path handling --- components/files/windowspath.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index ea1ca56d3c..a8cbcb24b7 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -10,8 +10,12 @@ #pragma comment(lib, "Shlwapi.lib") +#include +namespace bconv = boost::locale::conv; + /** * FIXME: Someone with Windows system should check this and correct if necessary + * FIXME: MAX_PATH is irrelevant for extended-length paths, i.e. \\?\... */ /** @@ -29,16 +33,15 @@ boost::filesystem::path WindowsPath::getUserConfigPath() const { boost::filesystem::path userPath("."); - TCHAR path[MAX_PATH]; + WCHAR path[MAX_PATH + 1]; memset(path, 0, sizeof(path)); - if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path))) + if(SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path))) { - PathAppend(path, TEXT("My Games")); - userPath = boost::filesystem::path(path); + userPath = boost::filesystem::path(bconv::utf_to_utf(path)); } - return userPath / mName; + return userPath / "MyGames" / mName; } boost::filesystem::path WindowsPath::getUserDataPath() const @@ -51,12 +54,12 @@ boost::filesystem::path WindowsPath::getGlobalConfigPath() const { boost::filesystem::path globalPath("."); - TCHAR path[MAX_PATH]; + WCHAR path[MAX_PATH + 1]; memset(path, 0, sizeof(path)); - if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES | CSIDL_FLAG_CREATE, NULL, 0, path))) + if(SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROGRAM_FILES | CSIDL_FLAG_CREATE, NULL, 0, path))) { - globalPath = boost::filesystem::path(path); + globalPath = boost::filesystem::path(bconv::utf_to_utf(path)); } return globalPath / mName; From eafdefe9993b550e1cc5a1edbd3b92183473e9bb Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 14 Jan 2014 23:08:54 +0400 Subject: [PATCH 316/545] using WindowsPath implies utf-8 for boost fs::path --- components/files/windowspath.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index a8cbcb24b7..f27c1cc925 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -27,6 +27,7 @@ namespace Files WindowsPath::WindowsPath(const std::string& application_name) : mName(application_name) { + boost::filesystem::path::imbue(boost::locale::generator.generate("")); } boost::filesystem::path WindowsPath::getUserConfigPath() const @@ -41,7 +42,7 @@ boost::filesystem::path WindowsPath::getUserConfigPath() const userPath = boost::filesystem::path(bconv::utf_to_utf(path)); } - return userPath / "MyGames" / mName; + return userPath / "My Games" / mName; } boost::filesystem::path WindowsPath::getUserDataPath() const From cd990a665a5b59770174ceeece71c0b675865cb7 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 14 Jan 2014 23:29:24 +0400 Subject: [PATCH 317/545] create QString from utf-8 when expected --- apps/launcher/maindialog.cpp | 20 ++++++++++---------- apps/launcher/settings/gamesettings.cpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 5cf8f8a892..fb4c09b918 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -41,11 +41,11 @@ Launcher::MainDialog::MainDialog(QWidget *parent) // Check if the font is installed if (!fonts.contains("EB Garamond")) { - QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + QString font = QString::fromUtf8(mCfgMgr.getGlobalDataPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf"); file.setFileName(font); if (!file.exists()) { - font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + font = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf"); } fontDatabase.addApplicationFont(font); @@ -243,7 +243,7 @@ bool Launcher::MainDialog::showFirstRunDialog() } // Create the file if it doesn't already exist, else the importer will fail - QString path = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + QString("openmw.cfg"); + QString path = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()) + QString("openmw.cfg"); QFile file(path); if (!file.exists()) { @@ -358,7 +358,7 @@ bool Launcher::MainDialog::setupLauncherSettings() { mLauncherSettings.setMultiValueEnabled(true); - QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()); + QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QStringList paths; paths.append(QString("launcher.cfg")); @@ -464,8 +464,8 @@ bool Launcher::expansions(Launcher::UnshieldThread& cd) bool Launcher::MainDialog::setupGameSettings() { - QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()); - QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); + QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str()); // Load the user config file first, separately // So we can write it properly, uncontaminated @@ -594,7 +594,7 @@ bool Launcher::MainDialog::setupGameSettings() while(expansions(cd)); - selectedFile = QString::fromStdString(cd.GetMWEsmPath()); + selectedFile = QString::fromUtf8(cd.GetMWEsmPath().c_str()); } #endif // WIN32 @@ -615,8 +615,8 @@ bool Launcher::MainDialog::setupGraphicsSettings() { mGraphicsSettings.setMultiValueEnabled(false); - QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()); - QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); + QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str()); QFile localDefault(QString("settings-default.cfg")); QFile globalDefault(globalPath + QString("settings-default.cfg")); @@ -702,7 +702,7 @@ bool Launcher::MainDialog::writeSettings() mGraphicsPage->saveSettings(); mDataFilesPage->saveSettings(); - QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()); + QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QDir dir(userPath); if (!dir.exists()) { diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index e7e5cf1ea7..0a09c5cc04 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -53,7 +53,7 @@ void Launcher::GameSettings::validatePaths() mDataDirs.clear(); for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { - QString path = QString::fromStdString(it->string()); + QString path = QString::fromUtf8(it->string().c_str()); path.remove(QChar('\"')); QDir dir(path); @@ -73,7 +73,7 @@ void Launcher::GameSettings::validatePaths() mCfgMgr.processPaths(dataDirs); if (!dataDirs.empty()) { - QString path = QString::fromStdString(dataDirs.front().string()); + QString path = QString::fromUtf8(dataDirs.front().string().c_str()); path.remove(QChar('\"')); QDir dir(path); From b4950509bc5e55016f79ad0aa50fb8d9164c35c5 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 14 Jan 2014 23:30:56 +0400 Subject: [PATCH 318/545] use converted widechars in ini importer --- apps/mwiniimporter/main.cpp | 32 ++++++++++++++++++++++++++++++++ components/files/windowspath.cpp | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 364a6b1a4a..58ae1d593a 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -4,11 +4,43 @@ #include #include #include +#include namespace bpo = boost::program_options; +#ifndef _WIN32 int main(int argc, char *argv[]) { +#else +class utf8argv +{ +public: + + utf8argv(int argc, wchar_t *wargv[]) + { + args.reserve(argc); + argv = new const char *[argc]; + + for (int i = 0; i < argc; ++i) { + args.push_back(boost::locale::conv::utf_to_utf(wargv[i])); + argv[i] = args.back().c_str(); + } + } + + ~utf8argv() { delete[] argv; } + const char * const *get() const { return argv; } + +private: + + const char **argv; + std::vector args; +}; + +int wmain(int argc, wchar_t *wargv[]) { + utf8argv converter(argc, wargv); + char **argv = converter.get(); + boost::filesystem::path::imbue(boost::locale::generator().generate("")); +#endif bpo::options_description desc("Syntax: mwiniimporter inifile configfile\nAllowed options"); bpo::positional_options_description p_desc; desc.add_options() diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index f27c1cc925..41240ae488 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -27,7 +27,7 @@ namespace Files WindowsPath::WindowsPath(const std::string& application_name) : mName(application_name) { - boost::filesystem::path::imbue(boost::locale::generator.generate("")); + boost::filesystem::path::imbue(boost::locale::generator().generate("")); } boost::filesystem::path WindowsPath::getUserConfigPath() const From 18b3cfebdbb4bfe371333c6273480feeca002853 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 15 Jan 2014 01:43:55 +0400 Subject: [PATCH 319/545] fix importer crash on empty lines (thanks to Ace) --- apps/mwiniimporter/importer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 648ab3ebee..3226278fe9 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -674,6 +674,10 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam line = line.substr(0, line.length()-1); } + if(line.empty()) { + continue; + } + if(line[0] == '[') { int pos = line.find(']'); if(pos < 2) { @@ -690,10 +694,6 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam line = line.substr(0,comment_pos); } - if(line.empty()) { - continue; - } - int pos = line.find("="); if(pos < 1) { continue; From a22ec223d86246dc0640701b3637f40fdeaa89da Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 19 Jan 2014 11:34:54 +0400 Subject: [PATCH 320/545] open fstreams from boost::filesystem::path, vol.1 --- apps/launcher/unshieldthread.cpp | 6 +++--- apps/openmw/mwgui/console.cpp | 6 +++++- components/files/configurationmanager.cpp | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/launcher/unshieldthread.cpp b/apps/launcher/unshieldthread.cpp index 52f9357108..26010faf3f 100644 --- a/apps/launcher/unshieldthread.cpp +++ b/apps/launcher/unshieldthread.cpp @@ -1,6 +1,6 @@ #include "unshieldthread.hpp" -#include +#include #include namespace bfs = boost::filesystem; @@ -49,7 +49,7 @@ namespace std::string read_to_string(const bfs::path& path) { - std::ifstream strstream(path.c_str(), std::ios::in | std::ios::binary); + bfs::ifstream strstream(path, std::ios::in | std::ios::binary); std::string str; strstream.seekg(0, std::ios::end); @@ -201,7 +201,7 @@ namespace add_setting("Archives", "Archive 1", "Bloodmoon.bsa", ini); } - std::ofstream inistream(ini_path.c_str()); + bfs::ofstream inistream(ini_path) inistream << ini; inistream.close(); } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index d51d4298f6..dd3a67e940 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -1,5 +1,8 @@ #include "console.hpp" +#include +#include + #include #include @@ -194,7 +197,8 @@ namespace MWGui void Console::executeFile (const std::string& path) { - std::ifstream stream (path.c_str()); + namespace bfs = boost::filesystem; + bfs::ifstream stream (bfs::path(path)); if (!stream.is_open()) printError ("failed to open file: " + path); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 761b7ca5ad..ffa911b44f 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -1,12 +1,12 @@ #include "configurationmanager.hpp" #include -#include #include #include #include #include +#include /** * \namespace Files @@ -125,7 +125,7 @@ void ConfigurationManager::loadConfig(const boost::filesystem::path& path, { std::cout << "Loading config file: " << cfgFile.string() << "... "; - std::ifstream configFileStream(cfgFile.string().c_str()); + boost::filesystem::ifstream configFileStream(cfgFile); if (configFileStream.is_open()) { boost::program_options::store(boost::program_options::parse_config_file( From 2236216344c489503cbd5945478b0ae196237a12 Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 19 Jan 2014 14:55:12 +0400 Subject: [PATCH 321/545] minor simplification --- components/files/multidircollection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/files/multidircollection.cpp b/components/files/multidircollection.cpp index 347de96a6a..1abbae3ae8 100644 --- a/components/files/multidircollection.cpp +++ b/components/files/multidircollection.cpp @@ -60,10 +60,10 @@ namespace Files { boost::filesystem::path path = *dirIter; - if (!equal (extension, boost::filesystem::path (path.extension()).string())) + if (!equal (extension, path.extension().string())) continue; - std::string filename = boost::filesystem::path (path.filename()).string(); + std::string filename = path.filename().string(); TIter result = mFiles.find (filename); From 424d06a6f88906b4d10f76060c4cd0032440d150 Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 19 Jan 2014 15:20:08 +0400 Subject: [PATCH 322/545] open fstreams from boost::filesystem::path, vol.2 --- components/settings/settings.cpp | 6 ++++-- components/translation/translation.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 13015e39c9..3a3a3dddda 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -1,7 +1,8 @@ #include "settings.hpp" -#include #include +#include +#include #include #include @@ -25,7 +26,8 @@ void Manager::loadDefault (const std::string& file) void Manager::saveUser(const std::string& file) { - std::fstream fout(file.c_str(), std::ios::out); + namespace bfs = boost::filesystem; + bfs::ofstream fout(bfs::path(file)); Ogre::ConfigFile::SectionIterator seci = mFile.getSectionIterator(); diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index d0ea4b7fb6..423c3971a0 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -1,7 +1,8 @@ #include "translation.hpp" -#include -#include +#include + +#include namespace Translation { @@ -28,9 +29,8 @@ namespace Translation if (dataFileCollections.getCollection (extension).doesExist (fileName)) { - std::string path = dataFileCollections.getCollection (extension).getPath (fileName).string(); - - std::ifstream stream (path.c_str()); + boost::filesystem::ifstream stream ( + dataFileCollections.getCollection (extension).getPath (fileName)); if (!stream.is_open()) throw std::runtime_error ("failed to open translation file: " + fileName); From e02b04536f8e840cde337fd3cd622e7c765f3050 Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 19 Jan 2014 18:13:35 +0400 Subject: [PATCH 323/545] fix most vexing parse issue --- apps/launcher/unshieldthread.cpp | 2 +- apps/openmw/mwgui/console.cpp | 2 +- components/settings/settings.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/launcher/unshieldthread.cpp b/apps/launcher/unshieldthread.cpp index 26010faf3f..3d0f2e5da6 100644 --- a/apps/launcher/unshieldthread.cpp +++ b/apps/launcher/unshieldthread.cpp @@ -201,7 +201,7 @@ namespace add_setting("Archives", "Archive 1", "Bloodmoon.bsa", ini); } - bfs::ofstream inistream(ini_path) + bfs::ofstream inistream((ini_path)); inistream << ini; inistream.close(); } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index dd3a67e940..237d145a2e 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -198,7 +198,7 @@ namespace MWGui void Console::executeFile (const std::string& path) { namespace bfs = boost::filesystem; - bfs::ifstream stream (bfs::path(path)); + bfs::ifstream stream ((bfs::path(path))); if (!stream.is_open()) printError ("failed to open file: " + path); diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 3a3a3dddda..ac09db9d95 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -27,7 +27,7 @@ void Manager::loadDefault (const std::string& file) void Manager::saveUser(const std::string& file) { namespace bfs = boost::filesystem; - bfs::ofstream fout(bfs::path(file)); + bfs::ofstream fout((bfs::path(file))); Ogre::ConfigFile::SectionIterator seci = mFile.getSectionIterator(); From 74697f811692456cc1e82e77c8016c2423fb79a4 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 18 May 2014 15:41:15 +0400 Subject: [PATCH 324/545] travis fix #2 --- apps/openmw/mwmechanics/aisequence.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index b74a5da5ae..2da2135299 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -159,7 +159,9 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) if (mPackages.begin() != itActualCombat) { // move combat package with nearest target to the front - mPackages.splice(mPackages.begin(), mPackages, itActualCombat); + AiPackage *package = (*itActualCombat)->clone(); + mPackages.erase(itActualCombat); + mPackages.push_front(package); } } From 66307dd8894c95176eedfc5757642c6a14c2c88d Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 18 May 2014 16:10:14 +0400 Subject: [PATCH 325/545] travis fix #3 :( --- apps/openmw/mwmechanics/aisequence.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 2da2135299..f0f6bffc16 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -133,14 +133,14 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) // if active package is combat one, choose nearest target if (mLastAiPackage == AiPackage::TypeIdCombat) { - std::list::const_iterator itActualCombat; + std::list::iterator itActualCombat; float nearestDist = std::numeric_limits::max(); Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); const AiCombat *package; - for(std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { package = static_cast(*it); @@ -159,9 +159,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) if (mPackages.begin() != itActualCombat) { // move combat package with nearest target to the front - AiPackage *package = (*itActualCombat)->clone(); - mPackages.erase(itActualCombat); - mPackages.push_front(package); + mPackages.splice(mPackages.begin(), mPackages, itActualCombat); } } From 1677fcf324f23c298bcd21a37d764dd22f3cf8c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 20 Feb 2014 16:59:20 +0100 Subject: [PATCH 326/545] Dialogue merging --- apps/esmtool/record.cpp | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 4 +- apps/openmw/mwdialogue/filter.cpp | 6 +-- apps/openmw/mwdialogue/journalentry.cpp | 4 +- apps/openmw/mwdialogue/journalimp.cpp | 2 +- apps/openmw/mwdialogue/quest.cpp | 8 ++-- apps/openmw/mwworld/esmstore.cpp | 7 ++-- components/esm/loaddial.cpp | 38 +++++++++++++++++++ components/esm/loaddial.hpp | 10 ++++- 9 files changed, 62 insertions(+), 19 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 25b2a45050..fd4b97acb9 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -651,7 +651,7 @@ void Record::print() // Sadly, there are no DialInfos, because the loader dumps as it // loads, rather than loading and then dumping. :-( Anyone mind if // I change this? - std::vector::iterator iit; + ESM::Dialogue::InfoContainer::iterator iit; for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); iit++) std::cout << "INFO!" << iit->mId << std::endl; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 323b450647..fe37f37ff7 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -289,7 +289,7 @@ namespace MWDialogue // Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group, // in which case it should not be added to the journal. - for (std::vector::const_iterator iter = dialogue.mInfo.begin(); + for (ESM::Dialogue::InfoContainer::const_iterator iter = dialogue.mInfo.begin(); iter!=dialogue.mInfo.end(); ++iter) { if (iter->mId == info->mId) @@ -467,7 +467,7 @@ namespace MWDialogue // Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group, // in which case it should not be added to the journal. - for (std::vector::const_iterator iter = mDialogueMap[mLastTopic].mInfo.begin(); + for (ESM::Dialogue::InfoContainer::const_iterator iter = mDialogueMap[mLastTopic].mInfo.begin(); iter!=mDialogueMap[mLastTopic].mInfo.end(); ++iter) { if (iter->mId == info->mId) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index b1c700e315..8b9ee9184f 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -621,7 +621,7 @@ std::vector MWDialogue::Filter::list (const ESM::Dialogue bool infoRefusal = false; // Iterate over topic responses to find a matching one - for (std::vector::const_iterator iter = dialogue.mInfo.begin(); + for (ESM::Dialogue::InfoContainer::const_iterator iter = dialogue.mInfo.begin(); iter!=dialogue.mInfo.end(); ++iter) { if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter)) @@ -646,7 +646,7 @@ std::vector MWDialogue::Filter::list (const ESM::Dialogue const ESM::Dialogue& infoRefusalDialogue = *dialogues.find ("Info Refusal"); - for (std::vector::const_iterator iter = infoRefusalDialogue.mInfo.begin(); + for (ESM::Dialogue::InfoContainer::const_iterator iter = infoRefusalDialogue.mInfo.begin(); iter!=infoRefusalDialogue.mInfo.end(); ++iter) if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter, invertDisposition)) { infos.push_back(&*iter); @@ -660,7 +660,7 @@ std::vector MWDialogue::Filter::list (const ESM::Dialogue bool MWDialogue::Filter::responseAvailable (const ESM::Dialogue& dialogue) const { - for (std::vector::const_iterator iter = dialogue.mInfo.begin(); + for (ESM::Dialogue::InfoContainer::const_iterator iter = dialogue.mInfo.begin(); iter!=dialogue.mInfo.end(); ++iter) { if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter)) diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp index 9463e4c45b..55574bf3eb 100644 --- a/apps/openmw/mwdialogue/journalentry.cpp +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -20,7 +20,7 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (topic); - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mId == mInfoId) { @@ -73,7 +73,7 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (topic); - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mData.mDisposition==index) /// \todo cleanup info structure { diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index 724d531cfb..04aa0534dd 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -56,7 +56,7 @@ namespace MWDialogue if (infoId.empty()) return true; - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mId == infoId) return true; diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp index 8ecb4bd13a..a699286a15 100644 --- a/apps/openmw/mwdialogue/quest.cpp +++ b/apps/openmw/mwdialogue/quest.cpp @@ -27,7 +27,7 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mQuestStatus==ESM::DialInfo::QS_Name) return iter->mResponse; @@ -45,7 +45,7 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (mTopic); - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mData.mDisposition==index && iter->mQuestStatus!=ESM::DialInfo::QS_Name) { @@ -53,8 +53,6 @@ namespace MWDialogue mFinished = true; else if (iter->mQuestStatus==ESM::DialInfo::QS_Restart) mFinished = false; - - // Don't return here. Quest status may actually be in a different info record, since we don't merge these (yet?) } // The index must be set even if no related journal entry was found @@ -73,7 +71,7 @@ namespace MWDialogue const ESM::Dialogue *dialogue = MWBase::Environment::get().getWorld()->getStore().get().find (entry.mTopic); - for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin()); iter!=dialogue->mInfo.end(); ++iter) if (iter->mId == entry.mInfoId) { diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index ed140434b5..ce8c800b9a 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -72,9 +72,10 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) if (n.val == ESM::REC_INFO) { std::string id = esm.getHNOString("INAM"); if (dialogue) { - dialogue->mInfo.push_back(ESM::DialInfo()); - dialogue->mInfo.back().mId = id; - dialogue->mInfo.back().load(esm); + ESM::DialInfo info; + info.mId = id; + info.load(esm); + dialogue->addInfo(info, esm.getIndex() != 0); } else { std::cerr << "error: info record without dialog" << std::endl; esm.skipRecord(); diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index fb43ee8586..4a2f17e26c 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -1,5 +1,7 @@ #include "loaddial.hpp" +#include + #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" @@ -43,4 +45,40 @@ void Dialogue::save(ESMWriter &esm) const mInfo.clear(); } +void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) +{ + // TODO: use std::move + if (!merge || mInfo.empty() || info.mNext.empty()) + { + mInfo.push_back(info); + return; + } + if (info.mPrev.empty()) + { + mInfo.push_front(info); + return; + } + int i=0; + for (ESM::Dialogue::InfoContainer::iterator it = mInfo.begin(); it != mInfo.end(); ++it) + { + if (info.mPrev == it->mId) + { + mInfo.insert(++it, info); + return; + } + if (info.mNext == it->mId) + { + mInfo.insert(it, info); + return; + } + if (info.mId == it->mId) + { + *it = info; + return; + } + ++i; + } + std::cerr << "Failed to insert info " << info.mId << std::endl; +} + } diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 63d78833e1..612c4fee6b 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -2,7 +2,7 @@ #define OPENMW_ESM_DIAL_H #include -#include +#include #include "loadinfo.hpp" @@ -33,11 +33,17 @@ struct Dialogue std::string mId; signed char mType; - std::vector mInfo; + + typedef std::list InfoContainer; + + InfoContainer mInfo; void load(ESMReader &esm); void save(ESMWriter &esm) const; + /// @param merge Merge with existing list, or just push each record to the end of the list? + void addInfo (const ESM::DialInfo& info, bool merge); + void blank(); ///< Set record to default state (does not touch the ID and does not change the type). }; From 0aa1042fd79488aa8f51bb80492b246b199cb481 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 15:59:45 +0200 Subject: [PATCH 327/545] Optimized dialogue merging with a lookup map --- components/esm/loaddial.cpp | 51 ++++++++++++++++++++++--------------- components/esm/loaddial.hpp | 6 +++++ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index 4a2f17e26c..5adf409bba 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -47,37 +47,46 @@ void Dialogue::save(ESMWriter &esm) const void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) { - // TODO: use std::move if (!merge || mInfo.empty() || info.mNext.empty()) { - mInfo.push_back(info); + mLookup[info.mId] = mInfo.insert(mInfo.end(), info); return; } if (info.mPrev.empty()) { - mInfo.push_front(info); + mLookup[info.mId] = mInfo.insert(mInfo.begin(), info); return; } - int i=0; - for (ESM::Dialogue::InfoContainer::iterator it = mInfo.begin(); it != mInfo.end(); ++it) + + ESM::Dialogue::InfoContainer::iterator it = mInfo.end(); + + std::map::iterator lookup; + lookup = mLookup.find(info.mPrev); + if (lookup != mLookup.end()) { - if (info.mPrev == it->mId) - { - mInfo.insert(++it, info); - return; - } - if (info.mNext == it->mId) - { - mInfo.insert(it, info); - return; - } - if (info.mId == it->mId) - { - *it = info; - return; - } - ++i; + it = lookup->second; + + mLookup[info.mId] = mInfo.insert(++it, info); + return; } + + lookup = mLookup.find(info.mNext); + if (lookup != mLookup.end()) + { + it = lookup->second; + + mLookup[info.mId] = mInfo.insert(it, info); + return; + } + + lookup = mLookup.find(info.mId); + if (lookup != mLookup.end()) + { + it = lookup->second; + *it = info; + return; + } + std::cerr << "Failed to insert info " << info.mId << std::endl; } diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 612c4fee6b..6ec5527f9f 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "loadinfo.hpp" @@ -36,8 +37,13 @@ struct Dialogue typedef std::list InfoContainer; + typedef std::map LookupMap; + InfoContainer mInfo; + // This is only used during the loading phase to speed up DialInfo merging. + LookupMap mLookup; + void load(ESMReader &esm); void save(ESMWriter &esm) const; From a87b64d2da4795d9d6accb8c7f63cbdc06f91002 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 16:29:24 +0200 Subject: [PATCH 328/545] Fix some ancient code --- apps/openmw/mwworld/esmstore.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index ce8c800b9a..1fdf3c5a50 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -27,8 +27,6 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) { listener->setProgressRange(1000); - std::set missing; - ESM::Dialogue *dialogue = 0; /// \todo Move this to somewhere else. ESMReader? @@ -85,9 +83,9 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) } else if (n.val == ESM::REC_SKIL) { mSkills.load (esm); } else { - // Not found (this would be an error later) - esm.skipRecord(); - missing.insert(n.toString()); + std::stringstream error; + error << "Unknown record: " << n.toString(); + throw std::runtime_error(error.str()); } } else { // Load it @@ -114,19 +112,6 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) } listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000); } - - /* This information isn't needed on screen. But keep the code around - for debugging purposes later. - - cout << "\n" << mStores.size() << " record types:\n"; - for(RecListList::iterator it = mStores.begin(); it != mStores.end(); it++) - cout << " " << toStr(it->first) << ": " << it->second->getSize() << endl; - cout << "\nNot implemented yet: "; - for(set::iterator it = missing.begin(); - it != missing.end(); it++ ) - cout << *it << " "; - cout << endl; - */ } void ESMStore::setUp() From e1249f6a31087e6a127b5d8d3dd3218d87ee1b58 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 18 May 2014 20:13:46 +0400 Subject: [PATCH 329/545] actor handle and id confusing fix --- apps/openmw/mwmechanics/aisequence.cpp | 11 +++-------- apps/openmw/mwmechanics/aisequence.hpp | 2 +- apps/openmw/mwmechanics/creaturestats.cpp | 6 ++---- apps/openmw/mwscript/aiextensions.cpp | 5 +++-- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index f0f6bffc16..9dc2380f85 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -59,14 +59,13 @@ int AiSequence::getTypeId() const return mPackages.front()->getTypeId(); } -bool AiSequence::getCombatTarget(std::string &targetActorId) const +bool AiSequence::getCombatTarget(MWWorld::Ptr &targetActor) const { if (getTypeId() != AiPackage::TypeIdCombat) return false; const AiCombat *combat = static_cast(mPackages.front()); - MWWorld::Ptr target = combat->getTarget(); - targetActorId = target.getClass().getCreatureStats(target).getActorId(); + targetActor = combat->getTarget(); return true; } @@ -138,15 +137,11 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) float nearestDist = std::numeric_limits::max(); Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); - const AiCombat *package; - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { - package = static_cast(*it); - if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; - ESM::Position &targetPos = package->getTarget().getRefData().getPosition(); + ESM::Position &targetPos = static_cast(*it)->getTarget().getRefData().getPosition(); float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); if (distTo < nearestDist) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 7e977cf581..41a280da80 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -53,7 +53,7 @@ namespace MWMechanics int getLastRunTypeId() const { return mLastAiPackage; } /// Return true and assign target if combat package is currently active, return false otherwise - bool getCombatTarget (std::string &targetActorId) const; + bool getCombatTarget (MWWorld::Ptr &targetActor) const; bool canAddTarget(const ESM::Position& actorPos, float distToTarget) const; ///< Function assumes that actor can have only 1 target apart player diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 57618e6e93..d8dfa158db 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -322,11 +322,9 @@ namespace MWMechanics bool CreatureStats::getCreatureTargetted() const { - std::string target; - if (mAiSequence.getCombatTarget(target)) + MWWorld::Ptr targetPtr; + if (mAiSequence.getCombatTarget(targetPtr)) { - MWWorld::Ptr targetPtr; - targetPtr = MWBase::Environment::get().getWorld()->getPtr(target, true); return targetPtr.getTypeName() == typeid(ESM::Creature).name(); } return false; diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 8ed19925ec..695954bc20 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -419,9 +419,10 @@ namespace MWScript std::string currentTargetId; bool targetsAreEqual = false; - if (creatureStats.getAiSequence().getCombatTarget (currentTargetId)) + MWWorld::Ptr targetPtr; + if (creatureStats.getAiSequence().getCombatTarget (targetPtr)) { - if (currentTargetId == testedTargetId) + if (targetPtr.getRefData().getHandle() == testedTargetId) targetsAreEqual = true; } runtime.push(int(targetsAreEqual)); From 3dceb7ee4fc1b100e249d672e77b6e080477f736 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 May 2014 18:58:32 +0200 Subject: [PATCH 330/545] Fix overwriting DialInfo --- components/esm/loaddial.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index 5adf409bba..ee7ddbfadf 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -61,6 +61,15 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) ESM::Dialogue::InfoContainer::iterator it = mInfo.end(); std::map::iterator lookup; + + lookup = mLookup.find(info.mId); + if (lookup != mLookup.end()) + { + it = lookup->second; + *it = info; + return; + } + lookup = mLookup.find(info.mPrev); if (lookup != mLookup.end()) { @@ -79,14 +88,6 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) return; } - lookup = mLookup.find(info.mId); - if (lookup != mLookup.end()) - { - it = lookup->second; - *it = info; - return; - } - std::cerr << "Failed to insert info " << info.mId << std::endl; } From a5f0fe7282d200a88f357b1bf9b2cca0743630a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 18 May 2014 20:07:41 +0200 Subject: [PATCH 331/545] incremented version number --- CMakeLists.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c5c156dbd..541720f7e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) -set(OPENMW_VERSION_MINOR 29) +set(OPENMW_VERSION_MINOR 30) set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_COMMITHASH "") diff --git a/readme.txt b/readme.txt index 4db9425b6d..92cb35f31f 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.29.0 +Version: 0.30.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org From fa14df62b7e863ba17ee7f82dd3363e0bba62b6f Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 18 May 2014 23:15:22 +0400 Subject: [PATCH 332/545] fix crash on disappeared target --- apps/openmw/mwmechanics/aisequence.cpp | 28 ++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 9dc2380f85..6a5cf572a9 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -141,17 +141,33 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) { if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; - ESM::Position &targetPos = static_cast(*it)->getTarget().getRefData().getPosition(); + MWWorld::Ptr target = static_cast(*it)->getTarget(); - float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); - if (distTo < nearestDist) + // target disappeared (e.g. summoned creatures) + if (target.isEmpty()) { - nearestDist = distTo; - itActualCombat = it; + mPackages.erase(it++); + } + else + { + ESM::Position &targetPos = target.getRefData().getPosition(); + + float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); + if (distTo < nearestDist) + { + nearestDist = distTo; + itActualCombat = it; + } } } - if (mPackages.begin() != itActualCombat) + // all targets disappeared + if (nearestDist == std::numeric_limits::max()) + { + mDone = true; + return; + } + else if (mPackages.begin() != itActualCombat) { // move combat package with nearest target to the front mPackages.splice(mPackages.begin(), mPackages, itActualCombat); From 0fe0dc33a63d4254bdbdd4e29d0356a80e8c311f Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 May 2014 05:35:16 +0200 Subject: [PATCH 333/545] Fixes #1338: Bring back a label that got lost --- files/mygui/openmw_settings_window.layout | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index bcf4374a46..6119ab7b4d 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -440,8 +440,12 @@ + + + + From 510b7f850538df2ebe1f6c894ebb89868ca87199 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 May 2014 07:31:19 +0200 Subject: [PATCH 334/545] Task #1333: Remove cmake git tag reading --- CMakeLists.txt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8179021a4c..7451415026 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,18 +36,8 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/.git) string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}") string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}") - set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}") - - if(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) - message(FATAL_ERROR "Silly Zini forgot to update the version again...") - else(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) - set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR}) - set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR}) - set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE}) - - set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}") - set(OPENMW_VERSION_TAGHASH "${TAGHASH}") - endif(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) + set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}") + set(OPENMW_VERSION_TAGHASH "${TAGHASH}") message(STATUS "OpenMW version ${OPENMW_VERSION}") else(MATCH) From 6f03694d505f2ec15ee845056d8db8a7b3309050 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 May 2014 08:03:55 +0200 Subject: [PATCH 335/545] Fixes #1334: Only unequip item if the sell/drag action is actually successful --- apps/openmw/mwgui/inventorywindow.cpp | 62 ++++++++++++++------------- apps/openmw/mwgui/inventorywindow.hpp | 3 ++ 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4d52d59bb6..e9a4a18e5a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -176,35 +176,6 @@ namespace MWGui return; } - if (item.mType == ItemStack::Type_Equipped) - { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - MWWorld::Ptr newStack = *invStore.unequipItem(item.mBase, mPtr); - - // The unequipped item was re-stacked. We have to update the index - // since the item pointed does not exist anymore. - if (item.mBase != newStack) - { - // newIndex will store the index of the ItemStack the item was stacked on - int newIndex = -1; - for (size_t i=0; i < mTradeModel->getItemCount(); ++i) - { - if (mTradeModel->getItem(i).mBase == newStack) - { - newIndex = i; - break; - } - } - - if (newIndex == -1) - throw std::runtime_error("Can't find restacked item"); - - index = newIndex; - object = mTradeModel->getItem(index).mBase; - } - - } - bool shift = MyGUI::InputManager::getInstance().isShiftPressed(); if (MyGUI::InputManager::getInstance().isControlPressed()) count = 1; @@ -247,13 +218,46 @@ namespace MWGui notifyContentChanged(); } + void InventoryWindow::ensureSelectedItemUnequipped() + { + const ItemStack& item = mTradeModel->getItem(mSelectedItem); + if (item.mType == ItemStack::Type_Equipped) + { + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::Ptr newStack = *invStore.unequipItem(item.mBase, mPtr); + + // The unequipped item was re-stacked. We have to update the index + // since the item pointed does not exist anymore. + if (item.mBase != newStack) + { + // newIndex will store the index of the ItemStack the item was stacked on + int newIndex = -1; + for (size_t i=0; i < mTradeModel->getItemCount(); ++i) + { + if (mTradeModel->getItem(i).mBase == newStack) + { + newIndex = i; + break; + } + } + + if (newIndex == -1) + throw std::runtime_error("Can't find restacked item"); + + mSelectedItem = newIndex; + } + } + } + void InventoryWindow::dragItem(MyGUI::Widget* sender, int count) { + ensureSelectedItemUnequipped(); mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count); } void InventoryWindow::sellItem(MyGUI::Widget* sender, int count) { + ensureSelectedItemUnequipped(); const ItemStack& item = mTradeModel->getItem(mSelectedItem); std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 17a25e5027..df563b3d46 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -102,6 +102,9 @@ namespace MWGui void notifyContentChanged(); void adjustPanes(); + + /// Unequips mSelectedItem, if it is equipped, and then updates mSelectedItem in case it was re-stacked + void ensureSelectedItemUnequipped(); }; } From 2c82da8e6e5d535e2032c8e21150d7a8d3a60f07 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 10:07:43 +0400 Subject: [PATCH 336/545] load Ogre::ConfigFile from DataStream --- components/settings/settings.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index ac09db9d95..56e937c8ef 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -6,9 +6,12 @@ #include #include +#include using namespace Settings; +namespace bfs = boost::filesystem; + Ogre::ConfigFile Manager::mFile = Ogre::ConfigFile(); Ogre::ConfigFile Manager::mDefaultFile = Ogre::ConfigFile(); CategorySettingVector Manager::mChangedSettings = CategorySettingVector(); @@ -16,17 +19,20 @@ CategorySettingValueMap Manager::mNewSettings = CategorySettingValueMap(); void Manager::loadUser (const std::string& file) { - mFile.load(file); + bfs::ifstream fin((bfs::path(file))); + Ogre::DataStreamPtr stream((OGRE_NEW Ogre::FileStreamDataStream(file, &fin, false))); + mFile.load(stream); } void Manager::loadDefault (const std::string& file) { - mDefaultFile.load(file); + bfs::ifstream fin((bfs::path(file))); + Ogre::DataStreamPtr stream((OGRE_NEW Ogre::FileStreamDataStream(file, &fin, false))); + mDefaultFile.load(stream); } void Manager::saveUser(const std::string& file) { - namespace bfs = boost::filesystem; bfs::ofstream fout((bfs::path(file))); Ogre::ConfigFile::SectionIterator seci = mFile.getSectionIterator(); From 6cb795ef7d86f14358f2b497c561de1c226465c4 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 10:47:02 +0400 Subject: [PATCH 337/545] attempt to fix LowLevelFile, minor code reuse --- components/files/lowlevelfile.cpp | 5 ++++- components/settings/settings.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/components/files/lowlevelfile.cpp b/components/files/lowlevelfile.cpp index 06ee9fb4e8..4466e354d1 100644 --- a/components/files/lowlevelfile.cpp +++ b/components/files/lowlevelfile.cpp @@ -206,6 +206,8 @@ size_t LowLevelFile::read (void * data, size_t size) } #elif FILE_API == FILE_API_WIN32 + +#include /* * * Implementation of LowLevelFile methods using Win32 API calls @@ -227,7 +229,8 @@ void LowLevelFile::open (char const * filename) { assert (mHandle == INVALID_HANDLE_VALUE); - HANDLE handle = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + std::wstring wname = boost::locale::conv::utf_to_utf(filename); + HANDLE handle = CreateFileW (wname.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (handle == NULL) { diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 56e937c8ef..0def0afdb7 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -8,6 +8,8 @@ #include #include +#include + using namespace Settings; namespace bfs = boost::filesystem; @@ -19,15 +21,13 @@ CategorySettingValueMap Manager::mNewSettings = CategorySettingValueMap(); void Manager::loadUser (const std::string& file) { - bfs::ifstream fin((bfs::path(file))); - Ogre::DataStreamPtr stream((OGRE_NEW Ogre::FileStreamDataStream(file, &fin, false))); + Ogre::DataStreamPtr stream = openConstrainedFileDataStream(file.c_str()); mFile.load(stream); } void Manager::loadDefault (const std::string& file) { - bfs::ifstream fin((bfs::path(file))); - Ogre::DataStreamPtr stream((OGRE_NEW Ogre::FileStreamDataStream(file, &fin, false))); + Ogre::DataStreamPtr stream = openConstrainedFileDataStream(file.c_str()); mDefaultFile.load(stream); } From 417e07fbcef11d94d903925bf9a6bd91f3e0bbb4 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 10:59:36 +0400 Subject: [PATCH 338/545] fix irrelevant error reporting --- components/files/lowlevelfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/files/lowlevelfile.cpp b/components/files/lowlevelfile.cpp index 4466e354d1..4cdeec043a 100644 --- a/components/files/lowlevelfile.cpp +++ b/components/files/lowlevelfile.cpp @@ -232,7 +232,7 @@ void LowLevelFile::open (char const * filename) std::wstring wname = boost::locale::conv::utf_to_utf(filename); HANDLE handle = CreateFileW (wname.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - if (handle == NULL) + if (handle == INVALID_HANDLE_VALUE) { std::ostringstream os; os << "Failed to open '" << filename << "' for reading."; From 493f8c60504222e5fe51a34548c69907bdec2ae0 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 13:39:07 +0400 Subject: [PATCH 339/545] fix opening BSA on Unicode path --- components/bsa/bsa_file.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 25b006fb3e..0958c8f0c2 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -25,6 +25,9 @@ #include +#include +#include + #include "../files/constrainedfiledatastream.hpp" using namespace std; @@ -72,7 +75,8 @@ void BSAFile::readHeader() */ assert(!isLoaded); - std::ifstream input(filename.c_str(), std::ios_base::binary); + namespace bfs = boost::filesystem; + bfs::ifstream input(bfs::path(filename), std::ios_base::binary); // Total archive size size_t fsize = 0; From 9c6224c74d0e19e680a9f22f037503ba28451b10 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 15:43:25 +0400 Subject: [PATCH 340/545] fix saving to Unicode path destination --- apps/openmw/mwstate/statemanagerimp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 304228010a..0cd23eb6ff 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -12,6 +12,8 @@ #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/journal.hpp" @@ -187,7 +189,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot else slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile); - std::ofstream stream (slot->mPath.string().c_str(), std::ios::binary); + boost::filesystem::ofstream stream (slot->mPath, std::ios::binary); ESM::ESMWriter writer; From db16bb89834954adc94a5bcab82d8f1a72d42502 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 15:52:19 +0400 Subject: [PATCH 341/545] fix OpenCS saving to Unicode path destination --- apps/opencs/model/doc/savingstages.cpp | 4 ++-- apps/opencs/model/doc/savingstate.cpp | 4 ++-- apps/opencs/model/doc/savingstate.hpp | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index eb93d90475..34d93c49a2 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -27,7 +27,7 @@ void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages) { mState.start (mDocument, mProjectFile); - mState.getStream().open ((mProjectFile ? mState.getPath() : mState.getTmpPath()).string().c_str()); + mState.getStream().open (mProjectFile ? mState.getPath() : mState.getTmpPath()); if (!mState.getStream().is_open()) throw std::runtime_error ("failed to open stream for saving"); @@ -260,4 +260,4 @@ void CSMDoc::FinalSavingStage::perform (int stage, Messages& messages) mDocument.getUndoStack().setClean(); } -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 8742148226..07c42a490f 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -47,7 +47,7 @@ const boost::filesystem::path& CSMDoc::SavingState::getTmpPath() const return mTmpPath; } -std::ofstream& CSMDoc::SavingState::getStream() +boost::filesystem::ofstream& CSMDoc::SavingState::getStream() { return mStream; } @@ -60,4 +60,4 @@ ESM::ESMWriter& CSMDoc::SavingState::getWriter() bool CSMDoc::SavingState::isProjectFile() const { return mProjectFile; -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 6b45655846..7b0c373866 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -20,7 +21,7 @@ namespace CSMDoc boost::filesystem::path mPath; boost::filesystem::path mTmpPath; ToUTF8::Utf8Encoder mEncoder; - std::ofstream mStream; + boost::filesystem::ofstream mStream; ESM::ESMWriter mWriter; boost::filesystem::path mProjectPath; bool mProjectFile; @@ -39,7 +40,7 @@ namespace CSMDoc const boost::filesystem::path& getTmpPath() const; - std::ofstream& getStream(); + boost::filesystem::ofstream& getStream(); ESM::ESMWriter& getWriter(); @@ -50,4 +51,4 @@ namespace CSMDoc } -#endif \ No newline at end of file +#endif From 6bd0bbb8df974c09c369f6e15a0b9a9726d0fcac Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 May 2014 14:09:16 +0200 Subject: [PATCH 342/545] Do not load (0,0) on new game --- apps/openmw/mwscript/cellextensions.cpp | 5 ++ .../mwscript/transformationextensions.cpp | 3 +- apps/openmw/mwstate/statemanagerimp.cpp | 2 - apps/openmw/mwworld/worldimp.cpp | 52 +++++++++++-------- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 903612258e..825d62efb5 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -104,6 +104,11 @@ namespace MWScript std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + runtime.push(0); + return; + } const ESM::Cell *cell = MWBase::Environment::get().getWorld()->getPlayerPtr().getCell()->getCell(); std::string current = cell->mName; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 7051937989..e4c1a26772 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -271,7 +271,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - if (!ptr.isInCell()) + if (ptr.getContainerStore()) return; if (ptr.getRefData().getHandle() == "player") @@ -308,6 +308,7 @@ namespace MWScript if(store) { MWBase::Environment::get().getWorld()->moveObject(ptr,store,x,y,z); + ptr = MWWorld::Ptr(ptr.getBase(), store); float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees(); float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees(); if(ptr.getTypeName() == typeid(ESM::NPC).name())//some morrowind oddity diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 304228010a..48c7508a66 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -136,8 +136,6 @@ void MWState::StateManager::newGame (bool bypass) else MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); - mState = State_Running; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1f645fd860..896877dda9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -6,7 +6,8 @@ #else #include #endif - +#include "../mwbase/scriptmanager.hpp" +#include "../mwscript/globalscripts.hpp" #include #include @@ -188,6 +189,18 @@ namespace MWWorld MWBase::Environment::get().getWindowManager()->updatePlayer(); + if (!bypass) + { + // FIXME: should be set to 1, but the sound manager won't pause newly started sounds + mPlayIntro = 2; + + // set new game mark + mGlobalVariables["chargenstate"].setInteger (1); + mGlobalVariables["pcrace"].setInteger (3); + + MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); + } + if (bypass && !mStartCell.empty()) { ESM::Position pos; @@ -204,27 +217,20 @@ namespace MWWorld } else { - /// \todo if !bypass, do not add player location to global map for the duration of one - /// frame - ESM::Position pos; - const int cellSize = 8192; - pos.pos[0] = cellSize/2; - pos.pos[1] = cellSize/2; - pos.pos[2] = 0; - pos.rot[0] = 0; - pos.rot[1] = 0; - pos.rot[2] = 0; - mWorldScene->changeToExteriorCell(pos); - } - - if (!bypass) - { - // FIXME: should be set to 1, but the sound manager won't pause newly started sounds - mPlayIntro = 2; - - // set new game mark - mGlobalVariables["chargenstate"].setInteger (1); - mGlobalVariables["pcrace"].setInteger (3); + for (int i=0; i<5; ++i) + MWBase::Environment::get().getScriptManager()->getGlobalScripts().run(); + if (!getPlayerPtr().isInCell()) + { + ESM::Position pos; + const int cellSize = 8192; + pos.pos[0] = cellSize/2; + pos.pos[1] = cellSize/2; + pos.pos[2] = 0; + pos.rot[0] = 0; + pos.rot[1] = 0; + pos.rot[2] = 0; + mWorldScene->changeToExteriorCell(pos); + } } // we don't want old weather to persist on a new game @@ -938,7 +944,7 @@ namespace MWWorld Ogre::Vector3 vec(x, y, z); - CellStore *currCell = ptr.getCell(); + CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; bool isPlayer = ptr == mPlayer->getPlayer(); bool haveToMove = isPlayer || mWorldScene->isCellActive(*currCell); From 20527e0bd4418b107634247e78b08d6ec9c608fa Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 16:56:41 +0400 Subject: [PATCH 343/545] use boost::filesystem instead of boost::iostreams --- apps/mwiniimporter/importer.cpp | 13 ++++++++----- apps/mwiniimporter/importer.hpp | 5 ++--- apps/mwiniimporter/main.cpp | 9 ++++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 3226278fe9..3a52592ae8 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -1,6 +1,5 @@ #include "importer.hpp" -#include -#include + #include #include #include @@ -9,6 +8,10 @@ #include #include +#include +#include + +namespace bfs = boost::filesystem; MwIniImporter::MwIniImporter() : mVerbose(false) @@ -661,7 +664,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam std::string section(""); MwIniImporter::multistrmap map; - boost::iostreams::streamfile(filename.c_str()); + bfs::ifstream file((bfs::path(filename))); ToUTF8::Utf8Encoder encoder(mEncoding); std::string line; @@ -720,7 +723,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam std::cout << "load cfg file: " << filename << std::endl; MwIniImporter::multistrmap map; - boost::iostreams::streamfile(filename.c_str()); + bfs::ifstream file((bfs::path(filename))); std::string line; while (std::getline(file, line)) { @@ -858,7 +861,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co } } -void MwIniImporter::writeToFile(boost::iostreams::stream &out, const multistrmap &cfg) { +void MwIniImporter::writeToFile(std::ostream &out, const multistrmap &cfg) { for(multistrmap::const_iterator it=cfg.begin(); it != cfg.end(); ++it) { for(std::vector::const_iterator entry=it->second.begin(); entry != it->second.end(); ++entry) { diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 784980e090..72b14ba75f 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -1,12 +1,11 @@ #ifndef MWINIIMPORTER_IMPORTER #define MWINIIMPORTER_IMPORTER 1 -#include -#include #include #include #include #include +#include #include @@ -24,7 +23,7 @@ class MwIniImporter { void mergeFallback(multistrmap &cfg, const multistrmap &ini) const; void importGameFiles(multistrmap &cfg, const multistrmap &ini) const; void importArchives(multistrmap &cfg, const multistrmap &ini) const; - static void writeToFile(boost::iostreams::stream &out, const multistrmap &cfg); + static void writeToFile(std::ostream &out, const multistrmap &cfg); private: static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value); diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 58ae1d593a..d9c1454fc2 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -1,12 +1,15 @@ #include "importer.hpp" -#include #include + #include -#include #include +#include +#include +#include namespace bpo = boost::program_options; +namespace bfs = boost::filesystem; #ifndef _WIN32 int main(int argc, char *argv[]) { @@ -126,7 +129,7 @@ int wmain(int argc, wchar_t *wargv[]) { } std::cout << "write to: " << outputFile << std::endl; - boost::iostreams::stream file(outputFile); + bfs::ofstream file((bfs::path(outputFile))); importer.writeToFile(file, cfg); return 0; From 444a07c01b89b7eda8ae4346d821f65231d79d4d Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 18:12:13 +0400 Subject: [PATCH 344/545] workaround OgreLog Unicode path handling --- components/ogreinit/ogreinit.cpp | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 01b8764c2b..5827645f53 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -1,11 +1,15 @@ #include "ogreinit.hpp" #include +#include +#include +#include #include #include #include #include +#include #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE #include @@ -13,8 +17,47 @@ #include +#include +#include + #include "ogreplugin.hpp" +namespace bfs = boost::filesystem; + +namespace +{ + class LogListener : public Ogre::LogListener + { + bfs::ofstream file; + char buffer[16]; + + + public: + + LogListener(const std::string &path) + : file((bfs::path(path))) + { + memset(buffer, sizeof(buffer), 0); + } + + void timestamp() + { + int local = time(0) % 86400; + int sec = local % 60; + int min = (local / 60) % 60; + int hrs = local / 3600; + sprintf(buffer, "%02d:%02d:%02d: ", hrs, min, sec); + } + + virtual void messageLogged(const std::string &msg, Ogre::LogMessageLevel lvl, bool mask, const std::string &logName, bool &skip) + { + timestamp(); + file << buffer << msg << std::endl; + skip = true; + } + }; +} + namespace OgreInit { @@ -43,6 +86,10 @@ namespace OgreInit new Ogre::LogManager; Ogre::Log *log = Ogre::LogManager::getSingleton().createLog(logPath); + #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + log->addListener(new LogListener(logPath)); + #endif + // Disable logging to cout/cerr log->setDebugOutputEnabled(false); From 86a89663066f20b65a40293eddf85fdb97c24717 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 19 May 2014 22:56:40 +0400 Subject: [PATCH 345/545] manual screenshot creation and uploading (scrawl) --- libs/openengine/ogre/renderer.cpp | 35 ++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index caf62546e5..ae0d477d29 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -15,6 +15,9 @@ #include +#include +#include + #include #include @@ -48,7 +51,37 @@ void OgreRenderer::update(float dt) void OgreRenderer::screenshot(const std::string &file) { - mWindow->writeContentsToFile(file); + namespace bfs = boost::filesystem; + bfs::ofstream out((bfs::path(file))); + + Ogre::Image image; + + Ogre::PixelFormat pf = mWindow->suggestPixelFormat(); + int w = mWindow->getWidth(); + int h = mWindow->getHeight(); + + image.loadDynamicImage( + OGRE_ALLOC_T(Ogre::uchar, w * h * Ogre::PixelUtil::getNumElemBytes(pf), Ogre::MEMCATEGORY_GENERAL), + w, h, 1, pf, true + ); + mWindow->copyContentsToMemory(image.getPixelBox()); + + Ogre::DataStreamPtr stream = image.encode("png"); + Ogre::MemoryDataStream *mem = dynamic_cast(stream.get()); + if (mem != 0) { // likely + const char *ptr = reinterpret_cast(mem->getCurrentPtr()); + out.write(ptr, mem->size()); + } + else { + char buf[4096]; + size_t size = stream->size(); + while (size > 0) { + size_t chunk = (size > sizeof(buf)) ? sizeof(buf) : size; + stream->read(buf, chunk); + out.write(buf, chunk); + size -= chunk; + } + } } float OgreRenderer::getFPS() From 638df221a6f2ef7c1f1a1b727b43ab7dbc6d4655 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Mon, 19 May 2014 23:29:35 +0400 Subject: [PATCH 346/545] memory leak fix --- apps/openmw/mwmechanics/aisequence.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 6a5cf572a9..980a23a3ed 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -146,6 +146,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) // target disappeared (e.g. summoned creatures) if (target.isEmpty()) { + delete *it; mPackages.erase(it++); } else From 130349e0cd044b3972920380f81655cb6d6ed93f Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 08:14:29 +0400 Subject: [PATCH 347/545] open files in binary mode when necessary --- apps/opencs/model/doc/savingstages.cpp | 4 +++- libs/openengine/ogre/renderer.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 34d93c49a2..066c76734e 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -27,7 +27,9 @@ void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages) { mState.start (mDocument, mProjectFile); - mState.getStream().open (mProjectFile ? mState.getPath() : mState.getTmpPath()); + mState.getStream().open ( + mProjectFile ? mState.getPath() : mState.getTmpPath(), + std::ios::binary); if (!mState.getStream().is_open()) throw std::runtime_error ("failed to open stream for saving"); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index ae0d477d29..64d65ea0da 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -52,7 +52,7 @@ void OgreRenderer::update(float dt) void OgreRenderer::screenshot(const std::string &file) { namespace bfs = boost::filesystem; - bfs::ofstream out((bfs::path(file))); + bfs::ofstream out(bfs::path(file), std::ios::binary); Ogre::Image image; From a46662043ad1f0eab2c0fb9b8c877a067b96815e Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 09:17:32 +0400 Subject: [PATCH 348/545] tinyxml convert path to UTF-16 on Windows --- extern/oics/tinyxml.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp index 29a4768aa0..2cd42eb307 100644 --- a/extern/oics/tinyxml.cpp +++ b/extern/oics/tinyxml.cpp @@ -31,18 +31,33 @@ distribution. #include "tinyxml.h" +#ifdef _WIN32 +#include +#endif + bool TiXmlBase::condenseWhiteSpace = true; // Microsoft compiler security FILE* TiXmlFOpen( const char* filename, const char* mode ) { - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + #if defined(_WIN32) FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; + size_t len = strlen(filename); + wchar_t *wname = new wchar_t[len] + wchar_t wmode[32] = { 0 }; + + MultiByteToWideChar(CP_UTF8, 0, filename, len, wname, len); + MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, sizeof(wmode) / sizeof(*wmode)); + + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + errno_t err = _wfopen_s( &fp, wname, wmode ); + #else + fp = _wfopen(wname, wmode) + #endif + delete[] wname; + + return fp; #else return fopen( filename, mode ); #endif From 46c32f6c4753fe7c04ab3e598784d52625de314e Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 10:37:04 +0400 Subject: [PATCH 349/545] OpenEngine MyGUI logging facility --- CMakeLists.txt | 1 + libs/openengine/gui/loglistener.cpp | 39 +++++++++++++++++++++++++++++ libs/openengine/gui/loglistener.hpp | 35 ++++++++++++++++++++++++++ libs/openengine/gui/manager.cpp | 39 +++++++++++++++++++++++++---- libs/openengine/gui/manager.hpp | 2 ++ 5 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 libs/openengine/gui/loglistener.cpp create mode 100644 libs/openengine/gui/loglistener.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8179021a4c..9abd6ac3f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ set(OENGINE_OGRE ) set(OENGINE_GUI + ${LIBDIR}/openengine/gui/loglistener.cpp ${LIBDIR}/openengine/gui/manager.cpp ${LIBDIR}/openengine/gui/layout.hpp ) diff --git a/libs/openengine/gui/loglistener.cpp b/libs/openengine/gui/loglistener.cpp new file mode 100644 index 0000000000..da36b90a2f --- /dev/null +++ b/libs/openengine/gui/loglistener.cpp @@ -0,0 +1,39 @@ +#include "loglistener.hpp" + +#include +#include + +#include + +namespace MyGUI +{ + void CustomLogListener::open() + { + mStream.open(boost::filesystem::path(mFileName), std::ios_base::out); + } + + void CustomLogListener::close() + { + if (mStream.is_open()) + mStream.close(); + } + + void CustomLogListener::flush() + { + if (mStream.is_open()) + mStream.flush(); + } + + void CustomLogListener::log(const std::string& _section, LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line) + { + if (mStream.is_open()) + { + const char* separator = " | "; + mStream << std::setw(2) << std::setfill('0') << _time->tm_hour << ":" + << std::setw(2) << std::setfill('0') << _time->tm_min << ":" + << std::setw(2) << std::setfill('0') << _time->tm_sec << separator + << _section << separator << _level.print() << separator + << _message << separator << _file << separator << _line << std::endl; + } + } +} diff --git a/libs/openengine/gui/loglistener.hpp b/libs/openengine/gui/loglistener.hpp new file mode 100644 index 0000000000..20f23cf0ce --- /dev/null +++ b/libs/openengine/gui/loglistener.hpp @@ -0,0 +1,35 @@ +#ifndef OPENENGINE_MYGUI_LOGLISTENER_H +#define OPENENGINE_MYGUI_LOGLISTENER_H + +#include +#include + +#include + +namespace MyGUI +{ + class CustomLogListener : public ILogListener + { + public: + CustomLogListener(const std::string &name) + : mFileName(name) + {} + + ~CustomLogListener() {} + + virtual void open(); + virtual void close(); + virtual void flush(); + + virtual void log(const std::string& _section, LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line); + + const std::string& getFileName() const { return mFileName; } + + private: + boost::filesystem::ofstream mStream; + std::string mFileName; + }; + +} + +#endif diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 91937d24bc..fa7419b32d 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -1,9 +1,14 @@ #include "manager.hpp" +#include "loglistener.hpp" #include #include #include +#include +#include +#include + #include #include @@ -554,8 +559,32 @@ public: } }; -} +class LogFacility +{ + ConsoleLogListener mConsole; + CustomLogListener mFile; + LevelLogFilter mFilter; + LogSource mSource; +public: + + LogFacility(const std::string &output, bool console) + : mFile(output) + { + mConsole.setEnabled(console); + mFilter.setLoggingLevel(LogLevel::Info); + + mSource.addLogListener(&mFile); + mSource.addLogListener(&mConsole); + mSource.setLogFilter(&mFilter); + + mSource.open(); + } + + LogSource *getSource() { return &mSource; } +}; + +} void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir) { @@ -586,10 +615,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool mRenderManager = new MyGUI::OgreRenderManager(); mDataManager = new MyGUI::FixedOgreDataManager(); - LogManager::getInstance().setSTDOutputEnabled(logging); - - if (!theLogFile.empty()) - LogManager::getInstance().createDefaultSource(theLogFile); + mLogFacility = new MyGUI::LogFacility(theLogFile, logging); + LogManager::getInstance().addLogSource(mLogFacility->getSource()); if (mShaderRenderManager) mShaderRenderManager->initialise(wnd, mgr); @@ -648,5 +675,7 @@ void MyGUIManager::shutdown() delete mLogManager; mLogManager = NULL; } + delete mLogFacility; + mGui = NULL; } diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index cca70dfcfe..8923a5cc8e 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -10,6 +10,7 @@ namespace MyGUI class OgreDataManager; class OgreRenderManager; class ShaderBasedRenderManager; + class LogFacility; } namespace Ogre @@ -25,6 +26,7 @@ namespace GUI { MyGUI::Gui *mGui; MyGUI::LogManager* mLogManager; + MyGUI::LogFacility* mLogFacility; MyGUI::OgreDataManager* mDataManager; MyGUI::OgreRenderManager* mRenderManager; MyGUI::ShaderBasedRenderManager* mShaderRenderManager; From 9dbe3f21d987ba307498351fb8437058d43776dd Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 10:42:21 +0400 Subject: [PATCH 350/545] keep non-const signature for argv after conversion --- apps/mwiniimporter/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index d9c1454fc2..a4e5cad4df 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -31,7 +31,7 @@ public: } ~utf8argv() { delete[] argv; } - const char * const *get() const { return argv; } + char **get() const { return const_cast(argv); } private: From d8440e1fdc84baee8e781333da6a26b53f45119b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 20 May 2014 09:02:22 +0200 Subject: [PATCH 351/545] implemented reference record merging --- apps/opencs/model/world/cell.cpp | 5 --- apps/opencs/model/world/cell.hpp | 3 -- apps/opencs/model/world/data.cpp | 7 ++- apps/opencs/model/world/data.hpp | 1 + apps/opencs/model/world/ref.cpp | 10 ----- apps/opencs/model/world/ref.hpp | 8 ---- apps/opencs/model/world/refcollection.cpp | 52 ++++++++++++++++++----- apps/opencs/model/world/refcollection.hpp | 5 ++- components/esm/cellref.cpp | 11 +++++ components/esm/cellref.hpp | 1 + 10 files changed, 65 insertions(+), 38 deletions(-) diff --git a/apps/opencs/model/world/cell.cpp b/apps/opencs/model/world/cell.cpp index cd58fca1e4..40520a9ba7 100644 --- a/apps/opencs/model/world/cell.cpp +++ b/apps/opencs/model/world/cell.cpp @@ -18,8 +18,3 @@ void CSMWorld::Cell::load (ESM::ESMReader &esm) mId = stream.str(); } } - -void CSMWorld::Cell::addRef (const std::string& id) -{ - mRefs.push_back (std::make_pair (id, false)); -} \ No newline at end of file diff --git a/apps/opencs/model/world/cell.hpp b/apps/opencs/model/world/cell.hpp index e6f3c8c355..a47dbf45df 100644 --- a/apps/opencs/model/world/cell.hpp +++ b/apps/opencs/model/world/cell.hpp @@ -15,12 +15,9 @@ namespace CSMWorld struct Cell : public ESM::Cell { std::string mId; - std::vector > mRefs; // ID, modified - std::vector mDeletedRefs; void load (ESM::ESMReader &esm); - void addRef (const std::string& id); }; } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index ff33b46655..8b9d9f6dfb 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -489,6 +489,7 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base delete mReader; mReader = 0; mDialogue = 0; + mRefLoadCache.clear(); mReader = new ESM::ESMReader; mReader->setEncoder (&mEncoder); @@ -513,6 +514,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) delete mReader; mReader = 0; mDialogue = 0; + mRefLoadCache.clear(); return true; } @@ -534,9 +536,12 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break; case ESM::REC_CELL: + { mCells.load (*mReader, mBase); - mRefs.load (*mReader, mCells.getSize()-1, mBase); + std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (mCells.getSize()-1)); + mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId]); break; + } case ESM::REC_ACTI: mReferenceables.load (*mReader, mBase, UniversalId::Type_Activator); break; case ESM::REC_ALCH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Potion); break; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index ab247b6a34..2b521c5487 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -77,6 +77,7 @@ namespace CSMWorld const ESM::Dialogue *mDialogue; // last loaded dialogue bool mBase; bool mProject; + std::map > mRefLoadCache; // not implemented Data (const Data&); diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index cf9e496ee6..44ffa92b94 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -1,12 +1,2 @@ #include "ref.hpp" - -#include "cell.hpp" - -void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string& id) -{ - mId = id; - mCell = cell.mId; - - cell.addRef (mId); -} \ No newline at end of file diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index fcf016ee24..b60cbd7e41 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -3,11 +3,6 @@ #include -namespace ESM -{ - class ESMReader; -} - namespace CSMWorld { class Cell; @@ -17,9 +12,6 @@ namespace CSMWorld { std::string mId; std::string mCell; - - void load (ESM::ESMReader &esm, Cell& cell, const std::string& id); - ///< Load cell ref and register it with \a cell. }; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 4fdd979097..db6e294fa5 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -3,12 +3,15 @@ #include +#include + #include "ref.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, + std::map& cache) { Record cell = mCells.getRecord (cellIndex); @@ -17,19 +20,48 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool CellRef ref; bool deleted = false; - while (cell2.getNextRef (reader, ref, deleted)) + + while (ESM::Cell::getNextRef (reader, ref, deleted)) { - /// \todo handle deleted and moved references - ref.load (reader, cell2, getNewId()); + ref.mCell = cell2.mId; - Record record2; - record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; - (base ? record2.mBase : record2.mModified) = ref; + /// \todo handle moved references - appendRecord (record2); + if (deleted) + { + /// \todo handle deleted references + continue; + } + + std::map::iterator iter = cache.find (ref.mRefNum); + + if (iter==cache.end()) + { + // new reference + ref.mId = getNewId(); + + Record record; + record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; + (base ? record.mBase : record.mModified) = ref; + + appendRecord (record); + + cache.insert (std::make_pair (ref.mRefNum, ref.mId)); + } + else + { + // old reference -> merge + ref.mId = iter->second; + + int index = getIndex (ref.mId); + + Record record = getRecord (index); + record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_Modified; + (base ? record.mBase : record.mModified) = ref; + + setRecord (index, record); + } } - - mCells.setRecord (cellIndex, cell); } std::string CSMWorld::RefCollection::getNewId() diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 173efba05b..45aa5758be 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WOLRD_REFCOLLECTION_H #define CSM_WOLRD_REFCOLLECTION_H +#include + #include "collection.hpp" #include "ref.hpp" #include "record.hpp" @@ -22,7 +24,8 @@ namespace CSMWorld : mCells (cells), mNextId (0) {} - void load (ESM::ESMReader& reader, int cellIndex, bool base); + void load (ESM::ESMReader& reader, int cellIndex, bool base, + std::map& cache); ///< Load a sequence of references. std::string getNewId(); diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index f04e819c88..00d7dfc19e 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -172,3 +172,14 @@ bool ESM::operator== (const CellRef::RefNum& left, const CellRef::RefNum& right) { return left.mIndex==right.mIndex && left.mContentFile==right.mContentFile; } + +bool ESM::operator< (const CellRef::RefNum& left, const CellRef::RefNum& right) +{ + if (left.mIndexright.mIndex) + return false; + + return left.mContentFile Date: Tue, 20 May 2014 09:28:18 +0200 Subject: [PATCH 352/545] implemented reference record deleting --- apps/opencs/model/world/data.cpp | 2 +- apps/opencs/model/world/refcollection.cpp | 33 ++++++++++++++++++++--- apps/opencs/model/world/refcollection.hpp | 5 +++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 8b9d9f6dfb..442e73e511 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -539,7 +539,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) { mCells.load (*mReader, mBase); std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (mCells.getSize()-1)); - mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId]); + mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId], messages); break; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index db6e294fa5..3a60c49341 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -11,7 +11,7 @@ #include "record.hpp" void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map& cache) + std::map& cache, CSMDoc::Stage::Messages& messages) { Record cell = mCells.getRecord (cellIndex); @@ -27,14 +27,39 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool /// \todo handle moved references + std::map::iterator iter = cache.find (ref.mRefNum); + if (deleted) { - /// \todo handle deleted references + if (iter==cache.end()) + { + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell, + mCells.getId (cellIndex)); + + messages.push_back (std::make_pair (id, + "Attempt to delete a non-existing reference")); + + continue; + } + + int index = getIndex (iter->second); + + Record record = getRecord (index); + + if (record.mState==RecordBase::State_BaseOnly) + { + removeRows (index, 1); + cache.erase (iter); + } + else + { + record.mState = RecordBase::State_Deleted; + setRecord (index, record); + } + continue; } - std::map::iterator iter = cache.find (ref.mRefNum); - if (iter==cache.end()) { // new reference diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 45aa5758be..d80ea24694 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -3,6 +3,8 @@ #include +#include "../doc/stage.hpp" + #include "collection.hpp" #include "ref.hpp" #include "record.hpp" @@ -25,7 +27,8 @@ namespace CSMWorld {} void load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map& cache); + std::map& cache, + CSMDoc::Stage::Messages& messages); ///< Load a sequence of references. std::string getNewId(); From 220ab86ecae466d93e3cc4f68b98f6ab8bf443e0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 20 May 2014 09:45:39 +0200 Subject: [PATCH 353/545] Simplify new game movie player --- apps/openmw/mwgui/hud.cpp | 3 +++ apps/openmw/mwgui/windowmanagerimp.cpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 16 ++++------------ apps/openmw/mwworld/worldimp.hpp | 2 -- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index dc02f9976e..079793ee19 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -628,6 +628,9 @@ namespace MWGui effectsDx = (viewSize.width - mMinimapBoxBaseRight) - (viewSize.width - mEffectBoxBaseRight); mMapVisible = mMinimapBox->getVisible (); + if (!mMapVisible) + mCellNameBox->setVisible(false); + mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop()); } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index d701e56abb..81b28aa66f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -298,6 +298,7 @@ namespace MWGui delete mCharGen; mCharGen = new CharacterCreation(); mGuiModes.clear(); + MWBase::Environment::get().getInputManager()->changeInputMode(false); mHud->unsetSelectedWeapon(); mHud->unsetSelectedSpell(); unsetForceHide(GW_ALL); @@ -1412,6 +1413,7 @@ namespace MWGui mConsole->resetReference(); mGuiModes.clear(); + MWBase::Environment::get().getInputManager()->changeInputMode(false); updateVisible(); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 896877dda9..f8523726e6 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -130,7 +130,7 @@ namespace MWWorld : mPlayer (0), mLocalScripts (mStore), mSky (true), mCells (mStore, mEsm), mActivationDistanceOverride (activationDistanceOverride), - mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mLevitationEnabled(true), + mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true), mFacedDistance(FLT_MAX), mGodMode(false), mContentFiles (contentFiles), mGoToJail(false), mStartCell (startCell) @@ -191,9 +191,6 @@ namespace MWWorld if (!bypass) { - // FIXME: should be set to 1, but the sound manager won't pause newly started sounds - mPlayIntro = 2; - // set new game mark mGlobalVariables["chargenstate"].setInteger (1); mGlobalVariables["pcrace"].setInteger (3); @@ -233,6 +230,9 @@ namespace MWWorld } } + if (!bypass) + MWBase::Environment::get().getWindowManager()->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); + // we don't want old weather to persist on a new game delete mWeatherManager; mWeatherManager = 0; @@ -271,7 +271,6 @@ namespace MWWorld mGodMode = false; mSky = true; mTeleportEnabled = true; - mPlayIntro = 0; mFacedDistance = FLT_MAX; mGlobalVariables.fill (mStore); @@ -1369,13 +1368,6 @@ namespace MWWorld void World::update (float duration, bool paused) { - if (mPlayIntro) - { - --mPlayIntro; - if (mPlayIntro == 0) - MWBase::Environment::get().getWindowManager()->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); - } - if (mGoToJail && !paused) goToJail(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 285d5fef6d..ca0e63c2d1 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -138,8 +138,6 @@ namespace MWWorld void loadContentFiles(const Files::Collections& fileCollections, const std::vector& content, ContentLoader& contentLoader); - int mPlayIntro; - bool mTeleportEnabled; bool mLevitationEnabled; bool mGoToJail; From 1b7ed98325e6e3b4f43d0b08a6956963d8af3820 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 12:41:45 +0400 Subject: [PATCH 354/545] fix typos, reset memory before using --- extern/oics/tinyxml.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp index 2cd42eb307..5be99f166a 100644 --- a/extern/oics/tinyxml.cpp +++ b/extern/oics/tinyxml.cpp @@ -44,7 +44,8 @@ FILE* TiXmlFOpen( const char* filename, const char* mode ) #if defined(_WIN32) FILE* fp = 0; size_t len = strlen(filename); - wchar_t *wname = new wchar_t[len] + wchar_t *wname = new wchar_t[len + 1]; + memset(wname, 0, sizeof(*wname) * (len + 1)); wchar_t wmode[32] = { 0 }; MultiByteToWideChar(CP_UTF8, 0, filename, len, wname, len); @@ -53,7 +54,7 @@ FILE* TiXmlFOpen( const char* filename, const char* mode ) #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) errno_t err = _wfopen_s( &fp, wname, wmode ); #else - fp = _wfopen(wname, wmode) + fp = _wfopen(wname, wmode); #endif delete[] wname; From b728a919a2089272a853bf8f31d84e71f3c05915 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 12:59:58 +0400 Subject: [PATCH 355/545] write dependency on boost::locale to CMake files --- CMakeLists.txt | 2 +- apps/opencs/CMakeLists.txt | 2 +- apps/openmw/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9abd6ac3f8..e4d8d1b9fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ if (HAVE_UNORDERED_MAP) endif () -set(BOOST_COMPONENTS system filesystem program_options) +set(BOOST_COMPONENTS system filesystem program_options locale) IF(BOOST_STATIC) set(Boost_USE_STATIC_LIBS ON) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 35551f97b8..6141790a8c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -144,7 +144,7 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -set(BOOST_COMPONENTS system filesystem program_options thread wave) +set(BOOST_COMPONENTS system filesystem program_options thread wave locale) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e791ab8910..cf72cc7325 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -82,7 +82,7 @@ add_openmw_dir (mwbase ) # Main executable -set(BOOST_COMPONENTS system filesystem program_options thread wave) +set(BOOST_COMPONENTS system filesystem program_options thread wave locale) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) IF(OGRE_STATIC) From 7ab98f0c6fdfbc4770a3f593fb93953eb0e0a76b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 20 May 2014 16:57:38 +0200 Subject: [PATCH 356/545] Clear choices when dialogue starts This is usually not needed, because it is not possible to exit dialogue while in a choice. However you can still exit dialogue by loading a different savegame. --- apps/openmw/mwgui/dialogue.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 8f1b9f6f39..dcd26d4698 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -363,6 +363,8 @@ namespace MWGui mTopicsList->setEnabled(true); setTitle(npcName); + clearChoices(); + mTopicsList->clear(); for (std::vector::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) From abd6b6ab33700af01fc2c4e6394da29f02d4e0e8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 20 May 2014 17:11:26 +0200 Subject: [PATCH 357/545] Fix not returning to main menu on failed loads when using quickload --- apps/openmw/mwgui/savegamedialog.cpp | 6 ------ apps/openmw/mwstate/statemanagerimp.cpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index c0daa2c0ea..16e939eb24 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -222,12 +222,6 @@ namespace MWGui MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot); } } - - if (MWBase::Environment::get().getStateManager()->getState()== - MWBase::StateManager::State_NoGame) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); - } } void SaveGameDialog::onOkButtonClicked(MyGUI::Widget *sender) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 48c7508a66..43972e9f91 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -371,6 +371,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl { std::cerr << "failed to load saved game: " << e.what() << std::endl; cleanup (true); + + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f8523726e6..d5e572b13c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -233,6 +233,10 @@ namespace MWWorld if (!bypass) MWBase::Environment::get().getWindowManager()->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); + // enable collision + if (!mPhysics->toggleCollisionMode()) + mPhysics->toggleCollisionMode(); + // we don't want old weather to persist on a new game delete mWeatherManager; mWeatherManager = 0; @@ -248,10 +252,6 @@ namespace MWWorld mLocalScripts.clear(); mPlayer->clear(); - // enable collision - if (!mPhysics->toggleCollisionMode()) - mPhysics->toggleCollisionMode(); - mWorldScene->changeToVoid(); mStore.clearDynamic(); From 9fe505c8fa9483dcdc711fca841ca39d132fc2c4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 20 May 2014 18:35:17 +0200 Subject: [PATCH 358/545] Only run --script-run commands when bypassing the menu Running them while no game is started yet is dangerous, and also leaves bits and pieces of state (e.g. in LocalScripts for scripted items added to inventory) that will not get cleaned up properly when a game is loaded (since when no game was previously running, no cleanup is performed). As a result, dangling MWWorld::Ptrs were left in LocalScripts. --- apps/openmw/engine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 66c09b6ff7..8c817b380e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -462,10 +462,12 @@ void OMW::Engine::go() catch (...) {} } else + { MWBase::Environment::get().getStateManager()->newGame (true); - if (!mStartupScript.empty()) - MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript); + if (!mStartupScript.empty()) + MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript); + } // Start the main rendering loop while (!mEnvironment.get().getStateManager()->hasQuitRequest()) From 4346e3b4d09e84aa7f15b2df06b68ed8a08d1541 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 20 May 2014 21:42:51 +0400 Subject: [PATCH 359/545] try to load plugins from relative paths --- components/ogreinit/ogreinit.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 5827645f53..44d5fe3d53 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -188,11 +188,6 @@ namespace OgreInit pluginDir = OGRE_PLUGIN_DIR_REL; #endif } - - boost::filesystem::path absPluginPath = boost::filesystem::absolute(boost::filesystem::path(pluginDir)); - - pluginDir = absPluginPath.string(); - Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mRoot); Files::loadOgrePlugin(pluginDir, "RenderSystem_GLES2", *mRoot); Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mRoot); From b39b572c5aea39a4e0dff139b92a93e66b2170d4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 May 2014 09:25:45 +0200 Subject: [PATCH 360/545] Moved mStartupScript to World, so that it is executed for a New game --- apps/openmw/engine.cpp | 5 +---- apps/openmw/mwworld/worldimp.cpp | 6 ++++-- apps/openmw/mwworld/worldimp.hpp | 4 +++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8c817b380e..26ff7e96ed 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -380,7 +380,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, - mActivationDistanceOverride, mCellName)); + mActivationDistanceOverride, mCellName, mStartupScript)); MWBase::Environment::get().getWorld()->setupPlayer(); input->setPlayer(&mEnvironment.getWorld()->getPlayer()); @@ -464,9 +464,6 @@ void OMW::Engine::go() else { MWBase::Environment::get().getStateManager()->newGame (true); - - if (!mStartupScript.empty()) - MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript); } // Start the main rendering loop diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d5e572b13c..9b5f9d9d3d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -126,14 +126,14 @@ namespace MWWorld const std::vector& contentFiles, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, - int activationDistanceOverride, const std::string& startCell) + int activationDistanceOverride, const std::string& startCell, const std::string& startupScript) : mPlayer (0), mLocalScripts (mStore), mSky (true), mCells (mStore, mEsm), mActivationDistanceOverride (activationDistanceOverride), mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true), mFacedDistance(FLT_MAX), mGodMode(false), mContentFiles (contentFiles), mGoToJail(false), - mStartCell (startCell) + mStartCell (startCell), mStartupScript(startupScript) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); @@ -241,6 +241,8 @@ namespace MWWorld delete mWeatherManager; mWeatherManager = 0; mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback); + + MWBase::Environment::get().getWindowManager()->executeInConsole(mStartupScript); } void World::clear() diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index ca0e63c2d1..0a396ef5c6 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -94,6 +94,8 @@ namespace MWWorld std::string mFacedHandle; float mFacedDistance; + std::string mStartupScript; + std::map mDoorStates; ///< only holds doors that are currently moving. 1 = opening, 2 = closing @@ -151,7 +153,7 @@ namespace MWWorld const std::vector& contentFiles, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, - int activationDistanceOverride, const std::string& startCell); + int activationDistanceOverride, const std::string& startCell, const std::string& startupScript); virtual ~World(); From 8b94e310623a2b54fd2ae8488d0dac5f0ff55f25 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 21 May 2014 15:39:58 +0400 Subject: [PATCH 361/545] try to set relative path to resources --- apps/openmw/engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 66c09b6ff7..27739fd26c 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -236,7 +236,7 @@ void OMW::Engine::addArchive (const std::string& archive) { // Set resource dir void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir) { - mResDir = boost::filesystem::system_complete(parResDir); + mResDir = parResDir; } // Set start cell name (only interiors for now) From 3a7e2f8bb579e79c72d12d4e84711f4bf8a3f04f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 May 2014 14:18:14 +0200 Subject: [PATCH 362/545] Allow invoking Journal instruction with non-existing index This is used by the MG_EscortScholar1 quest. --- apps/openmw/mwscript/dialogueextensions.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index a882ae05e7..6958084f4a 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -34,7 +34,15 @@ namespace MWScript Interpreter::Type_Integer index = runtime[0].mInteger; runtime.pop(); - MWBase::Environment::get().getJournal()->addEntry (quest, index); + // Invoking Journal with a non-existing index is allowed, and triggers no errors. Seriously? :( + try + { + MWBase::Environment::get().getJournal()->addEntry (quest, index); + } + catch (...) + { + MWBase::Environment::get().getJournal()->setJournalIndex(quest, index); + } } }; From f812746010a835b0b8dba4a4d333fafa9c363170 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 May 2014 16:36:55 +0200 Subject: [PATCH 363/545] Auto-select first save in load dialog --- apps/openmw/mwgui/savegamedialog.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 16e939eb24..6048e49b41 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -256,7 +256,16 @@ namespace MWGui { mSaveList->addItem(it->mProfile.mDescription); } - onSlotSelected(mSaveList, MyGUI::ITEM_NONE); + // When loading, Auto-select the first save, if there is one + if (mSaveList->getItemCount() && !mSaving) + { + mSaveList->setIndexSelected(0); + onSlotSelected(mSaveList, 0); + // Give key focus to save list so we can confirm the selection with Enter + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); + } + else + onSlotSelected(mSaveList, MyGUI::ITEM_NONE); } void SaveGameDialog::onSlotSelected(MyGUI::ListBox *sender, size_t pos) From cf07d2ab93fcb05e6e7c5e92552c6da083026e29 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 May 2014 16:38:50 +0200 Subject: [PATCH 364/545] Fix swapped position of Save and Load menu buttons --- apps/openmw/mwgui/mainmenu.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 8b44af2ef3..bafd04311b 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -165,15 +165,15 @@ namespace MWGui buttons.push_back("newgame"); - 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 && MWBase::Environment::get().getWindowManager()->isSavingAllowed()) buttons.push_back("savegame"); + if (MWBase::Environment::get().getStateManager()->characterBegin()!= + MWBase::Environment::get().getStateManager()->characterEnd()) + buttons.push_back("loadgame"); + buttons.push_back("options"); if (state==MWBase::StateManager::State_NoGame) From 3721174ae433d530bb872fc4b2c70df37c1ac239 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 21 May 2014 23:50:58 +0400 Subject: [PATCH 365/545] proof-of-concept boost::wave iteration policy --- extern/shiny/Main/Preprocessor.cpp | 46 +++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/extern/shiny/Main/Preprocessor.cpp b/extern/shiny/Main/Preprocessor.cpp index 1a97668bcc..bc2957da1b 100644 --- a/extern/shiny/Main/Preprocessor.cpp +++ b/extern/shiny/Main/Preprocessor.cpp @@ -4,6 +4,50 @@ #include #include +#include + +namespace boost { +namespace wave { +namespace iteration_context_policies { + + struct load_utf8_path_to_string + { + template + class inner + { + public: + template + static void init_iterators(IterContextT &iter_ctx, + PositionT const &act_pos, language_support language) + { + typedef typename IterContextT::iterator_type iterator_type; + namespace bfs = boost::filesystem; + + // read in the file + bfs::ifstream instream(bfs::path(iter_ctx.filename.c_str())); + if (!instream.is_open()) { + BOOST_WAVE_THROW_CTX(iter_ctx.ctx, preprocess_exception, + bad_include_file, iter_ctx.filename.c_str(), act_pos); + return; + } + instream.unsetf(std::ios::skipws); + + iter_ctx.instring.assign( + std::istreambuf_iterator(instream.rdbuf()), + std::istreambuf_iterator()); + + iter_ctx.first = iterator_type( + iter_ctx.instring.begin(), iter_ctx.instring.end(), + PositionT(iter_ctx.filename), language); + iter_ctx.last = iterator_type(); + } + + private: + std::string instring; + }; + }; +} } } + namespace sh { std::string Preprocessor::preprocess (std::string source, const std::string& includePath, std::vector definitions, const std::string& name) @@ -29,7 +73,7 @@ namespace sh // match the iterator type used during construction of the context // instance (see below). It is the type of the underlying input stream. typedef boost::wave::context context_type; From 28b59f40084368d85b4659908069e01f08583876 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 22 May 2014 01:08:03 +0400 Subject: [PATCH 366/545] process paths as UTF-8 in launcher --- apps/launcher/settings/gamesettings.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 0a09c5cc04..4ebdb715a7 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -45,7 +45,8 @@ void Launcher::GameSettings::validatePaths() Files::PathContainer dataDirs; foreach (const QString &path, paths) { - dataDirs.push_back(Files::PathContainer::value_type(path.toStdString())); + QByteArray bytes = path.toUtf8(); + dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length()))); } // Parse the data dirs to convert the tokenized paths From cb598f0455b15962fe9f818290acb7b8b31e3d22 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 22 May 2014 01:13:27 +0400 Subject: [PATCH 367/545] the same for data-local entry --- apps/launcher/settings/gamesettings.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 4ebdb715a7..2f3dd9a458 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -69,7 +69,8 @@ void Launcher::GameSettings::validatePaths() return; dataDirs.clear(); - dataDirs.push_back(Files::PathContainer::value_type(local.toStdString())); + QByteArray bytes = local.toUtf8(); + dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length()))); mCfgMgr.processPaths(dataDirs); From 18bba6bcece30f3b0aaa8224b810fbc882237dbf Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 11:03:45 +0200 Subject: [PATCH 368/545] Fix layout glitch when autosaving --- apps/openmw/mwgui/waitdialog.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index ed1b9e0a90..d5b52ebae8 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -118,11 +118,12 @@ namespace MWGui void WaitDialog::startWaiting(int hoursToWait) { + if(Settings::Manager::getBool("autosave","Saves") && mSleeping) //autosaves when enabled and sleeping + MWBase::Environment::get().getStateManager()->quickSave("Autosave"); + MWBase::World* world = MWBase::Environment::get().getWorld(); world->getFader ()->fadeOut(0.2); setVisible(false); - if(Settings::Manager::getBool("autosave","Saves") && mSleeping) //autosaves when enabled and sleeping (Not resting, apparently) - MWBase::Environment::get().getStateManager()->quickSave("Autosave"); mProgressBar.setVisible (true); mWaiting = true; From c6c254d279259a105fe4acee9f86a794af700750 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 11:08:36 +0200 Subject: [PATCH 369/545] Do not trigger levelup if rest was interrupted --- apps/openmw/mwgui/waitdialog.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index d5b52ebae8..7eaba93613 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -219,8 +219,20 @@ namespace MWGui } if (mCurHour > mHours) + { stopWaiting(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + const MWMechanics::NpcStats &pcstats = MWWorld::Class::get(player).getNpcStats(player); + + // trigger levelup if possible + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + if (mSleeping && pcstats.getLevelProgress () >= gmst.find("iLevelUpTotal")->getInt()) + { + MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup); + } + } } void WaitDialog::stopWaiting () @@ -230,17 +242,6 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Rest); MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed); mWaiting = false; - - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &pcstats = MWWorld::Class::get(player).getNpcStats(player); - - // trigger levelup if possible - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - if (mSleeping && pcstats.getLevelProgress () >= gmst.find("iLevelUpTotal")->getInt()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup); - } } From 3380e1e1c563850d9b63a23f4b2c15c098232191 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 12:14:33 +0200 Subject: [PATCH 370/545] Fix ShouldAttack filter This makes NPCs exit dialogue properly when they should attack as a result of taunting actions. --- apps/openmw/mwdialogue/filter.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 8b9ee9184f..5bdf80593b 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -539,7 +539,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_ShouldAttack: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).isHostile(); + return mActor.getClass().getCreatureStats(mActor).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() >= 80; case SelectWrapper::Function_CreatureTargetted: diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index bf9a11d6e5..f5f2443303 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -666,8 +666,6 @@ namespace MWMechanics int fight = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Fight).getBase(); npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, std::max(0, std::min(100, flee + int(std::max(iPerMinChange, s))))); - // TODO: initiate combat and quit dialogue if fight rating is too high - // or should setAiSetting handle this? npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, std::max(0, std::min(100, fight + int(std::min(-iPerMinChange, -s))))); } From 8f9091550e6097ebd456911889472446860c0033 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 22 May 2014 15:42:47 +0400 Subject: [PATCH 371/545] require boost::locale only on Windows --- CMakeLists.txt | 5 ++++- apps/mwiniimporter/main.cpp | 4 +++- apps/opencs/CMakeLists.txt | 6 +++++- apps/openmw/CMakeLists.txt | 6 +++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4d8d1b9fa..b323d4759f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,10 @@ if (HAVE_UNORDERED_MAP) endif () -set(BOOST_COMPONENTS system filesystem program_options locale) +set(BOOST_COMPONENTS system filesystem program_options) +if(WIN32) + set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) +endif(WIN32) IF(BOOST_STATIC) set(Boost_USE_STATIC_LIBS ON) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index a4e5cad4df..e9e4302758 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -15,6 +14,9 @@ namespace bfs = boost::filesystem; int main(int argc, char *argv[]) { #else +// Include on Windows only +#include + class utf8argv { public: diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 6141790a8c..4576432e1c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -144,7 +144,11 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -set(BOOST_COMPONENTS system filesystem program_options thread wave locale) +set(BOOST_COMPONENTS system filesystem program_options thread wave) +if(WIN32) + set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) +endif(WIN32) + find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index cf72cc7325..9e959a986d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -82,7 +82,11 @@ add_openmw_dir (mwbase ) # Main executable -set(BOOST_COMPONENTS system filesystem program_options thread wave locale) +set(BOOST_COMPONENTS system filesystem program_options thread wave) +if(WIN32) + set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) +endif(WIN32) + find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) IF(OGRE_STATIC) From 663d5c314e38df474899744cdabdce56d063f792 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 22 May 2014 16:35:57 +0400 Subject: [PATCH 372/545] be more verbose on change reasons --- apps/mwiniimporter/main.cpp | 7 +++++++ components/files/windowspath.cpp | 7 +++++++ components/ogreinit/ogreinit.cpp | 8 ++++++++ extern/oics/tinyxml.cpp | 2 +- extern/shiny/Main/Preprocessor.cpp | 9 +++++++++ libs/openengine/gui/loglistener.hpp | 2 ++ libs/openengine/gui/manager.cpp | 4 ++++ libs/openengine/ogre/renderer.cpp | 4 ++++ 8 files changed, 42 insertions(+), 1 deletion(-) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index e9e4302758..c2408a5541 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -41,6 +41,13 @@ private: std::vector args; }; +/* The only way to pass Unicode on Winodws with CLI is to use wide + characters interface which presents UTF-16 encoding. The rest of + OpenMW application stack assumes UTF-8 encoding, therefore this + conversion. + + For boost::filesystem::path::imbue see components/files/windowspath.cpp +*/ int wmain(int argc, wchar_t *wargv[]) { utf8argv converter(argc, wargv); char **argv = converter.get(); diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 41240ae488..6b58304a0f 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -27,6 +27,13 @@ namespace Files WindowsPath::WindowsPath(const std::string& application_name) : mName(application_name) { + /* Since on Windows boost::path.string() returns string of narrow + characters in local encoding, it is required to path::imbue() + with UTF-8 encoding (generated for empty name from boost::locale) + to handle Unicode in platform-agnostic way using std::string. + + See boost::filesystem and boost::locale reference for details. + */ boost::filesystem::path::imbue(boost::locale::generator().generate("")); } diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 44d5fe3d53..77dbcb1ee1 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -26,6 +26,13 @@ namespace bfs = boost::filesystem; namespace { + /** \brief Custom Ogre::LogListener interface implementation being + able to portably handle UTF-8 encoded path. + + Effectively this is used in conjunction with default listener, + but since on every message messageLogged() set 'skip' flag to + true, there should be no troubles sharing same file. + */ class LogListener : public Ogre::LogListener { bfs::ofstream file; @@ -87,6 +94,7 @@ namespace OgreInit Ogre::Log *log = Ogre::LogManager::getSingleton().createLog(logPath); #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + // Use custom listener only on Windows log->addListener(new LogListener(logPath)); #endif diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp index 5be99f166a..21b2d9c9a3 100644 --- a/extern/oics/tinyxml.cpp +++ b/extern/oics/tinyxml.cpp @@ -32,7 +32,7 @@ distribution. #include "tinyxml.h" #ifdef _WIN32 -#include +#include // import MultiByteToWideChar #endif diff --git a/extern/shiny/Main/Preprocessor.cpp b/extern/shiny/Main/Preprocessor.cpp index bc2957da1b..c03879d460 100644 --- a/extern/shiny/Main/Preprocessor.cpp +++ b/extern/shiny/Main/Preprocessor.cpp @@ -6,6 +6,15 @@ #include +/* + Almost exact copy of load_file_to_string policy found in + boost::wave headers with the only change that it uses + boost::filesystem facility to handle UTF-8 paths used + throughout OpenMW (bfs::fstream, bfs::path). + + Original namespace is used due to required bost::wave + internal symbols. +*/ namespace boost { namespace wave { namespace iteration_context_policies { diff --git a/libs/openengine/gui/loglistener.hpp b/libs/openengine/gui/loglistener.hpp index 20f23cf0ce..47978ba447 100644 --- a/libs/openengine/gui/loglistener.hpp +++ b/libs/openengine/gui/loglistener.hpp @@ -8,6 +8,8 @@ namespace MyGUI { + /// \brief Custom MyGUI::ILogListener interface implementation + /// being able to portably handle UTF-8 encoded path. class CustomLogListener : public ILogListener { public: diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index fa7419b32d..383d37640b 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -559,6 +559,8 @@ public: } }; +/// \brief Helper class holding data that required during +/// MyGUI log creation class LogFacility { ConsoleLogListener mConsole; @@ -615,6 +617,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool mRenderManager = new MyGUI::OgreRenderManager(); mDataManager = new MyGUI::FixedOgreDataManager(); + // Do not use default log since it don't support Unicode path on Windows. + // Instead, manually create log source using LogFacility and pass it. mLogFacility = new MyGUI::LogFacility(theLogFile, logging); LogManager::getInstance().addLogSource(mLogFacility->getSource()); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 64d65ea0da..8fcf615ba4 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -51,6 +51,10 @@ void OgreRenderer::update(float dt) void OgreRenderer::screenshot(const std::string &file) { + /* Since Ogre uses narrow character interfaces, it does not support + Unicode paths on Windows. Therefore we had to implement screenshot + saving manually. + */ namespace bfs = boost::filesystem; bfs::ofstream out(bfs::path(file), std::ios::binary); From 4b5f02f6447a6596640c155c5eaaab7318d43d20 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 15:29:36 +0200 Subject: [PATCH 373/545] Remove useless throwing of exception --- apps/openmw/mwmechanics/levelledlist.hpp | 38 +++++++++++------------- apps/openmw/mwworld/esmstore.hpp | 3 +- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 6888d88a68..5d9e291181 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -53,29 +53,27 @@ namespace MWMechanics return std::string(); std::string item = candidates[std::rand()%candidates.size()]; - // Is this another levelled item or a real item? - try + // Vanilla doesn't fail on nonexistent items in levelled lists + if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) { - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item, 1); - if (ref.getPtr().getTypeName() != typeid(ESM::ItemLevList).name() - && ref.getPtr().getTypeName() != typeid(ESM::CreatureLevList).name()) - { - return item; - } - else - { - if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name()) - return getLevelledItem(ref.getPtr().get()->mBase, failChance); - else - return getLevelledItem(ref.getPtr().get()->mBase, failChance); - } - } - catch (std::logic_error&) - { - // Vanilla doesn't fail on nonexistent items in levelled lists - std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; + std::cerr << "Warning: ignoring nonexistent item '" << item << "' in levelled list '" << levItem->mId << "'" << std::endl; return std::string(); } + + // Is this another levelled item or a real item? + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item, 1); + if (ref.getPtr().getTypeName() != typeid(ESM::ItemLevList).name() + && ref.getPtr().getTypeName() != typeid(ESM::CreatureLevList).name()) + { + return item; + } + else + { + if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name()) + return getLevelledItem(ref.getPtr().get()->mBase, failChance); + else + return getLevelledItem(ref.getPtr().get()->mBase, failChance); + } } } diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index c6c9c1ffe2..90786acd42 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -85,7 +85,8 @@ namespace MWWorld return mStores.end(); } - // Look up the given ID in 'all'. Returns 0 if not found. + /// Look up the given ID in 'all'. Returns 0 if not found. + /// \note id must be in lower case. int find(const std::string &id) const { std::map::const_iterator it = mIds.find(id); From cba50c733839390736fa648f777dcddfcc99a90c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 15:46:35 +0200 Subject: [PATCH 374/545] Optimize ManualRef: look up correct Store instead of searching --- apps/openmw/mwworld/manualref.hpp | 75 ++++++++++++++++--------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 0e21c55acd..99accbb979 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -19,54 +19,57 @@ namespace MWWorld ManualRef& operator= (const ManualRef&); template - bool create (const MWWorld::Store& list, const std::string& name) + void create (const MWWorld::Store& list, const std::string& name) { - if (const T *instance = list.search (name)) - { - LiveCellRef ref; - ref.mBase = instance; - ref.mRef.mRefNum.mIndex = 0; - ref.mRef.mRefNum.mContentFile = -1; + const T* base = list.find(name); - mRef = ref; - mPtr = Ptr (&boost::any_cast&> (mRef), 0); + LiveCellRef ref; + ref.mBase = base; + ref.mRef.mRefNum.mIndex = 0; + ref.mRef.mRefNum.mContentFile = -1; - return true; - } - - return false; + mRef = ref; + mPtr = Ptr (&boost::any_cast&> (mRef), 0); } public: ManualRef (const MWWorld::ESMStore& store, const std::string& name, const int count=1) { - // create - if (!create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name) && - !create (store.get(), name)) - throw std::logic_error ("failed to create manual cell ref for " + name); + std::string lowerName = Misc::StringUtils::lowerCase (name); + switch (store.find (lowerName)) + { + case ESM::REC_ACTI: create (store.get(), lowerName); break; + case ESM::REC_ALCH: create (store.get(), lowerName); break; + case ESM::REC_APPA: create (store.get(), lowerName); break; + case ESM::REC_ARMO: create (store.get(), lowerName); break; + case ESM::REC_BOOK: create (store.get(), lowerName); break; + case ESM::REC_CLOT: create (store.get(), lowerName); break; + case ESM::REC_CONT: create (store.get(), lowerName); break; + case ESM::REC_CREA: create (store.get(), lowerName); break; + case ESM::REC_DOOR: create (store.get(), lowerName); break; + case ESM::REC_INGR: create (store.get(), lowerName); break; + case ESM::REC_LEVC: create (store.get(), lowerName); break; + case ESM::REC_LEVI: create (store.get(), lowerName); break; + case ESM::REC_LIGH: create (store.get(), lowerName); break; + case ESM::REC_LOCK: create (store.get(), lowerName); break; + case ESM::REC_MISC: create (store.get(), lowerName); break; + case ESM::REC_NPC_: create (store.get(), lowerName); break; + case ESM::REC_PROB: create (store.get(), lowerName); break; + case ESM::REC_REPA: create (store.get(), lowerName); break; + case ESM::REC_STAT: create (store.get(), lowerName); break; + case ESM::REC_WEAP: create (store.get(), lowerName); break; + + case 0: + throw std::logic_error ("failed to create manual cell ref for " + lowerName + " (unknown ID)"); + + default: + throw std::logic_error ("failed to create manual cell ref for " + lowerName + " (unknown type)"); + } // initialise ESM::CellRef& cellRef = mPtr.getCellRef(); - cellRef.mRefID = Misc::StringUtils::lowerCase (name); + cellRef.mRefID = lowerName; cellRef.mRefNum.mIndex = 0; cellRef.mRefNum.mContentFile = -1; cellRef.mScale = 1; From 20cfdd4b433fb90a64a08a540e50deaae0181b58 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Thu, 8 May 2014 13:47:54 +0200 Subject: [PATCH 375/545] Move LiveCellRefBase ctor where it belongs to --- apps/openmw/mwworld/livecellref.cpp | 5 +++++ apps/openmw/mwworld/ptr.cpp | 11 ++--------- apps/openmw/mwworld/ptr.hpp | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index 4a610b45ca..1b13e38038 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -10,6 +10,11 @@ #include "class.hpp" #include "esmstore.hpp" +MWWorld::LiveCellRefBase::LiveCellRefBase(std::string type, const ESM::CellRef &cref) + : mClass(&Class::get(type)), mRef(cref), mData(mRef) +{ +} + void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state) { mRef = state.mRef; diff --git a/apps/openmw/mwworld/ptr.cpp b/apps/openmw/mwworld/ptr.cpp index 3920a3e794..b047ba47ca 100644 --- a/apps/openmw/mwworld/ptr.cpp +++ b/apps/openmw/mwworld/ptr.cpp @@ -5,14 +5,7 @@ #include "containerstore.hpp" #include "class.hpp" - - -/* This shouldn't really be here. */ -MWWorld::LiveCellRefBase::LiveCellRefBase(std::string type, const ESM::CellRef &cref) - : mClass(&Class::get(type)), mRef(cref), mData(mRef) -{ -} - +#include "livecellref.hpp" const std::string& MWWorld::Ptr::getTypeName() const { @@ -59,4 +52,4 @@ MWWorld::ContainerStore *MWWorld::Ptr::getContainerStore() const MWWorld::Ptr::operator const void *() { return mRef; -} \ No newline at end of file +} diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index b830692831..f4696d3b3b 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -7,12 +7,12 @@ #include #include "cellreflist.hpp" -#include "livecellref.hpp" namespace MWWorld { class ContainerStore; class CellStore; + class LiveCellRefBase; /// \brief Pointer to a LiveCellRef From 1e4a854433115efa142001479489a23aa79dd0c4 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Thu, 22 May 2014 20:37:22 +0200 Subject: [PATCH 376/545] Remove static method MWWorld::Class::get(&Ptr) It was just adding a level of indirection to Ptr.getClass(). All the call were replaced by that instead. The number of lines changed is important, but the change itself is trivial, so everything should be fine. :) --- apps/openmw/engine.cpp | 4 +- apps/openmw/mwclass/activator.cpp | 2 +- apps/openmw/mwclass/armor.cpp | 2 +- apps/openmw/mwclass/book.cpp | 2 +- apps/openmw/mwclass/clothing.cpp | 2 +- apps/openmw/mwclass/container.cpp | 6 +- apps/openmw/mwclass/creature.cpp | 6 +- apps/openmw/mwclass/door.cpp | 4 +- apps/openmw/mwclass/ingredient.cpp | 2 +- apps/openmw/mwclass/light.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 26 ++-- apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwclass/weapon.cpp | 2 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 8 +- apps/openmw/mwdialogue/filter.cpp | 94 ++++++------ apps/openmw/mwgui/alchemywindow.cpp | 4 +- apps/openmw/mwgui/charactercreation.cpp | 4 +- apps/openmw/mwgui/companionwindow.cpp | 16 +- apps/openmw/mwgui/container.cpp | 18 +-- apps/openmw/mwgui/containeritemmodel.cpp | 4 +- apps/openmw/mwgui/dialogue.cpp | 4 +- apps/openmw/mwgui/enchantingdialog.cpp | 6 +- apps/openmw/mwgui/hud.cpp | 18 +-- apps/openmw/mwgui/inventoryitemmodel.cpp | 4 +- apps/openmw/mwgui/inventorywindow.cpp | 24 +-- apps/openmw/mwgui/itemmodel.cpp | 2 +- apps/openmw/mwgui/itemview.cpp | 2 +- apps/openmw/mwgui/levelupdialog.cpp | 10 +- apps/openmw/mwgui/merchantrepair.cpp | 12 +- apps/openmw/mwgui/quickkeysmenu.cpp | 18 +-- apps/openmw/mwgui/recharge.cpp | 8 +- apps/openmw/mwgui/repair.cpp | 12 +- apps/openmw/mwgui/sortfilteritemmodel.cpp | 4 +- apps/openmw/mwgui/spellbuyingwindow.cpp | 6 +- apps/openmw/mwgui/spellcreationdialog.cpp | 4 +- apps/openmw/mwgui/spellicons.cpp | 4 +- apps/openmw/mwgui/spellwindow.cpp | 18 +-- apps/openmw/mwgui/statswindow.cpp | 4 +- apps/openmw/mwgui/tooltips.cpp | 4 +- apps/openmw/mwgui/tradeitemmodel.cpp | 6 +- apps/openmw/mwgui/tradewindow.cpp | 14 +- apps/openmw/mwgui/trainingwindow.cpp | 8 +- apps/openmw/mwgui/travelwindow.cpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 6 +- apps/openmw/mwgui/windowmanagerimp.cpp | 8 +- apps/openmw/mwinput/inputmanagerimp.cpp | 6 +- apps/openmw/mwmechanics/actors.cpp | 28 ++-- apps/openmw/mwmechanics/aiactivate.cpp | 2 +- apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwmechanics/aiescort.cpp | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwmechanics/alchemy.cpp | 8 +- apps/openmw/mwmechanics/character.cpp | 10 +- apps/openmw/mwmechanics/enchanting.cpp | 12 +- .../mwmechanics/mechanicsmanagerimp.cpp | 28 ++-- apps/openmw/mwmechanics/repair.cpp | 14 +- apps/openmw/mwmechanics/security.cpp | 10 +- apps/openmw/mwrender/characterpreview.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 10 +- apps/openmw/mwrender/renderingmanager.cpp | 12 +- apps/openmw/mwscript/aiextensions.cpp | 28 ++-- apps/openmw/mwscript/compilercontext.cpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 12 +- apps/openmw/mwscript/dialogueextensions.cpp | 8 +- apps/openmw/mwscript/interpretercontext.cpp | 16 +- apps/openmw/mwscript/miscextensions.cpp | 20 +-- apps/openmw/mwscript/statsextensions.cpp | 140 +++++++++--------- .../mwscript/transformationextensions.cpp | 4 +- apps/openmw/mwworld/actionapply.cpp | 6 +- apps/openmw/mwworld/actioneat.cpp | 6 +- apps/openmw/mwworld/actionequip.cpp | 2 +- apps/openmw/mwworld/actionread.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 6 - apps/openmw/mwworld/containerstore.cpp | 8 +- apps/openmw/mwworld/inventorystore.cpp | 12 +- apps/openmw/mwworld/localscripts.cpp | 4 +- apps/openmw/mwworld/physicssystem.cpp | 6 +- apps/openmw/mwworld/player.cpp | 18 +-- apps/openmw/mwworld/scene.cpp | 6 +- apps/openmw/mwworld/worldimp.cpp | 36 ++--- 82 files changed, 453 insertions(+), 459 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 26ff7e96ed..41977ad7ed 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -492,11 +492,11 @@ void OMW::Engine::activate() MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); boost::shared_ptr action = - MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayerPtr()); + ptr.getClass().activate (ptr, MWBase::Environment::get().getWorld()->getPlayerPtr()); interpreterContext.activate (ptr, action); - std::string script = MWWorld::Class::get (ptr).getScript (ptr); + std::string script = ptr.getClass().getScript (ptr); MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayerPtr()); diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 16ab6321d5..fe9368b446 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -108,7 +108,7 @@ namespace MWClass boost::shared_ptr Activator::activate(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const { - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfActivator"); diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 550151e43b..26d1cab6d2 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -295,7 +295,7 @@ namespace MWClass return std::make_pair(0, "#{sInventoryMessage1}"); // slots that this item can be equipped in - std::pair, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); + std::pair, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr); if (slots_.first.empty()) return std::make_pair(0, ""); diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index ebc3b18e6f..183d91ca1f 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -61,7 +61,7 @@ namespace MWClass boost::shared_ptr Book::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfItem"); diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 18a40d5d30..a174f69a77 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -233,7 +233,7 @@ namespace MWClass std::pair Clothing::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { // slots that this item can be equipped in - std::pair, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); + std::pair, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr); if (slots_.first.empty()) return std::make_pair(0, ""); diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 2d9695c6b9..62734c03de 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -112,7 +112,7 @@ namespace MWClass if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) return boost::shared_ptr (new MWWorld::NullAction ()); - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfContainer"); @@ -127,7 +127,7 @@ namespace MWClass const std::string trapActivationSound = "Disarm Trap Fail"; MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player); + MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player); bool needKey = ptr.getCellRef().mLockLevel > 0; bool hasKey = false; @@ -143,7 +143,7 @@ namespace MWClass if (refId == keyId) { hasKey = true; - keyName = MWWorld::Class::get(*it).getName(*it); + keyName = it->getClass().getName(*it); } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 924021faae..7e484f9d48 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -277,7 +277,7 @@ namespace MWClass if (!weapon.isEmpty()) { - const bool weaphashealth = get(weapon).hasItemHealth(weapon); + const bool weaphashealth = weapon.getClass().hasItemHealth(weapon); const unsigned char *attack = NULL; if(type == ESM::Weapon::AT_Chop) attack = weapon.get()->mBase->mData.mChop; @@ -354,7 +354,7 @@ namespace MWClass } if(!object.isEmpty()) - getCreatureStats(ptr).setLastHitObject(MWWorld::Class::get(object).getId(object)); + getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") { @@ -444,7 +444,7 @@ namespace MWClass boost::shared_ptr Creature::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const { - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfCreature"); diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 06f0619cec..27903c4103 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -99,7 +99,7 @@ namespace MWClass const std::string lockedSound = "LockedDoor"; const std::string trapActivationSound = "Disarm Trap Fail"; - MWWorld::ContainerStore &invStore = get(actor).getContainerStore(actor); + MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor); bool needKey = ptr.getCellRef().mLockLevel > 0; bool hasKey = false; @@ -115,7 +115,7 @@ namespace MWClass if (refId == keyId) { hasKey = true; - keyName = get(*it).getName(*it); + keyName = it->getClass().getName(*it); } } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index e15424c388..ebe41bb537 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -153,7 +153,7 @@ namespace MWClass } MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats (player); int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase(); static const float fWortChanceValue = diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index bd25b66b2c..1b28a84625 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -250,7 +250,7 @@ namespace MWClass std::pair Light::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); MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon == invStore.end()) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 72505fa081..bca7708eab 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -484,10 +484,10 @@ namespace MWClass if(victim.isEmpty()) // Didn't hit anything return; - const MWWorld::Class &othercls = MWWorld::Class::get(victim); + const MWWorld::Class &othercls = victim.getClass(); if(!othercls.isActor()) // Can't hit non-actors return; - MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); + MWMechanics::CreatureStats &otherstats = othercls.getCreatureStats(victim); if(otherstats.isDead()) // Can't hit dead actors return; @@ -496,7 +496,7 @@ namespace MWClass int weapskill = ESM::Skill::HandToHand; if(!weapon.isEmpty()) - weapskill = get(weapon).getEquipmentSkill(weapon); + weapskill = weapon.getClass().getEquipmentSkill(weapon); float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill)); @@ -511,7 +511,7 @@ namespace MWClass MWMechanics::NpcStats &stats = getNpcStats(ptr); if(!weapon.isEmpty()) { - const bool weaphashealth = get(weapon).hasItemHealth(weapon); + const bool weaphashealth = weapon.getClass().hasItemHealth(weapon); const unsigned char *attack = NULL; if(type == ESM::Weapon::AT_Chop) attack = weapon.get()->mBase->mData.mChop; @@ -637,7 +637,7 @@ namespace MWClass } if(!object.isEmpty()) - getCreatureStats(ptr).setLastHitObject(get(object).getId(object)); + getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") { @@ -716,9 +716,9 @@ namespace MWClass inv.unequipItem(armor, ptr); if (ptr.getRefData().getHandle() == "player") - skillUsageSucceeded(ptr, get(armor).getEquipmentSkill(armor), 0); + skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0); - switch(get(armor).getEquipmentSkill(armor)) + switch(armor.getClass().getEquipmentSkill(armor)) { case ESM::Skill::LightArmor: sndMgr->playSound3D(ptr, "Light Armor Hit", 1.0f, 1.0f); @@ -802,7 +802,7 @@ namespace MWClass if(ptr.getRefData().getHandle() == "player") return boost::shared_ptr(new MWWorld::ActionTalk(actor)); - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfNPC"); @@ -814,7 +814,7 @@ namespace MWClass } if(getCreatureStats(ptr).isDead()) return boost::shared_ptr(new MWWorld::ActionOpen(ptr, true)); - if(get(ptr).getCreatureStats(ptr).isHostile()) + if(ptr.getClass().getCreatureStats(ptr).isHostile()) return boost::shared_ptr(new MWWorld::FailedAction("#{sActorInCombat}")); if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak)) return boost::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing @@ -943,7 +943,7 @@ namespace MWClass if (fallHeight >= fallDistanceMin) { - const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); + const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); const NpcCustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude; const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat(); @@ -1107,7 +1107,7 @@ namespace MWClass { MWWorld::LiveCellRef *ref = it->get(); - int armorSkillType = MWWorld::Class::get(*it).getEquipmentSkill(*it); + int armorSkillType = it->getClass().getEquipmentSkill(*it); int armorSkill = stats.getSkill(armorSkillType).getModified(); if(ref->mBase->mData.mWeight == 0) @@ -1177,7 +1177,7 @@ namespace MWClass if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) return "FootBareLeft"; - switch(Class::get(*boots).getEquipmentSkill(*boots)) + switch(boots->getClass().getEquipmentSkill(*boots)) { case ESM::Skill::LightArmor: return "FootLightLeft"; @@ -1204,7 +1204,7 @@ namespace MWClass if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) return "FootBareRight"; - switch(Class::get(*boots).getEquipmentSkill(*boots)) + switch(boots->getClass().getEquipmentSkill(*boots)) { case ESM::Skill::LightArmor: return "FootLightRight"; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 216f815cd6..f9d7947a66 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -133,7 +133,7 @@ namespace MWClass // hide effects the player doesnt know about MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats (player); int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase(); int i=0; static const float fWortChanceValue = diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index e9b0c8f3cb..146251ca29 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -392,7 +392,7 @@ namespace MWClass if (ptr.getCellRef().mCharge == 0) return std::make_pair(0, "#{sInventoryMessage1}"); - std::pair, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); + std::pair, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr); if (slots_.first.empty()) return std::make_pair (0, ""); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index fe37f37ff7..c7e832e4ab 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -134,13 +134,13 @@ namespace MWDialogue mActor = actor; - MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); + MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats (actor); mTalkedTo = creatureStats.hasTalkedToPlayer(); mActorKnownTopics.clear(); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); + win->startDialogue(actor, actor.getClass().getName (actor)); //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI updateTopics(); @@ -194,7 +194,7 @@ namespace MWDialogue Compiler::Locals locals; - std::string actorScript = MWWorld::Class::get (mActor).getScript (mActor); + std::string actorScript = mActor.getClass().getScript (mActor); if (!actorScript.empty()) { @@ -435,7 +435,7 @@ namespace MWDialogue // Apply disposition change to NPC's base disposition if (mActor.getClass().isNpc()) { - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor); + MWMechanics::NpcStats& npcStats = mActor.getClass().getNpcStats(mActor); npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange); } mPermanentDispositionChange = 0; diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 8b9ee9184f..0678623455 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -25,7 +25,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const // actor id if (!info.mActor.empty()) { - if ( !Misc::StringUtils::ciEqual(info.mActor, MWWorld::Class::get (mActor).getId (mActor))) + if ( !Misc::StringUtils::ciEqual(info.mActor, mActor.getClass().getId (mActor))) return false; } else if (isCreature) @@ -64,7 +64,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const if (isCreature) return false; - MWMechanics::NpcStats& stats = MWWorld::Class::get (mActor).getNpcStats (mActor); + MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor); std::map::iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction)); if (iter==stats.getFactionRanks().end()) @@ -98,7 +98,7 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const // check player faction if (!info.mPcFaction.empty()) { - MWMechanics::NpcStats& stats = MWWorld::Class::get (player).getNpcStats (player); + MWMechanics::NpcStats& stats = player.getClass().getNpcStats (player); std::map::iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase (info.mPcFaction)); if(iter==stats.getFactionRanks().end()) @@ -182,7 +182,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c case SelectWrapper::Function_Local: { - std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); + std::string scriptName = mActor.getClass().getScript (mActor); if (scriptName.empty()) return false; // no script @@ -220,8 +220,8 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() / - MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified(); + float ratio = player.getClass().getCreatureStats (player).getHealth().getCurrent() / + player.getClass().getCreatureStats (player).getHealth().getModified(); return select.selectCompare (static_cast(ratio*100)); } @@ -230,7 +230,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - float value = MWWorld::Class::get (player).getCreatureStats (player). + float value = player.getClass().getCreatureStats (player). getDynamic (select.getArgument()).getCurrent(); return select.selectCompare (value); @@ -238,8 +238,8 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c case SelectWrapper::Function_HealthPercent: { - float ratio = MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getCurrent() / - MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getModified(); + float ratio = mActor.getClass().getCreatureStats (mActor).getHealth().getCurrent() / + mActor.getClass().getCreatureStats (mActor).getHealth().getModified(); return select.selectCompare (ratio); } @@ -262,7 +262,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_Item: { - MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore (player); int sum = 0; @@ -285,29 +285,29 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_AiSetting: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting ( + return mActor.getClass().getCreatureStats (mActor).getAiSetting ( (MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified(); case SelectWrapper::Function_PcAttribute: - return MWWorld::Class::get (player).getCreatureStats (player). + return player.getClass().getCreatureStats (player). getAttribute (select.getArgument()).getModified(); case SelectWrapper::Function_PcSkill: - return static_cast (MWWorld::Class::get (player). + return static_cast (player.getClass(). getNpcStats (player).getSkill (select.getArgument()).getModified()); case SelectWrapper::Function_FriendlyHit: { - int hits = MWWorld::Class::get (mActor).getCreatureStats (mActor).getFriendlyHits(); + int hits = mActor.getClass().getCreatureStats (mActor).getFriendlyHits(); return hits>4 ? 4 : hits; } case SelectWrapper::Function_PcLevel: - return MWWorld::Class::get (player).getCreatureStats (player).getLevel(); + return player.getClass().getCreatureStats (player).getLevel(); case SelectWrapper::Function_PcGender: @@ -315,7 +315,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_PcClothingModifier: { - MWWorld::InventoryStore& store = MWWorld::Class::get (player).getInventoryStore (player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore (player); int value = 0; @@ -324,7 +324,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con MWWorld::ContainerStoreIterator slot = store.getSlot (i); if (slot!=store.end()) - value += MWWorld::Class::get (*slot).getValue (*slot); + value += slot->getClass().getValue (*slot); } return value; @@ -332,15 +332,15 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_PcCrimeLevel: - return MWWorld::Class::get (player).getNpcStats (player).getBounty(); + return player.getClass().getNpcStats (player).getBounty(); case SelectWrapper::Function_RankRequirement: { - if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty()) return 0; std::string faction = - MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first; int rank = getFactionRank (player, faction); @@ -360,11 +360,11 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_Level: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).getLevel(); + return mActor.getClass().getCreatureStats (mActor).getLevel(); case SelectWrapper::Function_PCReputation: - return MWWorld::Class::get (player).getNpcStats (player).getReputation(); + return player.getClass().getNpcStats (player).getReputation(); case SelectWrapper::Function_Weather: @@ -372,15 +372,15 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_Reputation: - return MWWorld::Class::get (mActor).getNpcStats (mActor).getReputation(); + return mActor.getClass().getNpcStats (mActor).getReputation(); case SelectWrapper::Function_FactionRankDiff: { - if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty()) return 0; std::pair faction = - *MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin(); + *mActor.getClass().getNpcStats (mActor).getFactionRanks().begin(); int rank = getFactionRank (player, faction.first); @@ -389,25 +389,25 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con case SelectWrapper::Function_WerewolfKills: - return MWWorld::Class::get (player).getNpcStats (player).getWerewolfKills(); + return player.getClass().getNpcStats (player).getWerewolfKills(); case SelectWrapper::Function_RankLow: case SelectWrapper::Function_RankHigh: { bool low = select.getFunction()==SelectWrapper::Function_RankLow; - if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty()) return 0; std::string factionId = - MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first; int value = 0; const ESM::Faction& faction = *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); - MWMechanics::NpcStats& playerStats = MWWorld::Class::get (player).getNpcStats (player); + MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player); for (std::vector::const_iterator iter (faction.mReactions.begin()); iter!=faction.mReactions.end(); ++iter) @@ -436,7 +436,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_NotId: - return !Misc::StringUtils::ciEqual(MWWorld::Class::get (mActor).getId (mActor), select.getName()); + return !Misc::StringUtils::ciEqual(mActor.getClass().getId (mActor), select.getName()); case SelectWrapper::Function_NotFaction: @@ -456,7 +456,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_NotLocal: { - std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); + std::string scriptName = mActor.getClass().getScript (mActor); if (scriptName.empty()) // This actor has no attached script, so there is no local variable @@ -489,36 +489,36 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_SameFaction: - return MWWorld::Class::get (mActor).getNpcStats (mActor).isSameFaction ( - MWWorld::Class::get (player).getNpcStats (player)); + return mActor.getClass().getNpcStats (mActor).isSameFaction ( + player.getClass().getNpcStats (player)); case SelectWrapper::Function_PcCommonDisease: - return MWWorld::Class::get (player).getCreatureStats (player).hasCommonDisease(); + return player.getClass().getCreatureStats (player).hasCommonDisease(); case SelectWrapper::Function_PcBlightDisease: - return MWWorld::Class::get (player).getCreatureStats (player).hasBlightDisease(); + return player.getClass().getCreatureStats (player).hasBlightDisease(); case SelectWrapper::Function_PcCorprus: - return MWWorld::Class::get (player).getCreatureStats (player). + return player.getClass().getCreatureStats (player). getMagicEffects().get (ESM::MagicEffect::Corprus).mMagnitude!=0; case SelectWrapper::Function_PcExpelled: { - if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) + if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty()) return false; std::string faction = - MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; + mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first; return player.getClass().getNpcStats(player).getExpelled(faction); } case SelectWrapper::Function_PcVampire: - return MWWorld::Class::get (player).getCreatureStats(player).getMagicEffects(). + return player.getClass().getCreatureStats(player).getMagicEffects(). get(ESM::MagicEffect::Vampirism).mMagnitude > 0; case SelectWrapper::Function_TalkedToPc: @@ -527,7 +527,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_Alarmed: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).isAlarmed(); + return mActor.getClass().getCreatureStats (mActor).isAlarmed(); case SelectWrapper::Function_Detected: @@ -535,11 +535,11 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_Attacked: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAttacked(); + return mActor.getClass().getCreatureStats (mActor).getAttacked(); case SelectWrapper::Function_ShouldAttack: - return MWWorld::Class::get (mActor).getCreatureStats (mActor).isHostile(); + return mActor.getClass().getCreatureStats (mActor).isHostile(); case SelectWrapper::Function_CreatureTargetted: @@ -547,7 +547,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co case SelectWrapper::Function_Werewolf: - return MWWorld::Class::get (mActor).getNpcStats (mActor).isWerewolf(); + return mActor.getClass().getNpcStats (mActor).isWerewolf(); default: @@ -557,7 +557,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const { - MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + MWMechanics::NpcStats& stats = actor.getClass().getNpcStats (actor); std::map::const_iterator iter = stats.getFactionRanks().find (factionId); @@ -573,13 +573,13 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements (const MWWorld::Ptr& ac if (rank<0 || rank>=10) throw std::runtime_error ("rank index out of range"); - if (!MWWorld::Class::get (actor).getNpcStats (actor).hasSkillsForRank (factionId, rank)) + if (!actor.getClass().getNpcStats (actor).hasSkillsForRank (factionId, rank)) return false; const ESM::Faction& faction = *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); - MWMechanics::CreatureStats& stats = MWWorld::Class::get (actor).getCreatureStats (actor); + MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats (actor); return stats.getAttribute (faction.mData.mAttribute[0]).getBase()>=faction.mData.mRankData[rank].mAttribute1 && stats.getAttribute (faction.mData.mAttribute[1]).getBase()>=faction.mData.mRankData[rank].mAttribute2; @@ -591,7 +591,7 @@ bool MWDialogue::Filter::hasFactionRankReputationRequirements (const MWWorld::Pt if (rank<0 || rank>=10) throw std::runtime_error ("rank index out of range"); - MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); + MWMechanics::NpcStats& stats = actor.getClass().getNpcStats (actor); const ESM::Faction& faction = *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index a6880ffcb5..6524c168e1 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -19,7 +19,7 @@ namespace std::string getIconPath(MWWorld::Ptr ptr) { std::string path = std::string("icons\\"); - path += MWWorld::Class::get(ptr).getInventoryIcon(ptr); + path += ptr.getClass().getInventoryIcon(ptr); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -174,7 +174,7 @@ namespace MWGui { update(); - std::string sound = MWWorld::Class::get(item).getUpSoundId(item); + std::string sound = item.getClass().getUpSoundId(item); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } } diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index fa1bd28be2..85f57a1a8c 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -47,7 +47,7 @@ namespace void updatePlayerHealth() { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player); + MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player); npcStats.updateHealth(); } } @@ -220,7 +220,7 @@ namespace MWGui { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); mReviewDialog->setHealth ( stats.getHealth() ); mReviewDialog->setMagicka( stats.getMagicka() ); diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index a0a34108eb..70093049da 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -61,7 +61,7 @@ void CompanionWindow::onItemSelected(int index) if (count > 1 && !shift) { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), "#{sTake}", count); + dialog->open(object.getClass().getName(object), "#{sTake}", count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &CompanionWindow::dragItem); } @@ -92,7 +92,7 @@ void CompanionWindow::open(const MWWorld::Ptr& npc) mSortModel = new SortFilterItemModel(mModel); mItemView->setModel(mSortModel); - setTitle(MWWorld::Class::get(npc).getName(npc)); + setTitle(npc.getClass().getName(npc)); } void CompanionWindow::onFrame() @@ -104,22 +104,22 @@ void CompanionWindow::updateEncumbranceBar() { if (mPtr.isEmpty()) return; - float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr); - float encumbrance = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); + float capacity = mPtr.getClass().getCapacity(mPtr); + float encumbrance = mPtr.getClass().getEncumbrance(mPtr); mEncumbranceBar->setValue(encumbrance, capacity); if (mPtr.getTypeName() != typeid(ESM::NPC).name()) mProfitLabel->setCaption(""); else { - MWMechanics::NpcStats& stats = MWWorld::Class::get(mPtr).getNpcStats(mPtr); + MWMechanics::NpcStats& stats = mPtr.getClass().getNpcStats(mPtr); mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + boost::lexical_cast(stats.getProfit())); } } void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { - if (mPtr.getTypeName() == typeid(ESM::NPC).name() && MWWorld::Class::get(mPtr).getNpcStats(mPtr).getProfit() < 0) + if (mPtr.getTypeName() == typeid(ESM::NPC).name() && mPtr.getClass().getNpcStats(mPtr).getProfit() < 0) { std::vector buttons; buttons.push_back("#{sCompanionWarningButtonOne}"); @@ -135,8 +135,8 @@ void CompanionWindow::onMessageBoxButtonClicked(int button) { if (button == 0) { - mPtr.getRefData().getLocals().setVarByInt(MWWorld::Class::get(mPtr).getScript(mPtr), - "minimumProfit", MWWorld::Class::get(mPtr).getNpcStats(mPtr).getProfit()); + mPtr.getRefData().getLocals().setVarByInt(mPtr.getClass().getScript(mPtr), + "minimumProfit", mPtr.getClass().getNpcStats(mPtr).getProfit()); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion); MWBase::Environment::get().getDialogueManager()->startDialogue (mPtr); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 02c4b93560..a207dec0c5 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -37,7 +37,7 @@ namespace MWGui mIsOnDragAndDrop = true; mDragAndDropWidget->setVisible(true); - std::string sound = MWWorld::Class::get(mItem.mBase).getUpSoundId(mItem.mBase); + std::string sound = mItem.mBase.getClass().getUpSoundId(mItem.mBase); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); if (mSourceSortModel) @@ -47,7 +47,7 @@ namespace MWGui } std::string path = std::string("icons\\"); - path += MWWorld::Class::get(mItem.mBase).getInventoryIcon(mItem.mBase); + path += mItem.mBase.getClass().getInventoryIcon(mItem.mBase); MyGUI::ImageBox* baseWidget = mDragAndDropWidget->createWidget ("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); mDraggedWidget = baseWidget; @@ -76,7 +76,7 @@ namespace MWGui void DragAndDrop::drop(ItemModel *targetModel, ItemView *targetView) { - std::string sound = MWWorld::Class::get(mItem.mBase).getDownSoundId(mItem.mBase); + std::string sound = mItem.mBase.getClass().getDownSoundId(mItem.mBase); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); mDragAndDropWidget->setVisible(false); @@ -155,7 +155,7 @@ namespace MWGui if (count > 1 && !shift) { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); - dialog->open(MWWorld::Class::get(object).getName(object), "#{sTake}", count); + dialog->open(object.getClass().getName(object), "#{sTake}", count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); } @@ -177,8 +177,8 @@ namespace MWGui { // check that we don't exceed container capacity MWWorld::Ptr item = mDragAndDrop->mItem.mBase; - float weight = MWWorld::Class::get(item).getWeight(item) * mDragAndDrop->mDraggedCount; - if (MWWorld::Class::get(mPtr).getCapacity(mPtr) < MWWorld::Class::get(mPtr).getEncumbrance(mPtr) + weight) + float weight = item.getClass().getWeight(item) * mDragAndDrop->mDraggedCount; + if (mPtr.getClass().getCapacity(mPtr) < mPtr.getClass().getEncumbrance(mPtr) + weight) { MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}"); return; @@ -227,7 +227,7 @@ namespace MWGui // 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. - setTitle(MWWorld::Class::get(container).getName(container)); + setTitle(container.getClass().getName(container)); } void ContainerWindow::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char) @@ -284,7 +284,7 @@ namespace MWGui { // play the sound of the first object MWWorld::Ptr item = mModel->getItem(i).mBase; - std::string sound = MWWorld::Class::get(item).getUpSoundId(item); + std::string sound = item.getClass().getUpSoundId(item); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } @@ -306,7 +306,7 @@ namespace MWGui { onTakeAllButtonClicked(mTakeButton); - if (MWWorld::Class::get(mPtr).isPersistent(mPtr)) + if (mPtr.getClass().isPersistent(mPtr)) MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); else MWBase::Environment::get().getWorld()->deleteObject(mPtr); diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index b5b498e5e6..b2befc3ba8 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -85,7 +85,7 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count) for (std::vector::iterator source = mItemSources.begin(); source != mItemSources.end(); ++source) { - MWWorld::ContainerStore& store = MWWorld::Class::get(*source).getContainerStore(*source); + MWWorld::ContainerStore& store = source->getClass().getContainerStore(*source); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { @@ -120,7 +120,7 @@ void ContainerItemModel::update() mItems.clear(); for (std::vector::iterator source = mItemSources.begin(); source != mItemSources.end(); ++source) { - MWWorld::ContainerStore& store = MWWorld::Class::get(*source).getContainerStore(*source); + MWWorld::ContainerStore& store = source->getClass().getContainerStore(*source); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index dcd26d4698..0002757947 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -386,8 +386,8 @@ namespace MWGui mTopicLinks.clear(); mKeywordSearch.clear(); - bool isCompanion = !MWWorld::Class::get(mPtr).getScript(mPtr).empty() - && mPtr.getRefData().getLocals().getIntVar(MWWorld::Class::get(mPtr).getScript(mPtr), "companion"); + bool isCompanion = !mPtr.getClass().getScript(mPtr).empty() + && mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion"); bool anyService = mServices > 0 || isCompanion || mPtr.getTypeName() == typeid(ESM::NPC).name(); diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index ada004612a..b303848df5 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -119,7 +119,7 @@ namespace MWGui MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(soulgem).getInventoryIcon(soulgem); + path += soulgem.getClass().getInventoryIcon(soulgem); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -164,7 +164,7 @@ namespace MWGui MyGUI::ImageBox* image = mItemBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -207,7 +207,7 @@ namespace MWGui MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 079793ee19..103c48ca14 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -348,7 +348,7 @@ namespace MWGui void HUD::onWeaponClicked(MyGUI::Widget* _sender) { const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf()) + if (player.getClass().getNpcStats(player).isWerewolf()) { MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}"); return; @@ -360,7 +360,7 @@ namespace MWGui void HUD::onMagicClicked(MyGUI::Widget* _sender) { const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf()) + if (player.getClass().getNpcStats(player).isWerewolf()) { MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}"); return; @@ -443,7 +443,7 @@ namespace MWGui void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) { - std::string itemName = MWWorld::Class::get(item).getName(item); + std::string itemName = item.getClass().getName(item); if (itemName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; @@ -466,7 +466,7 @@ namespace MWGui , MyGUI::Align::Stretch); std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(item).getInventoryIcon(item); + path+=item.getClass().getInventoryIcon(item); Widgets::fixTexturePath(path); itemBox->setImageTexture(path); itemBox->setNeedMouseFocus(false); @@ -474,7 +474,7 @@ namespace MWGui void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) { - std::string itemName = MWWorld::Class::get(item).getName(item); + std::string itemName = item.getClass().getName(item); if (itemName != mWeaponName && mWeaponVisible) { mWeaponSpellTimer = 5.0f; @@ -493,10 +493,10 @@ namespace MWGui MyGUI::Gui::getInstance().destroyWidget(mWeapImage->getChildAt(0)); std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(item).getInventoryIcon(item); + path+=item.getClass().getInventoryIcon(item); Widgets::fixTexturePath(path); - if (MWWorld::Class::get(item).getEnchantment(item) != "") + if (item.getClass().getEnchantment(item) != "") { mWeapImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); MyGUI::ImageBox* itemBox = mWeapImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) @@ -545,7 +545,7 @@ namespace MWGui MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf()) + if (player.getClass().getNpcStats(player).isWerewolf()) mWeapImage->setImageTexture("icons\\k\\tx_werewolf_hand.dds"); else mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); @@ -636,7 +636,7 @@ namespace MWGui void HUD::updateEnemyHealthBar() { - MWMechanics::CreatureStats& stats = MWWorld::Class::get(mEnemy).getCreatureStats(mEnemy); + MWMechanics::CreatureStats& stats = mEnemy.getClass().getCreatureStats(mEnemy); mEnemyHealth->setProgressRange(100); // Health is usually cast to int before displaying. Actors die whenever they are < 1 health. // Therefore any value < 1 should show as an empty health bar. We do the same in statswindow :) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index 718c6d991f..e1bc9d4daa 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -50,7 +50,7 @@ MWWorld::Ptr InventoryItemModel::copyItem (const ItemStack& item, size_t count, void InventoryItemModel::removeItem (const ItemStack& item, size_t count) { - MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor); + MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor); int removed = store.remove(item.mBase, count, mActor); if (removed == 0) @@ -77,7 +77,7 @@ MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, I void InventoryItemModel::update() { - MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor); + MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor); mItems.clear(); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e9a4a18e5a..788f90f504 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -162,7 +162,7 @@ namespace MWGui } const ItemStack& item = mTradeModel->getItem(index); - std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); + std::string sound = item.mBase.getClass().getDownSoundId(item.mBase); MWWorld::Ptr object = item.mBase; int count = item.mCount; @@ -184,7 +184,7 @@ namespace MWGui { // check if merchant accepts item int services = MWBase::Environment::get().getWindowManager()->getTradeWindow()->getMerchantServices(); - if (!MWWorld::Class::get(object).canSell(object, services)) + if (!object.getClass().canSell(object, services)) { MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getWindowManager()-> @@ -197,7 +197,7 @@ namespace MWGui { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); std::string message = mTrading ? "#{sQuanityMenuMessage01}" : "#{sTake}"; - dialog->open(MWWorld::Class::get(object).getName(object), message, count); + dialog->open(object.getClass().getName(object), message, count); dialog->eventOkClicked.clear(); if (mTrading) dialog->eventOkClicked += MyGUI::newDelegate(this, &InventoryWindow::sellItem); @@ -223,7 +223,7 @@ namespace MWGui const ItemStack& item = mTradeModel->getItem(mSelectedItem); if (item.mType == ItemStack::Type_Equipped) { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); MWWorld::Ptr newStack = *invStore.unequipItem(item.mBase, mPtr); // The unequipped item was re-stacked. We have to update the index @@ -259,7 +259,7 @@ namespace MWGui { ensureSelectedItemUnequipped(); const ItemStack& item = mTradeModel->getItem(mSelectedItem); - std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); + std::string sound = item.mBase.getClass().getDownSoundId(item.mBase); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); if (item.mType == ItemStack::Type_Barter) @@ -382,7 +382,7 @@ namespace MWGui if (script.empty() || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 0) { - boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + boost::shared_ptr action = ptr.getClass().use(ptr); action->execute (MWBase::Environment::get().getWorld()->getPlayerPtr()); @@ -447,7 +447,7 @@ namespace MWGui if (slot == -1) return MWWorld::Ptr(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); if(invStore.getSlot(slot) != invStore.end()) { MWWorld::Ptr item = *invStore.getSlot(slot); @@ -466,8 +466,8 @@ namespace MWGui { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - float capacity = MWWorld::Class::get(player).getCapacity(player); - float encumbrance = MWWorld::Class::get(player).getEncumbrance(player); + float capacity = player.getClass().getCapacity(player); + float encumbrance = player.getClass().getEncumbrance(player); mEncumbranceBar->setValue(encumbrance, capacity); } @@ -498,9 +498,9 @@ namespace MWGui mAvatarImage->setImageTile(MyGUI::IntSize(std::min(512, size.width), std::min(1024, size.height))); mArmorRating->setCaptionWithReplacing ("#{sArmor}: " - + boost::lexical_cast(static_cast(MWWorld::Class::get(mPtr).getArmorRating(mPtr)))); + + boost::lexical_cast(static_cast(mPtr.getClass().getArmorRating(mPtr)))); if (mArmorRating->getTextSize().width > mArmorRating->getSize().width) - mArmorRating->setCaptionWithReplacing (boost::lexical_cast(static_cast(MWWorld::Class::get(mPtr).getArmorRating(mPtr)))); + mArmorRating->setCaptionWithReplacing (boost::lexical_cast(static_cast(mPtr.getClass().getArmorRating(mPtr)))); } } @@ -534,7 +534,7 @@ namespace MWGui && (type != typeid(ESM::Potion).name())) return; - if (MWWorld::Class::get(object).getName(object) == "") // objects without name presented to user can never be picked up + if (object.getClass().getName(object) == "") // objects without name presented to user can never be picked up return; int count = object.getRefData().getCount(); diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 2cdd8a2e66..55317724e3 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -13,7 +13,7 @@ namespace MWGui , mType(Type_Normal) , mBase(base) { - if (MWWorld::Class::get(base).getEnchantment(base) != "") + if (base.getClass().getEnchantment(base) != "") mFlags |= Flag_Enchanted; } diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index 027c3201fc..24bc3fd630 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -81,7 +81,7 @@ void ItemView::update() /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item.mBase).getInventoryIcon(item.mBase); + path += item.mBase.getClass().getInventoryIcon(item.mBase); // background widget (for the "equipped" frame and magic item background image) bool isMagic = (item.mFlags & ItemStack::Flag_Enchanted); diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index 5a3fc2855d..38995ac326 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -61,8 +61,8 @@ namespace MWGui void LevelupDialog::setAttributeValues() { 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::CreatureStats& creatureStats = player.getClass().getCreatureStats (player); + MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); for (int i=0; i<8; ++i) { @@ -117,8 +117,8 @@ namespace MWGui { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player); - MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats (player); + MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); mSpentAttributes.clear(); resetCoins(); @@ -172,7 +172,7 @@ namespace MWGui void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender) { MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); if (mSpentAttributes.size() < 3) MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}"); diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 2a48e62a94..83527a8845 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -39,19 +39,19 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor; for (MWWorld::ContainerStoreIterator iter (store.begin(categories)); iter!=store.end(); ++iter) { - if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) + if (iter->getClass().hasItemHealth(*iter)) { - int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter); + int maxDurability = iter->getClass().getItemMaxHealth(*iter); int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; if (maxDurability == durability) continue; - int basePrice = MWWorld::Class::get(*iter).getValue(*iter); + int basePrice = iter->getClass().getValue(*iter); float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get() .find("fRepairMult")->getFloat(); @@ -64,7 +64,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); - std::string name = MWWorld::Class::get(*iter).getName(*iter) + std::string name = iter->getClass().getName(*iter) + " - " + boost::lexical_cast(price) + MWBase::Environment::get().getWorld()->getStore().get() .find("sgp")->getString();; @@ -114,7 +114,7 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) { // repair MWWorld::Ptr item = *sender->getUserData(); - item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item); + item.getCellRef().mCharge = item.getClass().getItemMaxHealth(item); MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 51e24e29c8..5df2b12b8d 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -166,7 +166,7 @@ namespace MWGui frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -200,7 +200,7 @@ namespace MWGui MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -265,7 +265,7 @@ namespace MWGui QuickKeyType type = *button->getUserData(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); if (type == Type_Item || type == Type_MagicItem) { @@ -290,7 +290,7 @@ namespace MWGui { // No replacement was found MWBase::Environment::get().getWindowManager ()->messageBox ( - "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item)); + "#{sQuickMenu5} " + item.getClass().getName(item)); return; } } @@ -330,7 +330,7 @@ namespace MWGui assert(it != store.end()); // equip, if it can be equipped - if (!MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) + if (!item.getClass().getEquipmentSlots(item).first.empty()) { MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item); } @@ -522,8 +522,8 @@ namespace MWGui const int spellHeight = 18; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); /// \todo lots of copy&pasted code from SpellWindow @@ -566,7 +566,7 @@ namespace MWGui std::vector items; for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) { - std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it); + std::string enchantId = it->getClass().getEnchantment(*it); if (enchantId != "") { // only add items with "Cast once" or "Cast on use" @@ -645,7 +645,7 @@ namespace MWGui MyGUI::Button* t = mMagicList->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); - t->setCaption(MWWorld::Class::get(item).getName(item)); + t->setCaption(item.getClass().getName(item)); t->setTextAlign(MyGUI::Align::Left); t->setUserData(item); t->setUserString("ToolTipType", "ItemPtr"); diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 683406d9eb..313650bb64 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -41,7 +41,7 @@ void Recharge::open() void Recharge::start (const MWWorld::Ptr &item) { std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -85,7 +85,7 @@ void Recharge::updateView() int currentY = 0; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) { @@ -99,14 +99,14 @@ void Recharge::updateView() MyGUI::TextBox* text = mView->createWidget ( "SandText", MyGUI::IntCoord(8, currentY, mView->getWidth()-8, 18), MyGUI::Align::Default); - text->setCaption(MWWorld::Class::get(*iter).getName(*iter)); + text->setCaption(iter->getClass().getName(*iter)); text->setNeedMouseFocus(false); currentY += 19; MyGUI::ImageBox* icon = mView->createWidget ( "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); + path += iter->getClass().getInventoryIcon(*iter); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index de96bcacd1..a3df2dfbea 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -40,7 +40,7 @@ void Repair::startRepairItem(const MWWorld::Ptr &item) mRepair.setTool(item); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(item).getInventoryIcon(item); + path += item.getClass().getInventoryIcon(item); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); @@ -90,28 +90,28 @@ void Repair::updateRepairView() int currentY = 0; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor; for (MWWorld::ContainerStoreIterator iter (store.begin(categories)); iter!=store.end(); ++iter) { - if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) + if (iter->getClass().hasItemHealth(*iter)) { - int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter); + int maxDurability = iter->getClass().getItemMaxHealth(*iter); int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; if (maxDurability == durability) continue; MyGUI::TextBox* text = mRepairView->createWidget ( "SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default); - text->setCaption(MWWorld::Class::get(*iter).getName(*iter)); + text->setCaption(iter->getClass().getName(*iter)); text->setNeedMouseFocus(false); currentY += 19; MyGUI::ImageBox* icon = mRepairView->createWidget ( "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); - path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); + path += iter->getClass().getInventoryIcon(*iter); int pos = path.rfind("."); path.erase(pos); path.append(".dds"); diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 74a4f88e79..475f73a072 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -47,8 +47,8 @@ namespace if (left.mBase.getTypeName() == right.mBase.getTypeName()) { - int cmp = MWWorld::Class::get(left.mBase).getName(left.mBase).compare( - MWWorld::Class::get(right.mBase).getName(right.mBase)); + int cmp = left.mBase.getClass().getName(left.mBase).compare( + right.mBase.getClass().getName(right.mBase)); return cmp < 0; } else diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 77df465146..99b85c13cc 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -83,7 +83,7 @@ namespace MWGui mPtr = actor; clearSpells(); - MWMechanics::Spells& merchantSpells = MWWorld::Class::get (actor).getCreatureStats (actor).getSpells(); + MWMechanics::Spells& merchantSpells = actor.getClass().getCreatureStats (actor).getSpells(); for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter) { @@ -107,7 +107,7 @@ namespace MWGui bool SpellBuyingWindow::playerHasSpell(const std::string &id) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells(); + MWMechanics::Spells& playerSpells = player.getClass().getCreatureStats (player).getSpells(); for (MWMechanics::Spells::TIterator it = playerSpells.begin(); it != playerSpells.end(); ++it) { if (Misc::StringUtils::ciEqual(id, it->first)) @@ -121,7 +121,7 @@ namespace MWGui int price = *_sender->getUserData(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); spells.add (mSpellsWidgetMap.find(_sender)->second); player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 469d7188ec..1ec4bd6da4 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -353,7 +353,7 @@ namespace MWGui const ESM::Spell* spell = MWBase::Environment::get().getWorld()->createRecord(mSpell); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); spells.add (spell->mId); @@ -445,7 +445,7 @@ namespace MWGui // get the list of magic effects that are known to the player MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); std::vector knownEffects; diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index d5ece298b0..1a9e418de6 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -40,14 +40,14 @@ namespace MWGui // TODO: Tracking add/remove/expire would be better than force updating every frame MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); EffectSourceVisitor visitor; // permanent item enchantments & permanent spells visitor.mIsPermanent = true; - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); store.visitEffectSources(visitor); stats.getSpells().visitEffectSources(visitor); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index a00c2480e2..16e4741432 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -84,8 +84,8 @@ namespace MWGui // retrieve all player spells, divide them into Powers and Spells and sort them std::vector spellList; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) @@ -122,7 +122,7 @@ namespace MWGui std::vector items; for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) { - std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it); + std::string enchantId = it->getClass().getEnchantment(*it); if (enchantId != "") { // only add items with "Cast once" or "Cast on use" @@ -203,7 +203,7 @@ namespace MWGui MWWorld::Ptr item = *it; const ESM::Enchantment* enchant = - esmStore.get().find(MWWorld::Class::get(item).getEnchantment(item)); + esmStore.get().find(item.getClass().getEnchantment(item)); // check if the item is currently equipped (will display in a different color) bool equipped = false; @@ -218,7 +218,7 @@ namespace MWGui MyGUI::Button* t = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); - t->setCaption(MWWorld::Class::get(item).getName(item)); + t->setCaption(item.getClass().getName(item)); t->setTextAlign(MyGUI::Align::Left); t->setUserData(item); t->setUserString("ToolTipType", "ItemPtr"); @@ -300,7 +300,7 @@ namespace MWGui void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); MWWorld::Ptr item = *_sender->getUserData(); // retrieve ContainerStoreIterator to the item @@ -316,7 +316,7 @@ namespace MWGui // equip, if it can be equipped and is not already equipped if (_sender->getUserString("Equipped") == "false" - && !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) + && !item.getClass().getEquipmentSlots(item).first.empty()) { MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item); } @@ -330,7 +330,7 @@ namespace MWGui { std::string spellId = _sender->getUserString("Spell"); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); if (MyGUI::InputManager::getInstance().isShiftPressed()) { @@ -384,7 +384,7 @@ namespace MWGui void SpellWindow::onDeleteSpellAccept() { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); if (MWBase::Environment::get().getWindowManager()->getSelectedSpell() == mSpellToDelete) diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 31a3b6fdd0..6ae44e3146 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -228,7 +228,7 @@ namespace MWGui NoDrop::onFrame(dt); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &PCstats = MWWorld::Class::get(player).getNpcStats(player); + const MWMechanics::NpcStats &PCstats = player.getClass().getNpcStats(player); // level progress MyGUI::Widget* levelWidget; @@ -459,7 +459,7 @@ namespace MWGui addSeparator(coord1, coord2); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &PCstats = MWWorld::Class::get(player).getNpcStats(player); + const MWMechanics::NpcStats &PCstats = player.getClass().getNpcStats(player); const std::set &expelled = PCstats.getExpelled(); addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index b931966f07..dd29f40ce4 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -89,7 +89,7 @@ namespace MWGui if (mFocusObject.isEmpty ()) return; - const MWWorld::Class& objectclass = MWWorld::Class::get (mFocusObject); + const MWWorld::Class& objectclass = mFocusObject.getClass(); MyGUI::IntSize tooltipSize; if ((!objectclass.hasToolTip(mFocusObject))&&(MWBase::Environment::get().getWindowManager()->getMode() == GM_Console)) @@ -305,7 +305,7 @@ namespace MWGui MyGUI::IntSize tooltipSize; - const MWWorld::Class& object = MWWorld::Class::get (mFocusObject); + const MWWorld::Class& object = mFocusObject.getClass(); if (!object.hasToolTip(mFocusObject)) { mDynamicToolTipBox->setVisible(false); diff --git a/apps/openmw/mwgui/tradeitemmodel.cpp b/apps/openmw/mwgui/tradeitemmodel.cpp index ad18a13e81..18b0d5ae3f 100644 --- a/apps/openmw/mwgui/tradeitemmodel.cpp +++ b/apps/openmw/mwgui/tradeitemmodel.cpp @@ -138,7 +138,7 @@ namespace MWGui int services = 0; if (!mMerchant.isEmpty()) - services = MWWorld::Class::get(mMerchant).getServices(mMerchant); + services = mMerchant.getClass().getServices(mMerchant); mItems.clear(); // add regular items @@ -150,7 +150,7 @@ namespace MWGui MWWorld::Ptr base = item.mBase; if(Misc::StringUtils::ciEqual(base.getCellRef().mRefID, MWWorld::ContainerStore::sGoldId)) continue; - if(!MWWorld::Class::get(base).canSell(base, services)) + if(!base.getClass().canSell(base, services)) continue; // Bound items may not be bought @@ -164,7 +164,7 @@ namespace MWGui if(mMerchant.getClass().hasInventoryStore(mMerchant)) { bool isEquipped = false; - MWWorld::InventoryStore& store = MWWorld::Class::get(mMerchant).getInventoryStore(mMerchant); + MWWorld::InventoryStore& store = mMerchant.getClass().getInventoryStore(mMerchant); for (int slot=0; slotgetCountDialog(); std::string message = "#{sQuanityMenuMessage02}"; - dialog->open(MWWorld::Class::get(object).getName(object), message, count); + dialog->open(object.getClass().getName(object), message, count); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::sellItem); mItemToSell = mSortModel->mapToSource(index); @@ -165,7 +165,7 @@ namespace MWGui void TradeWindow::sellItem(MyGUI::Widget* sender, int count) { const ItemStack& item = mTradeModel->getItem(mItemToSell); - std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase); + std::string sound = item.mBase.getClass().getDownSoundId(item.mBase); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel(); @@ -208,7 +208,7 @@ namespace MWGui void TradeWindow::addOrRemoveGold(int amount, const MWWorld::Ptr& actor) { - MWWorld::ContainerStore& store = MWWorld::Class::get(actor).getContainerStore(actor); + MWWorld::ContainerStore& store = actor.getClass().getContainerStore(actor); if (amount > 0) { @@ -442,7 +442,7 @@ namespace MWGui void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem) { - int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, boughtItem); + int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, item.getClass().getValue(item) * count, boughtItem); mCurrentBalance += diff; mCurrentMerchantOffer += diff; @@ -452,7 +452,7 @@ namespace MWGui void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem) { - int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, !soldItem); + int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, item.getClass().getValue(item) * count, !soldItem); mCurrentBalance -= diff; mCurrentMerchantOffer -= diff; diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index bee76992af..34873b9bc7 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -44,7 +44,7 @@ namespace MWGui mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(playerGold)); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats (actor); + MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats (actor); // NPC can train you in his best 3 skills std::vector< std::pair > bestSkills; @@ -73,7 +73,7 @@ namespace MWGui MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator (); MyGUI::Gui::getInstance ().destroyWidgets (widgets); - MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -115,7 +115,7 @@ namespace MWGui int skillId = *sender->getUserData(); MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -123,7 +123,7 @@ namespace MWGui int price = pcStats.getSkill (skillId).getBase() * store.get().find("iTrainingMod")->getInt (); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mPtr).getNpcStats (mPtr); + MWMechanics::NpcStats& npcStats = mPtr.getClass().getNpcStats (mPtr); if (npcStats.getSkill (skillId).getBase () <= pcStats.getSkill (skillId).getBase ()) { MWBase::Environment::get().getWindowManager()->messageBox ("#{sServiceTrainingWords}"); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 89d73215d0..642e1a6449 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -161,7 +161,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->changeToExteriorCell(pos); } - MWWorld::Class::get(player).adjustPosition(player); + player.getClass().adjustPosition(player); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index ed1b9e0a90..6c07e14d36 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -171,11 +171,11 @@ namespace MWGui void WaitDialog::setCanRest (bool canRest) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); bool full = (stats.getFatigue().getCurrent() >= stats.getFatigue().getModified()) && (stats.getHealth().getCurrent() >= stats.getHealth().getModified()) && (stats.getMagicka().getCurrent() >= stats.getMagicka().getModified()); - MWMechanics::NpcStats& npcstats = MWWorld::Class::get(player).getNpcStats(player); + MWMechanics::NpcStats& npcstats = player.getClass().getNpcStats(player); bool werewolf = npcstats.isWerewolf(); mUntilHealedButton->setVisible(canRest && !full); @@ -231,7 +231,7 @@ namespace MWGui mWaiting = false; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &pcstats = MWWorld::Class::get(player).getNpcStats(player); + const MWMechanics::NpcStats &pcstats = player.getClass().getNpcStats(player); // trigger levelup if possible const MWWorld::Store &gmst = diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 81b28aa66f..40fcc35300 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1027,20 +1027,20 @@ namespace MWGui { mSelectedSpell = ""; const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get() - .find(MWWorld::Class::get(item).getEnchantment(item)); + .find(item.getClass().getEnchantment(item)); int chargePercent = (item.getCellRef().mEnchantmentCharge == -1) ? 100 : (item.getCellRef().mEnchantmentCharge / static_cast(ench->mData.mCharge) * 100); mHud->setSelectedEnchantItem(item, chargePercent); - mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item)); + mSpellWindow->setTitle(item.getClass().getName(item)); } void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) { int durabilityPercent = (item.getCellRef().mCharge == -1) ? 100 - : (item.getCellRef().mCharge / static_cast(MWWorld::Class::get(item).getItemMaxHealth(item)) * 100); + : (item.getCellRef().mCharge / static_cast(item.getClass().getItemMaxHealth(item)) * 100); mHud->setSelectedWeapon(item, durabilityPercent); - mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item)); + mInventoryWindow->setTitle(item.getClass().getName(item)); } void WindowManager::unsetSelectedSpell() diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 8095b0d05d..cf71cc1aa4 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -172,7 +172,7 @@ namespace MWInput if (action == A_Use) { - MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); + mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); } if (currentValue == 1) @@ -359,7 +359,7 @@ namespace MWInput { MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); mOverencumberedMessageDelay -= dt; - if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) + if (player.getClass().getEncumbrance(player) >= player.getClass().getCapacity(player)) { mPlayer->setAutoMove (false); if (mOverencumberedMessageDelay <= 0) @@ -664,7 +664,7 @@ namespace MWInput return; // Not allowed if no spell selected - MWWorld::InventoryStore& inventory = MWWorld::Class::get(mPlayer->getPlayer()).getInventoryStore(mPlayer->getPlayer()); + MWWorld::InventoryStore& inventory = mPlayer->getPlayer().getClass().getInventoryStore(mPlayer->getPlayer()); if (MWBase::Environment::get().getWindowManager()->getSelectedSpell().empty() && inventory.getSelectedEnchantItem() == inventory.end()) return; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 363647467a..35667a23c4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -187,7 +187,7 @@ namespace MWMechanics void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) { - CreatureStats& creatureStats = MWWorld::Class::get(actor1).getCreatureStats(actor1); + CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1); if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player @@ -244,13 +244,13 @@ namespace MWMechanics void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) { - CreatureStats& creatureStats = MWWorld::Class::get (creature).getCreatureStats (creature); + CreatureStats& creatureStats = creature.getClass().getCreatureStats (creature); MagicEffects now = creatureStats.getSpells().getMagicEffects(); if (creature.getTypeName()==typeid (ESM::NPC).name()) { - MWWorld::InventoryStore& store = MWWorld::Class::get (creature).getInventoryStore (creature); + MWWorld::InventoryStore& store = creature.getClass().getInventoryStore (creature); now += store.getMagicEffects(); } @@ -265,7 +265,7 @@ namespace MWMechanics void Actors::calculateDynamicStats (const MWWorld::Ptr& ptr) { - CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr); int strength = creatureStats.getAttribute(ESM::Attribute::Strength).getBase(); int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getBase(); @@ -333,7 +333,7 @@ namespace MWMechanics void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration) { - CreatureStats &creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); + CreatureStats &creatureStats = ptr.getClass().getCreatureStats(ptr); const MagicEffects &effects = creatureStats.getMagicEffects(); // attributes @@ -600,7 +600,7 @@ namespace MWMechanics void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr) { - NpcStats &npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); + NpcStats &npcStats = ptr.getClass().getNpcStats(ptr); const MagicEffects &effects = npcStats.getMagicEffects(); // skills @@ -656,7 +656,7 @@ namespace MWMechanics { bool isPlayer = ptr.getRefData().getHandle()=="player"; - MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr); + MWWorld::InventoryStore &inventoryStore = ptr.getClass().getInventoryStore(ptr); MWWorld::ContainerStoreIterator heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); /** @@ -678,7 +678,7 @@ namespace MWMechanics { if (torch != inventoryStore.end()) { - if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile()) + if (!ptr.getClass().getCreatureStats (ptr).isHostile()) { // For non-hostile NPCs, unequip whatever is in the left slot in favor of a light. if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) @@ -755,8 +755,8 @@ namespace MWMechanics if (ptr != player && ptr.getClass().isNpc()) { // get stats of witness - CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); - NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); + CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr); + NpcStats& npcStats = ptr.getClass().getNpcStats(ptr); if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile()) { @@ -824,7 +824,7 @@ namespace MWMechanics void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately) { // erase previous death events since we are currently only tracking them while in an active cell - MWWorld::Class::get(ptr).getCreatureStats(ptr).clearHasDied(); + ptr.getClass().getCreatureStats(ptr).clearHasDied(); removeActor(ptr); @@ -964,7 +964,7 @@ namespace MWMechanics // Kill dead actors, update some variables for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { - const MWWorld::Class &cls = MWWorld::Class::get(iter->first); + const MWWorld::Class &cls = iter->first.getClass(); CreatureStats &stats = cls.getCreatureStats(iter->first); //KnockedOutOneFrameLogic @@ -1137,7 +1137,7 @@ namespace MWMechanics std::list list; for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { - const MWWorld::Class &cls = MWWorld::Class::get(iter->first); + const MWWorld::Class &cls = iter->first.getClass(); CreatureStats &stats = cls.getCreatureStats(iter->first); if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) { @@ -1158,7 +1158,7 @@ namespace MWMechanics neighbors); //only care about those within the alarm disance for(std::vector::iterator iter(neighbors.begin());iter != neighbors.end();iter++) { - const MWWorld::Class &cls = MWWorld::Class::get(*iter); + const MWWorld::Class &cls = iter->getClass(); CreatureStats &stats = cls.getCreatureStats(*iter); if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) { diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 4b4b36ed65..3dfacb853d 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -32,7 +32,7 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + target.getClass().activate(target,actor).get()->execute(actor); //Arrest player return true; } else { diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 44eacb0d1e..5045225828 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -63,7 +63,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors); for(std::vector::iterator it = actors.begin(); it != actors.end(); it++) { if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player - MWMechanics::AiSequence& seq = MWWorld::Class::get(*it).getCreatureStats(*it).getAiSequence(); + MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence(); if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr),*it); } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 0430adf06a..07bb9726ef 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -97,7 +97,7 @@ namespace MWMechanics { // Stop moving if the player is to far away MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; mMaxDist = 330; } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7120ff5afc..1c870bda47 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -572,7 +572,7 @@ namespace MWMechanics void AiWander::stopWalking(const MWWorld::Ptr& actor) { mPathFinder.clearPath(); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; } void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index af58e9ee0b..64b358b96c 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -292,13 +292,13 @@ void MWMechanics::Alchemy::addPotion (const std::string& name) void MWMechanics::Alchemy::increaseSkill() { - MWWorld::Class::get (mAlchemist).skillUsageSucceeded (mAlchemist, ESM::Skill::Alchemy, 0); + mAlchemist.getClass().skillUsageSucceeded (mAlchemist, ESM::Skill::Alchemy, 0); } float MWMechanics::Alchemy::getChance() const { - const CreatureStats& creatureStats = MWWorld::Class::get (mAlchemist).getCreatureStats (mAlchemist); - const NpcStats& npcStats = MWWorld::Class::get (mAlchemist).getNpcStats (mAlchemist); + const CreatureStats& creatureStats = mAlchemist.getClass().getCreatureStats (mAlchemist); + const NpcStats& npcStats = mAlchemist.getClass().getNpcStats (mAlchemist); return (npcStats.getSkill (ESM::Skill::Alchemy).getModified() + @@ -331,7 +331,7 @@ void MWMechanics::Alchemy::setAlchemist (const MWWorld::Ptr& npc) mEffects.clear(); - MWWorld::ContainerStore& store = MWWorld::Class::get (npc).getContainerStore (npc); + MWWorld::ContainerStore& store = npc.getClass().getContainerStore (npc); for (MWWorld::ContainerStoreIterator iter (store.begin (MWWorld::ContainerStore::Type_Apparatus)); iter!=store.end(); ++iter) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b6d91db583..60bccb3f7e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -459,7 +459,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim if(!mAnimation) return; - const MWWorld::Class &cls = MWWorld::Class::get(mPtr); + const MWWorld::Class &cls = mPtr.getClass(); if(cls.isActor()) { /* Accumulate along X/Y only for now, until we can figure out how we should @@ -549,7 +549,7 @@ bool CharacterController::updateCreatureState() bool CharacterController::updateWeaponState() { - const MWWorld::Class &cls = MWWorld::Class::get(mPtr); + const MWWorld::Class &cls = mPtr.getClass(); CreatureStats &stats = cls.getCreatureStats(mPtr); WeaponType weaptype = WeapType_None; MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); @@ -601,8 +601,8 @@ bool CharacterController::updateWeaponState() if(weapon != inv.end() && !(weaptype == WeapType_None && mWeaponType == WeapType_Spell)) { std::string soundid = (weaptype == WeapType_None) ? - MWWorld::Class::get(*weapon).getDownSoundId(*weapon) : - MWWorld::Class::get(*weapon).getUpSoundId(*weapon); + weapon->getClass().getDownSoundId(*weapon) : + weapon->getClass().getUpSoundId(*weapon); if(!soundid.empty()) { MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); @@ -983,7 +983,7 @@ bool CharacterController::updateWeaponState() void CharacterController::update(float duration) { MWBase::World *world = MWBase::Environment::get().getWorld(); - const MWWorld::Class &cls = MWWorld::Class::get(mPtr); + const MWWorld::Class &cls = mPtr.getClass(); Ogre::Vector3 movement(0.0f); updateVisibility(); diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 87337cdd70..23246c2945 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -52,7 +52,7 @@ namespace MWMechanics bool Enchanting::create() { const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); ESM::Enchantment enchantment; enchantment.mData.mCharge = getGemCharge(); @@ -67,7 +67,7 @@ namespace MWMechanics if(getEnchantChance() (RAND_MAX)*100) return false; - MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2); + mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2); } if(mCastStyle==ESM::Enchantment::ConstantEffect) @@ -84,7 +84,7 @@ namespace MWMechanics // Apply the enchantment const ESM::Enchantment *enchantmentPtr = MWBase::Environment::get().getWorld()->createRecord (enchantment); - MWWorld::Class::get(newItemPtr).applyEnchantment(newItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName); + newItemPtr.getClass().applyEnchantment(newItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName); // Add the new item to player inventory and remove the old one store.remove(mOldItemPtr, 1, player); @@ -212,7 +212,7 @@ namespace MWMechanics const float enchantCost = getEnchantPoints(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::NpcStats &stats = MWWorld::Class::get(player).getNpcStats(player); + MWMechanics::NpcStats &stats = player.getClass().getNpcStats(player); int eSkill = stats.getSkill(ESM::Skill::Enchant).getModified(); /* @@ -277,7 +277,7 @@ namespace MWMechanics float Enchanting::getEnchantChance() const { - const NpcStats& npcStats = MWWorld::Class::get (mEnchanter).getNpcStats (mEnchanter); + const NpcStats& npcStats = mEnchanter.getClass().getNpcStats (mEnchanter); float chance1 = (npcStats.getSkill (ESM::Skill::Enchant).getModified() + (0.25 * npcStats.getAttribute (ESM::Attribute::Intelligence).getModified()) @@ -295,7 +295,7 @@ namespace MWMechanics void Enchanting::payForEnchantment() const { const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); store.remove(MWWorld::ContainerStore::sGoldId, getEnchantPrice(), player); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index bf9a11d6e5..5a72c88837 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -49,8 +49,8 @@ namespace MWMechanics { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get (ptr).getNpcStats (ptr); + MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr); + MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats (ptr); const ESM::NPC *player = ptr.get()->mBase; @@ -215,7 +215,7 @@ namespace MWMechanics void MechanicsManager::add(const MWWorld::Ptr& ptr) { - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) mActors.addActor(ptr); else mObjects.addObject(ptr); @@ -234,7 +234,7 @@ namespace MWMechanics if(old == mWatched) mWatched = ptr; - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) mActors.updateActor(old, ptr); else mObjects.updateObject(old, ptr); @@ -475,13 +475,13 @@ namespace MWMechanics int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr) { - const MWMechanics::NpcStats& npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr); + const MWMechanics::NpcStats& npcSkill = ptr.getClass().getNpcStats(ptr); float x = npcSkill.getBaseDisposition(); MWWorld::LiveCellRef* npc = ptr.get(); MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::LiveCellRef* player = playerPtr.get(); - const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr); if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace)) x += MWBase::Environment::get().getWorld()->getStore().get().find("fDispRaceMod")->getFloat(); @@ -547,10 +547,10 @@ namespace MWMechanics if (ptr.getTypeName() == typeid(ESM::Creature).name()) return basePrice; - const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(ptr).getNpcStats(ptr); + const MWMechanics::NpcStats &sellerStats = ptr.getClass().getNpcStats(ptr); MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr); // I suppose the temporary disposition change _has_ to be considered here, // otherwise one would get different prices when exiting and re-entering the dialogue window... @@ -592,10 +592,10 @@ namespace MWMechanics const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(npc).getNpcStats(npc); + MWMechanics::NpcStats& npcStats = npc.getClass().getNpcStats(npc); MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr); float persTerm = playerStats.getAttribute(ESM::Attribute::Personality).getModified() / gmst.find("fPersonalityMod")->getFloat(); @@ -741,27 +741,27 @@ namespace MWMechanics void MechanicsManager::forceStateUpdate(const MWWorld::Ptr &ptr) { - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) mActors.forceStateUpdate(ptr); } void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) { - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) mActors.playAnimationGroup(ptr, groupName, mode, number); else mObjects.playAnimationGroup(ptr, groupName, mode, number); } void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr) { - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) mActors.skipAnimation(ptr); else mObjects.skipAnimation(ptr); } bool MechanicsManager::checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string &groupName) { - if(MWWorld::Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) return mActors.checkAnimationPlaying(ptr, groupName); else return false; diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp index 48179d3442..dc8b567a9b 100644 --- a/apps/openmw/mwmechanics/repair.cpp +++ b/apps/openmw/mwmechanics/repair.cpp @@ -31,8 +31,8 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses; mTool.getCellRef().mCharge = uses-1; - MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player); + MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); + MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player); float fatigueTerm = stats.getFatigueTerm(); int pcStrength = stats.getAttribute(ESM::Attribute::Strength).getModified(); @@ -55,15 +55,15 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) // repair by 'y' points itemToRepair.getCellRef().mCharge += y; itemToRepair.getCellRef().mCharge = std::min(itemToRepair.getCellRef().mCharge, - MWWorld::Class::get(itemToRepair).getItemMaxHealth(itemToRepair)); + itemToRepair.getClass().getItemMaxHealth(itemToRepair)); // set the OnPCRepair variable on the item's script - std::string script = MWWorld::Class::get(itemToRepair).getScript(itemToRepair); + std::string script = itemToRepair.getClass().getScript(itemToRepair); if(script != "") itemToRepair.getRefData().getLocals().setVarByInt(script, "onpcrepair", 1); // increase skill - MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Armorer, 0); + player.getClass().skillUsageSucceeded(player, ESM::Skill::Armorer, 0); MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairSuccess}"); @@ -78,14 +78,14 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) if (mTool.getCellRef().mCharge == 0) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); store.remove(mTool, 1, player); std::string message = MWBase::Environment::get().getWorld()->getStore().get() .find("sNotifyMessage51")->getString(); - MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % MWWorld::Class::get(mTool).getName(mTool)).str()); + MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % mTool.getClass().getName(mTool)).str()); // try to find a new tool of the same ID for (MWWorld::ContainerStoreIterator iter (store.begin()); diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 3751e58285..bb2e942238 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -18,8 +18,8 @@ namespace MWMechanics Security::Security(const MWWorld::Ptr &actor) : mActor(actor) { - CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); - NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats(actor); + CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); + NpcStats& npcStats = actor.getClass().getNpcStats(actor); mAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified(); mLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified(); mSecuritySkill = npcStats.getSkill(ESM::Skill::Security).getModified(); @@ -51,10 +51,10 @@ namespace MWMechanics int roll = static_cast (std::rand()) / RAND_MAX * 100; if (roll <= x) { - MWWorld::Class::get(lock).unlock(lock); + lock.getClass().unlock(lock); resultMessage = "#{sLockSuccess}"; resultSound = "Open Lock"; - MWWorld::Class::get(mActor).skillUsageSucceeded(mActor, ESM::Skill::Security, 1); + mActor.getClass().skillUsageSucceeded(mActor, ESM::Skill::Security, 1); } else resultMessage = "#{sLockFail}"; @@ -97,7 +97,7 @@ namespace MWMechanics resultSound = "Disarm Trap"; resultMessage = "#{sTrapSuccess}"; - MWWorld::Class::get(mActor).skillUsageSucceeded(mActor, ESM::Skill::Security, 0); + mActor.getClass().skillUsageSucceeded(mActor, ESM::Skill::Security, 0); } else resultMessage = "#{sTrapFail}"; diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 013e3daf4f..5e88b22505 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -118,7 +118,7 @@ namespace MWRender 0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); float scale=1.f; - MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale); + mCharacter.getClass().adjustScale(mCharacter, scale); mNode->setScale(Ogre::Vector3(scale)); mCamera->setPosition(mPosition * mNode->getScale()); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 14f5cc4e7f..03ccde388b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -237,7 +237,7 @@ void NpcAnimation::updateNpcBase() void NpcAnimation::updateParts() { mAlpha = 1.f; - const MWWorld::Class &cls = MWWorld::Class::get(mPtr); + const MWWorld::Class &cls = mPtr.getClass(); MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); NpcType curType = Type_Normal; @@ -668,12 +668,12 @@ void NpcAnimation::showWeapons(bool showWeapon) mShowWeapons = showWeapon; if(showWeapon) { - MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon != inv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*weapon); - std::string mesh = MWWorld::Class::get(*weapon).getModel(*weapon); + std::string mesh = weapon->getClass().getModel(*weapon); addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh, !weapon->getClass().getEnchantment(*weapon).empty(), &glowColor); @@ -701,13 +701,13 @@ void NpcAnimation::showWeapons(bool showWeapon) void NpcAnimation::showCarriedLeft(bool show) { mShowCarriedLeft = show; - MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if(show && iter != inv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*iter); - std::string mesh = MWWorld::Class::get(*iter).getModel(*iter); + std::string mesh = iter->getClass().getModel(*iter); if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor)) { diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 991ca690ee..882a3d09bf 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -249,7 +249,7 @@ void RenderingManager::cellAdded (MWWorld::CellStore *store) void RenderingManager::addObject (const MWWorld::Ptr& ptr){ const MWWorld::Class& class_ = - MWWorld::Class::get (ptr); + ptr.getClass(); class_.insertObjectRendering(ptr, *this); } @@ -279,7 +279,7 @@ void RenderingManager::rotateObject(const MWWorld::Ptr &ptr) mCamera->rotateCamera(-rot, false); Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(rot.z), Ogre::Vector3::NEGATIVE_UNIT_Z); - if(!MWWorld::Class::get(ptr).isActor()) + if(!ptr.getClass().isActor()) newo = Ogre::Quaternion(Ogre::Radian(rot.x), Ogre::Vector3::NEGATIVE_UNIT_X) * Ogre::Quaternion(Ogre::Radian(rot.y), Ogre::Vector3::NEGATIVE_UNIT_Y) * newo; ptr.getRefData().getBaseNode()->setOrientation(newo); @@ -294,7 +294,7 @@ RenderingManager::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr & Ogre::SceneNode *parent = child->getParentSceneNode(); parent->removeChild(child); - if (MWWorld::Class::get(old).isActor()) { + if (old.getClass().isActor()) { mActors->updateObjectCell(old, cur); } else { mObjects->updateObjectCell(old, cur); @@ -314,7 +314,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) NpcAnimation *anim = NULL; if(ptr.getRefData().getHandle() == "player") anim = mPlayerAnimation; - else if(MWWorld::Class::get(ptr).isActor()) + else if(ptr.getClass().isActor()) anim = dynamic_cast(mActors->getAnimation(ptr)); if(anim) { @@ -337,7 +337,7 @@ void RenderingManager::update (float duration, bool paused) MWWorld::Ptr player = world->getPlayerPtr(); - int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; + int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f))); setAmbientMode(); @@ -599,7 +599,7 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour) mAmbientColor = colour; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).mMagnitude; + int nightEye = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).mMagnitude; Ogre::ColourValue final = colour; final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f)); diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index ded25479c4..cc17905df6 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -47,7 +47,7 @@ namespace MWScript for (unsigned int i=0; i @@ -298,7 +298,7 @@ namespace MWScript for (unsigned int i=0; igetPtr (id, false); - script = MWWorld::Class::get (ptr).getScript (ptr); + script = ptr.getClass().getScript (ptr); reference = true; } diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 66c8d44687..6737d6a945 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -117,7 +117,7 @@ namespace MWScript if (count == 0) return; - MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); std::string itemName; for (MWWorld::ContainerStoreIterator iter(store.begin()); iter != store.end(); ++iter) @@ -231,7 +231,7 @@ namespace MWScript throw std::runtime_error ("armor index out of range"); } - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); if (it == invStore.end() || it->getTypeName () != typeid(ESM::Armor).name()) @@ -240,7 +240,7 @@ namespace MWScript return; } - int skill = MWWorld::Class::get(*it).getEquipmentSkill (*it) ; + int skill = it->getClass().getEquipmentSkill (*it) ; if (skill == ESM::Skill::HeavyArmor) runtime.push(2); else if (skill == ESM::Skill::MediumArmor) @@ -264,7 +264,7 @@ namespace MWScript std::string item = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); @@ -290,7 +290,7 @@ namespace MWScript const std::string &name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); for (MWWorld::ContainerStoreIterator it = invStore.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != invStore.end(); ++it) { @@ -314,7 +314,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); MWWorld::ContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight); if (it == invStore.end() || it->getTypeName () != typeid(ESM::Weapon).name()) { diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index a882ae05e7..993e99c2e6 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -141,7 +141,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (MWWorld::Class::get(ptr).getNpcStats (ptr).getReputation () + value); + ptr.getClass().getNpcStats (ptr).setReputation (ptr.getClass().getNpcStats (ptr).getReputation () + value); } }; @@ -156,7 +156,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get(ptr).getNpcStats (ptr).setReputation (value); + ptr.getClass().getNpcStats (ptr).setReputation (value); } }; @@ -169,7 +169,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).getReputation ()); + runtime.push (ptr.getClass().getNpcStats (ptr).getReputation ()); } }; @@ -184,7 +184,7 @@ namespace MWScript MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).isSameFaction (MWWorld::Class::get(player).getNpcStats (player))); + runtime.push (ptr.getClass().getNpcStats (ptr).isSameFaction (player.getClass().getNpcStats (player))); } }; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 1f5ad5b071..6f7968fac8 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -66,7 +66,7 @@ namespace MWScript { const MWWorld::Ptr ptr = getReference (id, false); - id = MWWorld::Class::get (ptr).getScript (ptr); + id = ptr.getClass().getScript (ptr); ptr.getRefData().setLocals ( *MWBase::Environment::get().getWorld()->getStore().get().find (id)); @@ -86,7 +86,7 @@ namespace MWScript { const MWWorld::Ptr ptr = getReference (id, false); - id = MWWorld::Class::get (ptr).getScript (ptr); + id = ptr.getClass().getScript (ptr); ptr.getRefData().setLocals ( *MWBase::Environment::get().getWorld()->getStore().get().find (id)); @@ -263,7 +263,7 @@ namespace MWScript std::string InterpreterContext::getNPCRank() const { - std::map ranks = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks(); + std::map ranks = mReference.getClass().getNpcStats (mReference).getFactionRanks(); std::map::const_iterator it = ranks.begin(); MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -299,9 +299,9 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; + std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first; - std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); int rank = -1; if (it != ranks.end()) @@ -326,9 +326,9 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; + std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first; - std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); int rank = -1; if (it != ranks.end()) @@ -353,7 +353,7 @@ namespace MWScript { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - return MWWorld::Class::get (player).getNpcStats (player).getBounty(); + return player.getClass().getNpcStats (player).getBounty(); } std::string InterpreterContext::getCurrentCellName() const diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 620a0d0c94..b0d73253ff 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -142,7 +142,7 @@ namespace MWScript runtime.pop(); } - MWWorld::Class::get (ptr).lock (ptr, lockLevel); + ptr.getClass().lock (ptr, lockLevel); } }; @@ -155,7 +155,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWWorld::Class::get (ptr).unlock (ptr); + ptr.getClass().unlock (ptr); } }; @@ -345,7 +345,7 @@ namespace MWScript if(key < 0 || key > 32767 || *end != '\0') key = ESM::MagicEffect::effectStringToId(effect); - runtime.push(MWWorld::Class::get(ptr).getCreatureStats(ptr).getMagicEffects().get( + runtime.push(ptr.getClass().getCreatureStats(ptr).getMagicEffects().get( MWMechanics::EffectKey(key)).mMagnitude > 0); } }; @@ -389,7 +389,7 @@ namespace MWScript for (unsigned int i=0; igetCellRef().mSoul, soul)) @@ -424,7 +424,7 @@ namespace MWScript if (amount == 0) return; - MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); int toRemove = amount; @@ -457,7 +457,7 @@ namespace MWScript std::string soul = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) @@ -481,7 +481,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push(MWWorld::Class::get(ptr).getCreatureStats (ptr).getAttacked ()); + runtime.push(ptr.getClass().getCreatureStats (ptr).getAttacked ()); } }; @@ -522,7 +522,7 @@ namespace MWScript std::string id = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); - runtime.push(MWWorld::Class::get(ptr).getCreatureStats(ptr).getActiveSpells().isSpellActive(id)); + runtime.push(ptr.getClass().getCreatureStats(ptr).getActiveSpells().isSpellActive(id)); } }; @@ -621,7 +621,7 @@ namespace MWScript std::string objectID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWMechanics::CreatureStats &stats = MWWorld::Class::get(ptr).getCreatureStats(ptr); + MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); runtime.push(::Misc::StringUtils::ciEqual(objectID, stats.getLastHitObject())); } }; @@ -657,7 +657,7 @@ namespace MWScript { std::stringstream str; - const std::string script = MWWorld::Class::get(ptr).getScript(ptr); + const std::string script = ptr.getClass().getScript(ptr); if(script.empty()) str<< ptr.getCellRef().mRefID<<" ("< stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + MWMechanics::DynamicStat stat (ptr.getClass().getCreatureStats (ptr) .getDynamic (mIndex)); stat.setModified (value, 0); stat.setCurrent(value); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); + ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -222,18 +222,18 @@ namespace MWScript Interpreter::Type_Float diff = runtime[0].mFloat; runtime.pop(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent(); - MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + MWMechanics::DynamicStat stat (ptr.getClass().getCreatureStats (ptr) .getDynamic (mIndex)); stat.setModified (diff + stat.getModified(), 0); stat.setCurrent (diff + current); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); + ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -253,16 +253,16 @@ namespace MWScript Interpreter::Type_Float diff = runtime[0].mFloat; runtime.pop(); - MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent(); - MWMechanics::DynamicStat stat (MWWorld::Class::get (ptr).getCreatureStats (ptr) + MWMechanics::DynamicStat stat (ptr.getClass().getCreatureStats (ptr) .getDynamic (mIndex)); stat.setCurrent (diff + current); - MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); + ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat); } }; @@ -279,7 +279,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); Interpreter::Type_Float value = 0; @@ -327,7 +327,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWMechanics::NpcStats& stats = MWWorld::Class::get (ptr).getNpcStats (ptr); + MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats (ptr); MWWorld::LiveCellRef *ref = ptr.get(); @@ -386,7 +386,7 @@ namespace MWScript { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - runtime.push (static_cast (MWWorld::Class::get (player).getNpcStats (player).getBounty())); + runtime.push (static_cast (player.getClass().getNpcStats (player).getBounty())); } }; @@ -399,7 +399,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - MWWorld::Class::get (player).getNpcStats (player).setBounty(runtime[0].mFloat); + player.getClass().getNpcStats (player).setBounty(runtime[0].mFloat); runtime.pop(); } }; @@ -413,7 +413,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - MWWorld::Class::get (player).getNpcStats (player).setBounty(runtime[0].mFloat + MWWorld::Class::get (player).getNpcStats (player).getBounty()); + player.getClass().getNpcStats (player).setBounty(runtime[0].mFloat + player.getClass().getNpcStats (player).getBounty()); runtime.pop(); } }; @@ -433,7 +433,7 @@ namespace MWScript // make sure a spell with this ID actually exists. MWBase::Environment::get().getWorld()->getStore().get().find (id); - MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().add (id); + ptr.getClass().getCreatureStats (ptr).getSpells().add (id); } }; @@ -449,7 +449,7 @@ namespace MWScript std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().remove (id); + ptr.getClass().getCreatureStats (ptr).getSpells().remove (id); MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); @@ -473,7 +473,7 @@ namespace MWScript std::string spellid = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().removeEffects(spellid); + ptr.getClass().getCreatureStats (ptr).getActiveSpells().removeEffects(spellid); } }; @@ -489,7 +489,7 @@ namespace MWScript Interpreter::Type_Integer effectId = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().purgeEffect(effectId); + ptr.getClass().getCreatureStats (ptr).getActiveSpells().purgeEffect(effectId); } }; @@ -509,8 +509,8 @@ namespace MWScript Interpreter::Type_Integer value = 0; for (MWMechanics::Spells::TIterator iter ( - MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().begin()); - iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).getSpells().end(); ++iter) + ptr.getClass().getCreatureStats (ptr).getSpells().begin()); + iter!=ptr.getClass().getCreatureStats (ptr).getSpells().end(); ++iter) if (iter->first==id) { value = 1; @@ -544,9 +544,9 @@ namespace MWScript if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if(MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().find(factionID) == MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().end()) + if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) == player.getClass().getNpcStats(player).getFactionRanks().end()) { - MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] = 0; + player.getClass().getNpcStats(player).getFactionRanks()[factionID] = 0; } } } @@ -575,13 +575,13 @@ namespace MWScript if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if(MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().find(factionID) == MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().end()) + if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) == player.getClass().getNpcStats(player).getFactionRanks().end()) { - MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] = 0; + player.getClass().getNpcStats(player).getFactionRanks()[factionID] = 0; } else { - MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] = MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] +1; + player.getClass().getNpcStats(player).getFactionRanks()[factionID] = player.getClass().getNpcStats(player).getFactionRanks()[factionID] +1; } } } @@ -610,9 +610,9 @@ namespace MWScript if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if(MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().find(factionID) != MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().end()) + if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) != player.getClass().getNpcStats(player).getFactionRanks().end()) { - MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] = MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID] -1; + player.getClass().getNpcStats(player).getFactionRanks()[factionID] = player.getClass().getNpcStats(player).getFactionRanks()[factionID] -1; } } } @@ -635,22 +635,22 @@ namespace MWScript } else { - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) { factionID = ""; } else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } } ::Misc::StringUtils::toLower(factionID); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if(factionID!="") { - if(MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().find(factionID) != MWWorld::Class::get(player).getNpcStats(player).getFactionRanks().end()) + if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) != player.getClass().getNpcStats(player).getFactionRanks().end()) { - runtime.push(MWWorld::Class::get(player).getNpcStats(player).getFactionRanks()[factionID]); + runtime.push(player.getClass().getNpcStats(player).getFactionRanks()[factionID]); } else { @@ -676,8 +676,8 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition - (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition() + value); + ptr.getClass().getNpcStats (ptr).setBaseDisposition + (ptr.getClass().getNpcStats (ptr).getBaseDisposition() + value); } }; @@ -693,7 +693,7 @@ namespace MWScript Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition (value); + ptr.getClass().getNpcStats (ptr).setBaseDisposition (value); } }; @@ -739,8 +739,8 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) - factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty()) + factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first; } if (factionId.empty()) @@ -750,7 +750,7 @@ namespace MWScript MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); runtime.push ( - MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)); + player.getClass().getNpcStats (player).getFactionReputation (factionId)); } }; @@ -775,8 +775,8 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) - factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty()) + factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first; } if (factionId.empty()) @@ -785,7 +785,7 @@ namespace MWScript ::Misc::StringUtils::toLower (factionId); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value); + player.getClass().getNpcStats (player).setFactionReputation (factionId, value); } }; @@ -810,8 +810,8 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty()) - factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first; + if (!ptr.getClass().getNpcStats (ptr).getFactionRanks().empty()) + factionId = ptr.getClass().getNpcStats (ptr).getFactionRanks().begin()->first; } if (factionId.empty()) @@ -820,8 +820,8 @@ namespace MWScript ::Misc::StringUtils::toLower (factionId); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, - MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId)+ + player.getClass().getNpcStats (player).setFactionReputation (factionId, + player.getClass().getNpcStats (player).getFactionReputation (factionId)+ value); } }; @@ -835,7 +835,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (MWWorld::Class::get (ptr).getCreatureStats (ptr).hasCommonDisease()); + runtime.push (ptr.getClass().getCreatureStats (ptr).hasCommonDisease()); } }; @@ -848,7 +848,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (MWWorld::Class::get (ptr).getCreatureStats (ptr).hasBlightDisease()); + runtime.push (ptr.getClass().getCreatureStats (ptr).hasBlightDisease()); } }; @@ -880,7 +880,7 @@ namespace MWScript { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - runtime.push (MWWorld::Class::get(ptr).getNpcStats (ptr).getWerewolfKills ()); + runtime.push (ptr.getClass().getNpcStats (ptr).getWerewolfKills ()); } }; @@ -901,13 +901,13 @@ namespace MWScript } else { - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) { factionID = ""; } else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } } ::Misc::StringUtils::toLower(factionID); @@ -939,13 +939,13 @@ namespace MWScript else { MWWorld::Ptr ptr = R()(runtime); - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) { factionID = ""; } else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } } MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -972,13 +972,13 @@ namespace MWScript else { MWWorld::Ptr ptr = R()(runtime); - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) { factionID = ""; } else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } } MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -997,11 +997,11 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); std::string factionID = ""; - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) return; else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -1009,7 +1009,7 @@ namespace MWScript if (ptr == player) return; - std::map& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks (); + std::map& ranks = ptr.getClass().getNpcStats(ptr).getFactionRanks (); ranks[factionID] = ranks[factionID]+1; } }; @@ -1024,11 +1024,11 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); std::string factionID = ""; - if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) + if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) return; else { - factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; + factionID = ptr.getClass().getNpcStats(ptr).getFactionRanks().begin()->first; } MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -1036,7 +1036,7 @@ namespace MWScript if (ptr == player) return; - std::map& ranks = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks (); + std::map& ranks = ptr.getClass().getNpcStats(ptr).getFactionRanks (); ranks[factionID] = ranks[factionID]-1; } }; @@ -1051,10 +1051,10 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = - MWWorld::Class::get (ptr).getCreatureStats (ptr).hasDied(); + ptr.getClass().getCreatureStats (ptr).hasDied(); if (value) - MWWorld::Class::get (ptr).getCreatureStats (ptr).clearHasDied(); + ptr.getClass().getCreatureStats (ptr).clearHasDied(); runtime.push (value); } @@ -1070,7 +1070,7 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = - MWWorld::Class::get (ptr).getCreatureStats (ptr).getKnockedDownOneFrame(); + ptr.getClass().getCreatureStats (ptr).getKnockedDownOneFrame(); runtime.push (value); } @@ -1084,7 +1084,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); - runtime.push(MWWorld::Class::get(ptr).getNpcStats(ptr).isWerewolf()); + runtime.push(ptr.getClass().getNpcStats(ptr).isWerewolf()); } }; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index e4c1a26772..fb27e73f44 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -319,7 +319,7 @@ namespace MWScript } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); - MWWorld::Class::get(ptr).adjustPosition(ptr); + ptr.getClass().adjustPosition(ptr); } else { @@ -366,7 +366,7 @@ namespace MWScript zRot = zRot/60.; } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); - MWWorld::Class::get(ptr).adjustPosition(ptr); + ptr.getClass().adjustPosition(ptr); } }; diff --git a/apps/openmw/mwworld/actionapply.cpp b/apps/openmw/mwworld/actionapply.cpp index bd3e875484..6b12cc3e65 100644 --- a/apps/openmw/mwworld/actionapply.cpp +++ b/apps/openmw/mwworld/actionapply.cpp @@ -16,7 +16,7 @@ namespace MWWorld { MWBase::Environment::get().getWorld()->breakInvisibility(actor); - MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor); + getTarget().getClass().apply (getTarget(), mId, actor); } @@ -29,7 +29,7 @@ namespace MWWorld { MWBase::Environment::get().getWorld()->breakInvisibility(actor); - if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1) - MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType); + if (getTarget().getClass().apply (getTarget(), mId, actor) && mUsageType!=-1) + getTarget().getClass().skillUsageSucceeded (actor, mSkillIndex, mUsageType); } } diff --git a/apps/openmw/mwworld/actioneat.cpp b/apps/openmw/mwworld/actioneat.cpp index 020bdb0ff7..6609155236 100644 --- a/apps/openmw/mwworld/actioneat.cpp +++ b/apps/openmw/mwworld/actioneat.cpp @@ -20,10 +20,10 @@ namespace MWWorld getTarget().getContainerStore()->remove(getTarget(), 1, actor); // apply to actor - std::string id = Class::get (getTarget()).getId (getTarget()); + std::string id = getTarget().getClass().getId (getTarget()); - if (Class::get (actor).apply (actor, id, actor)) - Class::get (actor).skillUsageSucceeded (actor, ESM::Skill::Alchemy, 1); + if (actor.getClass().apply (actor, id, actor)) + actor.getClass().skillUsageSucceeded (actor, ESM::Skill::Alchemy, 1); } ActionEat::ActionEat (const MWWorld::Ptr& object) : Action (false, object) {} diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 2a1b7a3aa4..05677cdc7f 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -40,7 +40,7 @@ namespace MWWorld } // slots that this item can be equipped in - std::pair, bool> slots_ = MWWorld::Class::get(getTarget()).getEquipmentSlots(getTarget()); + std::pair, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget()); // retrieve ContainerStoreIterator to the item MWWorld::ContainerStoreIterator it = invStore.begin(); diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 60af3d9b9e..0a4e2d6c9c 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -47,7 +47,7 @@ namespace MWWorld } MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); + MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats (player); // Skill gain from books if (ref->mBase->mData.mSkillID >= 0 && ref->mBase->mData.mSkillID < ESM::Skill::Length diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index aa247f0b90..04d733e2c4 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -36,7 +36,7 @@ namespace MWWorld::Ptr container (&*iter, 0); MWWorld::Ptr ptr = - MWWorld::Class::get (container).getContainerStore (container).search (id); + container.getClass().getContainerStore (container).search (id); if (!ptr.isEmpty()) return ptr; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 951ba7865e..6629f84f91 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -323,7 +323,7 @@ namespace MWWorld if(!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) return boost::shared_ptr(new NullAction()); - if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Sound *sound = store.get().searchRandom("WolfItem"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 0b1eb857c8..b47028e01f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -325,12 +325,6 @@ namespace MWWorld static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. - static const Class& get (const Ptr& ptr) - { - return ptr.getClass(); - } - ///< If there is no class for this pointer, an exception is thrown. - static void registerClass (const std::string& key, boost::shared_ptr instance); virtual int getBaseGold(const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 8f2a566461..d816f993bd 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -142,8 +142,8 @@ void MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container) bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { - const MWWorld::Class& cls1 = MWWorld::Class::get(ptr1); - const MWWorld::Class& cls2 = MWWorld::Class::get(ptr2); + const MWWorld::Class& cls1 = ptr1.getClass(); + const MWWorld::Class& cls2 = ptr2.getClass(); if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().mRefID, ptr2.getCellRef().mRefID)) return false; @@ -226,14 +226,14 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.getCellRef().mPos.pos[1] = 0; item.getCellRef().mPos.pos[2] = 0; - std::string script = MWWorld::Class::get(item).getScript(item); + std::string script = item.getClass().getScript(item); if(script != "") { CellStore *cell; MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); - if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) + if(&(player.getClass().getContainerStore (player)) == this) { cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 7127c92f3f..78a2950304 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -129,7 +129,7 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite std::pair, bool> slots_; - slots_ = Class::get (*iterator).getEquipmentSlots (*iterator); + slots_ = iterator->getClass().getEquipmentSlots (*iterator); if (std::find (slots_.first.begin(), slots_.first.end(), slot)==slots_.first.end()) throw std::runtime_error ("invalid slot"); @@ -258,7 +258,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) } } - switch(MWWorld::Class::get (test).canBeEquipped (test, actor).first) + switch(test.getClass().canBeEquipped (test, actor).first) { case 0: continue; @@ -325,7 +325,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) if (*iter==end()) continue; - std::string enchantmentId = MWWorld::Class::get (**iter).getEnchantment (**iter); + std::string enchantmentId = (*iter)->getClass().getEnchantment (**iter); if (!enchantmentId.empty()) { @@ -441,7 +441,7 @@ bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { if (*iter != end() && (ptr1 == **iter || ptr2 == **iter)) { - bool stackWhenEquipped = MWWorld::Class::get(**iter).getEquipmentSlots(**iter).second; + bool stackWhenEquipped = (*iter)->getClass().getEquipmentSlots(**iter).second; if (!stackWhenEquipped) return false; } @@ -527,7 +527,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c if (actor.getRefData().getHandle() == "player") { // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared - const std::string& script = Class::get(*it).getScript(*it); + const std::string& script = it->getClass().getScript(*it); if (script != "") (*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0); @@ -579,7 +579,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito if (*iter==end()) continue; - std::string enchantmentId = MWWorld::Class::get (**iter).getEnchantment (**iter); + std::string enchantmentId = (*iter)->getClass().getEnchantment (**iter); if (enchantmentId.empty()) continue; diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index 844e2b18ba..8a671cea8c 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -36,10 +36,10 @@ namespace MWWorld::Ptr containerPtr (&*iter, cell); - MWWorld::ContainerStore& container = MWWorld::Class::get(containerPtr).getContainerStore(containerPtr); + MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr); for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3) { - std::string script = MWWorld::Class::get(*it3).getScript(*it3); + std::string script = it3->getClass().getScript(*it3); if(script != "") { MWWorld::Ptr item = *it3; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index ced952861e..039fce0caa 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -538,7 +538,7 @@ namespace MWWorld void PhysicsSystem::addObject (const Ptr& ptr, bool placeable) { - std::string mesh = MWWorld::Class::get(ptr).getModel(ptr); + std::string mesh = ptr.getClass().getModel(ptr); Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); handleToMesh[node->getName()] = mesh; OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody( @@ -550,7 +550,7 @@ namespace MWWorld void PhysicsSystem::addActor (const Ptr& ptr) { - std::string mesh = MWWorld::Class::get(ptr).getModel(ptr); + std::string mesh = ptr.getClass().getModel(ptr); Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); //TODO:optimize this. Searching the std::map isn't very efficient i think. mEngine->addCharacter(node->getName(), mesh, node->getPosition(), node->getScale().x, node->getOrientation()); @@ -651,7 +651,7 @@ namespace MWWorld bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max) { - std::string model = MWWorld::Class::get(ptr).getModel(ptr); + std::string model = ptr.getClass().getModel(ptr); if (model.empty()) { return false; } diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 1f994d013d..5ca8f29525 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -75,7 +75,7 @@ namespace MWWorld void Player::setDrawState (MWMechanics::DrawState_ state) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get(ptr).getNpcStats(ptr).setDrawState (state); + ptr.getClass().getNpcStats(ptr).setDrawState (state); } bool Player::getAutoMove() const @@ -94,13 +94,13 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; + ptr.getClass().getMovementSettings (ptr).mPosition[1] = value; } void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; + ptr.getClass().getMovementSettings (ptr).mPosition[0] = value; } void Player::setForwardBackward (int value) @@ -112,13 +112,13 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; + ptr.getClass().getMovementSettings (ptr).mPosition[1] = value; } void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; + ptr.getClass().getMovementSettings (ptr).mPosition[2] = value; } void Player::setRunState(bool run) @@ -136,23 +136,23 @@ namespace MWWorld void Player::yaw(float yaw) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[2] += yaw; + ptr.getClass().getMovementSettings(ptr).mRotation[2] += yaw; } void Player::pitch(float pitch) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[0] += pitch; + ptr.getClass().getMovementSettings(ptr).mRotation[0] += pitch; } void Player::roll(float roll) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] += roll; + ptr.getClass().getMovementSettings(ptr).mRotation[1] += roll; } MWMechanics::DrawState_ Player::getDrawState() { MWWorld::Ptr ptr = getPlayer(); - return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState(); + return ptr.getClass().getNpcStats(ptr).getDrawState(); } bool Player::wasTeleported() const diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 25ee0c2e83..122a6f9bf5 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -198,7 +198,7 @@ namespace MWWorld float z = Ogre::Radian(pos.rot[2]).valueDegrees(); world->rotateObject(player, x, y, z); - MWWorld::Class::get(player).adjustPosition(player); + player.getClass().adjustPosition(player); } MWBase::MechanicsManager *mechMgr = @@ -399,7 +399,7 @@ namespace MWWorld float z = Ogre::Radian(position.rot[2]).valueDegrees(); world->rotateObject(world->getPlayerPtr(), x, y, z); - MWWorld::Class::get(world->getPlayerPtr()).adjustPosition(world->getPlayerPtr()); + world->getPlayerPtr().getClass().adjustPosition(world->getPlayerPtr()); world->getFader()->fadeIn(0.5f); return; } @@ -482,7 +482,7 @@ namespace MWWorld void Scene::addObjectToScene (const Ptr& ptr) { mRendering.addObject(ptr); - MWWorld::Class::get(ptr).insertObject(ptr, *mPhysics); + ptr.getClass().insertObject(ptr, *mPhysics); MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true); MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 9b5f9d9d3d..5a83a5bc74 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -537,8 +537,8 @@ namespace MWWorld return ptr; } - Ptr ptr = Class::get (mPlayer->getPlayer()). - getContainerStore (mPlayer->getPlayer()).search (lowerCaseName); + Ptr ptr = mPlayer->getPlayer().getClass() + .getContainerStore(mPlayer->getPlayer()).search(lowerCaseName); if (!ptr.isEmpty()) return ptr; @@ -589,10 +589,10 @@ namespace MWWorld reference.getTypeName()==typeid (ESM::NPC).name() || reference.getTypeName()==typeid (ESM::Creature).name()) { - MWWorld::ContainerStore& container = MWWorld::Class::get(reference).getContainerStore(reference); + MWWorld::ContainerStore& container = reference.getClass().getContainerStore(reference); for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) { - std::string script = MWWorld::Class::get(*it).getScript(*it); + std::string script = it->getClass().getScript(*it); if(script != "") { MWWorld::Ptr item = *it; @@ -624,10 +624,10 @@ namespace MWWorld reference.getTypeName()==typeid (ESM::NPC).name() || reference.getTypeName()==typeid (ESM::Creature).name()) { - MWWorld::ContainerStore& container = MWWorld::Class::get(reference).getContainerStore(reference); + MWWorld::ContainerStore& container = reference.getClass().getContainerStore(reference); for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) { - std::string script = MWWorld::Class::get(*it).getScript(*it); + std::string script = it->getClass().getScript(*it); if(script != "") { MWWorld::Ptr item = *it; @@ -976,14 +976,14 @@ namespace MWWorld removeContainerScripts (ptr); haveToMove = false; - MWWorld::Ptr newPtr = MWWorld::Class::get(ptr) + MWWorld::Ptr newPtr = ptr.getClass() .copyToCell(ptr, *newCell); newPtr.getRefData().setBaseNode(0); } else { MWWorld::Ptr copy = - MWWorld::Class::get(ptr).copyToCell(ptr, *newCell, pos); + ptr.getClass().copyToCell(ptr, *newCell, pos); mRendering->updateObjectCell(ptr, copy); MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy); @@ -992,7 +992,7 @@ namespace MWWorld mechMgr->updateCell(ptr, copy); std::string script = - MWWorld::Class::get(ptr).getScript(ptr); + ptr.getClass().getScript(ptr); if (!script.empty()) { mLocalScripts.remove(ptr); @@ -1035,7 +1035,7 @@ namespace MWWorld void World::scaleObject (const Ptr& ptr, float scale) { ptr.getCellRef().mScale = scale; - MWWorld::Class::get(ptr).adjustScale(ptr,scale); + ptr.getClass().adjustScale(ptr,scale); if(ptr.getRefData().getBaseNode() == 0) return; @@ -1062,7 +1062,7 @@ namespace MWWorld objRot[2] = rot.z; } - if(Class::get(ptr).isActor()) + if(ptr.getClass().isActor()) { /* HACK? Actors shouldn't really be rotating around X (or Y), but * currently it's done so for rotating the camera, which needs @@ -1580,7 +1580,7 @@ namespace MWWorld void World::PCDropped (const Ptr& item) { - std::string script = MWWorld::Class::get(item).getScript(item); + std::string script = item.getClass().getScript(item); // Set OnPCDrop Variable on item's script, if it has a script with that variable declared if(script != "") @@ -1648,13 +1648,13 @@ namespace MWWorld } MWWorld::Ptr dropped = - MWWorld::Class::get(object).copyToCell(object, *cell, pos); + object.getClass().copyToCell(object, *cell, pos); if (mWorldScene->isCellActive(*cell)) { if (dropped.getRefData().isEnabled()) { mWorldScene->addObjectToScene(dropped); } - std::string script = MWWorld::Class::get(dropped).getScript(dropped); + std::string script = dropped.getClass().getScript(dropped); if (!script.empty()) { mLocalScripts.add(script, dropped); } @@ -1863,7 +1863,7 @@ namespace MWWorld if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos)) return 2; if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) || - Class::get(player).getNpcStats(player).isWerewolf()) + player.getClass().getNpcStats(player).isWerewolf()) return 1; return 0; @@ -2107,7 +2107,7 @@ namespace MWWorld void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf) { - MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor); + MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor); // The actor does not have to change state if (npcStats.isWerewolf() == werewolf) @@ -2119,7 +2119,7 @@ namespace MWWorld // bones that do not even exist with the werewolf object root. // Therefore, make sure to unequip everything at once, and only fire the change event // (which will rebuild the animation parts) afterwards. unequipAll will do this for us. - MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); + MWWorld::InventoryStore& invStore = actor.getClass().getInventoryStore(actor); invStore.unequipAll(actor); if(werewolf) @@ -2158,7 +2158,7 @@ namespace MWWorld void World::applyWerewolfAcrobatics(const Ptr &actor) { const Store &gmst = getStore().get(); - MWMechanics::NpcStats &stats = Class::get(actor).getNpcStats(actor); + MWMechanics::NpcStats &stats = actor.getClass().getNpcStats(actor); stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getFloat()); } From e51300989cbb8ff0bb341da67bd7147c0cd5e3f9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 22:15:20 +0200 Subject: [PATCH 377/545] Handle NiBSPArrayController as alias for NiParticleSystemController The differences (if any) are unknown. NiBSPArrayController is used by the Atronach_Fire.nif model. Its particles are now visible, but they don't look right yet. Need to handle NiAutoNormalParticlesData? --- components/nifogre/ogrenifloader.cpp | 3 ++- components/nifogre/skeleton.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index ce82446194..36d7508214 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -863,7 +863,8 @@ class NIFObjectLoader Nif::ControllerPtr ctrl = partnode->controller; while(!ctrl.empty()) { - if(ctrl->recType == Nif::RC_NiParticleSystemController && ctrl->flags & Nif::NiNode::ControllerFlag_Active) + if((ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController) + && ctrl->flags & Nif::NiNode::ControllerFlag_Active) { const Nif::NiParticleSystemController *partctrl = static_cast(ctrl.getPtr()); diff --git a/components/nifogre/skeleton.cpp b/components/nifogre/skeleton.cpp index c0482cf5e3..26647e595d 100644 --- a/components/nifogre/skeleton.cpp +++ b/components/nifogre/skeleton.cpp @@ -42,6 +42,7 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, while(!ctrl.empty()) { if(!(ctrl->recType == Nif::RC_NiParticleSystemController || + ctrl->recType == Nif::RC_NiBSPArrayController || ctrl->recType == Nif::RC_NiVisController || ctrl->recType == Nif::RC_NiUVController || ctrl->recType == Nif::RC_NiKeyframeController || From df8e095c83ac2655cee0082d3f06c8419fc29e24 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 23:27:54 +0200 Subject: [PATCH 378/545] Small cleanup --- apps/openmw/mwdialogue/filter.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 5bdf80593b..863a0f2ffc 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -264,15 +264,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con { MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); - int sum = 0; - - std::string name = select.getName(); - - for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, name)) - sum += iter->getRefData().getCount(); - - return sum; + return store.count(select.getName()); } case SelectWrapper::Function_Dead: From a2f156be8e506503628c424e695ede9834f234b3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 22 May 2014 23:33:34 +0200 Subject: [PATCH 379/545] Prevent magic bolts from colliding with their caster --- apps/openmw/mwworld/projectilemanager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 266b566f70..bf0fb75795 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -152,6 +152,10 @@ namespace MWWorld MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second); MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); + + if (!obstacle.isEmpty() && obstacle == caster) + continue; + if (caster.isEmpty()) caster = obstacle; From f4334da42ec0076c073aed1a3aec6a4a17f1ba5a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 May 2014 09:32:34 +0200 Subject: [PATCH 380/545] added changed reference tracking for cells --- apps/opencs/model/world/cell.hpp | 7 ++-- apps/opencs/model/world/columnimp.hpp | 40 +++++++++++++++++++++++ apps/opencs/model/world/refcollection.cpp | 6 ++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/cell.hpp b/apps/opencs/model/world/cell.hpp index a47dbf45df..8a2781590d 100644 --- a/apps/opencs/model/world/cell.hpp +++ b/apps/opencs/model/world/cell.hpp @@ -1,7 +1,7 @@ #ifndef CSM_WOLRD_CELL_H #define CSM_WOLRD_CELL_H -#include +#include #include #include @@ -16,8 +16,11 @@ namespace CSMWorld { std::string mId; - void load (ESM::ESMReader &esm); + /// These are the references modified by the edited content file. These are stored in + /// mModified only. + std::set mTouchedRefs; + void load (ESM::ESMReader &esm); }; } diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6976b454d9..6b276d1517 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -10,6 +10,7 @@ #include "columnbase.hpp" #include "columns.hpp" #include "info.hpp" +#include "cell.hpp" namespace CSMWorld { @@ -87,6 +88,45 @@ namespace CSMWorld } }; + /// \brief Specialisation that takes care of the modified reference tracking + template<> + struct RecordStateColumn : public Column + { + RecordStateColumn() + : Column (Columns::ColumnId_Modification, ColumnBase::Display_RecordState) + {} + + virtual QVariant get (const Record& record) const + { + if (record.mState==Record::State_Erased) + return static_cast (Record::State_Deleted); + + if (!record.mModified.mTouchedRefs.empty() && + !record.mState==Record::State_Deleted && + !record.mState==Record::State_ModifiedOnly) + { + static_cast (Record::State_Modified); + } + + return static_cast (record.mState); + } + + virtual void set (Record& record, const QVariant& data) + { + record.mState = static_cast (data.toInt()); + } + + virtual bool isEditable() const + { + return true; + } + + virtual bool isUserEditable() const + { + return false; + } + }; + template struct FixedRecordTypeColumn : public Column { diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 3a60c49341..1cfa4df766 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -53,6 +53,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool } else { + cell.mModified.mTouchedRefs.insert (Misc::StringUtils::lowerCase ( + mCells.getId (cellIndex))); record.mState = RecordBase::State_Deleted; setRecord (index, record); } @@ -60,6 +62,10 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } + if (!base) + cell.mModified.mTouchedRefs.insert (Misc::StringUtils::lowerCase ( + mCells.getId (cellIndex))); + if (iter==cache.end()) { // new reference From 3718847ffc0c77db9d979d1a4aed7f351c92a96e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 23 May 2014 21:07:01 +1000 Subject: [PATCH 381/545] Disable video for Windows until the crash issues are fixed. --- apps/openmw/mwrender/videoplayer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 82400aac43..b1519b9d2c 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -1080,6 +1080,11 @@ VideoPlayer::~VideoPlayer() void VideoPlayer::playVideo(const std::string &resourceName) { +#ifdef WIN32 + // FIXME: Need FFmpeg FLTP audio support for BIK video format + std::cout<<"Temporarily disabled, did not play \""+resourceName+"\""< Date: Fri, 23 May 2014 21:55:47 +1000 Subject: [PATCH 382/545] Enable video but without sound. --- apps/openmw/mwrender/videoplayer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index b1519b9d2c..9fd1cee961 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -970,8 +970,13 @@ void VideoState::init(const std::string& resourceName) MWBase::Environment::get().getSoundManager()->pauseSounds(); this->external_clock_base = av_gettime(); +#ifdef WIN32 + // FIXME: Need FFmpeg FLTP audio support for BIK video format + std::cout<<"Sound temporarily disabled for \""+resourceName+"\""<= 0) this->stream_open(audio_index, this->format_ctx); +#endif if(video_index >= 0) { this->stream_open(video_index, this->format_ctx); @@ -1080,11 +1085,6 @@ VideoPlayer::~VideoPlayer() void VideoPlayer::playVideo(const std::string &resourceName) { -#ifdef WIN32 - // FIXME: Need FFmpeg FLTP audio support for BIK video format - std::cout<<"Temporarily disabled, did not play \""+resourceName+"\""< Date: Fri, 23 May 2014 08:41:49 -0400 Subject: [PATCH 383/545] missing #include in mwiniimporter missing #include in mwiniimporter/main.cpp --- apps/mwiniimporter/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index c2408a5541..c10103cd62 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -1,6 +1,7 @@ #include "importer.hpp" #include +#include #include #include From a7d525245ce81c583a8db943dd0df77fbea8b277 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 May 2014 16:07:02 +0200 Subject: [PATCH 384/545] Fix missing include --- apps/openmw/mwworld/projectilemanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index bf0fb75795..12cca27545 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -1,6 +1,7 @@ #include "projectilemanager.hpp" #include +#include #include From f09c8ddc9e3ba3258b3af1faafdb0800bd8ebfc2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 May 2014 16:39:42 +0200 Subject: [PATCH 385/545] Remove a pointless assert --- apps/openmw/mwmechanics/creaturestats.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 3648877fdd..3ef6ff4df9 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -102,7 +102,6 @@ namespace MWMechanics Stat CreatureStats::getAiSetting (AiSetting index) const { - assert (index>=0 && index<4); return mAiSettings[index]; } @@ -220,7 +219,6 @@ namespace MWMechanics void CreatureStats::setAiSetting (AiSetting index, Stat value) { - assert (index>=0 && index<4); mAiSettings[index] = value; } From 1d8da957564b4dd6823935961e7c58ecdfdef0fc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 May 2014 14:47:51 +0200 Subject: [PATCH 386/545] Warning fix --- apps/openmw/mwrender/localmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0d32dd0ef0..2b0323675e 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -353,7 +353,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture& Ogre::Image image; image.load(stream, "tga"); - if (image.getWidth() != sFogOfWarResolution || image.getHeight() != sFogOfWarResolution) + if (int(image.getWidth()) != sFogOfWarResolution || int(image.getHeight()) != sFogOfWarResolution) throw std::runtime_error("fog texture size mismatch"); std::string texName = texturePrefix + "_fog"; From a05c8fd3ceefa0d0f0ff287023eb332217552315 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 May 2014 14:48:37 +0200 Subject: [PATCH 387/545] Make applyEnchantment return the record ID instead of modifying Ptr --- apps/openmw/mwclass/armor.cpp | 5 ++--- apps/openmw/mwclass/armor.hpp | 3 ++- apps/openmw/mwclass/book.cpp | 5 ++--- apps/openmw/mwclass/book.hpp | 3 ++- apps/openmw/mwclass/clothing.cpp | 5 ++--- apps/openmw/mwclass/clothing.hpp | 3 ++- apps/openmw/mwclass/weapon.cpp | 5 ++--- apps/openmw/mwclass/weapon.hpp | 3 ++- apps/openmw/mwmechanics/enchanting.cpp | 10 ++-------- apps/openmw/mwmechanics/enchanting.hpp | 1 - apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 3 ++- 12 files changed, 21 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 26d1cab6d2..d7dae97a5b 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -272,7 +272,7 @@ namespace MWClass return ref->mBase->mEnchant; } - void Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -283,8 +283,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - ref->mBase = record; - ref->mRef.mRefID = record->mId; + return record->mId; } std::pair Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 17cfca4534..e9164f920b 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -67,7 +67,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. virtual std::pair canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. \n diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 183d91ca1f..338a7ba0d7 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -159,7 +159,7 @@ namespace MWClass return ref->mBase->mEnchant; } - void Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -171,8 +171,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - ref->mBase = record; - ref->mRef.mRefID = record->mId; + return record->mId; } boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 79b823fa9f..b60ef41d64 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -51,7 +51,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index a174f69a77..f596f60deb 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -215,7 +215,7 @@ namespace MWClass return ref->mBase->mEnchant; } - void Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -226,8 +226,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - ref->mBase = record; - ref->mRef.mRefID = record->mId; + return record->mId; } std::pair Clothing::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index a73b2c1907..052928238e 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,7 +59,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. virtual std::pair canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 146251ca29..5edf22b008 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -372,7 +372,7 @@ namespace MWClass return ref->mBase->mEnchant; } - void Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -383,8 +383,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - ref->mBase = record; - ref->mRef.mRefID = record->mId; + return record->mId; } std::pair Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index db44cd2b71..97ee102911 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -68,7 +68,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. virtual std::pair canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 23246c2945..9c5c9dbb9d 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -20,12 +20,10 @@ namespace MWMechanics if(!itemEmpty()) { mObjectType = mOldItemPtr.getTypeName(); - mOldItemId = mOldItemPtr.getCellRef().mRefID; } else { mObjectType=""; - mOldItemId=""; } } @@ -78,17 +76,13 @@ namespace MWMechanics enchantment.mData.mCost = getEnchantPoints(); enchantment.mEffects = mEffectList; - // Create a new item - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId, 1); - const MWWorld::Ptr& newItemPtr = ref.getPtr(); - // Apply the enchantment const ESM::Enchantment *enchantmentPtr = MWBase::Environment::get().getWorld()->createRecord (enchantment); - newItemPtr.getClass().applyEnchantment(newItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName); + std::string newItemId = mOldItemPtr.getClass().applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName); // Add the new item to player inventory and remove the old one store.remove(mOldItemPtr, 1, player); - store.add(newItemPtr, 1, player); + store.add(newItemId, 1, player); if(!mSelfEnchanting) payForEnchantment(); diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index ae0b25a4a2..01ca1e0e1d 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -21,7 +21,6 @@ namespace MWMechanics std::string mNewItemName; std::string mObjectType; - std::string mOldItemId; public: Enchanting(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 6629f84f91..100e758f24 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -304,7 +304,7 @@ namespace MWWorld return ""; } - void Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { throw std::runtime_error ("class can't be enchanted"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index b47028e01f..54cea9ab01 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -278,7 +278,8 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; - virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. virtual std::pair canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. From 56881cb7c91e956831a42340528530f58f8e4456 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sat, 24 May 2014 23:05:30 +0400 Subject: [PATCH 388/545] fix bugs in aisequence::execute --- apps/openmw/mwmechanics/aisequence.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 980a23a3ed..6d2c15549f 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -137,7 +137,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) float nearestDist = std::numeric_limits::max(); Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for(std::list::iterator it = mPackages.begin(); it != mPackages.end();) { if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; @@ -147,7 +147,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) if (target.isEmpty()) { delete *it; - mPackages.erase(it++); + it = mPackages.erase(it); } else { @@ -159,20 +159,26 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) nearestDist = distTo; itActualCombat = it; } + ++it; } } - // all targets disappeared - if (nearestDist == std::numeric_limits::max()) + if (!mPackages.empty()) + { + if (nearestDist < std::numeric_limits::max() && mPackages.begin() != itActualCombat) + { + // move combat package with nearest target to the front + mPackages.splice(mPackages.begin(), mPackages, itActualCombat); + } + + package = mPackages.front(); + mLastAiPackage = package->getTypeId(); + } + else { mDone = true; return; } - else if (mPackages.begin() != itActualCombat) - { - // move combat package with nearest target to the front - mPackages.splice(mPackages.begin(), mPackages, itActualCombat); - } } if (package->execute (actor,duration)) From 4f94a31b5422545a8ed7b76920c132192a9c5a9d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 25 May 2014 07:50:19 +1000 Subject: [PATCH 389/545] Fix crash starting a new game. --- apps/openmw/mwscript/cellextensions.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 825d62efb5..ac175634bd 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -88,6 +88,12 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + runtime.push (0); + return; + } + bool interior = !MWBase::Environment::get().getWorld()->getPlayerPtr().getCell()->getCell()->isExterior(); From d2794165bac7e4993510d1b9bf95f90fe7312508 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 25 May 2014 18:56:50 +1000 Subject: [PATCH 390/545] Disable binkaudio sound for FFmpeg libavocdec versions below 54.55.xxx (Windows x64) and 54.10.xxx (Windows 32bit). Later versions are all allowed, but due to sample formats there will be no sound and this message will be shown on the console "Sound Error: Unsupported sample format: fltp" --- apps/openmw/mwrender/videoplayer.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 82400aac43..fe97d77d4c 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -50,6 +50,29 @@ extern "C" #endif } +#ifdef _WIN32 + // Decide whether to play binkaudio. + #include + // libavcodec versions 54.10.100 (or maybe earlier) to 54.54.100 potentially crashes Windows 64bit. + // From version 54.56 or higher, there's no sound due to the encoding format changing from S16 to FLTP + // (see https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d and + // http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=3049d5b9b32845c86aa5588bb3352bdeb2edfdb2;hp=43c6b45a53a186a187f7266e4d6bd3c2620519f1), + // but does not crash (or at least no known crash). + #if (LIBAVCODEC_VERSION_MAJOR > 54) + #define FFMPEG_PLAY_BINKAUDIO + #else + #ifdef _WIN64 + #if ((LIBAVCODEC_VERSION_MAJOR == 54) && (LIBAVCODEC_VERSION_MINOR >= 55)) + #define FFMPEG_PLAY_BINKAUDIO + #endif + #else + #if ((LIBAVCODEC_VERSION_MAJOR == 54) && (LIBAVCODEC_VERSION_MINOR >= 10)) + #define FFMPEG_PLAY_BINKAUDIO + #endif + #endif + #endif +#endif + #define MAX_AUDIOQ_SIZE (5 * 16 * 1024) #define MAX_VIDEOQ_SIZE (5 * 256 * 1024) #define AV_SYNC_THRESHOLD 0.01 @@ -970,8 +993,12 @@ void VideoState::init(const std::string& resourceName) MWBase::Environment::get().getSoundManager()->pauseSounds(); this->external_clock_base = av_gettime(); +#if !defined(_WIN32) || defined(FFMPEG_PLAY_BINKAUDIO) if(audio_index >= 0) this->stream_open(audio_index, this->format_ctx); +#else + std::cout<<"FFmpeg sound disabled for \""+resourceName+"\""<= 0) { this->stream_open(video_index, this->format_ctx); From c62187bd555e3bcdef232c5c3e1c949809b2e5ca Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 25 May 2014 13:31:46 +0400 Subject: [PATCH 391/545] fix bug at http://bugs.openmw.org/issues/1155 Though it still can happen sometimes but not in such stupid manner. --- apps/openmw/mwmechanics/aicombat.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 1027cc48a7..9fe92f8070 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -330,7 +330,7 @@ namespace MWMechanics bool isStuck = false; float speed = 0.0f; - if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f) + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) * tReaction / 2) isStuck = true; mLastPos = pos; @@ -397,14 +397,10 @@ namespace MWMechanics { bool preferShortcut = false; bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); - - if(mReadyToAttack) isStuck = false; // check if shortcut is available - if(!isStuck - && (!mForceNoShortcut - || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) - && inLOS) + if(inLOS && (!isStuck || mReadyToAttack) + && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) { if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed @@ -467,7 +463,7 @@ namespace MWMechanics mReadyToAttack = false; } - if(distToTarget > rangeAttack && !distantCombat) + if(!isStuck && distToTarget > rangeAttack && !distantCombat) { //special run attack; it shouldn't affect melee combat tactics if(actorCls.getMovementSettings(actor).mPosition[1] == 1) From 039398c8aeecc54b627d6294b6c8e11c9abda133 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 May 2014 14:13:07 +0200 Subject: [PATCH 392/545] Basic RefData and CellRef change tracking Wrapped item charge handling in getItemHealth function --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwclass/activator.cpp | 4 +- apps/openmw/mwclass/apparatus.cpp | 4 +- apps/openmw/mwclass/armor.cpp | 15 +- apps/openmw/mwclass/book.cpp | 4 +- apps/openmw/mwclass/clothing.cpp | 6 +- apps/openmw/mwclass/container.cpp | 34 ++-- apps/openmw/mwclass/creature.cpp | 34 ++-- apps/openmw/mwclass/creaturelevlist.cpp | 4 +- apps/openmw/mwclass/door.cpp | 42 ++-- apps/openmw/mwclass/ingredient.cpp | 4 +- apps/openmw/mwclass/light.cpp | 4 +- apps/openmw/mwclass/lockpick.cpp | 11 +- apps/openmw/mwclass/misc.cpp | 37 ++-- apps/openmw/mwclass/npc.cpp | 47 ++--- apps/openmw/mwclass/potion.cpp | 4 +- apps/openmw/mwclass/probe.cpp | 11 +- apps/openmw/mwclass/repair.cpp | 11 +- apps/openmw/mwclass/weapon.cpp | 15 +- apps/openmw/mwgui/console.cpp | 2 +- apps/openmw/mwgui/enchantingdialog.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 2 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 4 +- apps/openmw/mwgui/inventorywindow.cpp | 6 +- apps/openmw/mwgui/merchantrepair.cpp | 4 +- apps/openmw/mwgui/pickpocketitemmodel.cpp | 4 +- apps/openmw/mwgui/quickkeysmenu.cpp | 11 +- apps/openmw/mwgui/recharge.cpp | 14 +- apps/openmw/mwgui/repair.cpp | 4 +- apps/openmw/mwgui/sortfilteritemmodel.cpp | 2 +- apps/openmw/mwgui/spellwindow.cpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 2 +- apps/openmw/mwgui/tradeitemmodel.cpp | 6 +- apps/openmw/mwgui/tradewindow.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 8 +- apps/openmw/mwmechanics/actors.cpp | 22 +-- apps/openmw/mwmechanics/aiavoiddoor.cpp | 5 - apps/openmw/mwmechanics/aiavoiddoor.hpp | 3 - apps/openmw/mwmechanics/aicombat.cpp | 4 +- apps/openmw/mwmechanics/aipackage.cpp | 2 +- apps/openmw/mwmechanics/combat.cpp | 9 +- apps/openmw/mwmechanics/enchanting.cpp | 4 +- .../mwmechanics/mechanicsmanagerimp.cpp | 8 +- apps/openmw/mwmechanics/obstacle.cpp | 2 +- apps/openmw/mwmechanics/repair.cpp | 14 +- apps/openmw/mwmechanics/security.cpp | 26 +-- apps/openmw/mwmechanics/spellcasting.cpp | 22 +-- apps/openmw/mwrender/actors.cpp | 4 +- apps/openmw/mwrender/animation.cpp | 6 +- apps/openmw/mwrender/objects.cpp | 4 +- apps/openmw/mwscript/cellextensions.cpp | 5 + apps/openmw/mwscript/containerextensions.cpp | 8 +- apps/openmw/mwscript/miscextensions.cpp | 16 +- .../mwscript/transformationextensions.cpp | 26 +-- apps/openmw/mwworld/actiontrap.cpp | 2 +- apps/openmw/mwworld/cellref.cpp | 185 ++++++++++++++++++ apps/openmw/mwworld/cellref.hpp | 99 ++++++++++ apps/openmw/mwworld/cellreflist.hpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 14 +- apps/openmw/mwworld/class.cpp | 8 + apps/openmw/mwworld/class.hpp | 5 +- apps/openmw/mwworld/containerstore.cpp | 60 +++--- apps/openmw/mwworld/inventorystore.cpp | 22 +-- apps/openmw/mwworld/livecellref.cpp | 4 +- apps/openmw/mwworld/livecellref.hpp | 8 +- apps/openmw/mwworld/manualref.hpp | 31 ++- apps/openmw/mwworld/physicssystem.cpp | 2 +- apps/openmw/mwworld/player.cpp | 6 +- apps/openmw/mwworld/projectilemanager.cpp | 8 +- apps/openmw/mwworld/ptr.cpp | 2 +- apps/openmw/mwworld/ptr.hpp | 2 +- apps/openmw/mwworld/refdata.cpp | 24 ++- apps/openmw/mwworld/refdata.hpp | 5 + apps/openmw/mwworld/scene.cpp | 12 +- apps/openmw/mwworld/worldimp.cpp | 32 +-- components/esm/cellref.cpp | 2 +- components/esm/cellref.hpp | 22 ++- components/esm/loadcell.cpp | 6 +- components/esm/loadcell.hpp | 6 +- 79 files changed, 720 insertions(+), 407 deletions(-) create mode 100644 apps/openmw/mwworld/cellref.cpp create mode 100644 apps/openmw/mwworld/cellref.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9e959a986d..8496b47a4a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwworld cells localscripts customdata weather inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor - contentloader esmloader omwloader actiontrap cellreflist projectilemanager + contentloader esmloader omwloader actiontrap cellreflist projectilemanager cellref ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index fe9368b446..043aadd359 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -97,8 +97,8 @@ namespace MWClass std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 8580d61ce0..947a9cb948 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -127,8 +127,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.text = text; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index d7dae97a5b..825b14978f 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -168,10 +168,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().mCharge == -1) - return ref->mBase->mData.mValue; - else - return ref->mBase->mData.mValue * (static_cast(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr)); + return ref->mBase->mData.mValue * (static_cast(getItemHealth(ptr)) / getItemMaxHealth(ptr)); } void Armor::registerSelf() @@ -242,7 +239,7 @@ namespace MWClass text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor); - int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth; + int remainingHealth = getItemHealth(ptr); text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); @@ -250,14 +247,14 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; + info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); info.text = text; @@ -290,7 +287,7 @@ namespace MWClass { MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); - if (ptr.getCellRef().mCharge == 0) + if (ptr.getCellRef().getCharge() == 0) return std::make_pair(0, "#{sInventoryMessage1}"); // slots that this item can be equipped in diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 338a7ba0d7..0cc2e60207 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -139,8 +139,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index f596f60deb..c0362188b8 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -193,14 +193,14 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; + info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); info.text = text; diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 62734c03de..9498ea52df 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -53,7 +53,7 @@ namespace MWClass ptr.get(); data->mContainerStore.fill( - ref->mBase->mInventory, ptr.getCellRef().mOwner, ptr.getCellRef().mFaction, MWBase::Environment::get().getWorld()->getStore()); + ref->mBase->mInventory, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), MWBase::Environment::get().getWorld()->getStore()); // store ptr.getRefData().setCustomData (data.release()); @@ -75,7 +75,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; MWWorld::ContainerStore& store = getContainerStore(ptr); - store.restock(list, ptr, ptr.getCellRef().mOwner, ptr.getCellRef().mFaction); + store.restock(list, ptr, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction()); } void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -129,16 +129,16 @@ namespace MWClass MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player); - bool needKey = ptr.getCellRef().mLockLevel > 0; + bool needKey = ptr.getCellRef().getLockLevel() > 0; bool hasKey = false; std::string keyName; // make key id lowercase - std::string keyId = ptr.getCellRef().mKey; + std::string keyId = ptr.getCellRef().getKey(); Misc::StringUtils::toLower(keyId); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - std::string refId = it->getCellRef().mRefID; + std::string refId = it->getCellRef().getRefId(); Misc::StringUtils::toLower(refId); if (refId == keyId) { @@ -152,13 +152,13 @@ namespace MWClass MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); unlock(ptr); // using a key disarms the trap - ptr.getCellRef().mTrap = ""; + ptr.getCellRef().setTrap(""); } if (!needKey || hasKey) { - if(ptr.getCellRef().mTrap.empty()) + if(ptr.getCellRef().getTrap().empty()) { boost::shared_ptr action (new MWWorld::ActionOpen(ptr)); return action; @@ -166,7 +166,7 @@ namespace MWClass else { // Activate trap - boost::shared_ptr action(new MWWorld::ActionTrap(actor, ptr.getCellRef().mTrap, ptr)); + boost::shared_ptr action(new MWWorld::ActionTrap(actor, ptr.getCellRef().getTrap(), ptr)); action->setSound(trapActivationSound); return action; } @@ -227,16 +227,16 @@ namespace MWClass info.caption = ref->mBase->mName; std::string text; - if (ref->mRef.mLockLevel > 0) - text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); - else if (ref->mRef.mLockLevel < 0) + if (ptr.getCellRef().getLockLevel() > 0) + text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel()); + else if (ptr.getCellRef().getLockLevel() < 0) text += "\n#{sUnlocked}"; - if (ref->mRef.mTrap != "") + if (ptr.getCellRef().getTrap() != "") text += "\n#{sTrapped}"; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } @@ -261,14 +261,14 @@ namespace MWClass void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const { if(lockLevel!=0) - ptr.getCellRef().mLockLevel = abs(lockLevel); //Changes lock to locklevel, in positive + ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive else - ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //No locklevel given, just flip the oriional one + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one } void Container::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel negative + ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 7e484f9d48..1a6e4e321d 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -291,20 +291,24 @@ namespace MWClass weaponDamage *= 0.5f + (stats.getAttribute(ESM::Attribute::Luck).getModified() / 100.0f); if(weaphashealth) { - int weapmaxhealth = weapon.get()->mBase->mData.mHealth; - if(weapon.getCellRef().mCharge == -1) - weapon.getCellRef().mCharge = weapmaxhealth; - weaponDamage *= float(weapon.getCellRef().mCharge) / weapmaxhealth; + int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon); + int weaphealth = weapon.getClass().getItemHealth(weapon); + weaponDamage *= float(weaphealth) / weapmaxhealth; + + if (!MWBase::Environment::get().getWorld()->getGodModeState()) + { + // Reduce weapon charge by at least one, but cap at 0 + weaphealth -= std::min(std::max(1, + (int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weaphealth); + + weapon.getCellRef().setCharge(weaphealth); + } + + // Weapon broken? unequip it + if (weapon.getCellRef().getCharge() == 0) + weapon = *getInventoryStore(ptr).unequipItem(weapon, ptr); } - 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; } @@ -825,14 +829,14 @@ namespace MWClass { // Note we do not respawn moved references in the cell they were moved to. Instead they are respawned in the original cell. // This also means we cannot respawn dynamically placed references with no content file connection. - if (ptr.getCellRef().mRefNum.mContentFile != -1) + if (ptr.getCellRef().getRefNum().mContentFile != -1) { if (ptr.getRefData().getCount() == 0) ptr.getRefData().setCount(1); // Reset to original position ESM::Position& pos = ptr.getRefData().getPosition(); - pos = ptr.getCellRef().mPos; + pos = ptr.getCellRef().getPosition(); ptr.getRefData().setCustomData(NULL); } @@ -844,7 +848,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; MWWorld::ContainerStore& store = getContainerStore(ptr); - store.restock(list, ptr, ptr.getCellRef().mRefID, ptr.getCellRef().mFaction); + store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); } const ESM::GameSetting* Creature::fMinWalkSpeedCreature; diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index fea30735c6..7843048044 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -73,8 +73,8 @@ namespace MWClass const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); MWWorld::ManualRef ref(store, id); - ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos; - MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos); + ref.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition()); + MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition()); customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId(); customData.mSpawn = false; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 27903c4103..12645c9f39 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -83,8 +83,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->mRef.mTeleport && !ref->mRef.mDestCell.empty()) // TODO doors that lead to exteriors - return ref->mRef.mDestCell; + if (ptr.getCellRef().getTeleport() && !ptr.getCellRef().getDestCell().empty()) // TODO doors that lead to exteriors + return ptr.getCellRef().getDestCell(); return ref->mBase->mName; } @@ -101,16 +101,16 @@ namespace MWClass MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor); - bool needKey = ptr.getCellRef().mLockLevel > 0; + bool needKey = ptr.getCellRef().getLockLevel() > 0; bool hasKey = false; std::string keyName; // make key id lowercase - std::string keyId = ptr.getCellRef().mKey; + std::string keyId = ptr.getCellRef().getKey(); Misc::StringUtils::toLower(keyId); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - std::string refId = it->getCellRef().mRefID; + std::string refId = it->getCellRef().getRefId(); Misc::StringUtils::toLower(refId); if (refId == keyId) { @@ -125,22 +125,22 @@ namespace MWClass MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}"); unlock(ptr); //Call the function here. because that makes sense. // using a key disarms the trap - ptr.getCellRef().mTrap = ""; + ptr.getCellRef().getTrap() = ""; } if (!needKey || hasKey) { - if(!ptr.getCellRef().mTrap.empty()) + if(!ptr.getCellRef().getTrap().empty()) { // Trap activation - boost::shared_ptr action(new MWWorld::ActionTrap(actor, ptr.getCellRef().mTrap, ptr)); + boost::shared_ptr action(new MWWorld::ActionTrap(actor, ptr.getCellRef().getTrap(), ptr)); action->setSound(trapActivationSound); return action; } - if (ref->mRef.mTeleport) + if (ptr.getCellRef().getTeleport()) { - boost::shared_ptr action(new MWWorld::ActionTeleport (ref->mRef.mDestCell, ref->mRef.mDoorDest)); + boost::shared_ptr action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest())); action->setSound(openSound); @@ -191,14 +191,14 @@ namespace MWClass void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const { if(lockLevel!=0) - ptr.getCellRef().mLockLevel = abs(lockLevel); //Changes lock to locklevel, in positive + ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive else - ptr.getCellRef().mLockLevel = abs(ptr.getCellRef().mLockLevel); //No locklevel given, just flip the origional one + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one } void Door::unlock (const MWWorld::Ptr& ptr) const { - ptr.getCellRef().mLockLevel = -abs(ptr.getCellRef().mLockLevel); //Makes lockLevel negative + ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative } std::string Door::getScript (const MWWorld::Ptr& ptr) const @@ -234,17 +234,17 @@ namespace MWClass std::string text; - if (ref->mRef.mTeleport) + if (ptr.getCellRef().getTeleport()) { text += "\n#{sTo}"; text += "\n" + getDestination(*ref); } - if (ref->mRef.mLockLevel > 0) - text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ref->mRef.mLockLevel); - else if (ref->mRef.mLockLevel < 0) + if (ptr.getCellRef().getLockLevel() > 0) + text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel()); + else if (ptr.getCellRef().getLockLevel() < 0) text += "\n#{sUnlocked}"; - if (ref->mRef.mTrap != "") + if (ptr.getCellRef().getTrap() != "") text += "\n#{sTrapped}"; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) @@ -260,16 +260,16 @@ namespace MWClass const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); std::string dest; - if (door.mRef.mDestCell != "") + if (door.mRef.getDestCell() != "") { // door leads to an interior, use interior name as tooltip - dest = door.mRef.mDestCell; + dest = door.mRef.getDestCell(); } else { // door leads to exterior, use cell name (if any), otherwise translated region name int x,y; - MWBase::Environment::get().getWorld()->positionToIndex (door.mRef.mDoorDest.pos[0], door.mRef.mDoorDest.pos[1], x, y); + MWBase::Environment::get().getWorld()->positionToIndex (door.mRef.getDoorDest().pos[0], door.mRef.getDoorDest().pos[1], x, y); const ESM::Cell* cell = store.get().find(x,y); if (cell->mName != "") dest = cell->mName; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index ebe41bb537..60c0efeb86 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -147,8 +147,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 1b28a84625..fd45ec8592 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -187,8 +187,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 60ffec7b9b..19381a3fd5 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -86,10 +86,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().mCharge == -1) - return ref->mBase->mData.mValue; - else - return ref->mBase->mData.mValue * (static_cast(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr)); + return ref->mBase->mData.mValue * (static_cast(getItemHealth(ptr)) / getItemMaxHealth(ptr)); } void Lockpick::registerSelf() @@ -136,7 +133,7 @@ namespace MWClass std::string text; - int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; + int remainingUses = getItemHealth(ptr); text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); @@ -144,8 +141,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index e568bf8697..1044fb01d4 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -28,11 +28,11 @@ namespace { bool isGold (const MWWorld::Ptr& ptr) { - return Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); + return Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_100"); } } @@ -94,12 +94,12 @@ namespace MWClass ptr.get(); int value = ref->mBase->mData.mValue; - if (ptr.getCellRef().mGoldValue > 1 && ptr.getRefData().getCount() == 1) - value = ptr.getCellRef().mGoldValue; + if (ptr.getCellRef().getGoldValue() > 1 && ptr.getRefData().getCount() == 1) + value = ptr.getCellRef().getGoldValue(); - if (ptr.getCellRef().mSoul != "") + if (ptr.getCellRef().getSoul() != "") { - const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get().find(ref->mRef.mSoul); + const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get().find(ref->mRef.getSoul()); value *= creature->mData.mSoul; } @@ -167,9 +167,9 @@ namespace MWClass info.caption = ref->mBase->mName + countString; info.icon = ref->mBase->mIcon; - if (ref->mRef.mSoul != "") + if (ref->mRef.getSoul() != "") { - const ESM::Creature *creature = store.get().find(ref->mRef.mSoul); + const ESM::Creature *creature = store.get().find(ref->mRef.getSoul()); info.caption += " (" + creature->mName + ")"; } @@ -182,8 +182,8 @@ namespace MWClass } if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } @@ -219,7 +219,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = newRef.getPtr().get(); newPtr = MWWorld::Ptr(&cell.get().insert(*ref), &cell); - newPtr.getCellRef().mGoldValue = goldAmount; + newPtr.getCellRef().setGoldValue(goldAmount); newPtr.getRefData().setCount(1); } else { MWWorld::LiveCellRef *ref = @@ -231,7 +231,7 @@ namespace MWClass boost::shared_ptr Miscellaneous::use (const MWWorld::Ptr& ptr) const { - if (ptr.getCellRef().mSoul == "") + if (ptr.getCellRef().getSoul().empty()) return boost::shared_ptr(new MWWorld::NullAction()); else return boost::shared_ptr(new MWWorld::ActionSoulgem(ptr)); @@ -242,12 +242,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = item.get(); - return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc) - && !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001") - && !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_005") - && !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_010") - && !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_025") - && !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_100"); + return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc) && !isGold(item); } float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index bca7708eab..7405292b4b 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -526,20 +526,24 @@ namespace MWClass (stats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult->getFloat() * 0.1); if(weaphashealth) { - int weapmaxhealth = weapon.get()->mBase->mData.mHealth; - if(weapon.getCellRef().mCharge == -1) - weapon.getCellRef().mCharge = weapmaxhealth; - damage *= float(weapon.getCellRef().mCharge) / weapmaxhealth; + int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon); + int weaphealth = weapon.getClass().getItemHealth(weapon); + + damage *= float(weaphealth) / weapmaxhealth; + + if (!MWBase::Environment::get().getWorld()->getGodModeState()) + { + // Reduce weapon charge by at least one, but cap at 0 + weaphealth -= std::min(std::max(1, + (int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weaphealth); + + weapon.getCellRef().setCharge(weaphealth); + } + + // Weapon broken? unequip it + if (weaphealth == 0) + weapon = *inv.unequipItem(weapon, ptr); } - - 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 = *inv.unequipItem(weapon, ptr); - } healthdmg = true; } @@ -705,14 +709,13 @@ namespace MWClass MWWorld::Ptr armor = ((armorslot != inv.end()) ? *armorslot : MWWorld::Ptr()); if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name()) { - ESM::CellRef &armorref = armor.getCellRef(); - if(armorref.mCharge == -1) - armorref.mCharge = armor.get()->mBase->mData.mHealth; - armorref.mCharge -= std::min(std::max(1, (int)damagediff), - armorref.mCharge); + int armorhealth = armor.getClass().getItemHealth(armor); + armorhealth -= std::min(std::max(1, (int)damagediff), + armorhealth); + armor.getCellRef().setCharge(armorhealth); // Armor broken? unequip it - if (armorref.mCharge == 0) + if (armorhealth == 0) inv.unequipItem(armor, ptr); if (ptr.getRefData().getHandle() == "player") @@ -1316,14 +1319,14 @@ namespace MWClass { // Note we do not respawn moved references in the cell they were moved to. Instead they are respawned in the original cell. // This also means we cannot respawn dynamically placed references with no content file connection. - if (ptr.getCellRef().mRefNum.mContentFile != -1) + if (ptr.getCellRef().getRefNum().mContentFile != -1) { if (ptr.getRefData().getCount() == 0) ptr.getRefData().setCount(1); // Reset to original position ESM::Position& pos = ptr.getRefData().getPosition(); - pos = ptr.getCellRef().mPos; + pos = ptr.getCellRef().getPosition(); ptr.getRefData().setCustomData(NULL); } @@ -1335,7 +1338,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); const ESM::InventoryList& list = ref->mBase->mInventory; MWWorld::ContainerStore& store = getContainerStore(ptr); - store.restock(list, ptr, ptr.getCellRef().mRefID, ptr.getCellRef().mFaction); + store.restock(list, ptr, ptr.getCellRef().getRefId(), ptr.getCellRef().getFaction()); } const ESM::GameSetting *Npc::fMinWalkSpeed; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index f9d7947a66..7440617c25 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -151,8 +151,8 @@ namespace MWClass info.isPotion = true; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index d376270cb3..5d076a3c5e 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -85,10 +85,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().mCharge == -1) - return ref->mBase->mData.mValue; - else - return ref->mBase->mData.mValue * (static_cast(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr)); + return ref->mBase->mData.mValue * (static_cast(getItemHealth(ptr)) / getItemMaxHealth(ptr)); } void Probe::registerSelf() @@ -135,7 +132,7 @@ namespace MWClass std::string text; - int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; + int remainingUses = getItemHealth(ptr); text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); @@ -143,8 +140,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index af79a96915..9b528a4fce 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -76,10 +76,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().mCharge == -1) - return ref->mBase->mData.mValue; - else - return ref->mBase->mData.mValue * (static_cast(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr)); + return ref->mBase->mData.mValue * (static_cast(getItemHealth(ptr)) / getItemMaxHealth(ptr)); } void Repair::registerSelf() @@ -139,7 +136,7 @@ namespace MWClass std::string text; - int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; + int remainingUses = getItemHealth(ptr); text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); @@ -147,8 +144,8 @@ namespace MWClass text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 5edf22b008..26618c021c 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -154,10 +154,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - if (ptr.getCellRef().mCharge == -1) - return ref->mBase->mData.mValue; - else - return ref->mBase->mData.mValue * (static_cast(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr)); + return ref->mBase->mData.mValue * (static_cast(getItemHealth(ptr)) / getItemMaxHealth(ptr)); } void Weapon::registerSelf() @@ -340,7 +337,7 @@ namespace MWClass if (ref->mBase->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity { - int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth; + int remainingHealth = getItemHealth(ptr); text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); } @@ -351,11 +348,11 @@ namespace MWClass info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; + info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); - text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner"); + text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); } @@ -388,7 +385,7 @@ namespace MWClass std::pair Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { - if (ptr.getCellRef().mCharge == 0) + if (ptr.getCellRef().getCharge() == 0) return std::make_pair(0, "#{sInventoryMessage1}"); std::pair, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr); diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 237d145a2e..811f93b486 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -413,7 +413,7 @@ namespace MWGui } else { - setTitle("#{sConsoleTitle} (" + object.getCellRef().mRefID + ")"); + setTitle("#{sConsoleTitle} (" + object.getCellRef().getRefId() + ")"); mPtr = object; } // User clicked on an object. Restore focus to the console command line. diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index b303848df5..29fe6f82d5 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -306,7 +306,7 @@ namespace MWGui 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)) + if (Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), mPtr.getCellRef().getRefId())) { std::string msg = MWBase::Environment::get().getWorld()->getStore().get().find("sNotifyMessage49")->getString(); if (msg.find("%s") != std::string::npos) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 103c48ca14..ede5750a56 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -40,7 +40,7 @@ namespace MWGui else dropped = world->dropObjectOnGround(world->getPlayerPtr(), item.mBase, count); if (setNewOwner) - dropped.getCellRef().mOwner = ""; + dropped.getCellRef().setOwner(""); return dropped; } diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index e1bc9d4daa..ad1a4e9537 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -67,7 +67,7 @@ MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, I if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead() // Make sure that the item is actually owned by the dead actor // Prevents a potential exploit for resetting the owner of any item, by placing the item in a corpse - && Misc::StringUtils::ciEqual(item.mBase.getCellRef().mOwner, mActor.getCellRef().mRefID)) + && Misc::StringUtils::ciEqual(item.mBase.getCellRef().getOwner(), mActor.getCellRef().getRefId())) setNewOwner = true; MWWorld::Ptr ret = otherModel->copyItem(item, count, setNewOwner); @@ -87,7 +87,7 @@ void InventoryItemModel::update() // NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken. // Vanilla likely uses a hack like this since there's no other way to prevent it from // being shown or taken. - if(item.getCellRef().mRefID == "werewolfrobe") + if(item.getCellRef().getRefId() == "werewolfrobe") continue; ItemStack newItem (item, this, item.getRefData().getCount()); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 788f90f504..b1e8052d8c 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -168,8 +168,8 @@ namespace MWGui int count = item.mCount; // Bound items may not be moved - if (item.mBase.getCellRef().mRefID.size() > 6 - && item.mBase.getCellRef().mRefID.substr(0,6) == "bound_") + if (item.mBase.getCellRef().getRefId().size() > 6 + && item.mBase.getCellRef().getRefId().substr(0,6) == "bound_") { MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}"); @@ -454,7 +454,7 @@ namespace MWGui // NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla // likely uses a hack like this since there's no other way to prevent it from being // taken. - if(item.getCellRef().mRefID == "werewolfrobe") + if(item.getCellRef().getRefId() == "werewolfrobe") return MWWorld::Ptr(); return item; } diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 83527a8845..50e7644fb9 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -47,7 +47,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) if (iter->getClass().hasItemHealth(*iter)) { int maxDurability = iter->getClass().getItemMaxHealth(*iter); - int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; + int durability = iter->getClass().getItemHealth(*iter); if (maxDurability == durability) continue; @@ -114,7 +114,7 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) { // repair MWWorld::Ptr item = *sender->getUserData(); - item.getCellRef().mCharge = item.getClass().getItemMaxHealth(item); + item.getCellRef().setCharge(item.getClass().getItemMaxHealth(item)); MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index 0196bf02d3..230282f152 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -42,8 +42,8 @@ namespace MWGui const ItemStack& item = mSourceModel->getItem(i); // Bound items may not be stolen - if (item.mBase.getCellRef().mRefID.size() > 6 - && item.mBase.getCellRef().mRefID.substr(0,6) == "bound_") + if (item.mBase.getCellRef().getRefId().size() > 6 + && item.mBase.getCellRef().getRefId().substr(0,6) == "bound_") { continue; } diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 5df2b12b8d..90abbb1450 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -274,11 +274,11 @@ namespace MWGui if (item.getRefData ().getCount() < 1) { // Try searching for a compatible replacement - std::string id = item.getCellRef().mRefID; + std::string id = item.getCellRef().getRefId(); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { - if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id)) + if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id)) { item = *it; button->getChildAt(0)->setUserData(item); @@ -408,7 +408,7 @@ namespace MWGui case Type_MagicItem: { MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); - key.mId = item.getCellRef().mRefID; + key.mId = item.getCellRef().getRefId(); break; } case Type_Magic: @@ -458,11 +458,12 @@ namespace MWGui MWWorld::Ptr item; for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { - if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id)) + if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id)) { if (item.isEmpty() || // Prefer the stack with the lowest remaining uses - (it->getCellRef().mCharge != -1 && (item.getCellRef().mCharge == -1 || it->getCellRef().mCharge < item.getCellRef().mCharge) )) + !item.getClass().hasItemHealth(*it) || + it->getClass().getItemHealth(*it) < item.getClass().getItemHealth(item)) { item = *it; } diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 313650bb64..5c4f3eb5a5 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -56,7 +56,7 @@ void Recharge::updateView() { MWWorld::Ptr gem = *mGemIcon->getUserData(); - std::string soul = gem.getCellRef().mSoul; + std::string soul = gem.getCellRef().getSoul(); const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get().find(soul); mChargeLabel->setCaptionWithReplacing("#{sCharges} " + boost::lexical_cast(creature->mData.mSoul)); @@ -93,8 +93,8 @@ void Recharge::updateView() if (enchantmentName.empty()) continue; const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find(enchantmentName); - if (iter->getCellRef().mEnchantmentCharge >= enchantment->mData.mCharge - || iter->getCellRef().mEnchantmentCharge == -1) + if (iter->getCellRef().getEnchantmentCharge() >= enchantment->mData.mCharge + || iter->getCellRef().getEnchantmentCharge() == -1) continue; MyGUI::TextBox* text = mView->createWidget ( @@ -118,7 +118,7 @@ void Recharge::updateView() Widgets::MWDynamicStatPtr chargeWidget = mView->createWidget ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default); - chargeWidget->setValue(iter->getCellRef().mEnchantmentCharge, enchantment->mData.mCharge); + chargeWidget->setValue(iter->getCellRef().getEnchantmentCharge(), enchantment->mData.mCharge); chargeWidget->setNeedMouseFocus(false); currentY += 32 + 4; @@ -159,15 +159,15 @@ void Recharge::onItemClicked(MyGUI::Widget *sender) int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] if (roll < x) { - std::string soul = gem.getCellRef().mSoul; + std::string soul = gem.getCellRef().getSoul(); const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get().find(soul); float restored = creature->mData.mSoul * (roll / x); const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find( item.getClass().getEnchantment(item)); - item.getCellRef().mEnchantmentCharge = - std::min(item.getCellRef().mEnchantmentCharge + restored, static_cast(enchantment->mData.mCharge)); + item.getCellRef().setEnchantmentCharge( + std::min(item.getCellRef().getEnchantmentCharge() + restored, static_cast(enchantment->mData.mCharge))); player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0); } diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index a3df2dfbea..1ae02599ee 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -56,7 +56,7 @@ void Repair::updateRepairView() MWWorld::LiveCellRef *ref = mRepair.getTool().get(); - int uses = (mRepair.getTool().getCellRef().mCharge != -1) ? mRepair.getTool().getCellRef().mCharge : ref->mBase->mData.mUses; + int uses = mRepair.getTool().getClass().getItemHealth(mRepair.getTool()); float quality = ref->mBase->mData.mQuality; @@ -98,7 +98,7 @@ void Repair::updateRepairView() if (iter->getClass().hasItemHealth(*iter)) { int maxDurability = iter->getClass().getItemMaxHealth(*iter); - int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; + int durability = iter->getClass().getItemHealth(*iter); if (maxDurability == durability) continue; diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 475f73a072..b8dcbcbbb1 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -114,7 +114,7 @@ namespace MWGui if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted)) return false; if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name() - || base.getCellRef().mSoul == "")) + || base.getCellRef().getSoul() == "")) return false; if ((mFilter & Filter_OnlyEnchantable) && (item.mFlags & ItemStack::Flag_Enchanted || (base.getTypeName() != typeid(ESM::Armor).name() diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 16e4741432..fb5a80cc7d 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -238,7 +238,7 @@ namespace MWGui int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10)); std::string cost = boost::lexical_cast(castCost); - int currentCharge = int(item.getCellRef().mEnchantmentCharge); + int currentCharge = int(item.getCellRef().getEnchantmentCharge()); if (currentCharge == -1) currentCharge = enchant->mData.mCharge; std::string charge = boost::lexical_cast(currentCharge); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index dd29f40ce4..aeb79a9381 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -97,7 +97,7 @@ namespace MWGui setCoord(0, 0, 300, 300); mDynamicToolTipBox->setVisible(true); ToolTipInfo info; - info.caption=mFocusObject.getCellRef().mRefID; + info.caption=mFocusObject.getCellRef().getRefId(); info.icon=""; tooltipSize = createToolTip(info); } diff --git a/apps/openmw/mwgui/tradeitemmodel.cpp b/apps/openmw/mwgui/tradeitemmodel.cpp index 18b0d5ae3f..fe43eb5483 100644 --- a/apps/openmw/mwgui/tradeitemmodel.cpp +++ b/apps/openmw/mwgui/tradeitemmodel.cpp @@ -148,14 +148,14 @@ namespace MWGui if(!mMerchant.isEmpty()) { MWWorld::Ptr base = item.mBase; - if(Misc::StringUtils::ciEqual(base.getCellRef().mRefID, MWWorld::ContainerStore::sGoldId)) + if(Misc::StringUtils::ciEqual(base.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) continue; if(!base.getClass().canSell(base, services)) continue; // Bound items may not be bought - if (item.mBase.getCellRef().mRefID.size() > 6 - && item.mBase.getCellRef().mRefID.substr(0,6) == "bound_") + if (item.mBase.getCellRef().getRefId().size() > 6 + && item.mBase.getCellRef().getRefId().substr(0,6) == "bound_") { continue; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 4baa48e7cf..558e955f0d 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -277,7 +277,7 @@ namespace MWGui // check if the player is attempting to sell back an item stolen from this actor for (std::vector::iterator it = merchantBought.begin(); it != merchantBought.end(); ++it) { - if (Misc::StringUtils::ciEqual(it->mBase.getCellRef().mOwner, mPtr.getCellRef().mRefID)) + if (Misc::StringUtils::ciEqual(it->mBase.getCellRef().getOwner(), mPtr.getCellRef().getRefId())) { std::string msg = gmst.find("sNotifyMessage49")->getString(); if (msg.find("%s") != std::string::npos) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 40fcc35300..a42dca79e5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1029,16 +1029,16 @@ namespace MWGui const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get() .find(item.getClass().getEnchantment(item)); - int chargePercent = (item.getCellRef().mEnchantmentCharge == -1) ? 100 - : (item.getCellRef().mEnchantmentCharge / static_cast(ench->mData.mCharge) * 100); + int chargePercent = (item.getCellRef().getEnchantmentCharge() == -1) ? 100 + : (item.getCellRef().getEnchantmentCharge() / static_cast(ench->mData.mCharge) * 100); mHud->setSelectedEnchantItem(item, chargePercent); mSpellWindow->setTitle(item.getClass().getName(item)); } void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) { - int durabilityPercent = (item.getCellRef().mCharge == -1) ? 100 - : (item.getCellRef().mCharge / static_cast(item.getClass().getItemMaxHealth(item)) * 100); + int durabilityPercent = + (item.getClass().getItemHealth(item) / static_cast(item.getClass().getItemMaxHealth(item)) * 100); mHud->setSelectedWeapon(item, durabilityPercent); mInventoryWindow->setTitle(item.getClass().getName(item)); } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 35667a23c4..9f141a951b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -62,17 +62,17 @@ bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate) { if (!item->getClass().hasItemHealth(*item)) return false; - if (item->getCellRef().mCharge == -1) - item->getCellRef().mCharge = item->getClass().getItemMaxHealth(*item); + int charge = item->getClass().getItemHealth(*item); - if (item->getCellRef().mCharge == 0) + if (charge == 0) return false; - item->getCellRef().mCharge -= + charge -= std::min(disintegrate, - static_cast(item->getCellRef().mCharge)); + static_cast(charge)); + item->getCellRef().setCharge(charge); - if (item->getCellRef().mCharge == 0) + if (charge == 0) { // Will unequip the broken item and try to find a replacement if (ptr.getRefData().getHandle() != "player") @@ -147,13 +147,13 @@ namespace MWMechanics for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != container.end(); ++it) { - const std::string& id = it->getCellRef().mRefID; + const std::string& id = it->getCellRef().getRefId(); if (id.size() >= soulgemFilter.size() && id.substr(0,soulgemFilter.size()) == soulgemFilter) { float thisGemCapacity = it->get()->mBase->mData.mValue * fSoulgemMult; if (thisGemCapacity >= creatureSoulValue && thisGemCapacity < gemCapacity - && it->getCellRef().mSoul.empty()) + && it->getCellRef().getSoul().empty()) { gem = it; gemCapacity = thisGemCapacity; @@ -166,7 +166,7 @@ namespace MWMechanics // Set the soul on just one of the gems, not the whole stack gem->getContainerStore()->unstack(*gem, caster); - gem->getCellRef().mSoul = mCreature.getCellRef().mRefID; + gem->getCellRef().setSoul(mCreature.getCellRef().getRefId()); if (caster.getRefData().getHandle() == "player") MWBase::Environment::get().getWindowManager()->messageBox("#{sSoultrapSuccess}"); @@ -546,7 +546,7 @@ namespace MWMechanics { MWWorld::CellStore* store = ptr.getCell(); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1); - ref.getPtr().getCellRef().mPos = ipos; + ref.getPtr().getCellRef().setPosition(ipos); MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr()); @@ -1142,7 +1142,7 @@ namespace MWMechanics if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) { MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); - if(package->getFollowedActor() == actor.getCellRef().mRefID) + if(package->getFollowedActor() == actor.getCellRef().getRefId()) list.push_front(iter->first); } } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 5045225828..ea6f296cc8 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -73,11 +73,6 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration return false; } -std::string MWMechanics::AiAvoidDoor::getAvoidedDoor() -{ - return mDoorPtr.getCellRef().mRefID; -} - MWMechanics::AiAvoidDoor *MWMechanics::AiAvoidDoor::clone() const { return new AiAvoidDoor(*this); diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index c1b3261981..d2a2e33a1f 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -24,9 +24,6 @@ namespace MWMechanics virtual int getTypeId() const; - /// Returns the door being avoided - std::string getAvoidedDoor(); - private: float mDuration; MWWorld::Ptr mDoorPtr; diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 1027cc48a7..8ea9be3399 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -517,7 +517,7 @@ namespace MWMechanics { MWWorld::LiveCellRef& ref = *mDoorIter; float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility - if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && + if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.getPosition().pos)) < minSqr && ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening { //std::cout<<"closed door id \""<execute(actor); mLastDoorChecked = door; } diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 5ffa7a547f..69c3c08f76 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -102,10 +102,11 @@ namespace MWMechanics if (roll < x) { // Reduce shield durability by incoming damage - if (shield->getCellRef().mCharge == -1) - shield->getCellRef().mCharge = shield->getClass().getItemMaxHealth(*shield); - shield->getCellRef().mCharge -= std::min(shield->getCellRef().mCharge, int(damage)); - if (!shield->getCellRef().mCharge) + int shieldhealth = shield->getClass().getItemHealth(*shield); + + shieldhealth -= std::min(shieldhealth, int(damage)); + shield->getCellRef().setCharge(shieldhealth); + if (shieldhealth == 0) inv.unequipItem(*shield, blocker); // Reduce blocker fatigue diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 9c5c9dbb9d..f3f6795db8 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -234,9 +234,9 @@ namespace MWMechanics const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); if(soulEmpty()) return 0; - if(mSoulGemPtr.getCellRef().mSoul=="") + if(mSoulGemPtr.getCellRef().getSoul()=="") return 0; - const ESM::Creature* soul = store.get().find(mSoulGemPtr.getCellRef().mSoul); + const ESM::Creature* soul = store.get().find(mSoulGemPtr.getCellRef().getSoul()); return soul->mData.mSoul; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index d25be1e13f..0d5bae42bd 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -24,10 +24,10 @@ namespace /// @return is \a ptr allowed to take/use \a item or is it a crime? bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) { - const std::string& owner = item.getCellRef().mOwner; + const std::string& owner = item.getCellRef().getOwner(); bool isOwned = !owner.empty() && owner != "player"; - const std::string& faction = item.getCellRef().mFaction; + const std::string& faction = item.getCellRef().getFaction(); bool isFactionOwned = false; if (!faction.empty() && ptr.getClass().isNpc()) { @@ -36,8 +36,8 @@ namespace isFactionOwned = true; } - if (!item.getCellRef().mOwner.empty()) - victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().mOwner, true); + if (!item.getCellRef().getOwner().empty()) + victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true); return (!isOwned && !isFactionOwned); } diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index fc781e6377..55ebfeab54 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -50,7 +50,7 @@ namespace MWMechanics for (; it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; - if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + if(pos.squaredDistance(Ogre::Vector3(ref.mData.getPosition().pos)) < minSqr) if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp index dc8b567a9b..9f2c851cf8 100644 --- a/apps/openmw/mwmechanics/repair.cpp +++ b/apps/openmw/mwmechanics/repair.cpp @@ -28,8 +28,8 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) player.getClass().getContainerStore(player).unstack(mTool, player); // reduce number of uses left - int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses; - mTool.getCellRef().mCharge = uses-1; + int uses = mTool.getClass().getItemHealth(mTool); + mTool.getCellRef().setCharge(uses-1); MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player); @@ -53,9 +53,9 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) y = std::max(1, y); // repair by 'y' points - itemToRepair.getCellRef().mCharge += y; - itemToRepair.getCellRef().mCharge = std::min(itemToRepair.getCellRef().mCharge, - itemToRepair.getClass().getItemMaxHealth(itemToRepair)); + int charge = itemToRepair.getClass().getItemHealth(itemToRepair); + charge = std::min(charge + y, itemToRepair.getClass().getItemMaxHealth(itemToRepair)); + itemToRepair.getCellRef().setCharge(charge); // set the OnPCRepair variable on the item's script std::string script = itemToRepair.getClass().getScript(itemToRepair); @@ -75,7 +75,7 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) } // tool used up? - if (mTool.getCellRef().mCharge == 0) + if (mTool.getCellRef().getCharge() == 0) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); @@ -91,7 +91,7 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) { - if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, mTool.getCellRef().mRefID)) + if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), mTool.getCellRef().getRefId())) { mTool = *iter; break; diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index bb2e942238..4a049d60f8 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -29,10 +29,10 @@ namespace MWMechanics void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick, std::string& resultMessage, std::string& resultSound) { - if (!(lock.getCellRef().mLockLevel > 0)) //If it's unlocked back out immediately + if (!(lock.getCellRef().getLockLevel() > 0)) //If it's unlocked back out immediately return; - int lockStrength = lock.getCellRef().mLockLevel; + int lockStrength = lock.getCellRef().getLockLevel(); float pickQuality = lockpick.get()->mBase->mData.mQuality; @@ -60,22 +60,22 @@ namespace MWMechanics resultMessage = "#{sLockFail}"; } - if (lockpick.getCellRef().mCharge == -1) - lockpick.getCellRef().mCharge = lockpick.get()->mBase->mData.mUses; - --lockpick.getCellRef().mCharge; - if (!lockpick.getCellRef().mCharge) + int uses = lockpick.getClass().getItemHealth(lockpick); + --uses; + lockpick.getCellRef().setCharge(uses); + if (!uses) lockpick.getContainerStore()->remove(lockpick, 1, mActor); } void Security::probeTrap(const MWWorld::Ptr &trap, const MWWorld::Ptr &probe, std::string& resultMessage, std::string& resultSound) { - if (trap.getCellRef().mTrap == "") + if (trap.getCellRef().getTrap() == "") return; float probeQuality = probe.get()->mBase->mData.mQuality; - const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get().find(trap.getCellRef().mTrap); + const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get().find(trap.getCellRef().getTrap()); float trapSpellPoints = trapSpell->mData.mCost; float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get().find("fTrapCostMult")->getFloat(); @@ -93,7 +93,7 @@ namespace MWMechanics int roll = static_cast (std::rand()) / RAND_MAX * 100; if (roll <= x) { - trap.getCellRef().mTrap = ""; + trap.getCellRef().setTrap(""); resultSound = "Disarm Trap"; resultMessage = "#{sTrapSuccess}"; @@ -103,10 +103,10 @@ namespace MWMechanics resultMessage = "#{sTrapFail}"; } - if (probe.getCellRef().mCharge == -1) - probe.getCellRef().mCharge = probe.get()->mBase->mData.mUses; - --probe.getCellRef().mCharge; - if (!probe.getCellRef().mCharge) + int uses = probe.getClass().getItemHealth(probe); + --uses; + probe.getCellRef().setCharge(uses); + if (!uses) probe.getContainerStore()->remove(probe, 1, mActor); } diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 91a81c74be..c996e90d6f 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -470,21 +470,21 @@ namespace MWMechanics { if (effectId == ESM::MagicEffect::Lock) { - if (target.getCellRef().mLockLevel < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude - target.getCellRef().mLockLevel = magnitude; + if (target.getCellRef().getLockLevel() < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude + target.getCellRef().setLockLevel(magnitude); } else if (effectId == ESM::MagicEffect::Open) { - if (target.getCellRef().mLockLevel <= magnitude) + if (target.getCellRef().getLockLevel() <= magnitude) { - //Door not already unlocked - if (target.getCellRef().mLockLevel > 0) + if (target.getCellRef().getLockLevel() > 0) { + //Door not already unlocked MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock", 1.f, 1.f); if (!caster.isEmpty() && caster.getClass().isActor()) MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); } - target.getCellRef().mLockLevel = -abs(target.getCellRef().mLockLevel); //unlocks the door + target.getCellRef().setLockLevel(-abs(target.getCellRef().getLockLevel())); //unlocks the door } else MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f); @@ -588,7 +588,7 @@ namespace MWMechanics throw std::runtime_error("can't cast an item without an enchantment"); mSourceName = item.getClass().getName(item); - mId = item.getCellRef().mRefID; + mId = item.getCellRef().getRefId(); const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find(enchantmentName); @@ -601,10 +601,10 @@ namespace MWMechanics int eSkill = mCaster.getClass().getSkill(mCaster, ESM::Skill::Enchant); const int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10)); - if (item.getCellRef().mEnchantmentCharge == -1) - item.getCellRef().mEnchantmentCharge = enchantment->mData.mCharge; + if (item.getCellRef().getEnchantmentCharge() == -1) + item.getCellRef().setEnchantmentCharge(enchantment->mData.mCharge); - if (item.getCellRef().mEnchantmentCharge < castCost) + if (item.getCellRef().getEnchantmentCharge() < castCost) { // TODO: Should there be a sound here? if (mCaster.getRefData().getHandle() == "player") @@ -612,7 +612,7 @@ namespace MWMechanics return false; } // Reduce charge - item.getCellRef().mEnchantmentCharge -= castCost; + item.getCellRef().setEnchantmentCharge(item.getCellRef().getEnchantmentCharge() - castCost); } if (enchantment->mData.mType == ESM::Enchantment::WhenUsed) diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 820ba8acca..a9c9884d58 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -49,10 +49,10 @@ void Actors::insertBegin(const MWWorld::Ptr &ptr) Ogre::SceneNode* insert = cellnode->createChildSceneNode(); const float *f = ptr.getRefData().getPosition().pos; insert->setPosition(f[0], f[1], f[2]); - insert->setScale(ptr.getCellRef().mScale, ptr.getCellRef().mScale, ptr.getCellRef().mScale); + insert->setScale(ptr.getCellRef().getScale(), ptr.getCellRef().getScale(), ptr.getCellRef().getScale()); // Convert MW rotation to a quaternion: - f = ptr.getCellRef().mPos.rot; + f = ptr.getCellRef().getPosition().rot; // Rotate around X axis Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3b8b91b0e4..9124e89b88 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -290,7 +290,7 @@ void Animation::addAnimSource(const std::string &model) mAccumRoot = mNonAccumRoot->getParent(); if(!mAccumRoot) { - std::cerr<< "Non-Accum root for "<getParent(); if(!mAccumRoot) { - std::cerr<< "Non-Accum root for "<setPosition(f[0], f[1], f[2]); - insert->setScale(ptr.getCellRef().mScale, ptr.getCellRef().mScale, ptr.getCellRef().mScale); + insert->setScale(ptr.getCellRef().getScale(), ptr.getCellRef().getScale(), ptr.getCellRef().getScale()); // Convert MW rotation to a quaternion: - f = ptr.getCellRef().mPos.rot; + f = ptr.getCellRef().getPosition().rot; // Rotate around X axis Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 825d62efb5..a5bd121526 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -88,6 +88,11 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + runtime.push (0); + return; + } bool interior = !MWBase::Environment::get().getWorld()->getPlayerPtr().getCell()->getCell()->isExterior(); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 6737d6a945..93711d036e 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -121,7 +121,7 @@ namespace MWScript std::string itemName; for (MWWorld::ContainerStoreIterator iter(store.begin()); iter != store.end(); ++iter) - if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item)) + if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) itemName = iter->getClass().getName(*iter); int numRemoved = store.remove(item, count, ptr); @@ -165,7 +165,7 @@ namespace MWScript MWWorld::ContainerStoreIterator it = invStore.begin(); for (; it != invStore.end(); ++it) { - if (::Misc::StringUtils::ciEqual(it->getCellRef().mRefID, item)) + if (::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item)) break; } if (it == invStore.end()) @@ -268,7 +268,7 @@ namespace MWScript for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); - if (it != invStore.end() && ::Misc::StringUtils::ciEqual(it->getCellRef().mRefID, item)) + if (it != invStore.end() && ::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item)) { runtime.push(1); return; @@ -295,7 +295,7 @@ namespace MWScript it != invStore.end(); ++it) { - if (::Misc::StringUtils::ciEqual(it->getCellRef().mSoul, name)) + if (::Misc::StringUtils::ciEqual(it->getCellRef().getSoul(), name)) { runtime.push(1); return; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index b0d73253ff..fa17d96af3 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -131,7 +131,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer lockLevel = ptr.getCellRef().mLockLevel; + Interpreter::Type_Integer lockLevel = ptr.getCellRef().getLockLevel(); if(lockLevel==0) { //no lock level was ever set, set to 100 as default lockLevel = 100; } @@ -324,7 +324,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - runtime.push (ptr.getCellRef().mLockLevel > 0); + runtime.push (ptr.getCellRef().getLockLevel() > 0); } }; @@ -369,7 +369,7 @@ namespace MWScript store.get().find(creature); // This line throws an exception if it can't find the creature MWWorld::Ptr item = *ptr.getClass().getContainerStore(ptr).add(gem, 1, ptr); - item.getCellRef().mSoul = creature; + item.getCellRef().setSoul(creature); } }; @@ -392,7 +392,7 @@ namespace MWScript MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { - if (::Misc::StringUtils::ciEqual(it->getCellRef().mSoul, soul)) + if (::Misc::StringUtils::ciEqual(it->getCellRef().getSoul(), soul)) { store.remove(*it, 1, ptr); return; @@ -430,7 +430,7 @@ namespace MWScript int toRemove = amount; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) { - if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item)) + if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) { int removed = store.remove(*iter, toRemove, ptr); MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed); @@ -462,7 +462,7 @@ namespace MWScript for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) { - if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul)) + if (::Misc::StringUtils::ciEqual(iter->getCellRef().getSoul(), soul)) { MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, 1); store.remove(*iter, 1, ptr); @@ -659,10 +659,10 @@ namespace MWScript const std::string script = ptr.getClass().getScript(ptr); if(script.empty()) - str<< ptr.getCellRef().mRefID<<" ("<getLocals(script); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index fb27e73f44..a944a31b8d 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -47,7 +47,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); - runtime.push(ptr.getCellRef().mScale); + runtime.push(ptr.getCellRef().getScale()); } }; @@ -64,7 +64,7 @@ namespace MWScript runtime.pop(); // add the parameter to the object's scale. - MWBase::Environment::get().getWorld()->scaleObject(ptr,ptr.getCellRef().mScale + scale); + MWBase::Environment::get().getWorld()->scaleObject(ptr,ptr.getCellRef().getScale() + scale); } }; @@ -117,15 +117,15 @@ namespace MWScript if (axis == "x") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().getPosition().rot[0]).valueDegrees()); } else if (axis == "y") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().getPosition().rot[1]).valueDegrees()); } else if (axis == "z") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().getPosition().rot[2]).valueDegrees()); } else throw std::runtime_error ("invalid rotation axis: " + axis); @@ -247,15 +247,15 @@ namespace MWScript if(axis == "x") { - runtime.push(ptr.getCellRef().mPos.pos[0]); + runtime.push(ptr.getCellRef().getPosition().pos[0]); } else if(axis == "y") { - runtime.push(ptr.getCellRef().mPos.pos[1]); + runtime.push(ptr.getCellRef().getPosition().pos[1]); } else if(axis == "z") { - runtime.push(ptr.getCellRef().mPos.pos[2]); + runtime.push(ptr.getCellRef().getPosition().pos[2]); } else throw std::runtime_error ("invalid axis: " + axis); @@ -415,7 +415,7 @@ namespace MWScript pos.rot[0] = pos.rot[1] = 0; pos.rot[2] = zRot; MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID); - ref.getPtr().getCellRef().mPos = pos; + ref.getPtr().getCellRef().setPosition(pos); MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos); } else @@ -456,7 +456,7 @@ namespace MWScript pos.rot[0] = pos.rot[1] = 0; pos.rot[2] = zRot; MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID); - ref.getPtr().getCellRef().mPos = pos; + ref.getPtr().getCellRef().setPosition(pos); MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos); } else @@ -523,7 +523,7 @@ namespace MWScript // create item MWWorld::CellStore* store = actor.getCell(); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, count); - ref.getPtr().getCellRef().mPos = ipos; + ref.getPtr().getCellRef().setPosition(ipos); MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos); } @@ -617,8 +617,8 @@ namespace MWScript ptr.getRefData().getLocalRotation().rot[1] = 0; ptr.getRefData().getLocalRotation().rot[2] = 0; MWBase::Environment::get().getWorld()->rotateObject(ptr, 0,0,0,true); - MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().mPos.pos[0], - ptr.getCellRef().mPos.pos[1], ptr.getCellRef().mPos.pos[2]); + MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().pos[0], + ptr.getCellRef().getPosition().pos[1], ptr.getCellRef().getPosition().pos[2]); } }; diff --git a/apps/openmw/mwworld/actiontrap.cpp b/apps/openmw/mwworld/actiontrap.cpp index bcefb0181b..1472afc087 100644 --- a/apps/openmw/mwworld/actiontrap.cpp +++ b/apps/openmw/mwworld/actiontrap.cpp @@ -11,7 +11,7 @@ namespace MWWorld cast.mHitPosition = Ogre::Vector3(actor.getRefData().getPosition().pos); cast.cast(mSpellId); - mTrapSource.getCellRef().mTrap = ""; + mTrapSource.getCellRef().setTrap(""); } } diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp new file mode 100644 index 0000000000..f16d8e3d17 --- /dev/null +++ b/apps/openmw/mwworld/cellref.cpp @@ -0,0 +1,185 @@ +#include "cellref.hpp" + +#include + +namespace MWWorld +{ + + ESM::RefNum CellRef::getRefNum() const + { + return mCellRef.mRefNum; + } + + std::string CellRef::getRefId() const + { + return mCellRef.mRefID; + } + + bool CellRef::getTeleport() const + { + return mCellRef.mTeleport; + } + + ESM::Position CellRef::getDoorDest() const + { + return mCellRef.mDoorDest; + } + + std::string CellRef::getDestCell() const + { + return mCellRef.mDestCell; + } + + float CellRef::getScale() const + { + return mCellRef.mScale; + } + + void CellRef::setScale(float scale) + { + if (scale != mCellRef.mScale) + { + mChanged = true; + mCellRef.mScale = scale; + } + } + + ESM::Position CellRef::getPosition() const + { + return mCellRef.mPos; + } + + void CellRef::setPosition(const ESM::Position &position) + { + mChanged = true; + mCellRef.mPos = position; + } + + float CellRef::getEnchantmentCharge() const + { + return mCellRef.mEnchantmentCharge; + } + + void CellRef::setEnchantmentCharge(float charge) + { + if (charge != mCellRef.mEnchantmentCharge) + { + mChanged = true; + mCellRef.mEnchantmentCharge = charge; + } + } + + int CellRef::getCharge() const + { + return mCellRef.mCharge; + } + + void CellRef::setCharge(int charge) + { + if (charge != mCellRef.mCharge) + { + mChanged = true; + mCellRef.mCharge = charge; + } + } + + std::string CellRef::getOwner() const + { + return mCellRef.mOwner; + } + + void CellRef::setOwner(const std::string &owner) + { + if (owner != mCellRef.mOwner) + { + mChanged = true; + mCellRef.mOwner = owner; + } + } + + std::string CellRef::getSoul() const + { + return mCellRef.mSoul; + } + + void CellRef::setSoul(const std::string &soul) + { + if (soul != mCellRef.mSoul) + { + mChanged = true; + mCellRef.mSoul = soul; + } + } + + std::string CellRef::getFaction() const + { + return mCellRef.mFaction; + } + + void CellRef::setFaction(const std::string &faction) + { + if (faction != mCellRef.mFaction) + { + mChanged = true; + mCellRef.mFaction = faction; + } + } + + int CellRef::getLockLevel() const + { + return mCellRef.mLockLevel; + } + + void CellRef::setLockLevel(int lockLevel) + { + if (lockLevel != mCellRef.mLockLevel) + { + mChanged = true; + mCellRef.mLockLevel = lockLevel; + } + } + + std::string CellRef::getKey() const + { + return mCellRef.mKey; + } + + std::string CellRef::getTrap() const + { + return mCellRef.mTrap; + } + + void CellRef::setTrap(const std::string& trap) + { + if (trap != mCellRef.mTrap) + { + mChanged = true; + mCellRef.mTrap = trap; + } + } + + int CellRef::getGoldValue() const + { + return mCellRef.mGoldValue; + } + + void CellRef::setGoldValue(int value) + { + if (value != mCellRef.mGoldValue) + { + mChanged = true; + mCellRef.mGoldValue = value; + } + } + + void CellRef::writeState(ESM::ObjectState &state) const + { + state.mRef = mCellRef; + } + + bool CellRef::hasChanged() const + { + return mChanged; + } + +} diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp new file mode 100644 index 0000000000..3b0c2251be --- /dev/null +++ b/apps/openmw/mwworld/cellref.hpp @@ -0,0 +1,99 @@ +#ifndef OPENMW_MWWORLD_CELLREF_H +#define OPENMW_MWWORLD_CELLREF_H + +#include + +namespace ESM +{ + class ObjectState; +} + +namespace MWWorld +{ + + /// \brief Encapsulated variant of ESM::CellRef with change tracking + class CellRef + { + public: + + CellRef (const ESM::CellRef& ref) + : mCellRef(ref) + { + mChanged = false; + } + + // Note: Currently unused for items in containers + ESM::RefNum getRefNum() const; + + // Id of object being referenced + std::string getRefId() const; + + // For doors - true if this door teleports to somewhere else, false + // if it should open through animation. + bool getTeleport() const; + + // Teleport location for the door, if this is a teleporting door. + ESM::Position getDoorDest() const; + + // Destination cell for doors (optional) + std::string getDestCell() const; + + // Scale applied to mesh + float getScale() const; + void setScale(float scale); + + // Position and rotation of this object within the cell + ESM::Position getPosition() const; + void setPosition (const ESM::Position& position); + + // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). + float getEnchantmentCharge() const; + + void setEnchantmentCharge(float charge); + + // For weapon or armor, this is the remaining item health. + // For tools (lockpicks, probes, repair hammer) it is the remaining uses. + int getCharge() const; + void setCharge(int charge); + + // The NPC that owns this object (and will get angry if you steal it) + std::string getOwner() const; + void setOwner(const std::string& owner); + + // ID of creature trapped in this soul gem + std::string getSoul() const; + void setSoul(const std::string& soul); + + // The faction that owns this object (and will get angry if + // you take it and are not a faction member) + std::string getFaction() const; + void setFaction (const std::string& faction); + + // Lock level for doors and containers + // Positive for a locked door. 0 for a door that was never locked. + // For an unlocked door, it is set to -(previous locklevel) + int getLockLevel() const; + void setLockLevel(int lockLevel); + // Key and trap ID names, if any + std::string getKey() const; + std::string getTrap() const; + void setTrap(const std::string& trap); + + // This is 5 for Gold_005 references, 100 for Gold_100 and so on. + int getGoldValue() const; + void setGoldValue(int value); + + // Write the content of this CellRef into the given ObjectState + void writeState (ESM::ObjectState& state) const; + + // Has this CellRef changed since it was originally loaded? + bool hasChanged() const; + + private: + bool mChanged; + ESM::CellRef mCellRef; + }; + +} + +#endif diff --git a/apps/openmw/mwworld/cellreflist.hpp b/apps/openmw/mwworld/cellreflist.hpp index 264929bfb5..9c3370f08a 100644 --- a/apps/openmw/mwworld/cellreflist.hpp +++ b/apps/openmw/mwworld/cellreflist.hpp @@ -27,7 +27,7 @@ namespace MWWorld LiveRef *find (const std::string& name) { for (typename List::iterator iter (mList.begin()); iter!=mList.end(); ++iter) - if (iter->mData.getCount() > 0 && iter->mRef.mRefID == name) + if (iter->mData.getCount() > 0 && iter->mRef.getRefId() == name) return &*iter; return 0; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 04d733e2c4..63cdbfb1a3 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -72,8 +72,16 @@ namespace iter (collection.mList.begin()); iter!=collection.mList.end(); ++iter) { - if (iter->mData.getCount()==0 && iter->mRef.mRefNum.mContentFile==-1) - continue; // deleted reference that did not come from a content file -> ignore + if (!iter->mData.hasChanged() && !iter->mRef.hasChanged() && iter->mRef.getRefNum().mContentFile != -1) + { + // Reference that came from a content file and has not been changed -> ignore + continue; + } + if (iter->mData.getCount()==0 && iter->mRef.getRefNum().mContentFile==-1) + { + // Deleted reference that did not come from a content file -> ignore + continue; + } RecordType state; iter->save (state); @@ -117,7 +125,7 @@ namespace { for (typename MWWorld::CellRefList::List::iterator iter (collection.mList.begin()); iter!=collection.mList.end(); ++iter) - if (iter->mRef.mRefNum==state.mRef.mRefNum) + if (iter->mRef.getRefNum()==state.mRef.mRefNum) { // overwrite existing reference iter->load (state); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 100e758f24..c13ecfab5a 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -82,6 +82,14 @@ namespace MWWorld return false; } + int Class::getItemHealth(const Ptr &ptr) const + { + if (ptr.getCellRef().getCharge() == -1) + return getItemMaxHealth(ptr); + else + return ptr.getCellRef().getCharge(); + } + int Class::getItemMaxHealth (const Ptr& ptr) const { throw std::runtime_error ("class does not have item health"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 54cea9ab01..c3f94d7f10 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -116,9 +116,12 @@ namespace MWWorld virtual bool hasItemHealth (const Ptr& ptr) const; ///< \return Item health data available? (default implementation: false) + virtual int getItemHealth (const Ptr& ptr) const; + ///< Return current item health or throw an exception if class does not have item health + virtual int getItemMaxHealth (const Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health - /// (default implementation: throw an exceoption) + /// (default implementation: throw an exception) virtual void hit(const Ptr& ptr, int type=-1) const; ///< Execute a melee hit, using the current weapon. This will check the relevant skills diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index d816f993bd..2496a6eff4 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -74,7 +74,6 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::getState (CellRefList ref (record); ref.load (state); - ref.mRef.mRefNum.mContentFile = -1; collection.mList.push_back (ref); return ContainerStoreIterator (this, --collection.mList.end()); @@ -127,7 +126,7 @@ int MWWorld::ContainerStore::count(const std::string &id) { int total=0; for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, id)) + if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id)) total += iter->getRefData().getCount(); return total; } @@ -145,7 +144,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const MWWorld::Class& cls1 = ptr1.getClass(); const MWWorld::Class& cls2 = ptr2.getClass(); - if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().mRefID, ptr2.getCellRef().mRefID)) + if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().getRefId(), ptr2.getCellRef().getRefId())) return false; // If it has an enchantment, don't stack when some of the charge is already used @@ -154,25 +153,24 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find( ptr1.getClass().getEnchantment(ptr1)); float maxCharge = enchantment->mData.mCharge; - float enchantCharge1 = ptr1.getCellRef().mEnchantmentCharge == -1 ? maxCharge : ptr1.getCellRef().mEnchantmentCharge; - float enchantCharge2 = ptr2.getCellRef().mEnchantmentCharge == -1 ? maxCharge : ptr2.getCellRef().mEnchantmentCharge; + float enchantCharge1 = ptr1.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr1.getCellRef().getEnchantmentCharge(); + float enchantCharge2 = ptr2.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr2.getCellRef().getEnchantmentCharge(); if (enchantCharge1 != maxCharge || enchantCharge2 != maxCharge) return false; } return ptr1 != ptr2 // an item never stacks onto itself - && ptr1.getCellRef().mOwner == ptr2.getCellRef().mOwner - && ptr1.getCellRef().mSoul == ptr2.getCellRef().mSoul + && ptr1.getCellRef().getOwner() == ptr2.getCellRef().getOwner() + && ptr1.getCellRef().getSoul() == ptr2.getCellRef().getSoul() && ptr1.getClass().getRemainingUsageTime(ptr1) == ptr2.getClass().getRemainingUsageTime(ptr2) && cls1.getScript(ptr1) == cls2.getScript(ptr2) // item that is already partly used up never stacks - && (!cls1.hasItemHealth(ptr1) || ptr1.getCellRef().mCharge == -1 - || cls1.getItemMaxHealth(ptr1) == ptr1.getCellRef().mCharge) - && (!cls2.hasItemHealth(ptr2) || ptr2.getCellRef().mCharge == -1 - || cls2.getItemMaxHealth(ptr2) == ptr2.getCellRef().mCharge); + && (!cls1.hasItemHealth(ptr1) || ( + cls1.getItemHealth(ptr1) == cls1.getItemMaxHealth(ptr1) + && cls2.getItemHealth(ptr2) == cls2.getItemMaxHealth(ptr2))); } MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string &id, int count, const Ptr &actorPtr) @@ -195,19 +193,19 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr { // HACK: Set owner on the original item, then reset it after we have copied it // If we set the owner on the copied item, it would not stack correctly... - std::string oldOwner = itemPtr.getCellRef().mOwner; + std::string oldOwner = itemPtr.getCellRef().getOwner(); if (actorPtr == player) { // No point in setting owner to the player - NPCs will not respect this anyway // Additionally, setting it to "player" would make those items not stack with items that don't have an owner - itemPtr.getCellRef().mOwner = ""; + itemPtr.getCellRef().setOwner(""); } else - itemPtr.getCellRef().mOwner = actorPtr.getCellRef().mRefID; + itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId()); it = addImp(itemPtr, count); - itemPtr.getCellRef().mOwner = oldOwner; + itemPtr.getCellRef().setOwner(oldOwner); } else { @@ -219,12 +217,14 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr // we may have copied an item from the world, so reset a few things first item.getRefData().setBaseNode(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell - item.getCellRef().mPos.rot[0] = 0; - item.getCellRef().mPos.rot[1] = 0; - item.getCellRef().mPos.rot[2] = 0; - item.getCellRef().mPos.pos[0] = 0; - item.getCellRef().mPos.pos[1] = 0; - item.getCellRef().mPos.pos[2] = 0; + ESM::Position pos; + pos.rot[0] = 0; + pos.rot[1] = 0; + pos.rot[2] = 0; + pos.pos[0] = 0; + pos.pos[1] = 0; + pos.pos[2] = 0; + item.getCellRef().setPosition(pos); std::string script = item.getClass().getScript(item); if(script != "") @@ -259,17 +259,17 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, // gold needs special handling: when it is inserted into a container, the base object automatically becomes Gold_001 // this ensures that gold piles of different sizes stack with each other (also, several scripts rely on Gold_001 for detecting player gold) - if (Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100")) + if (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "gold_100")) { int realCount = count * ptr.getClass().getValue(ptr); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (Misc::StringUtils::ciEqual((*iter).getCellRef().mRefID, MWWorld::ContainerStore::sGoldId)) + if (Misc::StringUtils::ciEqual((*iter).getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) { iter->getRefData().setCount(iter->getRefData().getCount() + realCount); flagAsModified(); @@ -328,7 +328,7 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const int toRemove = count; for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, itemId)) + if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) toRemove -= remove(*iter, toRemove, actor); flagAsModified(); @@ -408,8 +408,8 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: } count = std::abs(count); - ref.getPtr().getCellRef().mOwner = owner; - ref.getPtr().getCellRef().mFaction = faction; + ref.getPtr().getCellRef().setOwner(owner); + ref.getPtr().getCellRef().setFaction(faction); addImp (ref.getPtr(), count); } } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 78a2950304..2eb8aeb465 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -206,7 +206,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) // 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().mOwner, actor.getCellRef().mRefID) && + if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && (actor.getClass().getScript(actor).empty() || !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) continue; @@ -337,7 +337,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) std::vector params; - bool existed = (mPermanentMagicEffectMagnitudes.find((**iter).getCellRef().mRefID) != mPermanentMagicEffectMagnitudes.end()); + bool existed = (mPermanentMagicEffectMagnitudes.find((**iter).getCellRef().getRefId()) != mPermanentMagicEffectMagnitudes.end()); if (!existed) { // Roll some dice, one for each effect @@ -358,10 +358,10 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) // Consider equipping the same item twice (e.g. a ring) // However, permanent enchantments with a random magnitude are kind of an exploit anyway, // so it doesn't really matter if both items will get the same magnitude. *Extreme* edge case. - mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID] = params; + mPermanentMagicEffectMagnitudes[(**iter).getCellRef().getRefId()] = params; } else - params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID]; + params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().getRefId()]; int i=0; for (std::vector::const_iterator effectIt (enchantment.mEffects.mList.begin()); @@ -407,7 +407,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) { if (*iter == end()) continue; - if ((**iter).getCellRef().mRefID == it->first) + if ((**iter).getCellRef().getRefId() == it->first) { found = true; } @@ -589,14 +589,14 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito if (enchantment.mData.mType != ESM::Enchantment::ConstantEffect) continue; - if (mPermanentMagicEffectMagnitudes.find((**iter).getCellRef().mRefID) == mPermanentMagicEffectMagnitudes.end()) + if (mPermanentMagicEffectMagnitudes.find((**iter).getCellRef().getRefId()) == mPermanentMagicEffectMagnitudes.end()) continue; int i=0; for (std::vector::const_iterator effectIt (enchantment.mEffects.mList.begin()); effectIt!=enchantment.mEffects.mList.end(); ++effectIt) { - const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i]; + const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().getRefId()][i]; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom; magnitude *= params.mMultiplier; visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), -1, magnitude); @@ -626,15 +626,15 @@ void MWWorld::InventoryStore::rechargeItems(float duration) { for (TRechargingItems::iterator it = mRechargingItems.begin(); it != mRechargingItems.end(); ++it) { - if (it->first->getCellRef().mEnchantmentCharge == -1 - || it->first->getCellRef().mEnchantmentCharge == it->second) + if (it->first->getCellRef().getEnchantmentCharge() == -1 + || it->first->getCellRef().getEnchantmentCharge() == it->second) continue; static float fMagicItemRechargePerSecond = MWBase::Environment::get().getWorld()->getStore().get().find( "fMagicItemRechargePerSecond")->getFloat(); - it->first->getCellRef().mEnchantmentCharge = std::min (it->first->getCellRef().mEnchantmentCharge + fMagicItemRechargePerSecond * duration, - it->second); + it->first->getCellRef().setEnchantmentCharge(std::min (it->first->getCellRef().getEnchantmentCharge() + fMagicItemRechargePerSecond * duration, + it->second)); } } diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index 1b13e38038..0921d3a1b5 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -11,7 +11,7 @@ #include "esmstore.hpp" MWWorld::LiveCellRefBase::LiveCellRefBase(std::string type, const ESM::CellRef &cref) - : mClass(&Class::get(type)), mRef(cref), mData(mRef) + : mClass(&Class::get(type)), mRef(cref), mData(cref) { } @@ -41,7 +41,7 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state) void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const { - state.mRef = mRef; + mRef.writeState(state); /// \todo get rid of this cast once const-correct Ptr are available Ptr ptr (const_cast (this)); diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index b2e4d6d567..3994d8a249 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -3,7 +3,7 @@ #include -#include +#include "cellref.hpp" #include "refdata.hpp" @@ -26,7 +26,7 @@ namespace MWWorld /** Information about this instance, such as 3D location and rotation * and individual type-dependent data. */ - ESM::CellRef mRef; + MWWorld::CellRef mRef; /** runtime-data */ RefData mData; @@ -62,9 +62,9 @@ namespace MWWorld /// \note Does not check if the RefId exists. }; - inline bool operator== (const LiveCellRefBase& cellRef, const ESM::CellRef::RefNum refNum) + inline bool operator== (const LiveCellRefBase& cellRef, const ESM::RefNum refNum) { - return cellRef.mRef.mRefNum==refNum; + return cellRef.mRef.getRefNum()==refNum; } /// A reference to one object (of any type) in a cell. diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 99accbb979..3842e7ff1b 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -23,10 +23,20 @@ namespace MWWorld { const T* base = list.find(name); - LiveCellRef ref; - ref.mBase = base; - ref.mRef.mRefNum.mIndex = 0; - ref.mRef.mRefNum.mContentFile = -1; + ESM::CellRef cellRef; + cellRef.mRefNum.mIndex = 0; + cellRef.mRefNum.mContentFile = -1; + cellRef.mRefID = name; + cellRef.mScale = 1; + cellRef.mFactIndex = 0; + cellRef.mCharge = -1; + cellRef.mGoldValue = 1; + cellRef.mEnchantmentCharge = -1; + cellRef.mTeleport = false; + cellRef.mLockLevel = 0; + cellRef.mReferenceBlocked = 0; + + LiveCellRef ref(cellRef, base); mRef = ref; mPtr = Ptr (&boost::any_cast&> (mRef), 0); @@ -67,19 +77,6 @@ namespace MWWorld throw std::logic_error ("failed to create manual cell ref for " + lowerName + " (unknown type)"); } - // initialise - ESM::CellRef& cellRef = mPtr.getCellRef(); - cellRef.mRefID = lowerName; - cellRef.mRefNum.mIndex = 0; - cellRef.mRefNum.mContentFile = -1; - cellRef.mScale = 1; - cellRef.mFactIndex = 0; - cellRef.mCharge = -1; - cellRef.mGoldValue = 1; - cellRef.mEnchantmentCharge = -1; - cellRef.mTeleport = false; - cellRef.mLockLevel = 0; - cellRef.mReferenceBlocked = 0; mPtr.getRefData().setCount(count); } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 039fce0caa..b8f0f8699b 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -656,7 +656,7 @@ namespace MWWorld return false; } btVector3 btMin, btMax; - float scale = ptr.getCellRef().mScale; + float scale = ptr.getCellRef().getScale(); mEngine->getObjectAABB(model, scale, btMin, btMax); min.x = btMin.x(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 5ca8f29525..9913b888b2 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -39,8 +39,10 @@ namespace MWWorld mCurrentCrimeId(-1), mPaidCrimeId(-1) { - mPlayer.mBase = player; - mPlayer.mRef.mRefID = "player"; + ESM::CellRef cellRef; + cellRef.blank(); + cellRef.mRefID = "player"; + mPlayer = LiveCellRef(cellRef, player); float* playerPos = mPlayer.mData.getPosition().pos; playerPos[0] = playerPos[1] = playerPos[2] = 0; diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 12cca27545..4e4f0b271a 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -102,11 +102,11 @@ namespace MWWorld { ProjectileState state; state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); - state.mBowId = bow.getCellRef().mRefID; + state.mBowId = bow.getCellRef().getRefId(); state.mVelocity = orient.yAxis() * speed; - state.mId = projectile.getCellRef().mRefID; + state.mId = projectile.getCellRef().getRefId(); - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().mRefID); + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().getRefId()); MWWorld::Ptr ptr = ref.getPtr(); state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos, orient); @@ -241,7 +241,7 @@ namespace MWWorld { MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster); MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().mRefID, it->mBowId)) + if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId)) bow = *invIt; } diff --git a/apps/openmw/mwworld/ptr.cpp b/apps/openmw/mwworld/ptr.cpp index b047ba47ca..1cf22744a8 100644 --- a/apps/openmw/mwworld/ptr.cpp +++ b/apps/openmw/mwworld/ptr.cpp @@ -22,7 +22,7 @@ MWWorld::LiveCellRefBase *MWWorld::Ptr::getBase() const return mRef; } -ESM::CellRef& MWWorld::Ptr::getCellRef() const +MWWorld::CellRef& MWWorld::Ptr::getCellRef() const { assert(mRef); diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index f4696d3b3b..2f37a1cfd8 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -60,7 +60,7 @@ namespace MWWorld MWWorld::LiveCellRefBase *getBase() const; - ESM::CellRef& getCellRef() const; + MWWorld::CellRef& getCellRef() const; RefData& getRefData() const; diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 008782130b..2e267b37ce 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -22,6 +22,7 @@ namespace MWWorld mCount = refData.mCount; mPosition = refData.mPosition; mLocalRotation = refData.mLocalRotation; + mChanged = refData.mChanged; mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0; } @@ -35,7 +36,7 @@ namespace MWWorld } RefData::RefData() - : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0) + : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false) { for (int i=0; i<3; ++i) { @@ -47,7 +48,8 @@ namespace MWWorld RefData::RefData (const ESM::CellRef& cellRef) : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.mPos), - mCustomData (0) + mCustomData (0), + mChanged(false) // Loading from ESM/ESP files -> assume unchanged { mLocalRotation.rot[0]=0; mLocalRotation.rot[1]=0; @@ -56,8 +58,9 @@ namespace MWWorld RefData::RefData (const ESM::ObjectState& objectState) : mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled), - mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0) - { + mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0), + mChanged(true) // Loading from a savegame -> assume changed + { for (int i=0; i<3; ++i) mLocalRotation.rot[i] = objectState.mLocalRotation[i]; } @@ -149,6 +152,7 @@ namespace MWWorld { mLocals.configure (script); mHasLocals = true; + mChanged = true; } } @@ -157,6 +161,8 @@ namespace MWWorld if(count == 0) MWBase::Environment::get().getWorld()->removeRefScript(this); + mChanged = true; + mCount = count; } @@ -172,26 +178,31 @@ namespace MWWorld void RefData::enable() { + mChanged = !mEnabled; mEnabled = true; } void RefData::disable() { + mChanged = mEnabled; mEnabled = false; } ESM::Position& RefData::getPosition() { + mChanged = true; return mPosition; } LocalRotation& RefData::getLocalRotation() { + mChanged = true; return mLocalRotation; } void RefData::setCustomData (CustomData *data) { + mChanged = true; // We do not currently track CustomData, so assume anything with a CustomData is changed delete mCustomData; mCustomData = data; } @@ -200,4 +211,9 @@ namespace MWWorld { return mCustomData; } + + bool RefData::hasChanged() const + { + return mChanged; + } } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 82371b056a..a8ffad6843 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -47,6 +47,8 @@ namespace MWWorld void cleanup(); + bool mChanged; + public: RefData(); @@ -108,6 +110,9 @@ namespace MWWorld CustomData *getCustomData(); ///< May return a 0-pointer. The ownership of the return data object is not transferred. + + bool hasChanged() const; + ///< Has this RefData changed since it was originally loaded? }; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 122a6f9bf5..32bf773bd5 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -47,10 +47,10 @@ namespace { if (mRescale) { - if (ptr.getCellRef().mScale<0.5) - ptr.getCellRef().mScale = 0.5; - else if (ptr.getCellRef().mScale>2) - ptr.getCellRef().mScale = 2; + if (ptr.getCellRef().getScale()<0.5) + ptr.getCellRef().setScale(0.5); + else if (ptr.getCellRef().getScale()>2) + ptr.getCellRef().setScale(2); } if (ptr.getRefData().getCount() && ptr.getRefData().isEnabled()) @@ -65,7 +65,7 @@ namespace float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees(); MWBase::Environment::get().getWorld()->localRotateObject (ptr, ax, ay, az); - MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().mScale); + MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale()); ptr.getClass().adjustPosition (ptr); } catch (const std::exception& e) @@ -484,7 +484,7 @@ namespace MWWorld mRendering.addObject(ptr); ptr.getClass().insertObject(ptr, *mPhysics); MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true); - MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale); + MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale()); } void Scene::removeObjectFromScene (const Ptr& ptr) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5a83a5bc74..727b200f57 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1034,7 +1034,7 @@ namespace MWWorld void World::scaleObject (const Ptr& ptr, float scale) { - ptr.getCellRef().mScale = scale; + ptr.getCellRef().setScale(scale); ptr.getClass().adjustScale(ptr,scale); if(ptr.getRefData().getBaseNode() == 0) @@ -1544,7 +1544,7 @@ namespace MWWorld if (!ref.mData.isEnabled()) continue; - if (ref.mRef.mTeleport) + if (ref.mRef.getTeleport()) { World::DoorMarker newMarker; newMarker.name = MWClass::Door::getDestination(ref); @@ -1948,7 +1948,7 @@ namespace MWWorld for (CellRefList::List::iterator container = refList.begin(); container != refList.end(); ++container) { MWWorld::Ptr ptr (&*container, *cellIt); - if (Misc::StringUtils::ciEqual(ptr.getCellRef().mOwner, npc.getCellRef().mRefID)) + if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), npc.getCellRef().getRefId())) out.push_back(ptr); } } @@ -1976,7 +1976,7 @@ namespace MWWorld (*cellIt)->forEach(functor); for (std::vector::iterator it = functor.mHandles.begin(); it != functor.mHandles.end(); ++it) - if (Misc::StringUtils::ciEqual(searchPtrViaHandle(*it).getCellRef().mOwner, npc.getCellRef().mRefID)) + if (Misc::StringUtils::ciEqual(searchPtrViaHandle(*it).getCellRef().getOwner(), npc.getCellRef().getRefId())) out.push_back(searchPtrViaHandle(*it)); } } @@ -2032,34 +2032,34 @@ namespace MWWorld } const DoorList &doors = cellStore->get().mList; for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) { - if (!it->mRef.mTeleport) { + if (!it->mRef.getTeleport()) { continue; } MWWorld::CellStore *source = 0; // door to exterior - if (it->mRef.mDestCell.empty()) { + if (it->mRef.getDestCell().empty()) { int x, y; - const float *pos = it->mRef.mDoorDest.pos; + const float *pos = it->mRef.getDoorDest().pos; positionToIndex(pos[0], pos[1], x, y); source = getExterior(x, y); } // door to interior else { - source = getInterior(it->mRef.mDestCell); + source = getInterior(it->mRef.getDestCell()); } if (0 != source) { // Find door leading to our current teleport door // and use it destination to position inside cell. const DoorList &doors = source->get().mList; for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) { - if (it->mRef.mTeleport && - Misc::StringUtils::ciEqual(name, jt->mRef.mDestCell)) + if (it->mRef.getTeleport() && + Misc::StringUtils::ciEqual(name, jt->mRef.getDestCell())) { /// \note Using _any_ door pointed to the interior, /// not the one pointed to current door. - pos = jt->mRef.mDoorDest; + pos = jt->mRef.getDoorDest(); return true; } } @@ -2322,9 +2322,9 @@ namespace MWWorld for (CellRefList::List::iterator it = refList.begin(); it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; - if (ref.mRef.mTeleport && ref.mRef.mDestCell.empty()) + if (ref.mRef.getTeleport() && ref.mRef.getDestCell().empty()) { - ESM::Position pos = ref.mRef.mDoorDest; + ESM::Position pos = ref.mRef.getDoorDest(); result = Ogre::Vector3(pos.pos); return true; } @@ -2520,13 +2520,13 @@ namespace MWWorld ContainerStore& store = ptr.getClass().getContainerStore(ptr); for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest { - if (!it->getCellRef().mOwner.empty() && it->getCellRef().mOwner != "player") //Not owned by no one/player? + if (!it->getCellRef().getOwner().empty() && it->getCellRef().getOwner() != "player") //Not owned by no one/player? { closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest); store.remove(*it, it->getRefData().getCount(), ptr); } } - closestChest.getCellRef().mLockLevel = abs(closestChest.getCellRef().mLockLevel); + closestChest.getClass().unlock(closestChest); } } @@ -2630,7 +2630,7 @@ namespace MWWorld MWWorld::CellStore* cell = mPlayer->getPlayer().getCell(); MWWorld::ManualRef ref(getStore(), selectedCreature, 1); - ref.getPtr().getCellRef().mPos = ipos; + ref.getPtr().getCellRef().setPosition(ipos); safePlaceObject(ref.getPtr(), cell, ipos); } diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index f04e819c88..84518bed90 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -168,7 +168,7 @@ void ESM::CellRef::blank() } } -bool ESM::operator== (const CellRef::RefNum& left, const CellRef::RefNum& right) +bool ESM::operator== (const RefNum& left, const RefNum& right) { return left.mIndex==right.mIndex && left.mContentFile==right.mContentFile; } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 16f6603a28..5f53eadbe3 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -10,6 +10,13 @@ namespace ESM class ESMWriter; class ESMReader; + + struct RefNum + { + int mIndex; + int mContentFile; // -1 no content file + }; + /* Cell reference. This represents ONE object (of many) inside the cell. The cell references are not loaded as part of the normal loading process, but are rather loaded later on demand when we are @@ -20,13 +27,10 @@ namespace ESM { public: - struct RefNum - { - int mIndex; - int mContentFile; // -1 no content file - }; + // Reference number + // Note: Currently unused for items in containers + RefNum mRefNum; - RefNum mRefNum; // Reference number std::string mRefID; // ID of object being referenced float mScale; // Scale applied to mesh @@ -38,7 +42,7 @@ namespace ESM // I have no idea, looks like a link to a global variable? std::string mGlob; - // ID of creature trapped in this soul gem (?) + // ID of creature trapped in this soul gem std::string mSoul; // The faction that owns this object (and will get angry if @@ -53,7 +57,7 @@ namespace ESM // For tools (lockpicks, probes, repair hammer) it is the remaining uses. int mCharge; - // Remaining enchantment charge + // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). float mEnchantmentCharge; // This is 5 for Gold_005 references, 100 for Gold_100 and so on. @@ -94,7 +98,7 @@ namespace ESM void blank(); }; - bool operator== (const CellRef::RefNum& left, const CellRef::RefNum& right); + bool operator== (const RefNum& left, const RefNum& right); } #endif diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 55d043c8a4..0830c5de69 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -16,7 +16,7 @@ namespace { ///< Translate 8bit/24bit code (stored in refNum.mIndex) into a proper refNum - void adjustRefNum (ESM::CellRef::RefNum& refNum, ESM::ESMReader& reader) + void adjustRefNum (ESM::RefNum& refNum, ESM::ESMReader& reader) { int local = (refNum.mIndex & 0xff000000) >> 24; @@ -40,12 +40,12 @@ namespace ESM unsigned int Cell::sRecordId = REC_CELL; // Some overloaded compare operators. - bool operator== (const MovedCellRef& ref, const CellRef::RefNum& refNum) + bool operator== (const MovedCellRef& ref, const RefNum& refNum) { return ref.mRefNum == refNum; } - bool operator== (const CellRef& ref, const CellRef::RefNum& refNum) + bool operator== (const CellRef& ref, const RefNum& refNum) { return ref.mRefNum == refNum; } diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index f01c88c65d..28204c9ee1 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -28,7 +28,7 @@ class ESMWriter; class MovedCellRef { public: - CellRef::RefNum mRefNum; + RefNum mRefNum; // Target cell (if exterior) int mTarget[2]; @@ -39,8 +39,8 @@ public: }; /// Overloaded compare operator used to search inside a list of cell refs. -bool operator==(const MovedCellRef& ref, const CellRef::RefNum& refNum); -bool operator==(const CellRef& ref, const CellRef::RefNum& refNum); +bool operator==(const MovedCellRef& ref, const RefNum& refNum); +bool operator==(const CellRef& ref, const RefNum& refNum); typedef std::list MovedCellRefTracker; typedef std::list CellRefTracker; From 10d835a55c2d1bbd4fac3950d6253245e10a0feb Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 May 2014 15:06:53 +0200 Subject: [PATCH 393/545] Some more missing isInCell checks --- apps/openmw/mwscript/cellextensions.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index ac175634bd..2e2e9b6985 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -142,6 +142,11 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + runtime.push(0.f); + return; + } MWWorld::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(); if (cell->getCell()->hasWater()) runtime.push (cell->getWaterLevel()); @@ -158,6 +163,11 @@ namespace MWScript { Interpreter::Type_Float level = runtime[0].mFloat; + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + return; + } + MWWorld::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(); if (cell->getCell()->isExterior()) @@ -176,6 +186,11 @@ namespace MWScript { Interpreter::Type_Float level = runtime[0].mFloat; + if (!MWBase::Environment::get().getWorld()->getPlayerPtr().isInCell()) + { + return; + } + MWWorld::CellStore *cell = MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(); if (cell->getCell()->isExterior()) From befc7a40781cea62819e8d6de64bb2b848f22f93 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sun, 25 May 2014 15:46:23 +0200 Subject: [PATCH 394/545] adding column for the content of the container --- CMakeLists.txt | 4 -- apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/idtable.cpp | 1 + apps/opencs/model/world/refidadapterimp.cpp | 4 +- apps/opencs/model/world/refidadapterimp.hpp | 7 ++-- apps/opencs/model/world/refidcollection.cpp | 5 ++- apps/opencs/model/world/refiddata.hpp | 42 ++++++++++----------- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 392fdfc66c..9168d9a5a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,16 +38,12 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/.git) set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}") - if(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) - message(FATAL_ERROR "Silly Zini forgot to update the version again...") - else(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR}) set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR}) set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE}) set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}") set(OPENMW_VERSION_TAGHASH "${TAGHASH}") - endif(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION}) message(STATUS "OpenMW version ${OPENMW_VERSION}") else(MATCH) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 855e89cade..fa9c92e7d6 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -167,6 +167,7 @@ namespace CSMWorld ColumnId_PcRank = 154, ColumnId_Scope = 155, ColumnId_ReferenceableId = 156, + ColumnId_ContainerContent = 157, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 50998c36f1..31797d0812 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -130,6 +130,7 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin, CSMWorld::UniversalId::Type type) { int index = mIdCollection->getAppendIndex (destination); + beginInsertRows (QModelIndex(), index, index); mIdCollection->cloneRecord(origin, destination, type); endInsertRows(); diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index f00e9fc77b..afb61acc6b 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -173,9 +173,9 @@ void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdDa } CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns, - const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn) + const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content) : NameRefIdAdapter (UniversalId::Type_Container, columns), mWeight (weight), - mOrganic (organic), mRespawn (respawn) + mOrganic (organic), mRespawn (respawn), mContent(content) {} QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index bd509a86b6..59c8c64614 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -34,7 +34,7 @@ namespace CSMWorld BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base); 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) @@ -57,7 +57,7 @@ namespace CSMWorld { (dynamic_cast&> (record).get().mId) = id; } - + template std::string BaseRefIdAdapter::getId (const RecordBase& record) const { @@ -610,11 +610,12 @@ namespace CSMWorld const RefIdColumn *mWeight; const RefIdColumn *mOrganic; const RefIdColumn *mRespawn; + const RefIdColumn *mContent; public: ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, - const RefIdColumn *organic, const RefIdColumn *respawn); + const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index f515e34d8e..1745ce957f 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -165,6 +165,9 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean)); const RefIdColumn *respawn = &mColumns.back(); + mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_None, ColumnBase::Flag_Dialogue, false, false)); + const RefIdColumn *content = &mColumns.back(); + CreatureColumns creatureColumns (actorsColumns); mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType)); @@ -340,7 +343,7 @@ CSMWorld::RefIdCollection::RefIdCollection() mAdapters.insert (std::make_pair (UniversalId::Type_Clothing, new ClothingRefIdAdapter (enchantableColumns, clothingType))); mAdapters.insert (std::make_pair (UniversalId::Type_Container, - new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn))); + new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn, content))); mAdapters.insert (std::make_pair (UniversalId::Type_Creature, new CreatureRefIdAdapter (creatureColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_Door, diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 1b600364c7..535e914ee0 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -231,27 +231,27 @@ namespace CSMWorld void save (int index, ESM::ESMWriter& writer) const; - //RECORD CONTAINERS ACCESS METHODS - const RefIdDataContainer& getBooks() const; - const RefIdDataContainer& getActivators() const; - const RefIdDataContainer& getPotions() const; - const RefIdDataContainer& getApparati() const; - const RefIdDataContainer& getArmors() const; - const RefIdDataContainer& getClothing() const; - const RefIdDataContainer& getContainers() const; - const RefIdDataContainer& getCreatures() const; - const RefIdDataContainer& getDoors() const; - const RefIdDataContainer& getIngredients() const; - const RefIdDataContainer& getCreatureLevelledLists() const; - const RefIdDataContainer& getItemLevelledList() const; - const RefIdDataContainer& getLights() const; - const RefIdDataContainer& getLocpicks() const; - const RefIdDataContainer& getMiscellaneous() const; - const RefIdDataContainer& getNPCs() const; - const RefIdDataContainer& getWeapons() const; - const RefIdDataContainer& getProbes() const; - const RefIdDataContainer& getRepairs() const; - const RefIdDataContainer& getStatics() const; + //RECORD CONTAINERS ACCESS METHODS + const RefIdDataContainer& getBooks() const; + const RefIdDataContainer& getActivators() const; + const RefIdDataContainer& getPotions() const; + const RefIdDataContainer& getApparati() const; + const RefIdDataContainer& getArmors() const; + const RefIdDataContainer& getClothing() const; + const RefIdDataContainer& getContainers() const; + const RefIdDataContainer& getCreatures() const; + const RefIdDataContainer& getDoors() const; + const RefIdDataContainer& getIngredients() const; + const RefIdDataContainer& getCreatureLevelledLists() const; + const RefIdDataContainer& getItemLevelledList() const; + const RefIdDataContainer& getLights() const; + const RefIdDataContainer& getLocpicks() const; + const RefIdDataContainer& getMiscellaneous() const; + const RefIdDataContainer& getNPCs() const; + const RefIdDataContainer& getWeapons() const; + const RefIdDataContainer& getProbes() const; + const RefIdDataContainer& getRepairs() const; + const RefIdDataContainer& getStatics() const; }; } From 8fa7fcdbee3d63d61120526b24ef3b104c01e718 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 25 May 2014 21:03:37 +0400 Subject: [PATCH 395/545] fix bug http://bugs.openmw.org/issues/1335 (1304 as well) though fish detects if actor is swimming, but in MW it attacks even if the player is knee-deep in water --- apps/openmw/mwmechanics/actors.cpp | 8 +++++ apps/openmw/mwmechanics/aicombat.cpp | 29 +++++++++++++------ .../mwmechanics/mechanicsmanagerimp.cpp | 4 ++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 35667a23c4..fe89fda11b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -191,6 +191,14 @@ namespace MWMechanics if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player + // pure water creatures won't try to fight with the target on the ground + // except that creature is already hostile + if ((againstPlayer || !creatureStats.isHostile()) + && ((actor1.getClass().canSwim(actor1) && !actor1.getClass().canWalk(actor1) // pure water creature + && !MWBase::Environment::get().getWorld()->isSwimming(actor2)) + || (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target + return; + float fight; if (againstPlayer) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 9fe92f8070..8f81885597 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -53,7 +53,7 @@ namespace // cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target; // magnitude of pits/obstacles is defined by PATHFIND_Z_REACH - bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offset) + bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offsetXY) { if((to - from).length() >= PATHFIND_CAUTION_DIST || abs(from.z - to.z) <= PATHFIND_Z_REACH) { @@ -61,7 +61,7 @@ namespace dir.z = 0; dir.normalise(); float verticalOffset = 200; // instead of '200' here we want the height of the actor - Ogre::Vector3 _from = from + dir*offset + Ogre::Vector3::UNIT_Z * verticalOffset; + Ogre::Vector3 _from = from + dir*offsetXY + Ogre::Vector3::UNIT_Z * verticalOffset; // cast up-down ray and find height in world space of hit float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1); @@ -149,13 +149,24 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description - if(actor.getClass().getCreatureStats(actor).isDead()) return true; + if(actor.getClass().getCreatureStats(actor).isDead()) + return true; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); if(target.getClass().getCreatureStats(target).isDead()) return true; + if (!actor.getClass().isNpc() && target == MWBase::Environment::get().getWorld()->getPlayerPtr() && + (actor.getClass().canSwim(actor) && !actor.getClass().canWalk(actor) // pure water creature + && !MWBase::Environment::get().getWorld()->isSwimming(target)) // Player moved out of water + || (!actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(target))) // creature can't swim to Player + { + actor.getClass().getCreatureStats(actor).setHostile(false); + actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); + return true; + } + //Update every frame if(mCombatMove) { @@ -327,6 +338,7 @@ namespace MWMechanics Ogre::Vector3 vActorPos(pos.pos); Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; + float distToTarget = vDirToTarget.length(); bool isStuck = false; float speed = 0.0f; @@ -342,16 +354,15 @@ namespace MWMechanics // determine vertical angle to target // if actor can move along z-axis it will control movement dir // if can't - it will control correct aiming - mMovement.mRotation[0] = getXAngleToDir(vDirToTarget); - - vDirToTarget.z = 0; - float distToTarget = vDirToTarget.length(); + mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); // (within strike dist) || (not quite strike dist while following) if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); + + // if we preserve dir.z then horizontal angle can be inaccurate + mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); // (not quite strike dist while following) if (mFollowTarget && distToTarget > rangeAttack) @@ -405,7 +416,7 @@ namespace MWMechanics if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; // *2 - for reliability - preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); + preferShortcut = checkWayIsClear(vActorPos, vTargetPos, Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); } // don't use pathgrid when actor can move in 3 dimensions diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5a72c88837..c9a1814618 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1024,7 +1024,9 @@ namespace MWMechanics void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) { - MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + if (ptr.getClass().isNpc()) + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) ptr.getClass().getCreatureStats(ptr).setHostile(true); From b3ffd5b868fe40e92b401f657a20717c36dc9a82 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 26 May 2014 01:42:11 -0400 Subject: [PATCH 396/545] Fix for bug Bug #1098 --- apps/openmw/mwworld/class.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index c3f94d7f10..4e36a8da9b 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -165,7 +165,7 @@ namespace MWWorld virtual bool hasInventoryStore (const Ptr& ptr) const; ///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false) - virtual void lock (const Ptr& ptr, int lockLevel) const; + virtual void lock (const Ptr& ptr, int lockLevel = 0) const; ///< Lock object (default implementation: throw an exception) virtual void unlock (const Ptr& ptr) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 727b200f57..b8d531a58a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2526,7 +2526,7 @@ namespace MWWorld store.remove(*it, it->getRefData().getCount(), ptr); } } - closestChest.getClass().unlock(closestChest); + closestChest.getClass().lock(closestChest); } } From 7697b9e868b13f611d67ef5355d797f106735ad8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 26 May 2014 01:48:24 -0400 Subject: [PATCH 397/545] Ensures nothing bad will happen if we try to lock a door that never had a lock level --- apps/openmw/mwclass/container.cpp | 8 ++++++-- apps/openmw/mwclass/door.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 9498ea52df..7b62ad04f0 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -262,8 +262,12 @@ namespace MWClass { if(lockLevel!=0) ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive - else - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one + else { + if(abs(ptr.getCellRef().getLockLevel())!=0) + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one + else + ptr.getCellRef().setLockLevel(100); //There never was a locklevel, give it the default biggest one + } } void Container::unlock (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 12645c9f39..0788896297 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -192,8 +192,12 @@ namespace MWClass { if(lockLevel!=0) ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive - else - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one + else { + if(abs(ptr.getCellRef().getLockLevel())!=0) + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one + else + ptr.getCellRef().setLockLevel(100); + } } void Door::unlock (const MWWorld::Ptr& ptr) const From 4aab4bae6528af0caa5f0f98b5037383d3b6fa5a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 May 2014 10:14:24 +0200 Subject: [PATCH 398/545] minor cleanup and silenced a warning --- apps/openmw/mwmechanics/aicombat.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index d14251886e..9ec770c9d1 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -149,7 +149,7 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description - if(actor.getClass().getCreatureStats(actor).isDead()) + if(actor.getClass().getCreatureStats(actor).isDead()) return true; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); @@ -157,13 +157,16 @@ namespace MWMechanics if(target.getClass().getCreatureStats(target).isDead()) return true; - if (!actor.getClass().isNpc() && target == MWBase::Environment::get().getWorld()->getPlayerPtr() && - (actor.getClass().canSwim(actor) && !actor.getClass().canWalk(actor) // pure water creature - && !MWBase::Environment::get().getWorld()->isSwimming(target)) // Player moved out of water - || (!actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(target))) // creature can't swim to Player + const MWWorld::Class& actorClass = actor.getClass(); + MWBase::World& world = *MWBase::Environment::get().getWorld(); + + if ((!actorClass.isNpc() && target == world.getPlayerPtr() && + actorClass.canSwim(actor) && !actorClass.canWalk(actor) // pure water creature + && !world.isSwimming(target)) // Player moved out of water + || (!actorClass.canSwim(actor) && world.isSwimming(target))) // creature can't swim to Player { - actor.getClass().getCreatureStats(actor).setHostile(false); - actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); + actorClass.getCreatureStats(actor).setHostile(false); + actorClass.getCreatureStats(actor).setAttackingOrSpell(false); return true; } @@ -360,9 +363,9 @@ namespace MWMechanics if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - + // if we preserve dir.z then horizontal angle can be inaccurate - mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); + mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); // (not quite strike dist while following) if (mFollowTarget && distToTarget > rangeAttack) @@ -408,7 +411,7 @@ namespace MWMechanics { bool preferShortcut = false; bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); - + // check if shortcut is available if(inLOS && (!isStuck || mReadyToAttack) && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) From bfd91c0681ee766256a0295a2c3f8b0502397167 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 12:31:08 +0200 Subject: [PATCH 399/545] Fix potential NpcStats overwriting issue --- apps/openmw/mwmechanics/npcstats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 24e758e32e..d50f2c5ae4 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -496,10 +496,10 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state) mExpelled.insert (iter->first); if (iter->second.mRank >= 0) - mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank)); + mFactionRank[iter->first] = iter->second.mRank; if (iter->second.mReputation) - mFactionReputation.insert (std::make_pair (iter->first, iter->second.mReputation)); + mFactionReputation[iter->first] = iter->second.mReputation; } mDisposition = state.mDisposition; From f629307f6050e69cfa295cee59ffbb00b9656591 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 16:43:19 +0200 Subject: [PATCH 400/545] Fix frame delay for sound listener position (Fixes #1180) --- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 727b200f57..43153612d7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1375,11 +1375,11 @@ namespace MWWorld updateWeather(duration); - mWorldScene->update (duration, paused); - if (!paused) doPhysics (duration); + mWorldScene->update (duration, paused); + performUpdateSceneQueries (); updateWindowManager (); From 3cd835e61a4a2e1b8e9d28fee5fa1a570459a96d Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 17:34:36 +0200 Subject: [PATCH 401/545] Fix bsa file loading not being case insensitive (Fixes #1178) --- apps/openmw/mwworld/esmstore.cpp | 2 +- components/files/collections.cpp | 35 ++++++++++++++++++----- files/mygui/openmw_settings_window.layout | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 1fdf3c5a50..fc2bd4d773 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -42,7 +42,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) for (int i = 0; i < esm.getIndex(); i++) { const std::string &candidate = allPlugins->at(i).getContext().filename; std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); - if (fname == fnamecandidate) { + if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { index = i; break; } diff --git a/components/files/collections.cpp b/components/files/collections.cpp index c6195d88cf..a933eb682c 100644 --- a/components/files/collections.cpp +++ b/components/files/collections.cpp @@ -1,6 +1,7 @@ - #include "collections.hpp" +#include + namespace Files { Collections::Collections() @@ -36,9 +37,19 @@ namespace Files for (Files::PathContainer::const_iterator iter = mDirectories.begin(); iter != mDirectories.end(); ++iter) { - const boost::filesystem::path path = *iter / file; - if (boost::filesystem::exists(path)) - return path.string(); + for (boost::filesystem::directory_iterator iter2 (*iter); + iter2!=boost::filesystem::directory_iterator(); ++iter2) + { + boost::filesystem::path path = *iter2; + + if (mFoldCase) + { + if (Misc::StringUtils::ciEqual(file, path.filename().string())) + return path.string(); + } + else if (path.filename().string() == file) + return path.string(); + } } throw std::runtime_error ("file " + file + " not found"); @@ -49,9 +60,19 @@ namespace Files for (Files::PathContainer::const_iterator iter = mDirectories.begin(); iter != mDirectories.end(); ++iter) { - const boost::filesystem::path path = *iter / file; - if (boost::filesystem::exists(path)) - return true; + for (boost::filesystem::directory_iterator iter2 (*iter); + iter2!=boost::filesystem::directory_iterator(); ++iter2) + { + boost::filesystem::path path = *iter2; + + if (mFoldCase) + { + if (Misc::StringUtils::ciEqual(file, path.filename().string())) + return true; + } + else if (path.filename().string() == file) + return true; + } } return false; diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 6119ab7b4d..9ecae465c6 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -417,7 +417,7 @@ - + From 0966755a0c8393c6276f3217f6a215f7182f72f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 19:56:32 +0200 Subject: [PATCH 402/545] Store death animation index in CreatureStats --- apps/openmw/mwmechanics/character.cpp | 56 +++++++++++++++-------- apps/openmw/mwmechanics/character.hpp | 1 + apps/openmw/mwmechanics/creaturestats.cpp | 15 +++++- apps/openmw/mwmechanics/creaturestats.hpp | 6 +++ components/esm/creaturestats.cpp | 6 +++ components/esm/creaturestats.hpp | 1 + 6 files changed, 66 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 60bccb3f7e..c9da912dd2 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -407,29 +407,25 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I return inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); } -void CharacterController::playRandomDeath(float startpoint) +void CharacterController::playDeath(float startpoint, CharacterState death) { - if(MWBase::Environment::get().getWorld()->isSwimming(mPtr) && mAnimation->hasAnimation("swimdeath")) + switch (death) { - mDeathState = CharState_SwimDeath; + case CharState_SwimDeath: mCurrentDeath = "swimdeath"; - } - else if (mHitState == CharState_KnockDown) - { - mDeathState = CharState_DeathKnockDown; + break; + case CharState_DeathKnockDown: mCurrentDeath = "deathknockdown"; - } - else if (mHitState == CharState_KnockOut) - { - mDeathState = CharState_DeathKnockOut; + break; + case CharState_DeathKnockOut: mCurrentDeath = "deathknockout"; + break; + default: + mCurrentDeath = "death" + Ogre::StringConverter::toString(death - CharState_Death1 + 1); } - else - { - int selected=0; - mCurrentDeath = chooseRandomGroup("death", &selected); - mDeathState = static_cast(CharState_Death1 + (selected-1)); - } + mDeathState = death; + + mPtr.getClass().getCreatureStats(mPtr).setDeathAnimation(mDeathState - CharState_Death1); // For dead actors, refreshCurrentAnims is no longer called, so we need to disable the movement state manually. mMovementState = CharState_None; @@ -440,6 +436,29 @@ void CharacterController::playRandomDeath(float startpoint) false, 1.0f, "start", "stop", startpoint, 0); } +void CharacterController::playRandomDeath(float startpoint) +{ + if(MWBase::Environment::get().getWorld()->isSwimming(mPtr) && mAnimation->hasAnimation("swimdeath")) + { + mDeathState = CharState_SwimDeath; + } + else if (mHitState == CharState_KnockDown) + { + mDeathState = CharState_DeathKnockDown; + } + else if (mHitState == CharState_KnockOut) + { + mDeathState = CharState_DeathKnockOut; + } + else + { + int selected=0; + chooseRandomGroup("death", &selected); + mDeathState = static_cast(CharState_Death1 + (selected-1)); + } + playDeath(startpoint, mDeathState); +} + CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim) : mPtr(ptr) , mAnimation(anim) @@ -497,7 +516,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim if(mDeathState != CharState_None) { - playRandomDeath(1.0f); + int deathindex = mPtr.getClass().getCreatureStats(mPtr).getDeathAnimation(); + playDeath(1.0f, CharacterState(CharState_Death1 + deathindex)); } else refreshCurrentAnims(mIdleState, mMovementState, true); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 1b7caf34d7..5cefe13bc8 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -181,6 +181,7 @@ class CharacterController void updateVisibility(); + void playDeath(float startpoint, CharacterState death); void playRandomDeath(float startpoint = 0.0f); /// choose a random animation group with \a prefix and numeric suffix diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 3ef6ff4df9..7fd26c25c9 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -22,7 +22,8 @@ namespace MWMechanics mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), - mLastRestock(0,0), mGoldPool(0), mActorId(-1) + mLastRestock(0,0), mGoldPool(0), mActorId(-1), + mDeathAnimation(0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -498,6 +499,7 @@ namespace MWMechanics state.mDrawState = mDrawState; state.mLevel = mLevel; state.mActorId = mActorId; + state.mDeathAnimation = mDeathAnimation; mSpells.writeState(state.mSpells); mActiveSpells.writeState(state.mActiveSpells); @@ -537,6 +539,7 @@ namespace MWMechanics mDrawState = DrawState_(state.mDrawState); mLevel = state.mLevel; mActorId = state.mActorId; + mDeathAnimation = state.mDeathAnimation; mSpells.readState(state.mSpells); mActiveSpells.readState(state.mActiveSpells); @@ -590,4 +593,14 @@ namespace MWMechanics { esm.getHNT(sActorId, "COUN"); } + + unsigned char CreatureStats::getDeathAnimation() const + { + return mDeathAnimation; + } + + void CreatureStats::setDeathAnimation(unsigned char index) + { + mDeathAnimation = index; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 70a86536a0..8b2398dfbd 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -64,6 +64,9 @@ namespace MWMechanics int mActorId; + // The index of the death animation that was played + unsigned char mDeathAnimation; + protected: // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. bool mIsWerewolf; @@ -250,6 +253,9 @@ namespace MWMechanics void setGoldPool(int pool); int getGoldPool() const; + unsigned char getDeathAnimation() const; + void setDeathAnimation(unsigned char index); + int getActorId(); ///< Will generate an actor ID, if the actor does not have one yet. diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 66d8481240..3860e9351f 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -74,6 +74,9 @@ void ESM::CreatureStats::load (ESMReader &esm) mActorId = -1; esm.getHNOT (mActorId, "ACID"); + mDeathAnimation = 0; + esm.getHNOT (mDeathAnimation, "DANM"); + mSpells.load(esm); mActiveSpells.load(esm); } @@ -152,6 +155,9 @@ void ESM::CreatureStats::save (ESMWriter &esm) const if (mActorId != -1) esm.writeHNT ("ACID", mActorId); + if (mDeathAnimation) + esm.writeHNT ("DANM", mDeathAnimation); + mSpells.save(esm); mActiveSpells.save(esm); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 7814d937ae..5ca3d071fe 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -46,6 +46,7 @@ namespace ESM std::string mLastHitObject; bool mRecalcDynamicStats; int mDrawState; + unsigned char mDeathAnimation; int mLevel; From 5660f283dde88ce71ed9475c3b12a42c45075320 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 20:33:01 +0200 Subject: [PATCH 403/545] Fix actor models incorrectly being rotated on X/Y axes --- apps/openmw/mwrender/actors.cpp | 13 ++++--------- apps/openmw/mwworld/worldimp.cpp | 14 ++++++++------ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index a9c9884d58..b7e9f5730c 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -54,17 +54,12 @@ void Actors::insertBegin(const MWWorld::Ptr &ptr) // Convert MW rotation to a quaternion: f = ptr.getCellRef().getPosition().rot; - // Rotate around X axis - Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); - - // Rotate around Y axis - Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y); - - // Rotate around Z axis + // For rendering purposes, actors should only rotate around the Z axis. + // X rotation is used for camera rotation (for the player) and for + // ranged magic / ranged weapon aiming. Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z); - // Rotates first around z, then y, then x - insert->setOrientation(xr*yr*zr); + insert->setOrientation(zr); ptr.getRefData().setBaseNode(insert); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 43153612d7..435ca8b367 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1116,13 +1116,15 @@ namespace MWWorld while(ptr.getRefData().getLocalRotation().rot[2]<=-fullRotateRad) ptr.getRefData().getLocalRotation().rot[2]+=fullRotateRad; - Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)* - Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* - Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)); + Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z); + if (!ptr.getClass().isActor()) + worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)* + Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat; - Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)* - Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)* - Ogre::Quaternion(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z)); + Ogre::Quaternion rot(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z); + if (!ptr.getClass().isActor()) + rot = Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)* + Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot; ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot); mPhysics->rotateObject(ptr); From 4caa8c5ccaa31324c08b40a045f372e6fc2a5745 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 20:37:12 +0200 Subject: [PATCH 404/545] Fix offset to accumulation root not being cleared when adding an animation state with startpoint=1.f (observed with death animations) --- apps/openmw/mwrender/animation.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 9124e89b88..a2f901b26a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -775,11 +775,11 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo } /* Look in reverse; last-inserted source has priority. */ + AnimState state; AnimSourceList::reverse_iterator iter(mAnimSources.rbegin()); for(;iter != mAnimSources.rend();++iter) { const NifOgre::TextKeyMap &textkeys = (*iter)->mTextKeys; - AnimState state; if(reset(state, textkeys, groupname, start, stop, startpoint)) { state.mSource = *iter; @@ -821,6 +821,13 @@ void Animation::play(const std::string &groupname, int priority, int groups, boo std::cerr<< "Failed to find animation "<setPosition(-mNonAccumCtrl->getTranslation(state.mTime)*mAccumulate); + } } bool Animation::isPlaying(const std::string &groupname) const From cf68f6da96ad4d3be5137f39e6888f25d253019e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 00:06:34 +0200 Subject: [PATCH 405/545] Fix ESX dependencies not being checked except for the first one --- apps/openmw/mwworld/esmstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index fc2bd4d773..03d928d2a5 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -33,12 +33,12 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) // Cache parent esX files by tracking their indices in the global list of // all files/readers used by the engine. This will greaty accelerate // refnumber mangling, as required for handling moved references. - int index = ~0; const std::vector &masters = esm.getGameFiles(); std::vector *allPlugins = esm.getGlobalReaderList(); for (size_t j = 0; j < masters.size(); j++) { ESM::Header::MasterData &mast = const_cast(masters[j]); std::string fname = mast.name; + int index = ~0; for (int i = 0; i < esm.getIndex(); i++) { const std::string &candidate = allPlugins->at(i).getContext().filename; std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); From e3e51324a4376bfbad1a21871873cc79dde189f9 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Mon, 26 May 2014 23:13:37 -0400 Subject: [PATCH 406/545] Esc button exits all non-modal GUI windows --- apps/openmw/mwbase/windowmanager.hpp | 9 +- apps/openmw/mwgui/alchemywindow.cpp | 11 ++- apps/openmw/mwgui/alchemywindow.hpp | 1 + apps/openmw/mwgui/bookwindow.cpp | 13 ++- apps/openmw/mwgui/bookwindow.hpp | 2 + apps/openmw/mwgui/companionwindow.cpp | 5 ++ apps/openmw/mwgui/companionwindow.hpp | 2 + apps/openmw/mwgui/console.cpp | 5 ++ apps/openmw/mwgui/console.hpp | 105 ++++++++++++------------ apps/openmw/mwgui/container.cpp | 7 +- apps/openmw/mwgui/container.hpp | 2 + apps/openmw/mwgui/dialogue.cpp | 11 ++- apps/openmw/mwgui/dialogue.hpp | 2 + apps/openmw/mwgui/enchantingdialog.cpp | 7 +- apps/openmw/mwgui/enchantingdialog.hpp | 3 + apps/openmw/mwgui/merchantrepair.cpp | 7 +- apps/openmw/mwgui/merchantrepair.hpp | 2 + apps/openmw/mwgui/quickkeysmenu.cpp | 7 +- apps/openmw/mwgui/quickkeysmenu.hpp | 1 + apps/openmw/mwgui/recharge.cpp | 7 +- apps/openmw/mwgui/recharge.hpp | 2 + apps/openmw/mwgui/repair.cpp | 7 +- apps/openmw/mwgui/repair.hpp | 2 + apps/openmw/mwgui/scrollwindow.cpp | 11 ++- apps/openmw/mwgui/scrollwindow.hpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 7 +- apps/openmw/mwgui/settingswindow.hpp | 2 + apps/openmw/mwgui/spellbuyingwindow.cpp | 7 +- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 + apps/openmw/mwgui/tradewindow.cpp | 11 ++- apps/openmw/mwgui/tradewindow.hpp | 2 + apps/openmw/mwgui/trainingwindow.cpp | 7 +- apps/openmw/mwgui/trainingwindow.hpp | 2 + apps/openmw/mwgui/travelwindow.cpp | 7 +- apps/openmw/mwgui/travelwindow.hpp | 2 + apps/openmw/mwgui/waitdialog.cpp | 7 +- apps/openmw/mwgui/waitdialog.hpp | 2 + apps/openmw/mwgui/windowbase.hpp | 5 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 92 +++++++++++++++++++++ apps/openmw/mwgui/windowmanagerimp.hpp | 10 ++- apps/openmw/mwinput/inputmanagerimp.cpp | 20 +++-- 41 files changed, 321 insertions(+), 96 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 44ebed3e98..9c069cbc23 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -234,14 +234,19 @@ namespace MWBase virtual void addVisitedLocation(const std::string& name, int x, int y) = 0; + /// Hides dialog and schedules dialog to be deleted. virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0; - ///< Hides dialog and schedules dialog to be deleted. + + ///Gracefully attempts to exit the topmost GUI mode + /** No guarentee of actually closing the window **/ + virtual void exitCurrentGuiMode() = 0; virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector(), enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0; virtual void staticMessageBox(const std::string& message) = 0; virtual void removeStaticMessageBox() = 0; + + /// returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual int readPressedButton() = 0; - ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual void onFrame (float frameDuration) = 0; diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 6524c168e1..ab04189a68 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -66,10 +66,7 @@ namespace MWGui void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mAlchemy.clear(); - - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Alchemy); - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Inventory); + exit(); } void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) @@ -159,6 +156,12 @@ namespace MWGui update(); } + void AlchemyWindow::exit() { + mAlchemy.clear(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Alchemy); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Inventory); + } + void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) { removeIngredient(_sender); diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 3a58ebf060..4fd4b825c0 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -19,6 +19,7 @@ namespace MWGui AlchemyWindow(); virtual void open(); + virtual void exit(); private: ItemView* mItemView; diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 884d567c51..32a5255c9a 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -114,6 +114,14 @@ namespace MWGui setTakeButtonShow(true); } + void BookWindow::exit() + { + // no 3d sounds because the object could be in a container. + MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); + + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); + } + void BookWindow::setTakeButtonShow(bool show) { mTakeButtonShow = show; @@ -128,10 +136,7 @@ namespace MWGui void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) { - // no 3d sounds because the object could be in a container. - MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); + exit(); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender) diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index f8821ab50b..a944f56e25 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -14,6 +14,8 @@ namespace MWGui public: BookWindow(); + virtual void exit(); + void open(MWWorld::Ptr book); void setTakeButtonShow(bool show); void nextPage(); diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 70093049da..d0ac3e7c36 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -118,6 +118,11 @@ void CompanionWindow::updateEncumbranceBar() } void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender) +{ + exit(); +} + +void CompanionWindow::exit() { if (mPtr.getTypeName() == typeid(ESM::NPC).name() && mPtr.getClass().getNpcStats(mPtr).getProfit() < 0) { diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 02e3812f0b..006d0a3c35 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -18,6 +18,8 @@ namespace MWGui public: CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager); + virtual void exit(); + void open(const MWWorld::Ptr& npc); void onFrame (); diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 811f93b486..db87d0a594 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -143,6 +143,11 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL); } + void Console::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Console); + } + void Console::setFont(const std::string &fntName) { mHistory->setFontName(fntName); diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 8901763630..ec699b317c 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -21,86 +21,83 @@ namespace MWGui { - class Console : public WindowBase, private Compiler::ErrorHandler, public ReferenceInterface - { - private: + class Console : public WindowBase, private Compiler::ErrorHandler, public ReferenceInterface + { + public: + /// Set the implicit object for script execution + void setSelectedObject(const MWWorld::Ptr& object); - Compiler::Extensions mExtensions; - MWScript::CompilerContext mCompilerContext; - std::vector mNames; - bool mConsoleOnlyScripts; + MyGUI::EditBox* mCommandLine; + MyGUI::EditBox* mHistory; - bool compile (const std::string& cmd, Compiler::Output& output); + typedef std::list StringList; - /// Report error to the user. - virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); + // History of previous entered commands + StringList mCommandHistory; + StringList::iterator mCurrent; + std::string mEditString; - /// Report a file related error - virtual void report (const std::string& message, Type type); + Console(int w, int h, bool consoleOnlyScripts); - void listNames(); - ///< Write all valid identifiers and keywords into mNames and sort them. - /// \note If mNames is not empty, this function is a no-op. - /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same - /// time). + virtual void open(); + virtual void close(); - public: + virtual void exit(); - void setSelectedObject(const MWWorld::Ptr& object); - ///< Set the implicit object for script execution + void setFont(const std::string &fntName); - protected: + void onResChange(int width, int height); - virtual void onReferenceUnavailable(); + void clearHistory(); + // Print a message to the console. Messages may contain color + // code, eg. "#FFFFFF this is white". + void print(const std::string &msg); - public: - MyGUI::EditBox* mCommandLine; - MyGUI::EditBox* mHistory; + // These are pre-colored versions that you should use. - typedef std::list StringList; + /// Output from successful console command + void printOK(const std::string &msg); - // History of previous entered commands - StringList mCommandHistory; - StringList::iterator mCurrent; - std::string mEditString; + /// Error message + void printError(const std::string &msg); - Console(int w, int h, bool consoleOnlyScripts); + void execute (const std::string& command); - virtual void open(); - virtual void close(); + void executeFile (const std::string& path); - void setFont(const std::string &fntName); + protected: - void onResChange(int width, int height); + virtual void onReferenceUnavailable(); - void clearHistory(); + private: - // Print a message to the console. Messages may contain color - // code, eg. "#FFFFFF this is white". - void print(const std::string &msg); + void keyPress(MyGUI::Widget* _sender, + MyGUI::KeyCode key, + MyGUI::Char _char); - // These are pre-colored versions that you should use. + void acceptCommand(MyGUI::EditBox* _sender); - /// Output from successful console command - void printOK(const std::string &msg); + std::string complete( std::string input, std::vector &matches ); - /// Error message - void printError(const std::string &msg); + Compiler::Extensions mExtensions; + MWScript::CompilerContext mCompilerContext; + std::vector mNames; + bool mConsoleOnlyScripts; - void execute (const std::string& command); + bool compile (const std::string& cmd, Compiler::Output& output); - void executeFile (const std::string& path); + /// Report error to the user. + virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); - private: + /// Report a file related error + virtual void report (const std::string& message, Type type); - void keyPress(MyGUI::Widget* _sender, - MyGUI::KeyCode key, - MyGUI::Char _char); - - void acceptCommand(MyGUI::EditBox* _sender); - - std::string complete( std::string input, std::vector &matches ); + /// Write all valid identifiers and keywords into mNames and sort them. + /// \note If mNames is not empty, this function is a no-op. + /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same + /// time). + void listNames(); }; } #endif diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index a207dec0c5..609dea3857 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -263,7 +263,7 @@ namespace MWGui } } - void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) + void ContainerWindow::exit() { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { @@ -271,6 +271,11 @@ namespace MWGui } } + void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) + { + exit(); + } + void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 3aa923a239..5446a4ab73 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -54,6 +54,8 @@ namespace MWGui void open(const MWWorld::Ptr& container, bool loot=false); virtual void close(); + virtual void exit(); + private: DragAndDrop* mDragAndDrop; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0002757947..8f8bab0252 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -264,6 +264,13 @@ namespace MWGui static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize); } + void DialogueWindow::exit() + { + if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) + return; + MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); + } + void DialogueWindow::onWindowResize(MyGUI::Window* _sender) { mTopicsList->adjustSize(); @@ -281,9 +288,7 @@ namespace MWGui void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) { - if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) - return; - MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); + exit(); } void DialogueWindow::onSelectTopic(const std::string& topic, int id) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index befbd6eeeb..9bc40bb6fa 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -103,6 +103,8 @@ namespace MWGui public: DialogueWindow(); + virtual void exit(); + // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 29fe6f82d5..ccb1fab682 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -61,6 +61,11 @@ namespace MWGui onRemoveSoul(NULL); } + void EnchantingDialog::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting); + } + void EnchantingDialog::updateLabels() { std::stringstream enchantCost; @@ -141,7 +146,7 @@ namespace MWGui void EnchantingDialog::onCancelButtonClicked(MyGUI::Widget* sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting); + exit(); } void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 8bad60c8e6..7e641702e1 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -19,6 +19,9 @@ namespace MWGui virtual ~EnchantingDialog(); virtual void open(); + + virtual void exit(); + void startEnchanting(MWWorld::Ptr actor); void startSelfEnchanting(MWWorld::Ptr soulgem); diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 50e7644fb9..49cc60d8aa 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -110,6 +110,11 @@ void MerchantRepair::open() center(); } +void MerchantRepair::exit() +{ + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_MerchantRepair); +} + void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) { // repair @@ -128,7 +133,7 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_MerchantRepair); + exit(); } } diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp index 4cb39fe012..2f13873654 100644 --- a/apps/openmw/mwgui/merchantrepair.hpp +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -16,6 +16,8 @@ public: virtual void open(); + virtual void exit(); + void startRepair(const MWWorld::Ptr& actor); private: diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 90abbb1450..9321d2de23 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -57,6 +57,11 @@ namespace MWGui } } + void QuickKeysMenu::exit() + { + mAssignDialog->setVisible (false); + } + void QuickKeysMenu::clear() { for (int i=0; i<10; ++i) @@ -146,7 +151,7 @@ namespace MWGui void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender) { - mAssignDialog->setVisible (false); + exit(); } void QuickKeysMenu::onAssignItem(MWWorld::Ptr item) diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index c0e25a517c..56a04cfbbb 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -18,6 +18,7 @@ namespace MWGui QuickKeysMenu(); ~QuickKeysMenu(); + virtual void exit(); void onItemButtonClicked(MyGUI::Widget* sender); void onMagicButtonClicked(MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 5c4f3eb5a5..e5ea545917 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -38,6 +38,11 @@ void Recharge::open() center(); } +void Recharge::exit() +{ + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Recharge); +} + void Recharge::start (const MWWorld::Ptr &item) { std::string path = std::string("icons\\"); @@ -128,7 +133,7 @@ void Recharge::updateView() void Recharge::onCancel(MyGUI::Widget *sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Recharge); + exit(); } void Recharge::onItemClicked(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/recharge.hpp b/apps/openmw/mwgui/recharge.hpp index 2ffc5e10f8..5558b197e0 100644 --- a/apps/openmw/mwgui/recharge.hpp +++ b/apps/openmw/mwgui/recharge.hpp @@ -15,6 +15,8 @@ public: virtual void open(); + virtual void exit(); + void start (const MWWorld::Ptr& gem); protected: diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index 1ae02599ee..29ec62887a 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -35,6 +35,11 @@ void Repair::open() center(); } +void Repair::exit() +{ + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Repair); +} + void Repair::startRepairItem(const MWWorld::Ptr &item) { mRepair.setTool(item); @@ -134,7 +139,7 @@ void Repair::updateRepairView() void Repair::onCancel(MyGUI::Widget *sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Repair); + exit(); } void Repair::onRepairItem(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index d0f5c54c4b..42539ad9e0 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -15,6 +15,8 @@ public: virtual void open(); + virtual void exit(); + void startRepairItem (const MWWorld::Ptr& item); protected: diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index a084e6453a..3d07511143 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -67,6 +67,13 @@ namespace MWGui setTakeButtonShow(true); } + void ScrollWindow::exit() + { + MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); + + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); + } + void ScrollWindow::setTakeButtonShow(bool show) { mTakeButtonShow = show; @@ -81,9 +88,7 @@ namespace MWGui void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { - MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); + exit(); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 5feaff7bf8..17e56f3345 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -14,6 +14,7 @@ namespace MWGui ScrollWindow (); void open (MWWorld::Ptr scroll); + virtual void exit(); void setTakeButtonShow(bool show); void setInventoryAllowed(bool allowed); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 78adecd3ef..4730a7295a 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -242,7 +242,7 @@ namespace MWGui void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Settings); + exit(); } void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) @@ -510,4 +510,9 @@ namespace MWGui { updateControlsBox (); } + + void SettingsWindow::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Settings); + } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 7a6c1a5ed5..37f2c8af06 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -17,6 +17,8 @@ namespace MWGui virtual void open(); + virtual void exit(); + void updateControlsBox(); protected: diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 99b85c13cc..8d9f35daaa 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -33,6 +33,11 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked); } + void SpellBuyingWindow::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_SpellBuying); + } + void SpellBuyingWindow::addSpell(const std::string& spellId) { const MWWorld::ESMStore &store = @@ -132,7 +137,7 @@ namespace MWGui void SpellBuyingWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_SpellBuying); + exit(); } void SpellBuyingWindow::updateLabels() diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index f7ea54c89c..2a6dcfdcc4 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -25,6 +25,8 @@ namespace MWGui void startSpellBuying(const MWWorld::Ptr& actor); + virtual void exit(); + protected: MyGUI::Button* mCancelButton; MyGUI::TextBox* mPlayerGold; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 558e955f0d..cb7f3b0bd4 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -136,6 +136,13 @@ namespace MWGui return mPtr.getClass().getServices(mPtr); } + void TradeWindow::exit() + { + mTradeModel->abort(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel()->abort(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); + } + void TradeWindow::onItemSelected (int index) { const ItemStack& item = mSortModel->getItem(index); @@ -375,9 +382,7 @@ namespace MWGui void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mTradeModel->abort(); - MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel()->abort(); - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); + exit(); } void TradeWindow::onMaxSaleButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 2da58e72e1..420a642e81 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -35,6 +35,8 @@ namespace MWGui int getMerchantServices(); + virtual void exit(); + private: ItemView* mItemView; diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 34873b9bc7..9a2c3b8055 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -35,6 +35,11 @@ namespace MWGui center(); } + void TrainingWindow::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training); + } + void TrainingWindow::startTraining (MWWorld::Ptr actor) { mPtr = actor; @@ -107,7 +112,7 @@ namespace MWGui void TrainingWindow::onCancelButtonClicked (MyGUI::Widget *sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training); + exit(); } void TrainingWindow::onTrainingSelected (MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/trainingwindow.hpp b/apps/openmw/mwgui/trainingwindow.hpp index 740115cdfc..1fc902b20a 100644 --- a/apps/openmw/mwgui/trainingwindow.hpp +++ b/apps/openmw/mwgui/trainingwindow.hpp @@ -14,6 +14,8 @@ namespace MWGui virtual void open(); + virtual void exit(); + void startTraining(MWWorld::Ptr actor); void onFrame(float dt); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 642e1a6449..79d50cdc59 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -45,6 +45,11 @@ namespace MWGui mSelect->getHeight()); } + void TravelWindow::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); + } + void TravelWindow::addDestination(const std::string& travelId,ESM::Position pos,bool interior) { int price = 0; @@ -170,7 +175,7 @@ namespace MWGui void TravelWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); + exit(); } void TravelWindow::updateLabels() diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index f2a23b0486..5387bd690d 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -22,6 +22,8 @@ namespace MWGui public: TravelWindow(); + virtual void exit(); + void startTravel(const MWWorld::Ptr& actor); protected: diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 12bf97f7c9..460663682e 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -69,6 +69,11 @@ namespace MWGui mProgressBar.setVisible (false); } + void WaitDialog::exit() + { + MWBase::Environment::get().getWindowManager()->popGuiMode(); + } + void WaitDialog::open() { if (!MWBase::Environment::get().getWindowManager ()->getRestEnabled ()) @@ -160,7 +165,7 @@ namespace MWGui void WaitDialog::onCancelButtonClicked(MyGUI::Widget* sender) { - MWBase::Environment::get().getWindowManager()->popGuiMode (); + exit(); } void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position) diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index 5a66c3370e..1cf05bb06f 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -28,6 +28,8 @@ namespace MWGui virtual void open(); + virtual void exit(); + void onFrame(float dt); void bedActivated() { setCanRest(true); } diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index 48de9ea87c..d8bd2bd598 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -21,8 +21,13 @@ namespace MWGui // Events typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; + ///Unhides the window virtual void open() {} + ///Hides the window virtual void close () {} + ///Gracefully exits the window + virtual void exit() {} + ///Sets the visibility of the window virtual void setVisible(bool visible); void center(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index a42dca79e5..46aa781acf 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -23,6 +23,8 @@ #include "../mwworld/player.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwsound/soundmanagerimp.hpp" + #include "console.hpp" #include "journalwindow.hpp" #include "journalviewmodel.hpp" @@ -666,6 +668,96 @@ namespace MWGui mGarbageDialogs.push_back(dialog); } + void WindowManager::exitCurrentGuiMode() { + switch(mGuiModes.back()) { + case GM_QuickKeysMenu: + mQuickKeysMenu->exit(); + break; + case GM_MainMenu: + removeGuiMode(GM_MainMenu); //Simple way to remove it + break; + case GM_Settings: + mSettingsWindow->exit(); + break; + case GM_Console: + mConsole->exit(); + break; + case GM_Scroll: + mScrollWindow->exit(); + break; + case GM_Book: + mBookWindow->exit(); + break; + case GM_Alchemy: + mAlchemyWindow->exit(); + break; + case GM_Rest: + mWaitDialog->exit(); + break; + case GM_RestBed: + mWaitDialog->exit(); + break; + case GM_Levelup: + mLevelupDialog->exit(); + break; + case GM_Name: + case GM_Race: + case GM_Class: + case GM_ClassPick: + case GM_ClassCreate: + case GM_Birth: + case GM_ClassGenerate: + case GM_Review: + break; + case GM_Inventory: + removeGuiMode(GM_Inventory); //Simple way to remove it + break; + case GM_Container: + mContainerWindow->exit(); + break; + case GM_Companion: + mCompanionWindow->exit(); + break; + case GM_Dialogue: + mDialogueWindow->exit(); + break; + case GM_Barter: + mTradeWindow->exit(); + break; + case GM_SpellBuying: + mSpellBuyingWindow->exit(); + break; + case GM_Travel: + mTravelWindow->exit(); + break; + case GM_SpellCreation: + mSpellCreationDialog->exit(); + break; + case GM_Recharge: + mRecharge->exit(); + break; + case GM_Enchanting: + mEnchantingDialog->exit(); + break; + case GM_Training: + mTrainingWindow->exit(); + break; + case GM_MerchantRepair: + mMerchantRepair->exit(); + break; + case GM_Repair: + mRepair->exit(); + break; + case GM_Journal: + MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); + removeGuiMode(GM_Journal); //Simple way to remove it + break; + default: + // Unsupported mode, switch back to game + break; + } + } + void WindowManager::messageBox (const std::string& message, const std::vector& buttons, enum MWGui::ShowInDialogueMode showInDialogueMode) { if (buttons.empty()) { diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index c98c32c524..cd87113ce1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -132,10 +132,10 @@ namespace MWGui virtual void forceHide(MWGui::GuiWindow wnd); virtual void unsetForceHide(MWGui::GuiWindow wnd); - // Disallow all inventory mode windows + /// Disallow all inventory mode windows virtual void disallowAll(); - // Allow one or more windows + /// Allow one or more windows virtual void allow(GuiWindow wnd); virtual bool isAllowed(GuiWindow wnd) const; @@ -225,7 +225,11 @@ namespace MWGui virtual void addVisitedLocation(const std::string& name, int x, int y); - virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. + ///Hides dialog and schedules dialog to be deleted. + virtual void removeDialog(OEngine::GUI::Layout* dialog); + + ///Gracefully attempts to exit the topmost GUI mode + virtual void exitCurrentGuiMode(); virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector(), enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible); virtual void staticMessageBox(const std::string& message); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index cf71cc1aa4..f020ef9f28 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -28,6 +28,8 @@ #include "../mwmechanics/creaturestats.hpp" +#include "../mwdialogue/dialoguemanagerimp.hpp" + using namespace ICS; namespace @@ -633,19 +635,20 @@ namespace MWInput void InputManager::toggleMainMenu() { - if (MyGUI::InputManager::getInstance ().isModalAny()) +// TODO: Find a way to send an exit command to current Modal Widget + if (MyGUI::InputManager::getInstance().isModalAny()) return; - if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) - { - MWBase::Environment::get().getWindowManager()->popGuiMode(); - MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); - } - else + if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) //No open GUIs, open up the MainMenu { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); } + else //Close current GUI + { + MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); + MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); + } } void InputManager::quickLoad() { @@ -761,8 +764,7 @@ namespace MWInput } else if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Journal) { - MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); } // .. but don't touch any other mode. } From 79d0ed64d9edb2a740ba92448301503f7d7e50ba Mon Sep 17 00:00:00 2001 From: Digmaster Date: Mon, 26 May 2014 23:31:40 -0400 Subject: [PATCH 407/545] Undo some changes I made in the past that shouldn't exist --- apps/openmw/mwclass/container.cpp | 8 ++------ apps/openmw/mwclass/door.cpp | 8 ++------ apps/openmw/mwworld/class.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 7b62ad04f0..940a36b00f 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -262,12 +262,8 @@ namespace MWClass { if(lockLevel!=0) ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive - else { - if(abs(ptr.getCellRef().getLockLevel())!=0) - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one - else - ptr.getCellRef().setLockLevel(100); //There never was a locklevel, give it the default biggest one - } + else + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one } void Container::unlock (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 0788896297..12645c9f39 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -192,12 +192,8 @@ namespace MWClass { if(lockLevel!=0) ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive - else { - if(abs(ptr.getCellRef().getLockLevel())!=0) - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one - else - ptr.getCellRef().setLockLevel(100); - } + else + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one } void Door::unlock (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 4e36a8da9b..c3f94d7f10 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -165,7 +165,7 @@ namespace MWWorld virtual bool hasInventoryStore (const Ptr& ptr) const; ///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false) - virtual void lock (const Ptr& ptr, int lockLevel = 0) const; + virtual void lock (const Ptr& ptr, int lockLevel) const; ///< Lock object (default implementation: throw an exception) virtual void unlock (const Ptr& ptr) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f7297128ba..43153612d7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2526,7 +2526,7 @@ namespace MWWorld store.remove(*it, it->getRefData().getCount(), ptr); } } - closestChest.getClass().lock(closestChest); + closestChest.getClass().unlock(closestChest); } } From e0d55116a4cb6216980339fbce32c520f3fe0a11 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 00:30:37 -0400 Subject: [PATCH 408/545] Dims and disabled Goodbye button in dialogs when unavailable. --- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 940a36b00f..9498ea52df 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -263,7 +263,7 @@ namespace MWClass if(lockLevel!=0) ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive else - ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the origional one + ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one } void Container::unlock (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 8f8bab0252..0cea50f1be 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -509,6 +509,17 @@ namespace MWGui // no scrollbar onScrollbarMoved(mScrollBar, 0); } + + MyGUI::Button* byeButton; + getWidget(byeButton, "ByeButton"); + if(MWBase::Environment::get().getDialogueManager()->isInChoice()) { + byeButton->setAlpha(.2); + byeButton->setEnabled(false); + } + else { + byeButton->setAlpha(1); + byeButton->setEnabled(true); + } } void DialogueWindow::notifyLinkClicked (TypesetBook::InteractiveId link) From beba58268ce2374e10a0935f540686c814563cad Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Tue, 27 May 2014 01:47:57 -0500 Subject: [PATCH 409/545] Fix a typo within the launcher. Fixes bug #1058. --- apps/launcher/maindialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index fb4c09b918..41d662d30b 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -806,7 +806,7 @@ void Launcher::MainDialog::play() msgBox.setWindowTitle(tr("No game file selected")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
You do not have no game file selected.

\ + msgBox.setText(tr("
You do not have a game file selected.

\ OpenMW will not start without a game file selected.
")); msgBox.exec(); return; From e0356cf89d786d3fbc671220e32737fa9a379e23 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 03:00:31 -0400 Subject: [PATCH 410/545] Added support to close modal windows with Esc --- apps/openmw/mwbase/windowmanager.hpp | 9 +++++++++ apps/openmw/mwgui/confirmationdialog.cpp | 7 ++++++- apps/openmw/mwgui/confirmationdialog.hpp | 1 + apps/openmw/mwgui/dialogue.cpp | 7 ++++++- apps/openmw/mwgui/dialogue.hpp | 1 + apps/openmw/mwgui/savegamedialog.cpp | 7 ++++++- apps/openmw/mwgui/savegamedialog.hpp | 2 ++ apps/openmw/mwgui/spellcreationdialog.cpp | 22 ++++++++++++++++------ apps/openmw/mwgui/spellcreationdialog.hpp | 2 ++ apps/openmw/mwgui/windowbase.cpp | 9 +++++++++ apps/openmw/mwgui/windowbase.hpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 1 + apps/openmw/mwgui/windowmanagerimp.hpp | 11 +++++++++++ apps/openmw/mwinput/inputmanagerimp.cpp | 7 +++++-- 14 files changed, 76 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 9c069cbc23..69712ed037 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -57,6 +57,7 @@ namespace MWGui class InventoryWindow; class ContainerWindow; class DialogueWindow; + class WindowModal; enum ShowInDialogueMode { ShowInDialogueMode_IfPossible, @@ -314,6 +315,14 @@ namespace MWBase /// Does the current stack of GUI-windows permit saving? virtual bool isSavingAllowed() const = 0; + + /// Returns the current Modal + /** Used to send exit command to active Modal when Esc is pressed **/ + virtual MWGui::WindowModal* getCurrentModal() const = 0; + + /// Sets the current Modal + /** Used to send exit command to active Modal when Esc is pressed **/ + virtual void setCurrentModal(MWGui::WindowModal* input) = 0; }; } diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index f431f2f64c..89f477598f 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -28,13 +28,18 @@ namespace MWGui center(); } - void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) + void ConfirmationDialog::exit() { eventCancelClicked(); setVisible(false); } + void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) + { + exit(); + } + void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender) { eventOkClicked(); diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index 47b256017f..c50873c74c 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -10,6 +10,7 @@ namespace MWGui public: ConfirmationDialog(); void open(const std::string& message); + virtual void exit(); typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0cea50f1be..762c472d87 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -51,7 +51,7 @@ namespace MWGui void PersuasionDialog::onCancel(MyGUI::Widget *sender) { - setVisible(false); + exit(); } void PersuasionDialog::onPersuade(MyGUI::Widget *sender) @@ -87,6 +87,11 @@ namespace MWGui mGoldLabel->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(playerGold)); } + void PersuasionDialog::exit() + { + setVisible(false); + } + // -------------------------------------------------------------------------------------------------- Response::Response(const std::string &text, const std::string &title) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 9bc40bb6fa..fcb1338b5f 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -34,6 +34,7 @@ namespace MWGui PersuasionDialog(); virtual void open(); + virtual void exit(); private: MyGUI::Button* mCancelButton; diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 6048e49b41..b36baf87bd 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -159,6 +159,11 @@ namespace MWGui } + void SaveGameDialog::exit() + { + setVisible(false); + } + void SaveGameDialog::setLoadOrSave(bool load) { mSaving = !load; @@ -177,7 +182,7 @@ namespace MWGui void SaveGameDialog::onCancelButtonClicked(MyGUI::Widget *sender) { - setVisible(false); + exit(); } void SaveGameDialog::onConfirmationGiven() diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index 42c29f4bc9..9f44d53708 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -19,6 +19,8 @@ namespace MWGui virtual void open(); + virtual void exit(); + void setLoadOrSave(bool load); private: diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 1ec4bd6da4..030b8bf37c 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -75,6 +75,15 @@ namespace MWGui center(); } + void EditEffectDialog::exit() + { + setVisible(false); + if(mEditing) + eventEffectModified(mOldEffect); + else + eventEffectRemoved(mEffect); + } + void EditEffectDialog::newEffect (const ESM::MagicEffect *effect) { setMagicEffect(effect); @@ -222,11 +231,7 @@ namespace MWGui void EditEffectDialog::onCancelButtonClicked (MyGUI::Widget* sender) { - setVisible(false); - if(mEditing) - eventEffectModified(mOldEffect); - else - eventEffectRemoved(mEffect); + exit(); } void EditEffectDialog::setSkill (int skill) @@ -313,7 +318,7 @@ namespace MWGui void SpellCreationDialog::onCancelButtonClicked (MyGUI::Widget* sender) { - MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_SpellCreation); + exit(); } void SpellCreationDialog::onBuyButtonClicked (MyGUI::Widget* sender) @@ -367,6 +372,11 @@ namespace MWGui center(); } + void SpellCreationDialog::exit() + { + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_SpellCreation); + } + void SpellCreationDialog::onReferenceUnavailable () { MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue); diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index e424d73957..25c615678a 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -18,6 +18,7 @@ namespace MWGui EditEffectDialog(); virtual void open(); + virtual void exit(); void setSkill(int skill); void setAttribute(int attribute); @@ -127,6 +128,7 @@ namespace MWGui SpellCreationDialog(); virtual void open(); + virtual void exit(); void startSpellMaking(MWWorld::Ptr actor); diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index 87b26b814a..15b41813f5 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -2,6 +2,8 @@ #include "../mwbase/windowmanager.hpp" #include "container.hpp" +#include "../mwbase/environment.hpp" +#include "../mwgui/windowmanagerimp.hpp" using namespace MWGui; @@ -45,11 +47,18 @@ WindowModal::WindowModal(const std::string& parLayout) void WindowModal::open() { MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget); + MWBase::Environment::get().getWindowManager()->setCurrentModal(this); //Set so we can escape it if needed } void WindowModal::close() { MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget); + MWBase::Environment::get().getWindowManager()->setCurrentModal(NULL); +} + +void WindowModal::exit() +{ + close(); } NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget) diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index d8bd2bd598..79ab282990 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -47,6 +47,7 @@ namespace MWGui WindowModal(const std::string& parLayout); virtual void open(); virtual void close(); + virtual void exit(); }; /// A window that cannot be the target of a drag&drop action. diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 46aa781acf..5a228801af 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -136,6 +136,7 @@ namespace MWGui , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) + , currentModal(NULL) { // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index cd87113ce1..d146239017 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -82,6 +82,7 @@ namespace MWGui class Recharge; class CompanionWindow; class VideoWidget; + class WindowModal; class WindowManager : public MWBase::WindowManager { @@ -302,6 +303,14 @@ namespace MWGui /// Does the current stack of GUI-windows permit saving? virtual bool isSavingAllowed() const; + /// Returns the current Modal + /** Used to send exit command to active Modal when Esc is pressed **/ + virtual WindowModal* getCurrentModal() const {return currentModal;} + + /// Sets the current Modal + /** Used to send exit command to active Modal when Esc is pressed **/ + virtual void setCurrentModal(WindowModal* input) {currentModal = input;} + private: bool mConsoleOnlyScripts; @@ -311,6 +320,8 @@ namespace MWGui std::string mSelectedSpell; + WindowModal* currentModal; + OEngine::GUI::MyGUIManager *mGuiManager; OEngine::Render::OgreRenderer *mRendering; HUD *mHud; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index f020ef9f28..6206985dde 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -30,6 +30,8 @@ #include "../mwdialogue/dialoguemanagerimp.hpp" +#include "../mwgui/windowbase.hpp" + using namespace ICS; namespace @@ -635,9 +637,10 @@ namespace MWInput void InputManager::toggleMainMenu() { -// TODO: Find a way to send an exit command to current Modal Widget - if (MyGUI::InputManager::getInstance().isModalAny()) + if (MyGUI::InputManager::getInstance().isModalAny()) { + MWBase::Environment::get().getWindowManager()->getCurrentModal()->exit(); return; + } if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) //No open GUIs, open up the MainMenu { From ee7b5fa5c225aaaa9275b921c6da4935e4eb9686 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 04:38:13 -0400 Subject: [PATCH 411/545] Fixed crash when Esc-ing out of Save "are you sure" dialog. --- apps/openmw/mwbase/windowmanager.hpp | 7 ++++++- apps/openmw/mwgui/windowbase.cpp | 4 ++-- apps/openmw/mwgui/windowmanagerimp.cpp | 19 ++++++++++++++++++- apps/openmw/mwgui/windowmanagerimp.hpp | 11 ++++++++--- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 69712ed037..2dfa50eb51 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -322,7 +322,12 @@ namespace MWBase /// Sets the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ - virtual void setCurrentModal(MWGui::WindowModal* input) = 0; + virtual void addCurrentModal(MWGui::WindowModal* input) = 0; + + /// Removes the top Modal + /** Used when one Modal adds another Modal + \param input Pointer to the current modal, to ensure proper modal is removed **/ + virtual void removeCurrentModal(MWGui::WindowModal* input) = 0; }; } diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index 15b41813f5..4dcb680ec0 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -47,13 +47,13 @@ WindowModal::WindowModal(const std::string& parLayout) void WindowModal::open() { MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget); - MWBase::Environment::get().getWindowManager()->setCurrentModal(this); //Set so we can escape it if needed + MWBase::Environment::get().getWindowManager()->addCurrentModal(this); //Set so we can escape it if needed } void WindowModal::close() { MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget); - MWBase::Environment::get().getWindowManager()->setCurrentModal(NULL); + MWBase::Environment::get().getWindowManager()->removeCurrentModal(this); } void WindowModal::exit() diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 5a228801af..eb800ef9a4 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -136,7 +136,7 @@ namespace MWGui , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) - , currentModal(NULL) + , mCurrentModals() { // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); @@ -1606,4 +1606,21 @@ namespace MWGui mVideoWidget->setCoord(leftPadding, topPadding, screenWidth - leftPadding*2, screenHeight - topPadding*2); } + + WindowModal* WindowManager::getCurrentModal() const + { + if(mCurrentModals.size() > 0) + return mCurrentModals.top(); + else + return NULL; + } + + void WindowManager::removeCurrentModal(WindowModal* input) + { + // Only remove the top if it matches the current pointer. A lot of things hide their visibility before showing it, + //so just popping the top would cause massive issues. + if(mCurrentModals.size() > 0) + if(input == mCurrentModals.top()) + mCurrentModals.pop(); + } } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index d146239017..b1dbf3a24a 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -305,11 +305,16 @@ namespace MWGui /// Returns the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ - virtual WindowModal* getCurrentModal() const {return currentModal;} + virtual WindowModal* getCurrentModal() const; /// Sets the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ - virtual void setCurrentModal(WindowModal* input) {currentModal = input;} + virtual void addCurrentModal(WindowModal* input) {mCurrentModals.push(input);} + + /// Removes the top Modal + /** Used when one Modal adds another Modal + \param input Pointer to the current modal, to ensure proper modal is removed **/ + virtual void removeCurrentModal(WindowModal* input); private: bool mConsoleOnlyScripts; @@ -320,7 +325,7 @@ namespace MWGui std::string mSelectedSpell; - WindowModal* currentModal; + std::stack mCurrentModals; OEngine::GUI::MyGUIManager *mGuiManager; OEngine::Render::OgreRenderer *mRendering; From 2b3b11d848b4ce9708f65a89ec9024ee90b2035e Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 05:33:25 -0400 Subject: [PATCH 412/545] Give access to the main menu when at a choice in dialogue --- apps/openmw/mwgui/windowmanagerimp.cpp | 3 --- apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index eb800ef9a4..b931cd3706 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -698,9 +698,6 @@ namespace MWGui case GM_RestBed: mWaitDialog->exit(); break; - case GM_Levelup: - mLevelupDialog->exit(); - break; case GM_Name: case GM_Race: case GM_Class: diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 6206985dde..2d78e7875d 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -642,6 +642,14 @@ namespace MWInput return; } + if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Dialogue) { //Give access to the main menu when at a choice in Dialogue + if(MWBase::Environment::get().getDialogueManager()->isInChoice()) { + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); + MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); + return; + } + } + if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) //No open GUIs, open up the MainMenu { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); From e0ba9a4bf2fec0f8b6f9fa1863ece0c5710d6dce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 May 2014 12:39:26 +0200 Subject: [PATCH 413/545] added reference collection stage to saving operation (preparation for cell saving) --- apps/opencs/model/doc/saving.cpp | 3 ++ apps/opencs/model/doc/savingstages.cpp | 38 ++++++++++++++++++++++++++ apps/opencs/model/doc/savingstages.hpp | 16 +++++++++++ apps/opencs/model/doc/savingstate.cpp | 7 +++++ apps/opencs/model/doc/savingstate.hpp | 4 +++ apps/opencs/model/world/ref.cpp | 8 ++++++ apps/opencs/model/world/ref.hpp | 2 ++ 7 files changed, 78 insertions(+) diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 27d21635eb..337784765c 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -65,7 +65,10 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje appendStage (new WriteRefIdCollectionStage (mDocument, mState)); + appendStage (new CollectionReferencesStage (mDocument, mState)); + + // close file and clean up appendStage (new CloseSaveStage (mState)); appendStage (new FinalSavingStage (mDocument, mState)); diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index eb93d90475..fc35e21cd1 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -9,6 +9,8 @@ #include +#include + #include "../world/infocollection.hpp" #include "document.hpp" @@ -214,6 +216,42 @@ void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages) } +CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document, + SavingState& state) +: mDocument (document), mState (state) +{} + +int CSMDoc::CollectionReferencesStage::setup() +{ + mState.getSubRecords().clear(); + + int size = mDocument.getData().getReferences().getSize(); + + int steps = size/100; + if (size%100) ++steps; + + return steps; +} + +void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages) +{ + int size = mDocument.getData().getReferences().getSize(); + + for (int i=stage*100; i& record = + mDocument.getData().getReferences().getRecord (i); + + if (record.mState==CSMWorld::RecordBase::State_Deleted || + record.mState==CSMWorld::RecordBase::State_Modified || + record.mState==CSMWorld::RecordBase::State_ModifiedOnly) + { + mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mId)].push_back (i); + } + } +} + + CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state) : mState (state) {} diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index c2f0a150a9..653f3a9570 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -163,8 +163,24 @@ namespace CSMDoc virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. + }; + class CollectionReferencesStage : public Stage + { + Document& mDocument; + SavingState& mState; + + public: + + CollectionReferencesStage (Document& document, SavingState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; class CloseSaveStage : public Stage { diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 8742148226..294f830496 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -25,6 +25,8 @@ void CSMDoc::SavingState::start (Document& document, bool project) mStream.clear(); + mSubRecords.clear(); + if (project) mPath = mProjectPath; else @@ -60,4 +62,9 @@ ESM::ESMWriter& CSMDoc::SavingState::getWriter() bool CSMDoc::SavingState::isProjectFile() const { return mProjectFile; +} + +std::map > CSMDoc::SavingState::getSubRecords() +{ + return mSubRecords; } \ No newline at end of file diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 6b45655846..64085bf0d5 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -2,6 +2,7 @@ #define CSM_DOC_SAVINGSTATE_H #include +#include #include @@ -24,6 +25,7 @@ namespace CSMDoc ESM::ESMWriter mWriter; boost::filesystem::path mProjectPath; bool mProjectFile; + std::map > mSubRecords; // record ID, list of subrecords public: @@ -45,6 +47,8 @@ namespace CSMDoc bool isProjectFile() const; ///< Currently saving project file? (instead of content file) + + std::map > getSubRecords(); }; diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index 44ffa92b94..d1bd771f80 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -1,2 +1,10 @@ #include "ref.hpp" + +CSMWorld::CellRef::CellRef() +{ + mRefNum.mIndex = 0; + + // special marker: This reference does not have a RefNum assign to it yet. + mRefNum.mContentFile = -2; +} \ No newline at end of file diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index b60cbd7e41..eb62434cf2 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -12,6 +12,8 @@ namespace CSMWorld { std::string mId; std::string mCell; + + CellRef(); }; } From d3357cc279d1ab96096648454cbb3aa8f12beaee Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Tue, 27 May 2014 13:27:18 +0200 Subject: [PATCH 414/545] The MSVC linker is really pedantic with this. Functions compiled as taking a class can't be linked with functions giving a struct, because of the name mangling I'm guessing... unresolved external symbol "protected: void __thiscall MWWorld::LiveCellRefBase::loadImp(class ESM::ObjectState const &)" (?loadImp@LiveCellRefBase@MWWorld@@IAEXABVObjectState@ESM@@@Z) --- apps/openmw/mwworld/cellref.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 3b0c2251be..4db362b1e0 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -5,7 +5,7 @@ namespace ESM { - class ObjectState; + struct ObjectState; } namespace MWWorld From 578adb4ef6700d4dc812190b9b285739468fe4d5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 13:54:25 +0200 Subject: [PATCH 415/545] PcJoinFaction and friends: make sure the given faction exists --- apps/openmw/mwscript/statsextensions.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index d9c9e5e0b3..8b61237a1d 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -541,6 +541,9 @@ namespace MWScript runtime.pop(); } ::Misc::StringUtils::toLower(factionID); + // Make sure this faction exists + MWBase::Environment::get().getWorld()->getStore().get().find(factionID); + if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -572,6 +575,9 @@ namespace MWScript runtime.pop(); } ::Misc::StringUtils::toLower(factionID); + // Make sure this faction exists + MWBase::Environment::get().getWorld()->getStore().get().find(factionID); + if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -607,6 +613,9 @@ namespace MWScript runtime.pop(); } ::Misc::StringUtils::toLower(factionID); + // Make sure this faction exists + MWBase::Environment::get().getWorld()->getStore().get().find(factionID); + if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -645,6 +654,9 @@ namespace MWScript } } ::Misc::StringUtils::toLower(factionID); + // Make sure this faction exists + MWBase::Environment::get().getWorld()->getStore().get().find(factionID); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if(factionID!="") { From 41db48720d49d0b87bc1bc8d705bfb4ae7785ef5 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 27 May 2014 14:01:15 +0200 Subject: [PATCH 416/545] does not compile --- apps/opencs/model/world/refidadapter.cpp | 16 +++++- apps/opencs/model/world/refidadapter.hpp | 7 +++ apps/opencs/model/world/refidadapterimp.cpp | 60 +++++++++++++++++++++ apps/opencs/model/world/refidadapterimp.hpp | 8 +++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapter.cpp b/apps/opencs/model/world/refidadapter.cpp index 94ae38c3c2..283f062feb 100644 --- a/apps/opencs/model/world/refidadapter.cpp +++ b/apps/opencs/model/world/refidadapter.cpp @@ -1,6 +1,20 @@ #include "refidadapter.hpp" +#include "cassert" +#include + CSMWorld::RefIdAdapter::RefIdAdapter() {} -CSMWorld::RefIdAdapter::~RefIdAdapter() {} \ No newline at end of file +CSMWorld::RefIdAdapter::~RefIdAdapter() {} + +QVariant CSMWorld::RefIdAdapter::getData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int idnex, int subRowIndex, int subColIndex) const +{ + assert(false); + return QVariant(); +} + +void CSMWorld::RefIdAdapter::setData (const CSMWorld::RefIdColumn* column, CSMWorld::RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const +{ + assert(false); +} diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 0870a2d3e6..673b1f5a44 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -30,6 +30,13 @@ namespace CSMWorld const QVariant& value) const = 0; ///< If the data type does not match an exception is thrown. + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, + int idnex, int subRowIndex, int subColIndex) const; + + virtual void setData (const RefIdColumn *column, RefIdData& data, + const QVariant& value, int index, + int subRowIndex, int subColIndex) const; + virtual std::string getId (const RecordBase& record) const = 0; virtual void setId(RecordBase& record, const std::string& id) = 0; }; diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index afb61acc6b..df64e9f054 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -222,6 +222,66 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD NameRefIdAdapter::setData (column, data, index, value); } +void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdData& data, + int index, + const QVariant& value, + int subRowIndex, + int subColIndex) +{ + using RefIdAdapter::setData; + Record& record = static_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + if (column==mContent) + { + switch (subColIndex) + { + case 0: + record.get().mInventory.mList.at(subRowIndex).mItem.assign(std::string(value.toString().toUtf8().constData())); + break; + + case 1: + record.get().mInventory.mList.at(subRowIndex).mCount = value.toInt(); + break; + } + } else + { + throw "This column does not hold multiple values."; + } +} + +QVariant CSMWorld::ContainerRefIdAdapter::getData (const CSMWorld::RefIdColumn* column, + const CSMWorld::RefIdData& data, + int index, + int subRowIndex, + int subColIndex) const +{ + using RefIdAdapter::getData; + const Record& record = static_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + if (column==mContent) + { + const ESM::ContItem& content = record.get().mInventory.mList.at(subRowIndex); + + switch (subColIndex) + { + case 0: + return QString::fromUtf8(content.mItem.toString().c_str()); + + case 1: + return content.mCount; + + default: + throw "Trying to access non-existing column in the nested table!"; + } + } else + { + throw "This column does not hold multiple values."; + } +} + + CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) : ActorColumns (actorColumns) {} diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 59c8c64614..f295016985 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -617,9 +617,17 @@ namespace CSMWorld ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); + using RefIdAdapter::getData; + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index, + int subRowIndex, int subColIndex) const; + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const; + using RefIdAdapter::setData; + virtual void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value, int subRowIndex, int subColIndex) const; + virtual void setData (const RefIdColumn *column, RefIdData& data, int index, const QVariant& value) const; ///< If the data type does not match an exception is thrown. From ad911d4d033926965ed593ede3db3ec6ad6d5782 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 27 May 2014 22:09:08 +1000 Subject: [PATCH 417/545] MSVC generates different symbols for class vs struct, confusing the linker. --- apps/openmw/mwworld/cellref.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 3b0c2251be..4db362b1e0 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -5,7 +5,7 @@ namespace ESM { - class ObjectState; + struct ObjectState; } namespace MWWorld From 6720d85a04315ddd1d1807dfeb7646b438159790 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 27 May 2014 14:50:21 +0200 Subject: [PATCH 418/545] fixed compilation, thanks greye --- apps/opencs/model/world/refidadapterimp.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index df64e9f054..8c98e18082 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -226,9 +226,8 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa int index, const QVariant& value, int subRowIndex, - int subColIndex) + int subColIndex) const { - using RefIdAdapter::setData; Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); @@ -256,7 +255,6 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const CSMWorld::RefIdColumn* int subRowIndex, int subColIndex) const { - using RefIdAdapter::getData; const Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); From e266c39c5d831a45be5fa9e6df7eef2e11ea925d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 14:54:29 +0200 Subject: [PATCH 419/545] Implement modFactionReaction instruction (Closes #1347) --- apps/openmw/mwbase/dialoguemanager.hpp | 6 +++ apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 37 +++++++++++++++++++ apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 11 ++++++ apps/openmw/mwdialogue/filter.cpp | 15 ++++---- .../mwmechanics/mechanicsmanagerimp.cpp | 27 ++++++-------- apps/openmw/mwscript/dialogueextensions.cpp | 19 ++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 3 +- components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 1 + components/esm/dialoguestate.cpp | 30 ++++++++++++++- components/esm/dialoguestate.hpp | 5 ++- components/esm/loadfact.cpp | 14 +++---- components/esm/loadfact.hpp | 11 ++---- 13 files changed, 138 insertions(+), 42 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index f51fba07b7..cab6809aa0 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -68,6 +68,12 @@ namespace MWBase virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; + + /// Changes faction1's opinion of faction2 by \a diff. + virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0; + + /// @return faction1's opinion of faction2 + virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0; }; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index c7e832e4ab..3ca2b8345f 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -642,6 +642,8 @@ namespace MWDialogue if (iter->second) state.mKnownTopics.push_back (iter->first); + state.mModFactionReaction = mModFactionReaction; + writer.startRecord (ESM::REC_DIAS); state.save (writer); writer.endRecord (ESM::REC_DIAS); @@ -661,9 +663,44 @@ namespace MWDialogue iter!=state.mKnownTopics.end(); ++iter) if (store.get().search (*iter)) mKnownTopics.insert (std::make_pair (*iter, true)); + + mModFactionReaction = state.mModFactionReaction; } } + void DialogueManager::modFactionReaction(const std::string &faction1, const std::string &faction2, int diff) + { + std::string fact1 = Misc::StringUtils::lowerCase(faction1); + std::string fact2 = Misc::StringUtils::lowerCase(faction2); + + // Make sure the factions exist + MWBase::Environment::get().getWorld()->getStore().get().find(fact1); + MWBase::Environment::get().getWorld()->getStore().get().find(fact2); + + std::map& map = mModFactionReaction[fact1]; + if (map.find(fact2) == map.end()) + map[fact2] = 0; + map[fact2] += diff; + } + + int DialogueManager::getFactionReaction(const std::string &faction1, const std::string &faction2) const + { + std::string fact1 = Misc::StringUtils::lowerCase(faction1); + std::string fact2 = Misc::StringUtils::lowerCase(faction2); + + ModFactionReactionMap::const_iterator map = mModFactionReaction.find(fact1); + int diff = 0; + if (map != mModFactionReaction.end() && map->second.find(fact2) != map->second.end()) + diff = map->second.at(fact2); + + const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get().find(fact1); + + std::map::const_iterator it = faction->mReactions.find(fact2); + if (it == faction->mReactions.end()) + return diff; + else + return it->second + diff; + } std::vector ParseHyperText(const std::string& text) { diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 6cd2c75afb..db0b78d594 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -24,6 +24,11 @@ namespace MWDialogue { std::map mDialogueMap; std::map mKnownTopics;// Those are the topics the player knows. + + // Modified faction reactions. > + typedef std::map > ModFactionReactionMap; + ModFactionReactionMap mModFactionReaction; + std::list mActorKnownTopics; Translation::Storage& mTranslationDataStorage; @@ -86,6 +91,12 @@ namespace MWDialogue virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; virtual void readRecord (ESM::ESMReader& reader, int32_t type); + + /// Changes faction1's opinion of faction2 by \a diff. + virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff); + + /// @return faction1's opinion of faction2 + virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const; }; diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 3d67f3bce0..d301e88aac 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -396,16 +396,15 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con int value = 0; - const ESM::Faction& faction = - *MWBase::Environment::get().getWorld()->getStore().get().find (factionId); - MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player); - for (std::vector::const_iterator iter (faction.mReactions.begin()); - iter!=faction.mReactions.end(); ++iter) - if (playerStats.getFactionRanks().find (iter->mFaction)!=playerStats.getFactionRanks().end()) - if (low ? iter->mReactionmReaction>value) - value = iter->mReaction; + std::map::const_iterator playerFactionIt = playerStats.getFactionRanks().begin(); + for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt) + { + int reaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(factionId, playerFactionIt->first); + if (low ? reaction < value : reaction > value) + value = reaction; + } return value; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 1ea4be8432..1f9846aa71 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -498,27 +498,24 @@ namespace MWMechanics if (playerStats.getFactionRanks().find(npcFaction) != playerStats.getFactionRanks().end()) { - for(std::vector::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get().find(npcFaction)->mReactions.begin(); - it != MWBase::Environment::get().getWorld()->getStore().get().find(npcFaction)->mReactions.end(); ++it) + if (!playerStats.getExpelled(npcFaction)) { - if(Misc::StringUtils::ciEqual(it->mFaction, npcFaction) - && !playerStats.getExpelled(it->mFaction)) - reaction = it->mReaction; + reaction = playerStats.getFactionReputation(npcFaction); + + rank = playerStats.getFactionRanks().find(npcFaction)->second; } - rank = playerStats.getFactionRanks().find(npcFaction)->second; } - else if (npcFaction != "") + else if (!npcFaction.empty()) { - for(std::vector::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get().find(npcFaction)->mReactions.begin(); - it != MWBase::Environment::get().getWorld()->getStore().get().find(npcFaction)->mReactions.end();++it) + std::map::const_iterator playerFactionIt = playerStats.getFactionRanks().begin(); + for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt) { - if(playerStats.getFactionRanks().find(Misc::StringUtils::lowerCase(it->mFaction)) != playerStats.getFactionRanks().end() ) - { - if(it->mReaction < reaction) - reaction = it->mReaction; - } + std::string itFaction = playerFactionIt->first; + + int itReaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, itFaction); + if (playerFactionIt == playerStats.getFactionRanks().begin() || itReaction < reaction) + reaction = itReaction; } - rank = 0; } else { diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 047c4d92fa..19f6ca2df4 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -196,6 +196,24 @@ namespace MWScript } }; + class OpModFactionReaction : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string faction2 = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + int modReaction = runtime[0].mInteger; + runtime.pop(); + + MWBase::Environment::get().getDialogueManager()->modFactionReaction(faction1, faction2, modReaction); + } + }; void installOpcodes (Interpreter::Interpreter& interpreter) { @@ -215,6 +233,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Dialogue::opcodeGetReputationExplicit, new OpGetReputation); interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction); + interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction); } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index bf2273b17e..f81cfb460c 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -390,5 +390,6 @@ op 0x200023e: GetPcInJail op 0x200023f: GetPcTraveling op 0x2000240: onKnockout op 0x2000241: onKnockoutExplicit +op 0x2000242: ModFactionReaction -opcodes 0x2000242-0x3ffffff unused +opcodes 0x2000243-0x3ffffff unused diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index db1ac16095..24e875173a 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -179,6 +179,7 @@ namespace Compiler opcodeGetReputationExplicit); extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction, opcodeSameFactionExplicit); + extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 9e36cb68d7..381a052ac2 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -152,6 +152,7 @@ namespace Compiler const int opcodeGetReputationExplicit = 0x20001b2; const int opcodeSameFaction = 0x20001b5; const int opcodeSameFactionExplicit = 0x20001b6; + const int opcodeModFactionReaction = 0x2000242; } namespace Gui diff --git a/components/esm/dialoguestate.cpp b/components/esm/dialoguestate.cpp index b3544c85ce..14301ac198 100644 --- a/components/esm/dialoguestate.cpp +++ b/components/esm/dialoguestate.cpp @@ -8,6 +8,20 @@ void ESM::DialogueState::load (ESMReader &esm) { while (esm.isNextSub ("TOPI")) mKnownTopics.push_back (esm.getHString()); + + while (esm.isNextSub ("FACT")) + { + std::string faction = esm.getHString(); + + while (esm.isNextSub ("REAC")) + { + std::string faction2 = esm.getHString(); + int reaction; + esm.getHNT(reaction, "INTV"); + + mModFactionReaction[faction][faction2] = reaction; + } + } } void ESM::DialogueState::save (ESMWriter &esm) const @@ -16,6 +30,18 @@ void ESM::DialogueState::save (ESMWriter &esm) const iter!=mKnownTopics.end(); ++iter) { esm.writeHNString ("TOPI", *iter); - } -} \ No newline at end of file + + for (std::map >::const_iterator iter = mModFactionReaction.begin(); + iter != mModFactionReaction.end(); ++iter) + { + esm.writeHNString ("FACT", iter->first); + + for (std::map::const_iterator reactIter = iter->second.begin(); + reactIter != iter->second.end(); ++reactIter) + { + esm.writeHNString ("REAC", reactIter->first); + esm.writeHNT ("INTV", reactIter->second); + } + } +} diff --git a/components/esm/dialoguestate.hpp b/components/esm/dialoguestate.hpp index 9aa9eaefd3..5e5f602a30 100644 --- a/components/esm/dialoguestate.hpp +++ b/components/esm/dialoguestate.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace ESM { @@ -15,9 +16,11 @@ namespace ESM { std::vector mKnownTopics; + std::map > mModFactionReaction; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 84be21938b..0924efb174 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -44,10 +44,10 @@ void Faction::load(ESMReader &esm) // Read faction response values while (esm.hasMoreSubs()) { - Reaction r; - r.mFaction = esm.getHNString("ANAM"); - esm.getHNT(r.mReaction, "INTV"); - mReactions.push_back(r); + std::string faction = esm.getHNString("ANAM"); + int reaction; + esm.getHNT(reaction, "INTV"); + mReactions[faction] = reaction; } } void Faction::save(ESMWriter &esm) const @@ -64,10 +64,10 @@ void Faction::save(ESMWriter &esm) const esm.writeHNT("FADT", mData, 240); - for (std::vector::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it) + for (std::map::const_iterator it = mReactions.begin(); it != mReactions.end(); ++it) { - esm.writeHNString("ANAM", it->mFaction); - esm.writeHNT("INTV", it->mReaction); + esm.writeHNString("ANAM", it->first); + esm.writeHNT("INTV", it->second); } } diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index 9c257e068e..75e30a5bf1 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -2,7 +2,7 @@ #define OPENMW_ESM_FACT_H #include -#include +#include namespace ESM { @@ -53,13 +53,8 @@ struct Faction FADTstruct mData; - struct Reaction - { - std::string mFaction; - int mReaction; - }; - - std::vector mReactions; + // + std::map mReactions; // Name of faction ranks (may be empty for NPC factions) std::string mRanks[10]; From 3e2eed92695405eae7372cf64fea18acd0af7abe Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 15:23:22 +0200 Subject: [PATCH 420/545] Implement getFactionReaction function Strange bug when using value != 0 for the garbage argument? --- apps/openmw/mwscript/dialogueextensions.cpp | 22 +++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 3 ++- components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 19f6ca2df4..9dde65ab2c 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -215,6 +215,27 @@ namespace MWScript } }; + class OpGetFactionReaction : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string faction2 = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + // ignore extra garbage argument + runtime.pop(); + + runtime.push(MWBase::Environment::get().getDialogueManager() + ->getFactionReaction(faction1, faction2)); + } + }; + + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (Compiler::Dialogue::opcodeJournal, new OpJournal); @@ -234,6 +255,7 @@ namespace MWScript interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFaction, new OpSameFaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction); + interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction); } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index f81cfb460c..53c80a943b 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -391,5 +391,6 @@ op 0x200023f: GetPcTraveling op 0x2000240: onKnockout op 0x2000241: onKnockoutExplicit op 0x2000242: ModFactionReaction +op 0x2000243: GetFactionReaction -opcodes 0x2000243-0x3ffffff unused +opcodes 0x2000244-0x3ffffff unused diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 24e875173a..4ef638ef83 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -180,6 +180,7 @@ namespace Compiler extensions.registerFunction("samefaction", 'l', "", opcodeSameFaction, opcodeSameFactionExplicit); extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction); + extensions.registerFunction("getfactionreaction", 'l', "ccl", opcodeGetFactionReaction); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 381a052ac2..1dff046652 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -153,6 +153,7 @@ namespace Compiler const int opcodeSameFaction = 0x20001b5; const int opcodeSameFactionExplicit = 0x20001b6; const int opcodeModFactionReaction = 0x2000242; + const int opcodeGetFactionReaction = 0x2000243; } namespace Gui From 49a6579d3a9bce5d36530769af654ef792d7bf6e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 15:37:04 +0200 Subject: [PATCH 421/545] Fixed esmtool --- apps/esmtool/record.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index fd4b97acb9..bcf16091f4 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -707,9 +707,9 @@ void Record::print() std::cout << " Faction Reaction: " << mData.mData.mRankData[i].mFactReaction << std::endl; } - std::vector::iterator rit; + std::map::iterator rit; for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++) - std::cout << " Reaction: " << rit->mReaction << " = " << rit->mFaction << std::endl; + std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl; } template<> From f476aa4ade40a21e39d8a555580bebf66b3b4e84 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 17:07:14 +0200 Subject: [PATCH 422/545] Remove MyGUI color codes when copying to system clipboard --- apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index cf71cc1aa4..8cfe2c2b31 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -492,7 +492,8 @@ namespace MWInput } if (arg.keysym.sym == SDLK_x && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL))) { - std::string text = edit->getTextSelection(); + // Discard color codes and other escape characters + std::string text = MyGUI::TextIterator::getOnlyText(edit->getTextSelection()); if (text.length()) { SDL_SetClipboardText(text.c_str()); @@ -504,7 +505,8 @@ namespace MWInput { if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL))) { - std::string text = edit->getTextSelection(); + // Discard color codes and other escape characters + std::string text = MyGUI::TextIterator::getOnlyText(edit->getTextSelection()); if (text.length()) SDL_SetClipboardText(text.c_str()); } From 2fe86f2b85aa9a29f8a0d80b8982c97afc643b57 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 17:39:04 +0200 Subject: [PATCH 423/545] Consider hit normal for item drop test (Fixes #995) --- apps/openmw/mwworld/physicssystem.cpp | 4 ++-- apps/openmw/mwworld/physicssystem.hpp | 5 +++-- apps/openmw/mwworld/worldimp.cpp | 13 ++++++++----- libs/openengine/bullet/physic.cpp | 8 ++++++-- libs/openengine/bullet/physic.hpp | 4 +++- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index b8f0f8699b..e93d9e640f 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -492,7 +492,7 @@ namespace MWWorld return std::make_pair(true, ray.getPoint(len * test.second)); } - std::pair PhysicsSystem::castRay(float mouseX, float mouseY) + std::pair PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal) { Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay( mouseX, @@ -504,7 +504,7 @@ namespace MWWorld _from = btVector3(from.x, from.y, from.z); _to = btVector3(to.x, to.y, to.z); - std::pair result = mEngine->rayTest(_from, _to); + std::pair result = mEngine->rayTest(_from, _to, true, false, normal); if (result.first == "") return std::make_pair(false, Ogre::Vector3()); diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 3dcd088f54..899d7144d9 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -70,8 +70,9 @@ namespace MWWorld std::pair castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); - std::pair castRay(float mouseX, float mouseY); - ///< cast ray from the mouse, return true if it hit something and the first result (in OGRE coordinates) + std::pair castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL); + ///< cast ray from the mouse, return true if it hit something and the first result + /// @param normal if non-NULL, the hit normal will be written there (if there is a hit) OEngine::Physic::PhysicEngine* getEngine(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 435ca8b367..fdc2031823 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1620,13 +1620,16 @@ namespace MWWorld bool World::canPlaceObject(float cursorX, float cursorY) { - std::pair result = mPhysics->castRay(cursorX, cursorY); + Ogre::Vector3 normal(0,0,0); + std::pair result = mPhysics->castRay(cursorX, cursorY, &normal); - /// \todo also check if the wanted position is on a flat surface, and not e.g. against a vertical wall! - - if (!result.first) + if (result.first) + { + // check if the wanted position is on a flat surface, and not e.g. against a vertical wall + return (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() < 30); + } + else return false; - return true; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 6646ce2738..235300b438 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -677,7 +677,7 @@ namespace Physic { } - std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap) + std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap, Ogre::Vector3* normal) { std::string name = ""; float d = -1; @@ -694,7 +694,11 @@ namespace Physic if (resultCallback1.hasHit()) { name = static_cast(*resultCallback1.m_collisionObject).mName; - d = resultCallback1.m_closestHitFraction;; + d = resultCallback1.m_closestHitFraction; + if (normal) + *normal = Ogre::Vector3(resultCallback1.m_hitNormalWorld.x(), + resultCallback1.m_hitNormalWorld.y(), + resultCallback1.m_hitNormalWorld.z()); } return std::pair(name,d); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 16eb453068..803986d5b7 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -308,8 +308,10 @@ namespace Physic /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). + * If \a normal is non-NULL, the hit normal will be written there (if there is a hit) */ - std::pair rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true,bool ignoreHeightMap = false); + std::pair rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true, + bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL); /** * Return all objects hit by a ray. From 2b15b85af1472a5565310b6eae2000242198e584 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 17:58:18 +0200 Subject: [PATCH 424/545] Fix position adjustment not working properly for rotated objects --- apps/openmw/mwworld/worldimp.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fdc2031823..38edd8b8d6 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1635,13 +1635,24 @@ namespace MWWorld Ptr World::copyObjectToCell(const Ptr &object, CellStore* cell, ESM::Position pos, bool adjustPos) { - if (object.getClass().isActor() || adjustPos) + if (!object.getClass().isActor() && adjustPos) { + // Adjust position so the location we wanted ends up in the middle of the object bounding box Ogre::Vector3 min, max; if (mPhysics->getObjectAABB(object, min, max)) { - pos.pos[0] -= (min.x + max.x) / 2; - pos.pos[1] -= (min.y + max.y) / 2; - pos.pos[2] -= min.z; + Ogre::Quaternion xr(Ogre::Radian(-pos.rot[0]), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yr(Ogre::Radian(-pos.rot[1]), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zr(Ogre::Radian(-pos.rot[2]), Ogre::Vector3::UNIT_Z); + + Ogre::Vector3 adjust ( + (min.x + max.x) / 2, + (min.y + max.y) / 2, + min.z + ); + adjust = (xr*yr*zr) * adjust; + pos.pos[0] -= adjust.x; + pos.pos[1] -= adjust.y; + pos.pos[2] -= adjust.z; } } From 0b45a9e6b25865143f686d5738ea45faab269e0f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 19:02:48 +0200 Subject: [PATCH 425/545] Fix case folding for faction reaction from ESX records --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 3ca2b8345f..b6cef2fe7f 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -695,11 +695,13 @@ namespace MWDialogue const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get().find(fact1); - std::map::const_iterator it = faction->mReactions.find(fact2); - if (it == faction->mReactions.end()) - return diff; - else - return it->second + diff; + std::map::const_iterator it = faction->mReactions.begin(); + for (; it != faction->mReactions.end(); ++it) + { + if (Misc::StringUtils::ciEqual(it->first, fact2)) + return it->second + diff; + } + return diff; } std::vector ParseHyperText(const std::string& text) From 91f4967614795effdb0ade4cae408fc01a602313 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Tue, 27 May 2014 13:12:27 -0400 Subject: [PATCH 426/545] Fix for bug 1196. This bug would cause the player to jump when jump was assigned to Space and they closed a dialog with Space. I tested vanilla MW for behaviour and found that Jump was the only basic input which MW does not allow when closing dialogs (i.e. if Space is assigned to move forward, MW will move you forward after closing the dialog). There were two reasons for the bug: 1) OpenMW GUI does not consume UI events 2) Jump occurs so long as key is down (not only on first key down) To minimally fix the bug, I made it so that keypress events can be consumed by the GUI and not passed along to the player control input manager (1). However, if the player holds space, they will still jump (as the subsequent key held events will be captured and cause a jump). Unfortunately, there is no idiomatic way that I could find in the OpenMW input manager to perform events only on key down. Instead, I introduced a variable which tracks whether the jump key has been pressed for the first time within the current frame (2). Note: I was initially concerned that limiting the jump event to KeyDown and not Key Hold would cause issues with swimming, levitating, or variable height jumping. However, after a bunch of testing in vanilla MW and exploration of the OpenMW codebase I could find nothing suggesting the need to capture the jump key being held. --- apps/openmw/mwinput/inputmanagerimp.cpp | 195 ++++++++++++------------ apps/openmw/mwinput/inputmanagerimp.hpp | 1 + 2 files changed, 102 insertions(+), 94 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index e2d4f8cb2d..9c263e52d2 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -113,6 +113,7 @@ namespace MWInput , mTimeIdle(0.f) , mOverencumberedMessageDelay(0.f) , mAlwaysRunActive(false) + , mAttemptJump(false) { Ogre::RenderWindow* window = ogre.getWindow (); @@ -173,6 +174,11 @@ namespace MWInput MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); } + if (action == A_Jump) + { + mAttemptJump = (currentValue == 1.0 && previousValue == 0.0); + } + if (currentValue == 1) { // trigger action activated @@ -292,107 +298,107 @@ namespace MWInput } // Disable movement in Gui mode - if (MWBase::Environment::get().getWindowManager()->isGuiMode() - || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running) - return; - - - // Configure player movement according to keyboard input. Actual movement will - // be done in the physics system. - if (mControlSwitch["playercontrols"]) + if (!(MWBase::Environment::get().getWindowManager()->isGuiMode() + || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)) { - bool triedToMove = false; - if (actionIsActive(A_MoveLeft)) + // Configure player movement according to keyboard input. Actual movement will + // be done in the physics system. + if (mControlSwitch["playercontrols"]) { - triedToMove = true; - mPlayer->setLeftRight (-1); - } - else if (actionIsActive(A_MoveRight)) - { - triedToMove = true; - mPlayer->setLeftRight (1); - } - - if (actionIsActive(A_MoveForward)) - { - triedToMove = true; - mPlayer->setAutoMove (false); - mPlayer->setForwardBackward (1); - } - else if (actionIsActive(A_MoveBackward)) - { - triedToMove = true; - mPlayer->setAutoMove (false); - mPlayer->setForwardBackward (-1); - } - - else if(mPlayer->getAutoMove()) - { - triedToMove = true; - mPlayer->setForwardBackward (1); - } - - mPlayer->setSneak(actionIsActive(A_Sneak)); - - if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) - { - mPlayer->setUpDown (1); - triedToMove = true; - } - - if (mAlwaysRunActive) - mPlayer->setRunState(!actionIsActive(A_Run)); - else - mPlayer->setRunState(actionIsActive(A_Run)); - - // if player tried to start moving, but can't (due to being overencumbered), display a notification. - if (triedToMove) - { - MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - mOverencumberedMessageDelay -= dt; - if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) + bool triedToMove = false; + if (actionIsActive(A_MoveLeft)) { + triedToMove = true; + mPlayer->setLeftRight (-1); + } + else if (actionIsActive(A_MoveRight)) + { + triedToMove = true; + mPlayer->setLeftRight (1); + } + + if (actionIsActive(A_MoveForward)) + { + triedToMove = true; mPlayer->setAutoMove (false); - if (mOverencumberedMessageDelay <= 0) + mPlayer->setForwardBackward (1); + } + else if (actionIsActive(A_MoveBackward)) + { + triedToMove = true; + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (-1); + } + + else if(mPlayer->getAutoMove()) + { + triedToMove = true; + mPlayer->setForwardBackward (1); + } + + mPlayer->setSneak(actionIsActive(A_Sneak)); + + if (mAttemptJump && mControlSwitch["playerjumping"]) + { + mPlayer->setUpDown (1); + triedToMove = true; + } + + if (mAlwaysRunActive) + mPlayer->setRunState(!actionIsActive(A_Run)); + else + mPlayer->setRunState(actionIsActive(A_Run)); + + // if player tried to start moving, but can't (due to being overencumbered), display a notification. + if (triedToMove) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); + mOverencumberedMessageDelay -= dt; + if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) { - MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); - mOverencumberedMessageDelay = 1.0; + mPlayer->setAutoMove (false); + if (mOverencumberedMessageDelay <= 0) + { + MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); + mOverencumberedMessageDelay = 1.0; + } + } + } + + if (mControlSwitch["playerviewswitch"]) { + + // work around preview mode toggle when pressing Alt+Tab + if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) { + if (mPreviewPOVDelay <= 0.5 && + (mPreviewPOVDelay += dt) > 0.5) + { + mPreviewPOVDelay = 1.f; + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + } + } else { + //disable preview mode + MWBase::Environment::get().getWorld()->togglePreviewMode(false); + if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) { + MWBase::Environment::get().getWorld()->togglePOV(); + } + mPreviewPOVDelay = 0.f; } } } - - if (mControlSwitch["playerviewswitch"]) { - - // work around preview mode toggle when pressing Alt+Tab - if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) { - if (mPreviewPOVDelay <= 0.5 && - (mPreviewPOVDelay += dt) > 0.5) - { - mPreviewPOVDelay = 1.f; - MWBase::Environment::get().getWorld()->togglePreviewMode(true); - } - } else { - //disable preview mode - MWBase::Environment::get().getWorld()->togglePreviewMode(false); - if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) { - MWBase::Environment::get().getWorld()->togglePOV(); - } - mPreviewPOVDelay = 0.f; - } + if (actionIsActive(A_MoveForward) || + actionIsActive(A_MoveBackward) || + actionIsActive(A_MoveLeft) || + actionIsActive(A_MoveRight) || + actionIsActive(A_Jump) || + actionIsActive(A_Sneak) || + actionIsActive(A_TogglePOV)) + { + resetIdleTime(); + } else { + updateIdleTime(dt); } } - if (actionIsActive(A_MoveForward) || - actionIsActive(A_MoveBackward) || - actionIsActive(A_MoveLeft) || - actionIsActive(A_MoveRight) || - actionIsActive(A_Jump) || - actionIsActive(A_Sneak) || - actionIsActive(A_TogglePOV)) - { - resetIdleTime(); - } else { - updateIdleTime(dt); - } + mAttemptJump = false; // Can only jump on first frame input is on } void InputManager::setDragDrop(bool dragDrop) @@ -502,12 +508,13 @@ namespace MWInput } } - mInputBinder->keyPressed (arg); - OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); + bool passToBinder = true; if (kc != OIS::KC_UNASSIGNED) - MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + passToBinder = !MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + if(passToBinder) + mInputBinder->keyPressed (arg); } void InputManager::textInput(const SDL_TextInputEvent &arg) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 87fbda25cd..537c3a1827 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -161,6 +161,7 @@ namespace MWInput int mMouseWheel; bool mUserFileExists; bool mAlwaysRunActive; + bool mAttemptJump; std::map mControlSwitch; From 060a50f94a2b4746c69e26c8fec90ceb47031968 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 13:50:24 -0400 Subject: [PATCH 427/545] Fixed issue with QuickKeyMenu and ItemSelectionDialog --- apps/openmw/mwgui/itemselection.cpp | 7 ++++++- apps/openmw/mwgui/itemselection.hpp | 2 ++ apps/openmw/mwgui/quickkeysmenu.cpp | 16 +++++++++++++--- apps/openmw/mwgui/quickkeysmenu.hpp | 2 ++ apps/openmw/mwinput/inputmanagerimp.cpp | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp index 01ea3429c3..1b197f6d80 100644 --- a/apps/openmw/mwgui/itemselection.cpp +++ b/apps/openmw/mwgui/itemselection.cpp @@ -26,6 +26,11 @@ namespace MWGui center(); } + void ItemSelectionDialog::exit() + { + eventDialogCanceled(); + } + void ItemSelectionDialog::openContainer(const MWWorld::Ptr& container) { mModel = new InventoryItemModel(container); @@ -53,7 +58,7 @@ namespace MWGui void ItemSelectionDialog::onCancelButtonClicked(MyGUI::Widget* sender) { - eventDialogCanceled(); + exit(); } } diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp index c9ec23cfae..28c45c6056 100644 --- a/apps/openmw/mwgui/itemselection.hpp +++ b/apps/openmw/mwgui/itemselection.hpp @@ -14,6 +14,8 @@ namespace MWGui public: ItemSelectionDialog(const std::string& label); + virtual void exit(); + typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Item; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 9321d2de23..af4e20ca4a 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -59,7 +59,7 @@ namespace MWGui void QuickKeysMenu::exit() { - mAssignDialog->setVisible (false); + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_QuickKeysMenu); } void QuickKeysMenu::clear() @@ -151,7 +151,7 @@ namespace MWGui void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender) { - exit(); + mAssignDialog->setVisible (false); } void QuickKeysMenu::onAssignItem(MWWorld::Ptr item) @@ -390,6 +390,11 @@ namespace MWGui center(); } + void QuickKeysMenuAssign::exit() + { + setVisible(false); + } + void QuickKeysMenu::write(ESM::ESMWriter &writer) { writer.startRecord(ESM::REC_KEYS); @@ -513,7 +518,12 @@ namespace MWGui void MagicSelectionDialog::onCancelButtonClicked (MyGUI::Widget *sender) { - mParent->onAssignMagicCancel (); + exit(); + } + + void MagicSelectionDialog::exit() + { + mParent->onAssignMagicCancel(); } void MagicSelectionDialog::open () diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 56a04cfbbb..40c5dab565 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -70,6 +70,7 @@ namespace MWGui { public: QuickKeysMenuAssign(QuickKeysMenu* parent); + virtual void exit(); private: MyGUI::TextBox* mLabel; @@ -87,6 +88,7 @@ namespace MWGui MagicSelectionDialog(QuickKeysMenu* parent); virtual void open(); + virtual void exit(); private: MyGUI::Button* mCancelButton; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 2d78e7875d..332c8f6a7c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -642,7 +642,7 @@ namespace MWInput return; } - if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Dialogue) { //Give access to the main menu when at a choice in Dialogue + if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Dialogue) { //Give access to the main menu when at a choice in dialogue if(MWBase::Environment::get().getDialogueManager()->isInChoice()) { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); From 033f1850f9a747e3f9ba39e1955a1af948ffc1ec Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 14:30:26 -0400 Subject: [PATCH 428/545] Fixed crass on character creation, allowed some character creation windows to be Esc-able --- apps/openmw/mwgui/class.cpp | 15 +++++++++++++++ apps/openmw/mwgui/class.hpp | 6 ++++++ apps/openmw/mwgui/countdialog.cpp | 13 +++++++++---- apps/openmw/mwgui/countdialog.hpp | 1 + apps/openmw/mwgui/windowbase.cpp | 5 ----- apps/openmw/mwgui/windowbase.hpp | 2 +- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 1c8cc78403..9f6306830b 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -718,6 +718,11 @@ namespace MWGui } void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender) + { + exit(); + } + + void SelectSpecializationDialog::exit() { eventCancel(); } @@ -764,6 +769,11 @@ namespace MWGui } void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender) + { + exit(); + } + + void SelectAttributeDialog::exit() { eventCancel(); } @@ -855,6 +865,11 @@ namespace MWGui } void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender) + { + exit(); + } + + void SelectSkillDialog::exit() { eventCancel(); } diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index f78f7541b2..5c23c834d7 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -136,6 +136,8 @@ namespace MWGui SelectSpecializationDialog(); ~SelectSpecializationDialog(); + virtual void exit(); + ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; } // Events @@ -167,6 +169,8 @@ namespace MWGui SelectAttributeDialog(); ~SelectAttributeDialog(); + virtual void exit(); + ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; } // Events @@ -196,6 +200,8 @@ namespace MWGui SelectSkillDialog(); ~SelectSkillDialog(); + virtual void exit(); + ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } // Events diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 02ccbbc053..53c33b3c48 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -49,7 +49,12 @@ namespace MWGui mItemEdit->setCaption(boost::lexical_cast(maxCount)); } - void CountDialog::cancel() + void CountDialog::cancel() //Keeping this here as I don't know if anything else relies on it. + { + exit(); + } + + void CountDialog::exit() { setVisible(false); } @@ -65,16 +70,16 @@ namespace MWGui setVisible(false); } - + // essentially duplicating what the OK button does if user presses // Enter key void CountDialog::onEnterKeyPressed(MyGUI::EditBox* _sender) { eventOkClicked(NULL, mSlider->getScrollPosition()+1); - + setVisible(false); } - + void CountDialog::onEditTextChange(MyGUI::EditBox* _sender) { if (_sender->getCaption() == "") diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index 06de3eb887..a00b0b223b 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -11,6 +11,7 @@ namespace MWGui CountDialog(); void open(const std::string& item, const std::string& message, const int maxCount); void cancel(); + virtual void exit(); typedef MyGUI::delegates::CMultiDelegate2 EventHandle_WidgetInt; diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index 4dcb680ec0..c2515a6ded 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -56,11 +56,6 @@ void WindowModal::close() MWBase::Environment::get().getWindowManager()->removeCurrentModal(this); } -void WindowModal::exit() -{ - close(); -} - NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget) : mDrag(drag), mWidget(widget), mTransparent(false) { diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index 79ab282990..471d8ac709 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -47,7 +47,7 @@ namespace MWGui WindowModal(const std::string& parLayout); virtual void open(); virtual void close(); - virtual void exit(); + virtual void exit() {} }; /// A window that cannot be the target of a drag&drop action. From 12fc0aaecb856e4dd7966801bbdc6ebb36558e7a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 May 2014 21:08:29 +0200 Subject: [PATCH 429/545] removed an unused parser settings (implicitly fixing a case were this setting was not applied correctly) --- components/compiler/exprparser.cpp | 18 +++++------------- components/compiler/exprparser.hpp | 2 +- components/compiler/lineparser.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 0c013b18f1..90a294c0c6 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -730,7 +730,7 @@ namespace Compiler } int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner, - std::vector& code, bool invert) + std::vector& code) { bool optional = false; int optionalCount = 0; @@ -762,15 +762,10 @@ namespace Compiler if (*iter!='x') { - if (invert) - { - std::vector tmp; - stringParser.append (tmp); + std::vector tmp; + stringParser.append (tmp); - stack.push (tmp); - } - else - stringParser.append (code); + stack.push (tmp); if (optional) ++optionalCount; @@ -795,10 +790,7 @@ namespace Compiler if (type!=*iter) Generator::convert (tmp, type, *iter); - if (invert) - stack.push (tmp); - else - std::copy (tmp.begin(), tmp.end(), std::back_inserter (code)); + stack.push (tmp); if (optional) ++optionalCount; diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 93e0d1c366..e4e385ff0f 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -96,7 +96,7 @@ namespace Compiler /// \return Type ('l': integer, 'f': float) int parseArguments (const std::string& arguments, Scanner& scanner, - std::vector& code, bool invert = false); + std::vector& code); ///< Parse sequence of arguments specified by \a arguments. /// \param arguments Uses ScriptArgs typedef /// \see Compiler::ScriptArgs diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 98bd63ba1e..f7d2726e35 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -166,7 +166,7 @@ namespace Compiler if (!arguments.empty()) { mExprParser.reset(); - mExprParser.parseArguments (arguments, scanner, mCode, true); + mExprParser.parseArguments (arguments, scanner, mCode); } mName = name; @@ -278,7 +278,7 @@ namespace Compiler mExplicit.clear(); } - int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true); + int optionals = mExprParser.parseArguments (argumentType, scanner, mCode); extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals); mState = EndState; @@ -363,14 +363,14 @@ namespace Compiler case Scanner::K_startscript: - mExprParser.parseArguments ("c", scanner, mCode, true); + mExprParser.parseArguments ("c", scanner, mCode); Generator::startScript (mCode); mState = EndState; return true; case Scanner::K_stopscript: - mExprParser.parseArguments ("c", scanner, mCode, true); + mExprParser.parseArguments ("c", scanner, mCode); Generator::stopScript (mCode); mState = EndState; return true; From 9be219beba07bdd274fb9a80029827e147d36051 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Tue, 27 May 2014 22:09:37 -0400 Subject: [PATCH 430/545] Fixes Bug #1348 "Evidence Chest unlocking when arrested." --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 38edd8b8d6..c95a137ecc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2542,7 +2542,7 @@ namespace MWWorld store.remove(*it, it->getRefData().getCount(), ptr); } } - closestChest.getClass().unlock(closestChest); + closestChest.getClass().lock(closestChest,50); } } From 50a4d175da4fad6aa428a59839db157614c8fa3b Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Wed, 28 May 2014 03:42:26 -0400 Subject: [PATCH 431/545] Read NIF interpolation type 4 (XYZ_ROTATION_KEY) Don't actually do anything with it yet, but without this the "MW Containers Animated" mod made containers inaccessible. Partly implements Feature #1067 --- components/nif/niffile.hpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index d4b042726f..77e0acb9e5 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -155,6 +155,7 @@ struct KeyListT { static const int sLinearInterpolation = 1; static const int sQuadraticInterpolation = 2; static const int sTBCInterpolation = 3; + static const int sXYZInterpolation = 4; int mInterpolationType; VecType mKeys; @@ -199,6 +200,38 @@ struct KeyListT { key.mContinuity = nif->getFloat(); } } + //\FIXME This now reads the correct amount of data in the file, but doesn't actually do anything with it. + else if(mInterpolationType == sXYZInterpolation) + { + if (count != 1) + { + nif->file->fail("count should always be '1' for XYZ_ROTATION_KEY. Retrieved Value: "+Ogre::StringConverter::toString(count)); + return; + } + //KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) + //Chomp unknown and possibly unused float + nif->getFloat(); + for(size_t i=0;i<3;++i) + { + unsigned int numKeys = nif->getInt(); + if(numKeys != 0) + { + int interpolationTypeAgain = nif->getInt(); + if( interpolationTypeAgain != sLinearInterpolation) + { + nif->file->fail("XYZ_ROTATION_KEY's KeyGroup keyType must be '1' (Linear Interpolation). Retrieved Value: "+Ogre::StringConverter::toString(interpolationTypeAgain)); + return; + } + for(size_t j = 0;j < numKeys;j++) + { + //For now just chomp these + nif->getFloat(); + nif->getFloat(); + } + } + nif->file->warn("XYZ_ROTATION_KEY read, but not used!"); + } + } else if (mInterpolationType == 0) { if (count != 0) From 3244f2197a03c51fdddc6cc4f3523bedad4fb5d0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 28 May 2014 11:13:23 +0200 Subject: [PATCH 432/545] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 6f0561490b..da54170345 100644 --- a/credits.txt +++ b/credits.txt @@ -17,6 +17,7 @@ Alex McKibben (WeirdSexy) Alexander Nadeau (wareya) Alexander Olofsson (Ace) Artem Kotsynyak (greye) +Arthur Moore (EmperorArthur) athile Britt Mathis (galdor557) BrotherBrick From bbe77d656a99031b2fbcc31391701c1aabbf53f8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 May 2014 21:15:50 +1000 Subject: [PATCH 433/545] Minor fixes from static analysis. --- apps/esmtool/labels.cpp | 6 +++--- components/compiler/exprparser.cpp | 2 +- extern/shiny/Main/Factory.hpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index 7a42e6900f..ef45989efe 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -387,7 +387,7 @@ std::string magicEffectLabel(int idx) "sEffectSummonCreature04", "sEffectSummonCreature05" }; - if (idx >= 0 && idx <= 143) + if (idx >= 0 && idx <= 142) return magicEffectLabels[idx]; else return "Invalid"; @@ -471,7 +471,7 @@ std::string skillLabel(int idx) "Speechcraft", "Hand-to-hand" }; - if (idx >= 0 && idx <= 27) + if (idx >= 0 && idx <= 26) return skillLabels[idx]; else return "Invalid"; @@ -498,7 +498,7 @@ std::string rangeTypeLabel(int idx) "Touch", "Target" }; - if (idx >= 0 && idx <= 3) + if (idx >= 0 && idx <= 2) return rangeTypeLabels[idx]; else return "Invalid"; diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 90a294c0c6..ed628278b5 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -98,7 +98,7 @@ namespace Compiler else if (t1=='f' || t2=='f') mOperands.push_back ('f'); else - std::logic_error ("failed to determine result operand type"); + throw std::logic_error ("failed to determine result operand type"); } void ExprParser::pop() diff --git a/extern/shiny/Main/Factory.hpp b/extern/shiny/Main/Factory.hpp index 15c8599583..e8562011cb 100644 --- a/extern/shiny/Main/Factory.hpp +++ b/extern/shiny/Main/Factory.hpp @@ -206,7 +206,7 @@ namespace sh std::string getCacheFolder () { return mPlatform->getCacheFolder (); } bool getReadSourceCache() { return mReadSourceCache; } - bool getWriteSourceCache() { return mReadSourceCache; } + bool getWriteSourceCache() { return mWriteSourceCache; } public: bool getWriteMicrocodeCache() { return mWriteMicrocodeCache; } // Fixme From 56ff399f30729a5dcdb9f173d7c32c841570b4a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 13:59:31 +0200 Subject: [PATCH 434/545] Say attack voiced dialogue *after* the target is set up Required for the CreatureTargetted filter to function properly --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 1f9846aa71..900ea72cad 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1019,12 +1019,13 @@ namespace MWMechanics void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) { - if (ptr.getClass().isNpc()) - MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); - ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) ptr.getClass().getCreatureStats(ptr).setHostile(true); + + // Must be done after the target is set up, so that CreatureTargetted dialogue filter works properly + if (ptr.getClass().isNpc()) + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); } void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) From 42ea43c3d1a0c6b525596170476eecd08799eacf Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 18:45:07 +0200 Subject: [PATCH 435/545] Fix container scripts not getting removed properly on cell change Broken by f99eda1a543c7 --- apps/openmw/mwworld/containerstore.cpp | 28 +++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 2496a6eff4..8a076c3fc0 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -229,22 +229,26 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr std::string script = item.getClass().getScript(item); if(script != "") { - CellStore *cell; + if (actorPtr == player) + { + // Items in player's inventory have cell set to 0, so their scripts will never be removed + item.mCell = 0; + } + else + { + // Set mCell to the cell of the container/actor, so that the scripts are removed properly when + // the cell of the container/actor goes inactive + item.mCell = actorPtr.getCell(); + } + + item.mContainerStore = 0; MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); - if(&(player.getClass().getContainerStore (player)) == this) - { - cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed - - // Set OnPCAdd special variable, if it is declared + // Set OnPCAdd special variable, if it is declared + // Make sure to do this *after* we have added the script to LocalScripts + if (actorPtr == player) item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1); - } - else - cell = player.getCell(); - - item.mCell = cell; - item.mContainerStore = 0; } return it; From e68600eda25d40810f037ec6c44352ba67cb54b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 19:23:50 +0200 Subject: [PATCH 436/545] Make Activate instruction work properly even when onActivate was not called in the same frame. There are two major differences to the old implementation: - Activate can now be called on its own, e.g. in the console. In Vanilla this appears to be a no-op, so it is unlikely to be used and the potential for breakage is low. - The Action to execute is now determined when Activate is called, not when OnActivate is called. This however makes sense, since there may be a time difference between the two, and the object (or the player) could have changed in the meantime, requiring a different Action. Fixes #1166 and #1346. --- apps/openmw/engine.cpp | 7 ++----- apps/openmw/mwscript/docs/vmformat.txt | 3 ++- apps/openmw/mwscript/interpretercontext.cpp | 17 +++++++---------- apps/openmw/mwscript/interpretercontext.hpp | 9 ++++----- apps/openmw/mwscript/miscextensions.cpp | 8 ++++++-- components/compiler/extensions0.cpp | 2 +- components/compiler/opcodes.hpp | 1 + 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 820863cb95..d33e5300ec 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -491,10 +491,7 @@ void OMW::Engine::activate() MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); - boost::shared_ptr action = - ptr.getClass().activate (ptr, MWBase::Environment::get().getWorld()->getPlayerPtr()); - - interpreterContext.activate (ptr, action); + interpreterContext.activate (ptr); std::string script = ptr.getClass().getScript (ptr); @@ -508,7 +505,7 @@ void OMW::Engine::activate() if (!interpreterContext.hasActivationBeenHandled()) { - interpreterContext.executeActivation(); + interpreterContext.executeActivation(ptr); } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 53c80a943b..24b0b6f7aa 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -392,5 +392,6 @@ op 0x2000240: onKnockout op 0x2000241: onKnockoutExplicit op 0x2000242: ModFactionReaction op 0x2000243: GetFactionReaction +op 0x2000244: Activate, explicit -opcodes 0x2000244-0x3ffffff unused +opcodes 0x2000245-0x3ffffff unused diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 6f7968fac8..6bf50371b8 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -413,28 +413,25 @@ namespace MWScript return mActivationHandled; } - void InterpreterContext::activate (const MWWorld::Ptr& ptr, - boost::shared_ptr action) + void InterpreterContext::activate (const MWWorld::Ptr& ptr) { mActivated = ptr; mActivationHandled = false; - mAction = action; } - void InterpreterContext::executeActivation() + void InterpreterContext::executeActivation(MWWorld::Ptr ptr) { - if (!mAction.get()) - throw std::runtime_error ("activation failed, because no action to perform"); - - mAction->execute (MWBase::Environment::get().getWorld()->getPlayerPtr()); - mActivationHandled = true; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + boost::shared_ptr action = (ptr.getClass().activate(ptr, player)); + action->execute (player); + if (mActivated == ptr) + mActivationHandled = true; } void InterpreterContext::clearActivation() { mActivated = MWWorld::Ptr(); mActivationHandled = false; - mAction.reset(); } float InterpreterContext::getSecondsPassed() const diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 9fb7fa2bf8..1137efed31 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -31,7 +31,6 @@ namespace MWScript MWWorld::Ptr mActivated; bool mActivationHandled; - boost::shared_ptr mAction; MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true); @@ -126,12 +125,12 @@ namespace MWScript bool hasActivationBeenHandled() const; - void activate (const MWWorld::Ptr& ptr, boost::shared_ptr action); - ///< Store reference acted upon and action. The actual execution of the action does not + void activate (const MWWorld::Ptr& ptr); + ///< Store reference acted upon. The actual execution of the action does not /// take place here. - void executeActivation(); - ///< Execute the action defined by the last activate call. + void executeActivation(MWWorld::Ptr ptr); + ///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled. void clearActivation(); ///< Discard the action defined by the last activate call. diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index fa17d96af3..9d6d5e50dc 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -109,6 +109,7 @@ namespace MWScript } }; + template class OpActivate : public Interpreter::Opcode0 { public: @@ -118,7 +119,9 @@ namespace MWScript InterpreterContext& context = static_cast (runtime.getContext()); - context.executeActivation(); + MWWorld::Ptr ptr = R()(runtime); + + context.executeActivation(ptr); } }; @@ -860,7 +863,8 @@ namespace MWScript { interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox); interpreter.installSegment5 (Compiler::Misc::opcodeOnActivate, new OpOnActivate); - interpreter.installSegment5 (Compiler::Misc::opcodeActivate, new OpActivate); + interpreter.installSegment5 (Compiler::Misc::opcodeActivate, new OpActivate); + interpreter.installSegment5 (Compiler::Misc::opcodeActivateExplicit, new OpActivate); interpreter.installSegment3 (Compiler::Misc::opcodeLock, new OpLock); interpreter.installSegment3 (Compiler::Misc::opcodeLockExplicit, new OpLock); interpreter.installSegment5 (Compiler::Misc::opcodeUnlock, new OpUnlock); diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 4ef638ef83..0f726a52d2 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -224,7 +224,7 @@ namespace Compiler { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate); - extensions.registerInstruction ("activate", "", opcodeActivate); + extensions.registerInstruction ("activate", "", opcodeActivate, opcodeActivateExplicit); extensions.registerInstruction ("lock", "/l", opcodeLock, opcodeLockExplicit); extensions.registerInstruction ("unlock", "", opcodeUnlock, opcodeUnlockExplicit); extensions.registerInstruction ("cast", "SS", opcodeCast, opcodeCastExplicit); diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 1dff046652..8796c53c54 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -182,6 +182,7 @@ namespace Compiler const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; + const int opcodeActivateExplicit = 0x2000244; const int opcodeLock = 0x20004; const int opcodeLockExplicit = 0x20005; const int opcodeUnlock = 0x200008c; From b897080156825c577ce0fe5e476cc54fe35c6e8f Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 12:26:35 -0500 Subject: [PATCH 437/545] Started implementing sound time tracking so we can have NPCs' mouths move as they talk. --- apps/openmw/mwbase/soundmanager.hpp | 3 ++ apps/openmw/mwsound/soundmanagerimp.cpp | 41 +++++++++++++++++++++++-- apps/openmw/mwsound/soundmanagerimp.hpp | 7 +++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 15739730ba..68ec2cae8a 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -100,6 +100,9 @@ namespace MWBase virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr()) = 0; ///< Stop an actor speaking + + virtual float getSoundPlayingTime(const MWWorld::Ptr &reference=MWWorld::Ptr()) = 0; + ///< Get the amount of time this sound has been playing. virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; ///< Play a 2D audio track, using a custom decoder diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 4a3093b10d..f7c5863800 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -244,6 +244,7 @@ namespace MWSound MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f, 20.0f, 1500.0f, Play_Normal|Play_TypeVoice, 0); mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); + mSoundPlayTime[sound] = std::make_pair(ptr, 0); } catch(std::exception &e) { @@ -261,7 +262,9 @@ namespace MWSound std::string filePath = "Sound/"+filename; MWBase::SoundPtr sound = mOutput->playSound(filePath, 1.0f, basevol, 1.0f, Play_Normal|Play_TypeVoice, 0); - mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound")); + MWWorld::Ptr ptr = MWWorld::Ptr(); + mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); + mSoundPlayTime[sound] = std::make_pair(ptr, 0); } catch(std::exception &e) { @@ -288,6 +291,18 @@ namespace MWSound ++snditer; } } + + float SoundManager::getSoundPlayingTime(const MWWorld::Ptr &ptr) + { + typedef SoundPlayingTimeMap::iterator iter_type; + for(iter_type iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) + { + if (iterator->second.first == ptr) + return iterator->second.second; + } + + return 0; + } MWBase::SoundPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) @@ -602,8 +617,12 @@ namespace MWSound while(snditer != mActiveSounds.end()) { if(!snditer->first->isPlaying()) - mActiveSounds.erase(snditer++); - else + { + mActiveSounds.erase(snditer); + mSoundPlayTime.erase(snditer->first); + snditer++; + } + else { const MWWorld::Ptr &ptr = snditer->second.first; if(!ptr.isEmpty()) @@ -626,6 +645,22 @@ namespace MWSound ++snditer; } } + + // Update the total playing time for all sounds. + // This is primarily used for detecting amplitude for NPC mouth animation. + + typedef SoundPlayingTimeMap::iterator it_type; + for(it_type iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) + { + iterator->second.second += duration; + } + + std::cout << mSoundPlayTime.size() << " sounds currently playing." << std::endl; + typedef SoundPlayingTimeMap::iterator it_ty; + for(it_ty iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) + { + std::cout << iterator->first->getPlayType() << ": " << iterator->second.second << std::endl; + } } void SoundManager::update(float duration) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index ab9dcf7345..3f6490d851 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -43,6 +43,10 @@ namespace MWSound typedef std::pair PtrIDPair; typedef std::map SoundMap; SoundMap mActiveSounds; + + typedef std::pair PtrFloatPair; + typedef std::map SoundPlayingTimeMap; + SoundPlayingTimeMap mSoundPlayTime; MWBase::SoundPtr mUnderwaterSound; @@ -104,6 +108,9 @@ namespace MWSound virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr()); ///< Stop an actor speaking + + virtual float getSoundPlayingTime(const MWWorld::Ptr &reference=MWWorld::Ptr()); + ///< Get the amount of time this sound has been playing. virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type); ///< Play a 2D audio track, using a custom decoder From 16a6edbd0eeceff1bf87ca0b4aa84f841846b763 Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 12:58:45 -0500 Subject: [PATCH 438/545] Fix a possible crash due to a null pointer. --- apps/openmw/mwworld/worldimp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c95a137ecc..548a871ce1 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -252,7 +252,6 @@ namespace MWWorld mProjectileManager->clear(); mLocalScripts.clear(); - mPlayer->clear(); mWorldScene->changeToVoid(); @@ -261,9 +260,10 @@ namespace MWWorld if (mPlayer) { - mPlayer->setCell (0); + mPlayer->clear(); + mPlayer->setCell(0); mPlayer->getPlayer().getRefData() = RefData(); - mPlayer->set (mStore.get().find ("player")); + mPlayer->set(mStore.get().find ("player")); } mCells.clear(); From 545c3c312c43fae7e40a92076a077f7b8a726ae6 Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 13:03:40 -0500 Subject: [PATCH 439/545] Remove a superfluous clear. --- components/esm/loadclot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index d64564d77f..16101162ee 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -46,7 +46,6 @@ void Clothing::save(ESMWriter &esm) const mName.clear(); mModel.clear(); mIcon.clear(); - mIcon.clear(); mEnchant.clear(); mScript.clear(); } From 8e55eb800900fbce38a81f6003580c02c1f1484d Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 13:06:43 -0500 Subject: [PATCH 440/545] Fix some formatting. --- components/esm/loadclot.cpp | 41 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 16101162ee..97ccb9099f 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -8,33 +8,34 @@ namespace ESM { unsigned int Clothing::sRecordId = REC_CLOT; -void Clothing::load(ESMReader &esm) -{ - mModel = esm.getHNString("MODL"); - mName = esm.getHNOString("FNAM"); - esm.getHNT(mData, "CTDT", 12); + void Clothing::load(ESMReader &esm) + { + mModel = esm.getHNString("MODL"); + mName = esm.getHNOString("FNAM"); + esm.getHNT(mData, "CTDT", 12); - mScript = esm.getHNOString("SCRI"); - mIcon = esm.getHNOString("ITEX"); + mScript = esm.getHNOString("SCRI"); + mIcon = esm.getHNOString("ITEX"); - mParts.load(esm); + mParts.load(esm); - mEnchant = esm.getHNOString("ENAM"); -} -void Clothing::save(ESMWriter &esm) const -{ - esm.writeHNCString("MODL", mModel); - esm.writeHNOCString("FNAM", mName); - esm.writeHNT("CTDT", mData, 12); + mEnchant = esm.getHNOString("ENAM"); + } - esm.writeHNOCString("SCRI", mScript); - esm.writeHNOCString("ITEX", mIcon); + void Clothing::save(ESMWriter &esm) const + { + esm.writeHNCString("MODL", mModel); + esm.writeHNOCString("FNAM", mName); + esm.writeHNT("CTDT", mData, 12); - mParts.save(esm); + esm.writeHNOCString("SCRI", mScript); + esm.writeHNOCString("ITEX", mIcon); - esm.writeHNOCString("ENAM", mEnchant); -} + mParts.save(esm); + + esm.writeHNOCString("ENAM", mEnchant); + } void Clothing::blank() { From 18e24a2007d5318c4f084d74091ffea9277bd6be Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 21:08:20 +0200 Subject: [PATCH 441/545] Fix old savegames causing the save list to not fill properly (Error in framelistener: Object '$dynamic0' not found) Fixes #1357 --- apps/openmw/mwgui/savegamedialog.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 6048e49b41..2b064a603f 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -134,9 +134,12 @@ namespace MWGui else { // Find the localised name for this class from the store - const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().find( + const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().search( it->getSignature().mPlayerClassId); - className = class_->mName; + if (class_) + className = class_->mName; + else + className = "?"; // From an older savegame format that did not support custom classes properly. } title << " (Level " << it->getSignature().mPlayerLevel << " " << className << ")"; From 3f00f004263ba43aa340af28af69891b69e0f4fb Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 14:20:04 -0500 Subject: [PATCH 442/545] Remove some debug code. --- apps/openmw/mwsound/soundmanagerimp.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index f7c5863800..e778f6e343 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -654,13 +654,6 @@ namespace MWSound { iterator->second.second += duration; } - - std::cout << mSoundPlayTime.size() << " sounds currently playing." << std::endl; - typedef SoundPlayingTimeMap::iterator it_ty; - for(it_ty iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) - { - std::cout << iterator->first->getPlayType() << ": " << iterator->second.second << std::endl; - } } void SoundManager::update(float duration) From e9ab7c85c60ef0b32cecf8ac30896a489806df77 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 21:29:09 +0200 Subject: [PATCH 443/545] Fix exception when there are spaces in INI-imported color settings --- apps/openmw/mwworld/fallback.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/fallback.cpp b/apps/openmw/mwworld/fallback.cpp index 569a6b50c2..c0b21b2ef2 100644 --- a/apps/openmw/mwworld/fallback.cpp +++ b/apps/openmw/mwworld/fallback.cpp @@ -41,8 +41,9 @@ namespace MWWorld unsigned int j=0; for(unsigned int i=0;i(ret[0])/255.f,boost::lexical_cast(ret[1])/255.f,boost::lexical_cast(ret[2])/255.f); } } From 41a04b9c651bd33189bc8574e0658d22a1081f6a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 21:50:08 +0200 Subject: [PATCH 444/545] Slightly adjust menu button position --- apps/openmw/mwgui/mainmenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index bafd04311b..0c0ad53b24 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -229,7 +229,7 @@ namespace MWGui if (state == MWBase::StateManager::State_NoGame) { // Align with the background image - int bottomPadding=48; + int bottomPadding=24; mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight - curH - bottomPadding, maxwidth, curH); } else From 18314b17075c3b1c699ce0a52a226d85c7387461 Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 14:56:50 -0500 Subject: [PATCH 445/545] We use spaces, not tabs. --- components/esm/loadclot.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 97ccb9099f..17ecdf3ae5 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -10,31 +10,31 @@ namespace ESM void Clothing::load(ESMReader &esm) { - mModel = esm.getHNString("MODL"); - mName = esm.getHNOString("FNAM"); - esm.getHNT(mData, "CTDT", 12); + mModel = esm.getHNString("MODL"); + mName = esm.getHNOString("FNAM"); + esm.getHNT(mData, "CTDT", 12); - mScript = esm.getHNOString("SCRI"); - mIcon = esm.getHNOString("ITEX"); + mScript = esm.getHNOString("SCRI"); + mIcon = esm.getHNOString("ITEX"); - mParts.load(esm); + mParts.load(esm); - mEnchant = esm.getHNOString("ENAM"); + mEnchant = esm.getHNOString("ENAM"); } void Clothing::save(ESMWriter &esm) const { - esm.writeHNCString("MODL", mModel); - esm.writeHNOCString("FNAM", mName); - esm.writeHNT("CTDT", mData, 12); + esm.writeHNCString("MODL", mModel); + esm.writeHNOCString("FNAM", mName); + esm.writeHNT("CTDT", mData, 12); - esm.writeHNOCString("SCRI", mScript); - esm.writeHNOCString("ITEX", mIcon); + esm.writeHNOCString("SCRI", mScript); + esm.writeHNOCString("ITEX", mIcon); - mParts.save(esm); + mParts.save(esm); - esm.writeHNOCString("ENAM", mEnchant); + esm.writeHNOCString("ENAM", mEnchant); } void Clothing::blank() From 8516b837ff8376e7a5a7737fced5133c3a93ab16 Mon Sep 17 00:00:00 2001 From: Kevin Poitra Date: Wed, 28 May 2014 15:04:35 -0500 Subject: [PATCH 446/545] Revert "Started implementing sound time tracking so we can have NPCs' mouths move as they talk." This reverts commit b897080156825c577ce0fe5e476cc54fe35c6e8f. --- apps/openmw/mwbase/soundmanager.hpp | 3 --- apps/openmw/mwsound/soundmanagerimp.cpp | 34 +++---------------------- apps/openmw/mwsound/soundmanagerimp.hpp | 7 ----- 3 files changed, 3 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 68ec2cae8a..15739730ba 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -100,9 +100,6 @@ namespace MWBase virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr()) = 0; ///< Stop an actor speaking - - virtual float getSoundPlayingTime(const MWWorld::Ptr &reference=MWWorld::Ptr()) = 0; - ///< Get the amount of time this sound has been playing. virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; ///< Play a 2D audio track, using a custom decoder diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index e778f6e343..4a3093b10d 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -244,7 +244,6 @@ namespace MWSound MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f, 20.0f, 1500.0f, Play_Normal|Play_TypeVoice, 0); mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); - mSoundPlayTime[sound] = std::make_pair(ptr, 0); } catch(std::exception &e) { @@ -262,9 +261,7 @@ namespace MWSound std::string filePath = "Sound/"+filename; MWBase::SoundPtr sound = mOutput->playSound(filePath, 1.0f, basevol, 1.0f, Play_Normal|Play_TypeVoice, 0); - MWWorld::Ptr ptr = MWWorld::Ptr(); - mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); - mSoundPlayTime[sound] = std::make_pair(ptr, 0); + mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound")); } catch(std::exception &e) { @@ -291,18 +288,6 @@ namespace MWSound ++snditer; } } - - float SoundManager::getSoundPlayingTime(const MWWorld::Ptr &ptr) - { - typedef SoundPlayingTimeMap::iterator iter_type; - for(iter_type iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) - { - if (iterator->second.first == ptr) - return iterator->second.second; - } - - return 0; - } MWBase::SoundPtr SoundManager::playTrack(const DecoderPtr& decoder, PlayType type) @@ -617,12 +602,8 @@ namespace MWSound while(snditer != mActiveSounds.end()) { if(!snditer->first->isPlaying()) - { - mActiveSounds.erase(snditer); - mSoundPlayTime.erase(snditer->first); - snditer++; - } - else + mActiveSounds.erase(snditer++); + else { const MWWorld::Ptr &ptr = snditer->second.first; if(!ptr.isEmpty()) @@ -645,15 +626,6 @@ namespace MWSound ++snditer; } } - - // Update the total playing time for all sounds. - // This is primarily used for detecting amplitude for NPC mouth animation. - - typedef SoundPlayingTimeMap::iterator it_type; - for(it_type iterator = mSoundPlayTime.begin(); iterator != mSoundPlayTime.end(); iterator++) - { - iterator->second.second += duration; - } } void SoundManager::update(float duration) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 3f6490d851..ab9dcf7345 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -43,10 +43,6 @@ namespace MWSound typedef std::pair PtrIDPair; typedef std::map SoundMap; SoundMap mActiveSounds; - - typedef std::pair PtrFloatPair; - typedef std::map SoundPlayingTimeMap; - SoundPlayingTimeMap mSoundPlayTime; MWBase::SoundPtr mUnderwaterSound; @@ -108,9 +104,6 @@ namespace MWSound virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr()); ///< Stop an actor speaking - - virtual float getSoundPlayingTime(const MWWorld::Ptr &reference=MWWorld::Ptr()); - ///< Get the amount of time this sound has been playing. virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type); ///< Play a 2D audio track, using a custom decoder From c6a4506ac2c73321089c833f0c1c6594f20b63a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 22:32:26 +0200 Subject: [PATCH 447/545] Make console error prefix slightly less technical (see https://bugs.openmw.org/issues/1194#note-2) --- apps/openmw/mwgui/console.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 811f93b486..57de35fc52 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -61,7 +61,7 @@ namespace MWGui } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + printError (std::string ("Error: ") + error.what()); } return false; @@ -190,7 +190,7 @@ namespace MWGui } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + printError (std::string ("Error: ") + error.what()); } } } From a5cfa8a04978e7de82aee4ff1795ed16d759990a Mon Sep 17 00:00:00 2001 From: Digmaster Date: Thu, 29 May 2014 01:52:41 -0400 Subject: [PATCH 448/545] Removes add behavior when pressing escape while waiting. --- apps/openmw/mwgui/waitdialog.cpp | 3 ++- apps/openmw/mwgui/windowbase.cpp | 5 +++++ apps/openmw/mwgui/windowbase.hpp | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 460663682e..9c7757af93 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -71,7 +71,8 @@ namespace MWGui void WaitDialog::exit() { - MWBase::Environment::get().getWindowManager()->popGuiMode(); + if(!mProgressBar.isVisible()) //Only exit if not currently waiting + MWBase::Environment::get().getWindowManager()->popGuiMode(); } void WaitDialog::open() diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index c2515a6ded..cc18e6694e 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -23,6 +23,11 @@ void WindowBase::setVisible(bool visible) close(); } +bool WindowBase::isVisible() +{ + return mMainWidget->getVisible(); +} + void WindowBase::center() { // Centre dialog diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index 471d8ac709..81073d419a 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -29,6 +29,8 @@ namespace MWGui virtual void exit() {} ///Sets the visibility of the window virtual void setVisible(bool visible); + ///Returns the visibility state of the window + virtual bool isVisible(); void center(); /** Event : Dialog finished, OK button clicked.\n From 03d71376555050ab40e51cf8ee0e13ec010a90ee Mon Sep 17 00:00:00 2001 From: Digmaster Date: Thu, 29 May 2014 06:19:25 -0400 Subject: [PATCH 449/545] Fixes issue with pressing f1 in QuickKey menu, removed transparency in GoodBye button --- apps/openmw/mwgui/dialogue.cpp | 2 -- apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 762c472d87..5e3f93ab96 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -518,11 +518,9 @@ namespace MWGui MyGUI::Button* byeButton; getWidget(byeButton, "ByeButton"); if(MWBase::Environment::get().getDialogueManager()->isInChoice()) { - byeButton->setAlpha(.2); byeButton->setEnabled(false); } else { - byeButton->setAlpha(1); byeButton->setEnabled(true); } } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 332c8f6a7c..34e026fd70 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -791,8 +791,12 @@ namespace MWInput if (!MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")==-1) MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_QuickKeysMenu); - else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu) - MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_QuickKeysMenu); + else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu) { + while(MyGUI::InputManager::getInstance().isModalAny()) { //Handle any open Modal windows + MWBase::Environment::get().getWindowManager()->getCurrentModal()->exit(); + } + MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); //And handle the actual main window + } } void InputManager::activate() From 95b3026c7e7e633029699112a73ed6c4f28ef683 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 16:34:05 +0200 Subject: [PATCH 450/545] Fix cells being listed twice in console autocompletion when using --skip-menu=0 and loading a game --- apps/openmw/mwworld/store.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 0f8ab86824..1dfb2f9766 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -685,12 +685,14 @@ namespace MWWorld typedef std::map::iterator IntIterator; //std::sort(mInt.begin(), mInt.end(), RecordCmp()); + mSharedInt.clear(); mSharedInt.reserve(mInt.size()); for (IntIterator it = mInt.begin(); it != mInt.end(); ++it) { mSharedInt.push_back(&(it->second)); } //std::sort(mExt.begin(), mExt.end(), ExtCmp()); + mSharedExt.clear(); mSharedExt.reserve(mExt.size()); for (ExtIterator it = mExt.begin(); it != mExt.end(); ++it) { mSharedExt.push_back(&(it->second)); From a6788cfb0e2d398c46ad9270576aef9ac57264cd Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 16:44:50 +0200 Subject: [PATCH 451/545] Support lights that do not have a model (Fixes #1361) --- apps/openmw/mwclass/light.cpp | 6 +- apps/openmw/mwrender/animation.cpp | 34 +++++--- apps/openmw/mwrender/objects.cpp | 123 +++++++++++++++-------------- 3 files changed, 87 insertions(+), 76 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index fd45ec8592..ef4549268f 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -50,9 +50,9 @@ namespace MWClass void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); - if(!model.empty()) { - renderingInterface.getObjects().insertModel(ptr, model); - } + + // Insert even if model is empty, so that the light is added + renderingInterface.getObjects().insertModel(ptr, model); } void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a2f901b26a..9ed4cb6d3c 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1257,22 +1257,30 @@ Ogre::Vector3 Animation::getEnchantmentColor(MWWorld::Ptr item) ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model) : Animation(ptr, ptr.getRefData().getBaseNode()) { - setObjectRoot(model, false); + if (!model.empty()) + { + setObjectRoot(model, false); - Ogre::Vector3 extents = getWorldBounds().getSize(); - float size = std::max(std::max(extents.x, extents.y), extents.z); + Ogre::Vector3 extents = getWorldBounds().getSize(); + float size = std::max(std::max(extents.x, extents.y), extents.z); - bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && - Settings::Manager::getBool("limit small object distance", "Viewing distance"); - // do not fade out doors. that will cause holes and look stupid - if(ptr.getTypeName().find("Door") != std::string::npos) - small = false; + bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && + Settings::Manager::getBool("limit small object distance", "Viewing distance"); + // do not fade out doors. that will cause holes and look stupid + if(ptr.getTypeName().find("Door") != std::string::npos) + small = false; - float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f; - Ogre::Vector3 col = getEnchantmentColor(ptr); - setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ? - (small ? RV_StaticsSmall : RV_Statics) : RV_Misc, - RQG_Main, RQG_Alpha, dist, !ptr.getClass().getEnchantment(ptr).empty(), &col); + float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f; + Ogre::Vector3 col = getEnchantmentColor(ptr); + setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ? + (small ? RV_StaticsSmall : RV_Statics) : RV_Misc, + RQG_Main, RQG_Alpha, dist, !ptr.getClass().getEnchantment(ptr).empty(), &col); + } + else + { + // No model given. Create an object root anyway, so that lights can be added to it if needed. + mObjectRoot = NifOgre::ObjectScenePtr (new NifOgre::ObjectScene(mInsert->getCreator())); + } } void ObjectAnimation::addLight(const ESM::Light *light) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 3101100f2b..7953a31178 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -79,79 +79,82 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh) std::auto_ptr anim(new ObjectAnimation(ptr, mesh)); - Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); - Ogre::Vector3 extents = bounds.getSize(); - extents *= ptr.getRefData().getBaseNode()->getScale(); - float size = std::max(std::max(extents.x, extents.y), extents.z); - - bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && - Settings::Manager::getBool("limit small object distance", "Viewing distance"); - // do not fade out doors. that will cause holes and look stupid - if(ptr.getTypeName().find("Door") != std::string::npos) - small = false; - - if (mBounds.find(ptr.getCell()) == mBounds.end()) - mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; - mBounds[ptr.getCell()].merge(bounds); - if(ptr.getTypeName() == typeid(ESM::Light).name()) anim->addLight(ptr.get()->mBase); - if(ptr.getTypeName() == typeid(ESM::Static).name() && - Settings::Manager::getBool("use static geometry", "Objects") && - anim->canBatch()) + if (!mesh.empty()) { - Ogre::StaticGeometry* sg = 0; + Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); + Ogre::Vector3 extents = bounds.getSize(); + extents *= ptr.getRefData().getBaseNode()->getScale(); + float size = std::max(std::max(extents.x, extents.y), extents.z); - if (small) + bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && + Settings::Manager::getBool("limit small object distance", "Viewing distance"); + // do not fade out doors. that will cause holes and look stupid + if(ptr.getTypeName().find("Door") != std::string::npos) + small = false; + + if (mBounds.find(ptr.getCell()) == mBounds.end()) + mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; + mBounds[ptr.getCell()].merge(bounds); + + if(ptr.getTypeName() == typeid(ESM::Static).name() && + Settings::Manager::getBool("use static geometry", "Objects") && + anim->canBatch()) { - if(mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) - { - uniqueID = uniqueID+1; - sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); - sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); - mStaticGeometrySmall[ptr.getCell()] = sg; + Ogre::StaticGeometry* sg = 0; - sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); + if (small) + { + if(mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) + { + uniqueID = uniqueID+1; + sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); + sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); + mStaticGeometrySmall[ptr.getCell()] = sg; + + sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); + } + else + sg = mStaticGeometrySmall[ptr.getCell()]; } else - sg = mStaticGeometrySmall[ptr.getCell()]; - } - else - { - if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { - uniqueID = uniqueID+1; - sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); - sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); - mStaticGeometry[ptr.getCell()] = sg; + if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) + { + uniqueID = uniqueID+1; + sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); + sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); + mStaticGeometry[ptr.getCell()] = sg; + } + else + sg = mStaticGeometry[ptr.getCell()]; } + + // This specifies the size of a single batch region. + // If it is set too high: + // - there will be problems choosing the correct lights + // - the culling will be more inefficient + // If it is set too low: + // - there will be too many batches. + if(ptr.getCell()->isExterior()) + sg->setRegionDimensions(Ogre::Vector3(2048,2048,2048)); else - sg = mStaticGeometry[ptr.getCell()]; + sg->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); + + sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); + + sg->setCastShadows(true); + + sg->setRenderQueueGroup(RQG_Main); + + anim->fillBatch(sg); + /* TODO: We could hold on to this and just detach it from the scene graph, so if the Ptr + * ever needs to modify we can reattach it and rebuild the StaticGeometry object without + * it. Would require associating the Ptr with the StaticGeometry. */ + anim.reset(); } - - // This specifies the size of a single batch region. - // If it is set too high: - // - there will be problems choosing the correct lights - // - the culling will be more inefficient - // If it is set too low: - // - there will be too many batches. - if(ptr.getCell()->isExterior()) - sg->setRegionDimensions(Ogre::Vector3(2048,2048,2048)); - else - sg->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); - - sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); - - sg->setCastShadows(true); - - sg->setRenderQueueGroup(RQG_Main); - - anim->fillBatch(sg); - /* TODO: We could hold on to this and just detach it from the scene graph, so if the Ptr - * ever needs to modify we can reattach it and rebuild the StaticGeometry object without - * it. Would require associating the Ptr with the StaticGeometry. */ - anim.reset(); } if(anim.get() != NULL) From 3b3b53d6655be02f9f29671944853931e692ece5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 17:21:35 +0200 Subject: [PATCH 452/545] Support animated main menus (menu_background.bik) Closes #1362 --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwgui/mainmenu.cpp | 70 +++++++++++++++++++++++--- apps/openmw/mwgui/mainmenu.hpp | 8 +++ apps/openmw/mwgui/windowmanagerimp.cpp | 2 + 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d33e5300ec..3647f8ccb0 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -137,6 +137,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } // update GUI + MWBase::Environment::get().getWindowManager()->onFrame(frametime); if (MWBase::Environment::get().getStateManager()->getState()!= MWBase::StateManager::State_NoGame) { @@ -145,7 +146,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); - MWBase::Environment::get().getWindowManager()->onFrame(frametime); MWBase::Environment::get().getWindowManager()->update(); } } diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 0c0ad53b24..53ce8f488f 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -1,5 +1,7 @@ #include "mainmenu.hpp" +#include + #include #include "../mwbase/environment.hpp" @@ -16,6 +18,7 @@ #include "confirmationdialog.hpp" #include "imagebutton.hpp" #include "backgroundimage.hpp" +#include "videowidget.hpp" namespace MWGui { @@ -25,6 +28,7 @@ namespace MWGui , mButtonBox(0), mWidth (w), mHeight (h) , mSaveGameDialog(NULL) , mBackground(NULL) + , mVideo(NULL) { getWidget(mVersionText, "VersionText"); std::stringstream sstream; @@ -42,6 +46,8 @@ namespace MWGui std::string output = sstream.str(); mVersionText->setCaption(output); + mHasAnimatedMenu = (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("video\\menu_background.bik")); + updateMenu(); } @@ -134,14 +140,66 @@ namespace MWGui void MainMenu::showBackground(bool show) { - if (show && !mBackground) + if (mVideo && !show) { - mBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, - MyGUI::Align::Stretch, "Menu"); - mBackground->setBackgroundImage("textures\\menu_morrowind.dds"); + MyGUI::Gui::getInstance().destroyWidget(mVideo); + mVideo = NULL; } - if (mBackground) - mBackground->setVisible(show); + if (mBackground && !show) + { + MyGUI::Gui::getInstance().destroyWidget(mBackground); + mBackground = NULL; + } + + if (!show) + return; + + if (mHasAnimatedMenu) + { + if (!mVideo) + { + // Use black background to correct aspect ratio + mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Default, "Menu"); + mVideoBackground->setImageTexture("black.png"); + + mVideo = mVideoBackground->createWidget("ImageBox", 0,0,1,1, + MyGUI::Align::Stretch, "Menu"); + + mVideo->playVideo("video\\menu_background.bik", false); + } + + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + int screenWidth = viewSize.width; + int screenHeight = viewSize.height; + mVideoBackground->setSize(screenWidth, screenHeight); + + double imageaspect = static_cast(mVideo->getVideoWidth())/mVideo->getVideoHeight(); + + int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2); + int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2); + + mVideo->setCoord(leftPadding, topPadding, + screenWidth - leftPadding*2, screenHeight - topPadding*2); + + mVideo->setVisible(true); + } + else + { + if (!mBackground) + { + mBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Stretch, "Menu"); + mBackground->setBackgroundImage("textures\\menu_morrowind.dds"); + } + mBackground->setVisible(true); + } + } + + void MainMenu::update(float dt) + { + if (mVideo) + mVideo->update(); } void MainMenu::updateMenu() diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index c274425367..ccd8df4b0b 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -9,12 +9,15 @@ namespace MWGui class ImageButton; class BackgroundImage; class SaveGameDialog; + class VideoWidget; class MainMenu : public OEngine::GUI::Layout { int mWidth; int mHeight; + bool mHasAnimatedMenu; + public: MainMenu(int w, int h); @@ -24,6 +27,8 @@ namespace MWGui virtual void setVisible (bool visible); + void update(float dt); + private: MyGUI::Widget* mButtonBox; @@ -31,6 +36,9 @@ namespace MWGui BackgroundImage* mBackground; + MyGUI::ImageBox* mVideoBackground; + VideoWidget* mVideo; // For animated main menus + std::map mButtons; void onButtonClicked (MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index a42dca79e5..53752fc990 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -713,6 +713,8 @@ namespace MWGui mToolTips->onFrame(frameDuration); + mMenu->update(frameDuration); + if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) return; From ae5063277401901eedf12d8026ae6e90ed2118bd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 May 2014 18:08:40 +0200 Subject: [PATCH 453/545] implemented cell and reference saving int OpenCS --- apps/opencs/model/doc/saving.cpp | 1 + apps/opencs/model/doc/savingstages.cpp | 103 ++++++++++++++++++++++++- apps/opencs/model/doc/savingstages.hpp | 16 ++++ apps/opencs/model/doc/savingstate.cpp | 2 +- apps/opencs/model/doc/savingstate.hpp | 2 +- 5 files changed, 121 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 337784765c..45b53f4fe8 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -67,6 +67,7 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje appendStage (new CollectionReferencesStage (mDocument, mState)); + appendStage (new WriteCellCollectionStage (mDocument, mState)); // close file and clean up appendStage (new CloseSaveStage (mState)); diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index fc35e21cd1..4846d6c732 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -246,12 +246,113 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages) record.mState==CSMWorld::RecordBase::State_Modified || record.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mId)].push_back (i); + mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mCell)] + .push_back (i); } } } +CSMDoc::WriteCellCollectionStage::WriteCellCollectionStage (Document& document, + SavingState& state) +: mDocument (document), mState (state) +{} + +int CSMDoc::WriteCellCollectionStage::setup() +{ + return mDocument.getData().getCells().getSize(); +} + +void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) +{ + const CSMWorld::Record& cell = + mDocument.getData().getCells().getRecord (stage); + + std::map >::const_iterator references = + mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId)); + + if (cell.mState==CSMWorld::RecordBase::State_Modified || + cell.mState==CSMWorld::RecordBase::State_ModifiedOnly || + references!=mState.getSubRecords().end()) + { + bool interior = cell.get().mId.substr (0, 1)!="#"; + + // write cell data + mState.getWriter().startRecord (cell.mModified.sRecordId); + + mState.getWriter().writeHNOCString ("NAME", cell.get().mName); + + ESM::Cell cell2 = cell.get(); + + if (interior) + cell2.mData.mFlags |= ESM::Cell::Interior; + else + { + cell2.mData.mFlags &= ~ESM::Cell::Interior; + + std::istringstream stream (cell.get().mId.c_str()); + char ignore; + stream >> ignore >> cell2.mData.mX >> cell2.mData.mY; + } + cell2.save (mState.getWriter()); + + // write references + if (references!=mState.getSubRecords().end()) + { + // first pass: find highest RefNum + int lastRefNum = -1; + + for (std::vector::const_iterator iter (references->second.begin()); + iter!=references->second.end(); ++iter) + { + const CSMWorld::Record& ref = + mDocument.getData().getReferences().getRecord (*iter); + + if (ref.get().mRefNum.mContentFile==0 && ref.get().mRefNum.mIndex>lastRefNum) + lastRefNum = ref.get().mRefNum.mIndex; + } + + // second pass: write + for (std::vector::const_iterator iter (references->second.begin()); + iter!=references->second.end(); ++iter) + { + const CSMWorld::Record& ref = + mDocument.getData().getReferences().getRecord (*iter); + + if (ref.mState==CSMWorld::RecordBase::State_Modified || + ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) + { + if (ref.get().mRefNum.mContentFile==-2) + { + if (lastRefNum>=0xffffff) + throw std::runtime_error ( + "RefNums exhausted in cell: " + cell.get().mId); + + ESM::CellRef ref2 = ref.get(); + ref2.mRefNum.mContentFile = 0; + ref2.mRefNum.mIndex = ++lastRefNum; + + ref2.save (mState.getWriter()); + } + else + ref.get().save (mState.getWriter()); + } + else if (ref.mState==CSMWorld::RecordBase::State_Deleted) + { + /// \todo write record with delete flag + } + } + } + + mState.getWriter().endRecord (cell.mModified.sRecordId); + } + else if (cell.mState==CSMWorld::RecordBase::State_Deleted) + { + /// \todo write record with delete flag + } +} + + CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state) : mState (state) {} diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 653f3a9570..dcb1a86500 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -182,6 +182,22 @@ namespace CSMDoc ///< Messages resulting from this stage will be appended to \a messages. }; + class WriteCellCollectionStage : public Stage + { + Document& mDocument; + SavingState& mState; + + public: + + WriteCellCollectionStage (Document& document, SavingState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + class CloseSaveStage : public Stage { SavingState& mState; diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 294f830496..1d93a95f59 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -64,7 +64,7 @@ bool CSMDoc::SavingState::isProjectFile() const return mProjectFile; } -std::map > CSMDoc::SavingState::getSubRecords() +std::map >& CSMDoc::SavingState::getSubRecords() { return mSubRecords; } \ No newline at end of file diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 64085bf0d5..3abb724dea 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -48,7 +48,7 @@ namespace CSMDoc bool isProjectFile() const; ///< Currently saving project file? (instead of content file) - std::map > getSubRecords(); + std::map >& getSubRecords(); }; From 6a882e1e8d0113d5a619af37e98519600fd47db4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 17:53:54 +0200 Subject: [PATCH 454/545] Don't show hidden factions in StatsWindow (e.g. Nerevarine) --- apps/openmw/mwgui/statswindow.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 6ae44e3146..246ade7bf2 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -454,20 +454,30 @@ namespace MWGui if (!mFactions.empty()) { - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - addSeparator(coord1, coord2); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); const MWMechanics::NpcStats &PCstats = player.getClass().getNpcStats(player); const std::set &expelled = PCstats.getExpelled(); - addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); + bool firstFaction=true; FactionList::const_iterator end = mFactions.end(); for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) { const ESM::Faction *faction = store.get().find(it->first); + if (faction->mData.mIsHidden == 1) + continue; + + if (firstFaction) + { + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + addSeparator(coord1, coord2); + + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); + + firstFaction = false; + } + MyGUI::Widget* w = addItem(faction->mName, coord1, coord2); std::string text; From 50a72ed710bbe0261752123232bbb9151e00987f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 17:54:45 +0200 Subject: [PATCH 455/545] Fix ghosts in Cavern Of The Incarnate having -1 health --- components/esm/loadnpc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 08f678b45f..fd3e45bdc3 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -82,7 +82,7 @@ struct NPC char mSkills[Skill::Length]; char mReputation; - short mHealth, mMana, mFatigue; + unsigned short mHealth, mMana, mFatigue; char mDisposition, mFactionID, mRank; char mUnknown; int mGold; From afc1fa49f617c55f890504d795f754de8b4b0fad Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 20:35:57 +0200 Subject: [PATCH 456/545] Use mouse release instead of press for binding actions Resolves difficulties binding actions to mouse buttons (Fixes #1364) --- extern/oics/ICSInputControlSystem_mouse.cpp | 23 ++++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp index be18ebbc0e..fb11005281 100644 --- a/extern/oics/ICSInputControlSystem_mouse.cpp +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -333,11 +333,6 @@ namespace ICS } } } - else if(mDetectingBindingListener) - { - mDetectingBindingListener->mouseButtonBindingDetected(this, - mDetectingBindingControl, btn, mDetectingBindingDirection); - } } } @@ -345,11 +340,19 @@ namespace ICS { if(mActive) { - ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); - if(it != mControlsMouseButtonBinderMap.end()) - { - it->second.control->setChangingDirection(Control::STOP); - } + if (!mDetectingBindingControl) + { + ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); + if(it != mControlsMouseButtonBinderMap.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->mouseButtonBindingDetected(this, + mDetectingBindingControl, btn, mDetectingBindingDirection); + } } } From b81c7d05c60bdaf9029e40cb4632ed1695d72738 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 May 2014 23:16:36 +0200 Subject: [PATCH 457/545] Remove CG shaders from settings window (not fully supported on non-nvidia cards, amd profiles have an instruction limit making them useless) Can still be used by editing the config file, however. --- apps/openmw/mwgui/settingswindow.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 78adecd3ef..4b8f3ab805 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -73,17 +73,6 @@ namespace return (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") != std::string::npos) ? "glsl" : "hlsl"; } - bool cgAvailable () - { - Ogre::Root::PluginInstanceList list = Ogre::Root::getSingleton ().getInstalledPlugins (); - for (Ogre::Root::PluginInstanceList::const_iterator it = list.begin(); it != list.end(); ++it) - { - if ((*it)->getName() == "Cg Program Manager") - return true; - } - return false; - } - const char* checkButtonType = "CheckButton"; const char* sliderType = "Slider"; @@ -366,12 +355,7 @@ namespace MWGui void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender) { std::string val = static_cast(_sender)->getCaption(); - if (val == "cg") - { - val = hlslGlsl(); - } - else if (cgAvailable ()) - val = "cg"; + val = hlslGlsl(); static_cast(_sender)->setCaption(val); From 4778c27548cf59715ccaf8d917bdc76b5fe9658a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 30 May 2014 10:18:05 +0200 Subject: [PATCH 458/545] silenced two warnings --- apps/opencs/model/tools/referenceablecheck.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 488081f46f..1816d0808a 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -621,12 +621,6 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( } else { - if (npc.mNpdt52.mMana < 0) - messages.push_back (std::make_pair (id, npc.mId + " mana has negative value")); - - if (npc.mNpdt52.mFatigue < 0) - messages.push_back (std::make_pair (id, npc.mId + " fatigue has negative value")); - if (npc.mNpdt52.mAgility == 0) messages.push_back (std::make_pair (id, npc.mId + " agility has zero value")); From 11ce093a9e30f74a61b6371d017031227fcb20c7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 30 May 2014 18:46:18 +1000 Subject: [PATCH 459/545] Fix crashes caused when terrain materials don't get created (e.g. due to cg shader bug on Windows/D3D9). Should resolve Bug #1284. --- components/terrain/chunk.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/terrain/chunk.cpp b/components/terrain/chunk.cpp index 0820dcc732..7ecafda5e3 100644 --- a/components/terrain/chunk.cpp +++ b/components/terrain/chunk.cpp @@ -55,6 +55,9 @@ namespace Terrain mVertexData->vertexBufferBinding->setBinding(2, uvBuffer); mVertexData->vertexBufferBinding->setBinding(3, colourBuffer); + // Assign a default material in case terrain material fails to be created + mMaterial = Ogre::MaterialManager::getSingleton().getByName("BaseWhite"); + mIndexData = OGRE_NEW Ogre::IndexData(); mIndexData->indexStart = 0; } @@ -67,11 +70,13 @@ namespace Terrain Chunk::~Chunk() { + if (!mMaterial.isNull()) + { #if TERRAIN_USE_SHADER - sh::Factory::getInstance().destroyMaterialInstance(mMaterial->getName()); + sh::Factory::getInstance().destroyMaterialInstance(mMaterial->getName()); #endif - Ogre::MaterialManager::getSingleton().remove(mMaterial->getName()); - + Ogre::MaterialManager::getSingleton().remove(mMaterial->getName()); + } OGRE_DELETE mVertexData; OGRE_DELETE mIndexData; } From ac77b07e299edd5a4a576dd24c1ccea9bcaed7ce Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 30 May 2014 11:18:06 +0200 Subject: [PATCH 460/545] Small fix for menu background --- apps/openmw/mwgui/mainmenu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 53ce8f488f..628f00136d 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -142,7 +142,8 @@ namespace MWGui { if (mVideo && !show) { - MyGUI::Gui::getInstance().destroyWidget(mVideo); + MyGUI::Gui::getInstance().destroyWidget(mVideoBackground); + mVideoBackground = NULL; mVideo = NULL; } if (mBackground && !show) From 8761aa579563e092d62ce7aea456213699f38a3a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 30 May 2014 11:22:44 +0200 Subject: [PATCH 461/545] Loop main menu video when it's finished playing --- apps/openmw/mwgui/mainmenu.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 628f00136d..b5cd61f59c 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -200,7 +200,13 @@ namespace MWGui void MainMenu::update(float dt) { if (mVideo) - mVideo->update(); + { + if (!mVideo->update()) + { + // If finished playing, start again + mVideo->playVideo("video\\menu_background.bik", 0); + } + } } void MainMenu::updateMenu() From d26f756c53c263d080fcc62fd7d673d2798d667c Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 30 May 2014 14:52:47 +0200 Subject: [PATCH 462/545] Fix several edit boxes not receiving mouse input --- files/mygui/openmw_console.skin.xml | 2 +- files/mygui/openmw_edit.skin.xml | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/files/mygui/openmw_console.skin.xml b/files/mygui/openmw_console.skin.xml index 470451a0ed..c6d60231ad 100644 --- a/files/mygui/openmw_console.skin.xml +++ b/files/mygui/openmw_console.skin.xml @@ -13,8 +13,8 @@ - + diff --git a/files/mygui/openmw_edit.skin.xml b/files/mygui/openmw_edit.skin.xml index b10854b19e..50f37dbfc3 100644 --- a/files/mygui/openmw_edit.skin.xml +++ b/files/mygui/openmw_edit.skin.xml @@ -10,14 +10,12 @@ - - - - - - + + + + @@ -26,11 +24,6 @@ - - - - - @@ -41,7 +34,7 @@ - + From 6cc6172779e4df88da9accf17de1facfe04f6c03 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Fri, 30 May 2014 15:12:57 -0400 Subject: [PATCH 463/545] Update in response to comments. It turns out I was erroneous about problem (1) in my original commit message. I thought that in an edge case the OpenMWGUI could both handle the same event on the frame the GUI was closed. My test for this was broken. So after brainstorming many possible unsatisfactory solutions to this event handling, it's luckily not necessary! --- apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 9c263e52d2..344da5be1a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -510,11 +510,9 @@ namespace MWInput OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); - bool passToBinder = true; if (kc != OIS::KC_UNASSIGNED) - passToBinder = !MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); - if(passToBinder) - mInputBinder->keyPressed (arg); + MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + mInputBinder->keyPressed (arg); } void InputManager::textInput(const SDL_TextInputEvent &arg) From 4f4a37896e3c88831db8329e240ed127adbc2408 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Fri, 30 May 2014 22:37:13 -0500 Subject: [PATCH 464/545] Check if player's CellStore is non-NULL before configuring fog. This prevents an assertion fail in getCell() when changing the view distance while in the main menu. --- apps/openmw/mwrender/renderingmanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 882a3d09bf..8a22c63c64 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -751,7 +751,8 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec } else if (it->second == "max viewing distance" && it->first == "Viewing distance") { - if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior()) + if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior() + && MWBase::Environment::get().getWorld()->getPlayerPtr().mCell) configureFog(*MWBase::Environment::get().getWorld()->getPlayerPtr().getCell()); } else if (it->first == "Video" && ( From 16ac6e7aacc072e61ac481dd5ec99d9ffb4887be Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 00:36:37 +0200 Subject: [PATCH 465/545] Merge DialInfo objects by subrecord instead of overwriting the object Fixes #1360 --- apps/openmw/mwworld/esmstore.cpp | 13 ++++---- components/esm/loaddial.cpp | 55 +++++++++++++++++++++----------- components/esm/loaddial.hpp | 3 +- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 03d928d2a5..cd6cc4a165 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -68,13 +68,12 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) if (it == mStores.end()) { if (n.val == ESM::REC_INFO) { - std::string id = esm.getHNOString("INAM"); - if (dialogue) { - ESM::DialInfo info; - info.mId = id; - info.load(esm); - dialogue->addInfo(info, esm.getIndex() != 0); - } else { + if (dialogue) + { + dialogue->readInfo(esm, esm.getIndex() != 0); + } + else + { std::cerr << "error: info record without dialog" << std::endl; esm.skipRecord(); } diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index ee7ddbfadf..92077b572f 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -40,21 +40,21 @@ void Dialogue::save(ESMWriter &esm) const } } - void Dialogue::blank() - { - mInfo.clear(); - } - -void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) +void Dialogue::blank() { - if (!merge || mInfo.empty() || info.mNext.empty()) + mInfo.clear(); +} + +void Dialogue::readInfo(ESMReader &esm, bool merge) +{ + const std::string& id = esm.getHNOString("INAM"); + + if (!merge || mInfo.empty()) { - mLookup[info.mId] = mInfo.insert(mInfo.end(), info); - return; - } - if (info.mPrev.empty()) - { - mLookup[info.mId] = mInfo.insert(mInfo.begin(), info); + ESM::DialInfo info; + info.mId = id; + info.load(esm); + mLookup[id] = mInfo.insert(mInfo.end(), info); return; } @@ -62,11 +62,30 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) std::map::iterator lookup; - lookup = mLookup.find(info.mId); + lookup = mLookup.find(id); if (lookup != mLookup.end()) { it = lookup->second; - *it = info; + + // Merge with existing record. Only the subrecords that are present in + // the new record will be overwritten. + it->load(esm); + return; + } + + // New record + ESM::DialInfo info; + info.mId = id; + info.load(esm); + + if (info.mNext.empty()) + { + mLookup[id] = mInfo.insert(mInfo.end(), info); + return; + } + if (info.mPrev.empty()) + { + mLookup[id] = mInfo.insert(mInfo.begin(), info); return; } @@ -75,7 +94,7 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) { it = lookup->second; - mLookup[info.mId] = mInfo.insert(++it, info); + mLookup[id] = mInfo.insert(++it, info); return; } @@ -84,11 +103,11 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) { it = lookup->second; - mLookup[info.mId] = mInfo.insert(it, info); + mLookup[id] = mInfo.insert(it, info); return; } - std::cerr << "Failed to insert info " << info.mId << std::endl; + std::cerr << "Failed to insert info " << id << std::endl; } } diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 6ec5527f9f..fd46ad2109 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -47,8 +47,9 @@ struct Dialogue void load(ESMReader &esm); void save(ESMWriter &esm) const; + /// Read the next info record /// @param merge Merge with existing list, or just push each record to the end of the list? - void addInfo (const ESM::DialInfo& info, bool merge); + void readInfo (ESM::ESMReader& esm, bool merge); void blank(); ///< Set record to default state (does not touch the ID and does not change the type). From de7fcf0beba837bd1ae9071516d23229bfb0cf72 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 13:24:13 +0200 Subject: [PATCH 466/545] Fix unhandled edge case in TradeItemModel with items that are able to stack, but are not currently stacked (e.g. after repairing a damaged item) Fixes #1368 --- apps/openmw/mwgui/itemmodel.cpp | 4 ++-- apps/openmw/mwgui/tradeitemmodel.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 55317724e3..59b54e171d 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -100,7 +100,7 @@ namespace MWGui for (size_t i=0; igetItemCount(); ++i) { const ItemStack& item = mSourceModel->getItem(i); - if (item == itemToSearch) + if (item.mBase == itemToSearch.mBase) return i; } return -1; @@ -112,7 +112,7 @@ namespace MWGui for (size_t i=0; istacks(item)) + if (it->mBase == item.mBase) { it->mCount += item.mCount; found = true; @@ -52,7 +52,7 @@ namespace MWGui bool found = false; for (; it != out.end(); ++it) { - if (it->stacks(item)) + if (it->mBase == item.mBase) { if (it->mCount < count) throw std::runtime_error("Not enough borrowed items to return"); @@ -114,7 +114,7 @@ namespace MWGui size_t i=0; for (; igetItemCount(); ++i) { - if (it->stacks(sourceModel->getItem(i))) + if (it->mBase == sourceModel->getItem(i).mBase) break; } if (i == sourceModel->getItemCount()) @@ -182,7 +182,7 @@ namespace MWGui std::vector::iterator it = mBorrowedFromUs.begin(); for (; it != mBorrowedFromUs.end(); ++it) { - if (it->stacks(item)) + if (it->mBase == item.mBase) { if (item.mCount < it->mCount) throw std::runtime_error("Lent more items than present"); From a1bdf20958b11eb1f7dc56fe5a3b826aa19c3f9e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 13:53:36 +0200 Subject: [PATCH 467/545] Make trade balance label editable --- apps/openmw/mwgui/tradewindow.cpp | 15 +++++++++++++++ apps/openmw/mwgui/tradewindow.hpp | 3 ++- files/mygui/openmw_trade_window.layout | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index cb7f3b0bd4..03c73d1716 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -74,6 +74,8 @@ namespace MWGui mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed); mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased); + mTotalBalance->eventEditTextChange += MyGUI::newDelegate(this, &TradeWindow::onBalanceEdited); + setCoord(400, 0, 400, 300); } @@ -410,6 +412,19 @@ namespace MWGui mBalanceButtonsState = BBS_None; } + void TradeWindow::onBalanceEdited(MyGUI::EditBox *_sender) + { + try + { + unsigned int count = boost::lexical_cast(_sender->getCaption()); + mCurrentBalance = count * (mCurrentBalance >= 0 ? 1 : -1); + updateLabels(); + } + catch (std::bad_cast&) + { + } + } + void TradeWindow::onIncreaseButtonTriggered() { if(mCurrentBalance<=-1) mCurrentBalance -= 1; diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 420a642e81..cc70f1ae96 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -55,7 +55,7 @@ namespace MWGui MyGUI::Button* mIncreaseButton; MyGUI::Button* mDecreaseButton; MyGUI::TextBox* mTotalBalanceLabel; - MyGUI::TextBox* mTotalBalance; + MyGUI::EditBox* mTotalBalance; MyGUI::Widget* mBottomPane; @@ -91,6 +91,7 @@ namespace MWGui void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); + void onBalanceEdited(MyGUI::EditBox* _sender); void onIncreaseButtonTriggered(); void onDecreaseButtonTriggered(); diff --git a/files/mygui/openmw_trade_window.layout b/files/mygui/openmw_trade_window.layout index 8a1be496f4..cb00d7d50c 100644 --- a/files/mygui/openmw_trade_window.layout +++ b/files/mygui/openmw_trade_window.layout @@ -44,7 +44,7 @@ - + From 865486604f702b9468b51047474b3978b9031fce Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 13:57:07 +0200 Subject: [PATCH 468/545] Make trade disposition changes temporary again, as in vanilla --- apps/openmw/mwbase/dialoguemanager.hpp | 2 ++ apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 10 ---------- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 2 ++ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index cab6809aa0..dfb002cfc0 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -61,6 +61,8 @@ namespace MWBase virtual void persuade (int type) = 0; virtual int getTemporaryDispositionChange () const = 0; + + /// @note This change is temporary and gets discarded when dialogue ends. virtual void applyDispositionChange (int delta) = 0; virtual int countSavedGameRecords() const = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index b6cef2fe7f..57681b7fb0 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -560,17 +560,7 @@ namespace MWDialogue void DialogueManager::applyDispositionChange(int delta) { - int oldTemp = mTemporaryDispositionChange; mTemporaryDispositionChange += delta; - // don't allow increasing beyond 100 or decreasing below 0 - int curDisp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor); - if (curDisp + mTemporaryDispositionChange < 0) - mTemporaryDispositionChange = -curDisp; - else if (curDisp + mTemporaryDispositionChange > 100) - mTemporaryDispositionChange = 100 - curDisp; - - int diff = mTemporaryDispositionChange - oldTemp; - mPermanentDispositionChange += diff; } bool DialogueManager::checkServiceRefused() diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index db0b78d594..94f8f3ec1a 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -84,6 +84,8 @@ namespace MWDialogue virtual void persuade (int type); virtual int getTemporaryDispositionChange () const; + + /// @note This change is temporary and gets discarded when dialogue ends. virtual void applyDispositionChange (int delta); virtual int countSavedGameRecords() const; From 0f1b39bca46460e420e608180d12bfe6266e3485 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 18:28:00 +0200 Subject: [PATCH 469/545] Fix trade exploit Using the Max Sale button it was possible to "invert" the buying/selling state. --- apps/openmw/mwgui/tradewindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 03c73d1716..73f48c8cf4 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -302,6 +302,9 @@ namespace MWGui } } + // Is the player buying? + bool buying = (mCurrentMerchantOffer < 0); + if(mCurrentBalance > mCurrentMerchantOffer) { //if npc is a creature: reject (no haggle) @@ -315,7 +318,7 @@ namespace MWGui int a = abs(mCurrentMerchantOffer); int b = abs(mCurrentBalance); int d = 0; - if (mCurrentBalance<0) + if (buying) d = int(100 * (a - b) / a); else d = int(100 * (b - a) / a); @@ -336,7 +339,7 @@ namespace MWGui float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); float x = gmst.find("fBargainOfferMulti")->getFloat() * d + gmst.find("fBargainOfferBase")->getFloat(); - if (mCurrentBalance<0) + if (buying) x += abs(int(pcTerm - npcTerm)); else x += abs(int(npcTerm - pcTerm)); From 7c9c0830a9614c4b5f48c179228fa62761a65ed6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 May 2014 19:49:48 +0200 Subject: [PATCH 470/545] Fix errors due to BaseWhite material being removed --- components/terrain/chunk.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/terrain/chunk.cpp b/components/terrain/chunk.cpp index 7ecafda5e3..57db151249 100644 --- a/components/terrain/chunk.cpp +++ b/components/terrain/chunk.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -56,7 +57,11 @@ namespace Terrain mVertexData->vertexBufferBinding->setBinding(3, colourBuffer); // Assign a default material in case terrain material fails to be created - mMaterial = Ogre::MaterialManager::getSingleton().getByName("BaseWhite"); + // Since we are removing this material in the destructor, it must be cloned from BaseWhite + // so the original always stays available. + static int materialCount=0; + mMaterial = Ogre::MaterialManager::getSingleton().getByName("BaseWhite") + ->clone("BaseWhite"+Ogre::StringConverter::toString(++materialCount)); mIndexData = OGRE_NEW Ogre::IndexData(); mIndexData->indexStart = 0; From dcc0e2d1054178aea10ee51d151b1c4200c13af4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Jun 2014 00:21:14 +0200 Subject: [PATCH 471/545] When dialogue goodbye is forced, allow using either the red link or the goodbye button Fixes #1373 --- apps/openmw/mwgui/dialogue.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 5e3f93ab96..441e31e327 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -271,7 +271,8 @@ namespace MWGui void DialogueWindow::exit() { - if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) + if ((!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) + && !mGoodbye) return; MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); } @@ -517,7 +518,7 @@ namespace MWGui MyGUI::Button* byeButton; getWidget(byeButton, "ByeButton"); - if(MWBase::Environment::get().getDialogueManager()->isInChoice()) { + if(MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye) { byeButton->setEnabled(false); } else { From cd131e7f867fbc0c9a8d28259960dab40a23f248 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Sat, 31 May 2014 19:51:21 -0400 Subject: [PATCH 472/545] 1196/1217 fix Fixes an issue where inputs could be processed by both GUI and gameplay systems. An enabled/disable has been added to OIS channels, and OpenMW now disables player gameplay hotkeys when a GUI element has focus. GUI hotkeys are left enabled. --- apps/openmw/mwinput/inputmanagerimp.cpp | 19 ++++++++++++++++++- apps/openmw/mwinput/inputmanagerimp.hpp | 2 ++ extern/oics/ICSChannel.cpp | 13 +++++++++++-- extern/oics/ICSChannel.h | 6 +++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 344da5be1a..73399ee788 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -160,6 +160,20 @@ namespace MWInput delete mInputManager; } + void InputManager::setPlayerControlsEnabled(bool enabled) + { + int nPlayerChannels = 15; + int playerChannels[] = {A_Activate, A_AutoMove, A_AlwaysRun, A_ToggleWeapon, + A_ToggleSpell, A_Rest, A_QuickKey1, A_QuickKey2, + A_QuickKey3, A_QuickKey4, A_QuickKey5, A_QuickKey6, + A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10}; + + for(int i = 0; i < nPlayerChannels; i++) { + int pc = playerChannels[i]; + mInputBinder->getChannel(pc)->setEnabled(enabled); + } + } + void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) { if (mDragDrop) @@ -511,7 +525,10 @@ namespace MWInput OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); if (kc != OIS::KC_UNASSIGNED) - MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + { + bool guiFocus = MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + setPlayerControlsEnabled(!guiFocus); + } mInputBinder->keyPressed (arg); } diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 537c3a1827..dbd13e793c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -172,6 +172,8 @@ namespace MWInput void resetIdleTime(); void updateIdleTime(float dt); + void setPlayerControlsEnabled(bool enabled); + private: void toggleMainMenu(); void toggleSpell(); diff --git a/extern/oics/ICSChannel.cpp b/extern/oics/ICSChannel.cpp index 703f2207c9..268615c920 100644 --- a/extern/oics/ICSChannel.cpp +++ b/extern/oics/ICSChannel.cpp @@ -38,6 +38,7 @@ namespace ICS , mValue(initialValue) , mSymmetricAt(symmetricAt) , mBezierStep(bezierStep) + , mEnabled(true) { mBezierMidPoint.x = bezierMidPointX; mBezierMidPoint.y = bezierMidPointY; @@ -45,6 +46,11 @@ namespace ICS setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep); } + void Channel::setEnabled(bool enabled) + { + mEnabled = enabled; + } + float Channel::getValue() { if(mValue == 0 || mValue == 1) @@ -124,7 +130,10 @@ namespace ICS void Channel::update() { - if(this->getControlsCount() == 1) + if(!mEnabled) + return; + + if(this->getControlsCount() == 1) { ControlChannelBinderItem ccBinderItem = mAttachedControls.back(); float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue(); @@ -255,4 +264,4 @@ namespace ICS t += 1.0f / ((endX-startX)/step); } } -} \ No newline at end of file +} diff --git a/extern/oics/ICSChannel.h b/extern/oics/ICSChannel.h index 5ec6cd575b..3da53369c3 100644 --- a/extern/oics/ICSChannel.h +++ b/extern/oics/ICSChannel.h @@ -89,6 +89,8 @@ namespace ICS IntervalList& getIntervals(){ return mIntervals; }; + void setEnabled(bool enabled); + protected: int mNumber; @@ -112,7 +114,9 @@ namespace ICS std::vector mAttachedControls; std::list mListeners; - void notifyListeners(float previousValue); + void notifyListeners(float previousValue); + + bool mEnabled; }; From c018319940ded39892479fc4722c07cb293f0998 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Jun 2014 00:26:15 +0200 Subject: [PATCH 473/545] Addition to 7c9c0830a96: don't create useless BaseWhite clones --- components/terrain/chunk.cpp | 21 ++++++++++++++------- components/terrain/chunk.hpp | 5 +++-- components/terrain/material.cpp | 23 ++++++++--------------- components/terrain/material.hpp | 14 ++++---------- components/terrain/quadtreenode.cpp | 16 ++++++++-------- 5 files changed, 37 insertions(+), 42 deletions(-) diff --git a/components/terrain/chunk.cpp b/components/terrain/chunk.cpp index 57db151249..bb8710b872 100644 --- a/components/terrain/chunk.cpp +++ b/components/terrain/chunk.cpp @@ -16,6 +16,7 @@ namespace Terrain Chunk::Chunk(Ogre::HardwareVertexBufferSharedPtr uvBuffer, const Ogre::AxisAlignedBox& bounds, const LoadResponseData& data) : mBounds(bounds) + , mOwnMaterial(false) { mVertexData = OGRE_NEW Ogre::VertexData; mVertexData->vertexStart = 0; @@ -57,11 +58,7 @@ namespace Terrain mVertexData->vertexBufferBinding->setBinding(3, colourBuffer); // Assign a default material in case terrain material fails to be created - // Since we are removing this material in the destructor, it must be cloned from BaseWhite - // so the original always stays available. - static int materialCount=0; - mMaterial = Ogre::MaterialManager::getSingleton().getByName("BaseWhite") - ->clone("BaseWhite"+Ogre::StringConverter::toString(++materialCount)); + mMaterial = Ogre::MaterialManager::getSingleton().getByName("BaseWhite"); mIndexData = OGRE_NEW Ogre::IndexData(); mIndexData->indexStart = 0; @@ -75,7 +72,7 @@ namespace Terrain Chunk::~Chunk() { - if (!mMaterial.isNull()) + if (!mMaterial.isNull() && mOwnMaterial) { #if TERRAIN_USE_SHADER sh::Factory::getInstance().destroyMaterialInstance(mMaterial->getName()); @@ -86,9 +83,19 @@ namespace Terrain OGRE_DELETE mIndexData; } - void Chunk::setMaterial(const Ogre::MaterialPtr &material) + void Chunk::setMaterial(const Ogre::MaterialPtr &material, bool own) { + // Clean up the previous material, if we own it + if (!mMaterial.isNull() && mOwnMaterial) + { +#if TERRAIN_USE_SHADER + sh::Factory::getInstance().destroyMaterialInstance(mMaterial->getName()); +#endif + Ogre::MaterialManager::getSingleton().remove(mMaterial->getName()); + } + mMaterial = material; + mOwnMaterial = own; } const Ogre::AxisAlignedBox& Chunk::getBoundingBox(void) const diff --git a/components/terrain/chunk.hpp b/components/terrain/chunk.hpp index d037661aee..9550b30460 100644 --- a/components/terrain/chunk.hpp +++ b/components/terrain/chunk.hpp @@ -20,8 +20,8 @@ namespace Terrain virtual ~Chunk(); - /// @note Takes ownership of \a material - void setMaterial (const Ogre::MaterialPtr& material); + /// @param own Should we take ownership of the material? + void setMaterial (const Ogre::MaterialPtr& material, bool own=true); void setIndexBuffer(Ogre::HardwareIndexBufferSharedPtr buffer); @@ -43,6 +43,7 @@ namespace Terrain private: Ogre::AxisAlignedBox mBounds; Ogre::MaterialPtr mMaterial; + bool mOwnMaterial; // Should we remove mMaterial on destruction? Ogre::VertexData* mVertexData; Ogre::IndexData* mIndexData; diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index b56f706806..771dcdf91c 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -46,35 +46,28 @@ namespace Terrain } - Ogre::MaterialPtr MaterialGenerator::generate(Ogre::MaterialPtr mat) + Ogre::MaterialPtr MaterialGenerator::generate() { assert(!mLayerList.empty() && "Can't create material with no layers"); - return create(mat, false, false); + return create(false, false); } - Ogre::MaterialPtr MaterialGenerator::generateForCompositeMapRTT(Ogre::MaterialPtr mat) + Ogre::MaterialPtr MaterialGenerator::generateForCompositeMapRTT() { assert(!mLayerList.empty() && "Can't create material with no layers"); - return create(mat, true, false); + return create(true, false); } - Ogre::MaterialPtr MaterialGenerator::generateForCompositeMap(Ogre::MaterialPtr mat) + Ogre::MaterialPtr MaterialGenerator::generateForCompositeMap() { - return create(mat, false, true); + return create(false, true); } - Ogre::MaterialPtr MaterialGenerator::create(Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap) + Ogre::MaterialPtr MaterialGenerator::create(bool renderCompositeMap, bool displayCompositeMap) { assert(!renderCompositeMap || !displayCompositeMap); - if (!mat.isNull()) - { -#if TERRAIN_USE_SHADER - sh::Factory::getInstance().destroyMaterialInstance(mat->getName()); -#endif - Ogre::MaterialManager::getSingleton().remove(mat->getName()); - } static int count = 0; std::stringstream name; @@ -82,7 +75,7 @@ namespace Terrain if (!mShaders) { - mat = Ogre::MaterialManager::getSingleton().create(name.str(), + Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(name.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::Technique* technique = mat->getTechnique(0); technique->removeAllPasses(); diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index e7e0678991..7f607a7af8 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -29,23 +29,17 @@ namespace Terrain void enableSplitShadows(bool splitShadows) { mSplitShadows = splitShadows; } /// Creates a material suitable for displaying a chunk of terrain using alpha-blending. - /// @param mat Material that will be replaced by the generated material. May be empty as well, in which case - /// a new material is created. - Ogre::MaterialPtr generate (Ogre::MaterialPtr mat); + Ogre::MaterialPtr generate (); /// Creates a material suitable for displaying a chunk of terrain using a ready-made composite map. - /// @param mat Material that will be replaced by the generated material. May be empty as well, in which case - /// a new material is created. - Ogre::MaterialPtr generateForCompositeMap (Ogre::MaterialPtr mat); + Ogre::MaterialPtr generateForCompositeMap (); /// Creates a material suitable for rendering composite maps, i.e. for "baking" several layer textures /// into one. The main difference compared to a normal material is that no shading is applied at this point. - /// @param mat Material that will be replaced by the generated material. May be empty as well, in which case - /// a new material is created. - Ogre::MaterialPtr generateForCompositeMapRTT (Ogre::MaterialPtr mat); + Ogre::MaterialPtr generateForCompositeMapRTT (); private: - Ogre::MaterialPtr create (Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap); + Ogre::MaterialPtr create (bool renderCompositeMap, bool displayCompositeMap); std::vector mLayerList; std::vector mBlendmapList; diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index a14fe1f842..37c638da0c 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -400,13 +400,13 @@ void QuadTreeNode::load(const LoadResponseData &data) { if (mSize == 1) { - mChunk->setMaterial(mMaterialGenerator->generate(mChunk->getMaterial())); + mChunk->setMaterial(mMaterialGenerator->generate()); } else { ensureCompositeMap(); mMaterialGenerator->setCompositeMap(mCompositeMap->getName()); - mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap(mChunk->getMaterial())); + mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap()); } } // else: will be loaded in loadMaterials() after background thread has finished loading layers @@ -532,13 +532,13 @@ void QuadTreeNode::loadMaterials() { if (mSize == 1) { - mChunk->setMaterial(mMaterialGenerator->generate(mChunk->getMaterial())); + mChunk->setMaterial(mMaterialGenerator->generate()); } else { ensureCompositeMap(); mMaterialGenerator->setCompositeMap(mCompositeMap->getName()); - mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap(mChunk->getMaterial())); + mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap()); } } } @@ -554,7 +554,7 @@ void QuadTreeNode::prepareForCompositeMap(Ogre::TRect area) std::vector layer; layer.push_back(mTerrain->getStorage()->getDefaultLayer()); matGen.setLayerList(layer); - makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, matGen.generateForCompositeMapRTT(Ogre::MaterialPtr())); + makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, matGen.generateForCompositeMapRTT()); return; } if (mSize > 1) @@ -577,7 +577,7 @@ void QuadTreeNode::prepareForCompositeMap(Ogre::TRect area) else { // TODO: when to destroy? - Ogre::MaterialPtr material = mMaterialGenerator->generateForCompositeMapRTT(Ogre::MaterialPtr()); + Ogre::MaterialPtr material = mMaterialGenerator->generateForCompositeMapRTT(); makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, material); } } @@ -612,9 +612,9 @@ void QuadTreeNode::applyMaterials() mMaterialGenerator->enableShadows(mTerrain->getShadowsEnabled()); mMaterialGenerator->enableSplitShadows(mTerrain->getSplitShadowsEnabled()); if (mSize <= 1) - mChunk->setMaterial(mMaterialGenerator->generate(Ogre::MaterialPtr())); + mChunk->setMaterial(mMaterialGenerator->generate()); else - mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap(Ogre::MaterialPtr())); + mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap()); } if (hasChildren()) for (int i=0; i<4; ++i) From f6f6b5604afd9d6269cc0aed93bb47f05107d0de Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Jun 2014 23:11:38 +0200 Subject: [PATCH 474/545] Fix loading a savegame when some of its content files were disabled Fixes #1380 --- apps/openmw/mwworld/cells.cpp | 2 ++ apps/openmw/mwworld/globals.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 3b758f8660..16c1b497cd 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -314,6 +314,8 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type, catch (...) { // silently drop cells that don't exist anymore + reader.skipRecord(); + return true; /// \todo log } diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 663af640b8..15ba274980 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -100,7 +100,7 @@ namespace MWWorld if (iter!=mVariables.end()) iter->second.read (reader, ESM::Variant::Format_Global); else - reader.skipHRecord(); + reader.skipRecord(); return true; } From 5df9ff8e2c73668bd25710af3f172735e8f640ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Jun 2014 23:32:05 +0200 Subject: [PATCH 475/545] Respect CMAKE_INSTALL_PREFIX in the global openmw.cfg Fixes installing to /usr/local (Bug #1378) --- CMakeLists.txt | 8 ++++---- files/openmw.cfg | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f349e2236..f724b4204a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,13 +90,13 @@ endif(UNIX AND NOT APPLE) # Location of morrowind data files if (APPLE) set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files") - set(MORROWIND_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files") + set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files") elseif(UNIX) - set(MORROWIND_DATA_FILES "/usr/share/games/openmw/data/" CACHE PATH "location of Morrowind data files") - set(MORROWIND_RESOURCE_FILES "/usr/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files") + set(MORROWIND_DATA_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/data/" CACHE PATH "location of Morrowind data files") + set(OPENMW_RESOURCE_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files") else() set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files") - set(MORROWIND_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files") + set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files") endif(APPLE) if (WIN32) diff --git a/files/openmw.cfg b/files/openmw.cfg index 15fde1bcb9..4633141a69 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -1,4 +1,4 @@ data="?global?data" data="?mw?Data Files" data-local="?user?data" -resources=${MORROWIND_RESOURCE_FILES} +resources=${OPENMW_RESOURCE_FILES} From 576c06d791fb0f08a0ba781576e8a55d4df6e9d7 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 1 Jun 2014 17:48:26 -0400 Subject: [PATCH 476/545] Fix Bug #1371 Not properly reading in the NIF file's QuaternionKeyList. --- components/nif/niffile.cpp | 2 ++ components/nif/niffile.hpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 0f7e658fb8..10847e8f4d 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -318,6 +318,8 @@ void NIFFile::parse() Record *r = NULL; std::string rec = nif.getString(); + if(rec.empty()) + fail("Record number " + Ogre::StringConverter::toString(i) + " out of " + Ogre::StringConverter::toString(recNum) + " is blank."); RecordFactoryEntry const * entry = lookupRecordFactory (rec.c_str ()); diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 77e0acb9e5..29fa3951e7 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -137,8 +138,8 @@ template struct KeyT { float mTime; T mValue; - T mForwardValue; // Only for Quadratic interpolation - T mBackwardValue; // Only for Quadratic interpolation + T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList + T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList float mTension; // Only for TBC interpolation float mBias; // Only for TBC interpolation float mContinuity; // Only for TBC interpolation @@ -184,8 +185,11 @@ struct KeyListT { KeyT &key = mKeys[i]; key.mTime = nif->getFloat(); key.mValue = (nif->*getValue)(); - key.mForwardValue = (nif->*getValue)(); - key.mBackwardValue = (nif->*getValue)(); + if( typeid(Ogre::Quaternion) != typeid(T) ) + { + key.mForwardValue = (nif->*getValue)(); + key.mBackwardValue = (nif->*getValue)(); + } } } else if(mInterpolationType == sTBCInterpolation) From 20dabaead97cfed145ee6e8ee2c27a057872539e Mon Sep 17 00:00:00 2001 From: slothlife Date: Mon, 2 Jun 2014 02:34:43 -0500 Subject: [PATCH 477/545] Fix CMake scripts to link static dependencies Added FindDirectX scripts from Ogre so that FindOgre.cmake doesn't fail silently to find the libraries correctly. Modified top-level CMakelists.txt: - Correctly set include dirs, preprocessor definitions, and add libraries for static Ogre plugins. - Correctly set preprocessor definitions for static MyGUI. Modified launcher, openmw, and opencs to link the static Ogre plugins. Fixed FindSDL2.cmake to set a variable that contains only the SDL2 library, so that the launcher doesn't incorrectly link against SDL2main. Fixed FindMyGUI.cmake to correctly look for static variants. Fixed FindOgre.cmake to set variables for DirectX plugins correctly. --- CMakeLists.txt | 46 +++++++++++--- apps/launcher/CMakeLists.txt | 11 +--- apps/opencs/CMakeLists.txt | 1 + apps/openmw/CMakeLists.txt | 13 ---- cmake/FindDirectX.cmake | 72 ++++++++++++++++++++++ cmake/FindDirectX11.cmake | 114 +++++++++++++++++++++++++++++++++++ cmake/FindMyGUI.cmake | 60 ++++++------------ cmake/FindOGRE.cmake | 8 ++- cmake/FindSDL2.cmake | 5 +- 9 files changed, 253 insertions(+), 77 deletions(-) create mode 100644 cmake/FindDirectX.cmake create mode 100644 cmake/FindDirectX11.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f349e2236..fb0f5816e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,16 +239,40 @@ find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(SDL2 REQUIRED) find_package(OpenAL REQUIRED) find_package(Bullet REQUIRED) -IF(OGRE_STATIC) -find_package(Cg) -IF(WIN32) -set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS}) -ELSE(WIN32) -set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS}) -ENDIF(WIN32) -ENDIF(OGRE_STATIC) + +set(OGRE_PLUGIN_INCLUDE_DIRS "") +set(OGRE_STATIC_PLUGINS "") + +macro(add_static_ogre_plugin PLUGIN) + if(OGRE_${PLUGIN}_FOUND) + # strip RenderSystem_ or Plugin_ prefix from plugin name + string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN}) + string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP}) + add_definitions(-DENABLE_PLUGIN_${PLUGIN_NAME}) + + list(APPEND OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_${PLUGIN}_INCLUDE_DIRS}) + list(APPEND OGRE_STATIC_PLUGINS ${OGRE_${PLUGIN}_LIBRARIES}) + endif(OGRE_${PLUGIN}_FOUND) +endmacro(add_static_ogre_plugin) + +if(OGRE_STATIC) + # set up OGRE_PLUGIN_INCLUDE_DIRS and OGRE_STATIC_PLUGINS + add_static_ogre_plugin(Plugin_OctreeSceneManager) + add_static_ogre_plugin(Plugin_ParticleFX) + find_package(Cg) + if(Cg_FOUND) + add_static_ogre_plugin(Plugin_CgProgramManager) + list(APPEND OGRE_STATIC_PLUGINS ${Cg_LIBRARIES}) + endif(Cg_FOUND) + + add_static_ogre_plugin(RenderSystem_GL) + if(WIN32) + add_static_ogre_plugin(RenderSystem_Direct3D9) + endif(WIN32) +endif(OGRE_STATIC) + include_directories("." - ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS} + ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${PLATFORM_INCLUDE_DIR} @@ -260,6 +284,10 @@ include_directories("." link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) +if(MYGUI_STATIC) + add_definitions(-DMYGUI_STATIC) +endif (MYGUI_STATIC) + if (APPLE) # List used Ogre plugins SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL} diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index e4638c31b4..ec721a5e59 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -94,15 +94,6 @@ if(NOT WIN32) endif(NOT WIN32) # Main executable -IF(OGRE_STATIC) -IF(WIN32) -ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL) -set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES}) -ELSE(WIN32) -ADD_DEFINITIONS(-DENABLE_PLUGIN_GL) -set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_GL_LIBRARIES}) -ENDIF(WIN32) -ENDIF(OGRE_STATIC) add_executable(omwlauncher ${GUI_TYPE} ${LAUNCHER} @@ -116,7 +107,7 @@ target_link_libraries(omwlauncher ${Boost_LIBRARIES} ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} - ${SDL2_LIBRARY} + ${SDL2_LIBRARY_ONLY} ${QT_LIBRARIES} components ) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4576432e1c..f18ac0bcab 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -192,6 +192,7 @@ endif(APPLE) target_link_libraries(opencs ${OGRE_LIBRARIES} + ${OGRE_STATIC_PLUGINS} ${SHINY_LIBRARIES} ${Boost_LIBRARIES} ${QT_LIBRARIES} diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8496b47a4a..b76756ca07 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -89,19 +89,6 @@ endif(WIN32) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) -IF(OGRE_STATIC) -ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL) -set(OGRE_STATIC_PLUGINS ${OGRE_Plugin_OctreeSceneManager_LIBRARIES} ${OGRE_Plugin_ParticleFX_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES}) -IF(WIN32) -ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9) -list (APPEND OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES}) -ENDIF(WIN32) -IF (Cg_FOUND) -ADD_DEFINITIONS(-DENABLE_PLUGIN_CgProgramManager) -list (APPEND OGRE_STATIC_PLUGINS ${OGRE_Plugin_CgProgramManager_LIBRARIES} ${Cg_LIBRARIES}) -ENDIF (Cg_FOUND) -ENDIF(OGRE_STATIC) - add_executable(openmw ${OPENMW_LIBS} ${OPENMW_LIBS_HEADER} ${OPENMW_FILES} diff --git a/cmake/FindDirectX.cmake b/cmake/FindDirectX.cmake new file mode 100644 index 0000000000..4641b55a3d --- /dev/null +++ b/cmake/FindDirectX.cmake @@ -0,0 +1,72 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# Find DirectX9 SDK +# Define: +# DirectX9_FOUND +# DirectX9_INCLUDE_DIR +# DirectX9_LIBRARY +# DirectX9_ROOT_DIR + +if(WIN32) # The only platform it makes sense to check for DirectX9 SDK + include(FindPkgMacros) + findpkg_begin(DirectX9) + + # Get path, convert backslashes as ${ENV_DXSDK_DIR} + getenv_path(DXSDK_DIR) + getenv_path(DirectX_HOME) + getenv_path(DirectX_ROOT) + getenv_path(DirectX_BASE) + + # construct search paths + set(DirectX9_PREFIX_PATH + "${DXSDK_DIR}" "${ENV_DXSDK_DIR}" + "${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}" + "${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}" + "${DIRECTX_BASE}" "${ENV_DIRECTX_BASE}" + "C:/apps_x86/Microsoft DirectX SDK*" + "C:/Program Files (x86)/Microsoft DirectX SDK*" + "C:/apps/Microsoft DirectX SDK*" + "C:/Program Files/Microsoft DirectX SDK*" + "$ENV{ProgramFiles}/Microsoft DirectX SDK*" + ) + + create_search_paths(DirectX9) + # redo search if prefix path changed + clear_if_changed(DirectX9_PREFIX_PATH + DirectX9_LIBRARY + DirectX9_INCLUDE_DIR + ) + + find_path(DirectX9_INCLUDE_DIR NAMES d3d9.h D3DCommon.h HINTS ${DirectX9_INC_SEARCH_PATH}) + # dlls are in DirectX9_ROOT_DIR/Developer Runtime/x64|x86 + # lib files are in DirectX9_ROOT_DIR/Lib/x64|x86 + if(CMAKE_CL_64) + set(DirectX9_LIBPATH_SUFFIX "x64") + else(CMAKE_CL_64) + set(DirectX9_LIBPATH_SUFFIX "x86") + endif(CMAKE_CL_64) + find_library(DirectX9_LIBRARY NAMES d3d9 HINTS ${DirectX9_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX9_LIBPATH_SUFFIX}) + find_library(DirectX9_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX9_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX9_LIBPATH_SUFFIX}) + find_library(DirectX9_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX9_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX9_LIBPATH_SUFFIX}) + find_library(DirectX9_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX9_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX9_LIBPATH_SUFFIX}) + + findpkg_finish(DirectX9) + set(DirectX9_LIBRARIES ${DirectX9_LIBRARIES} + ${DirectX9_D3DX9_LIBRARY} + ${DirectX9_DXERR_LIBRARY} + ${DirectX9_DXGUID_LIBRARY} + ) + + mark_as_advanced(DirectX9_D3DX9_LIBRARY DirectX9_DXERR_LIBRARY DirectX9_DXGUID_LIBRARY + DirectX9_DXGI_LIBRARY DirectX9_D3DCOMPILER_LIBRARY) + + +endif(WIN32) diff --git a/cmake/FindDirectX11.cmake b/cmake/FindDirectX11.cmake new file mode 100644 index 0000000000..22d5b5441f --- /dev/null +++ b/cmake/FindDirectX11.cmake @@ -0,0 +1,114 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +# Find DirectX11 SDK +# Define: +# DirectX11_FOUND +# DirectX11_INCLUDE_DIR +# DirectX11_LIBRARY +# DirectX11_ROOT_DIR + +if(WIN32) # The only platform it makes sense to check for DirectX11 SDK + include(FindPkgMacros) + findpkg_begin(DirectX11) + + # Get path, convert backslashes as ${ENV_DXSDK_DIR} + getenv_path(DXSDK_DIR) + getenv_path(DIRECTX_HOME) + getenv_path(DIRECTX_ROOT) + getenv_path(DIRECTX_BASE) + + # construct search paths + set(DirectX11_PREFIX_PATH + "${DXSDK_DIR}" "${ENV_DXSDK_DIR}" + "${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}" + "${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}" + "${DIRECTX_BASE}" "${ENV_DIRECTX_BASE}" + "C:/apps_x86/Microsoft DirectX SDK*" + "C:/Program Files (x86)/Microsoft DirectX SDK*" + "C:/apps/Microsoft DirectX SDK*" + "C:/Program Files/Microsoft DirectX SDK*" + "$ENV{ProgramFiles}/Microsoft DirectX SDK*" + ) + + if(OGRE_BUILD_PLATFORM_WINRT) + # Windows 8 SDK has custom layout + set(DirectX11_INC_SEARCH_PATH + "C:/Program Files (x86)/Windows Kits/8.0/Include/shared" + "C:/Program Files (x86)/Windows Kits/8.0/Include/um" + ) + set(DirectX11_LIB_SEARCH_PATH + "C:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um" + ) + endif() + + create_search_paths(DirectX11) + # redo search if prefix path changed + clear_if_changed(DirectX11_PREFIX_PATH + DirectX11_LIBRARY + DirectX11_INCLUDE_DIR + ) + + # dlls are in DirectX11_ROOT_DIR/Developer Runtime/x64|x86 + # lib files are in DirectX11_ROOT_DIR/Lib/x64|x86 + if(CMAKE_CL_64) + set(DirectX11_LIBPATH_SUFFIX "x64") + else(CMAKE_CL_64) + set(DirectX11_LIBPATH_SUFFIX "x86") + endif(CMAKE_CL_64) + + # look for D3D11 components + find_path(DirectX11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX11_INC_SEARCH_PATH}) + find_library(DirectX11_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + find_library(DirectX11_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + find_library(DirectX11_DXGI_LIBRARY NAMES dxgi HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + find_library(DirectX11_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + + find_library(DirectX11_LIBRARY NAMES d3d11 HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + find_library(DirectX11_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX11_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX11_LIBPATH_SUFFIX}) + if (DirectX11_INCLUDE_DIR AND DirectX11_LIBRARY) + set(DirectX11_D3D11_FOUND TRUE) + set(DirectX11_INCLUDE_DIR ${DirectX11_INCLUDE_DIR}) + set(DirectX11_D3D11_LIBRARIES ${DirectX11_D3D11_LIBRARIES} + ${DirectX11_LIBRARY} + ${DirectX11_DXGI_LIBRARY} + ${DirectX11_DXGUID_LIBRARY} + ${DirectX11_D3DCOMPILER_LIBRARY} + ) + endif () + if (DirectX11_D3DX11_LIBRARY) + set(DirectX11_D3D11_LIBRARIES ${DirectX11_D3D11_LIBRARIES} ${DirectX11_D3DX11_LIBRARY}) + endif () + if (DirectX11_DXERR_LIBRARY) + set(DirectX11_D3D11_LIBRARIES ${DirectX11_D3D11_LIBRARIES} ${DirectX11_DXERR_LIBRARY}) + endif () + + findpkg_finish(DirectX11) + + set(DirectX11_LIBRARIES + ${DirectX11_D3D11_LIBRARIES} + ) + + if (OGRE_BUILD_PLATFORM_WINDOWS_PHONE) + set(DirectX11_FOUND TRUE) + set(DirectX11_INCLUDE_DIR "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/WPSDK/WP80/include" CACHE STRING "" FORCE) + set(DirectX11_LIBRARY "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/WPSDK/WP80/lib" CACHE STRING "" FORCE) + set(DirectX11_LIBRARIES ${DirectX11_LIBRARY}) + set(CMAKE_CXX_FLAGS "/EHsc" CACHE STRING "" FORCE) + endif () + + mark_as_advanced(DirectX11_INCLUDE_DIR + DirectX11_D3D11_LIBRARIES + DirectX11_D3DX11_LIBRARY + DirectX11_DXERR_LIBRARY + DirectX11_DXGUID_LIBRARY + DirectX11_DXGI_LIBRARY + DirectX11_D3DCOMPILER_LIBRARY) +endif(WIN32) \ No newline at end of file diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index e2fefac7dc..ebf0694046 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -19,58 +19,34 @@ include(FindPkgMacros) IF (WIN32) #Windows MESSAGE(STATUS "Looking for MyGUI") -SET(MYGUISDK $ENV{MYGUI_HOME}) + SET(MYGUISDK $ENV{MYGUI_HOME}) IF (MYGUISDK) -findpkg_begin ( "MYGUI" ) + findpkg_begin ( "MYGUI" ) MESSAGE(STATUS "Using MyGUI in MyGUI SDK") -STRING(REGEX REPLACE "[\\]" "/" MYGUISDK "${MYGUISDK}" ) + STRING(REGEX REPLACE "[\\]" "/" MYGUISDK "${MYGUISDK}" ) -find_path ( MYGUI_INCLUDE_DIRS -MyGUI.h -"${MYGUISDK}/MyGUIEngine/include" -NO_DEFAULT_PATH ) + find_path ( MYGUI_INCLUDE_DIRS MyGUI.h "${MYGUISDK}/MyGUIEngine/include" NO_DEFAULT_PATH ) + find_path ( MYGUI_PLATFORM_INCLUDE_DIRS MyGUI_OgrePlatform.h "${MYGUISDK}/Platforms/Ogre/OgrePlatform/include" NO_DEFAULT_PATH ) -find_path ( MYGUI_PLATFORM_INCLUDE_DIRS -MyGUI_OgrePlatform.h -"${MYGUISDK}/Platforms/Ogre/OgrePlatform/include" -NO_DEFAULT_PATH ) + SET ( MYGUI_LIB_DIR ${MYGUISDK}/lib ${MYGUISDK}/*/lib ) -SET ( MYGUI_LIB_DIR ${MYGUISDK}/lib ${MYGUISDK}/*/lib ) + if ( MYGUI_STATIC ) + set(LIB_SUFFIX "Static") + endif ( MYGUI_STATIC ) -find_library ( MYGUI_LIBRARIES_REL NAMES -MyGUIEngine.lib -MyGUI.OgrePlatform.lib -HINTS -${MYGUI_LIB_DIR} -PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + find_library ( MYGUI_LIBRARIES_REL NAMES MyGUIEngine${LIB_SUFFIX}.lib MyGUI.OgrePlatform.lib HINTS ${MYGUI_LIB_DIR} PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + find_library ( MYGUI_LIBRARIES_DBG NAMES MyGUIEngine${LIB_SUFFIX}_d.lib MyGUI.OgrePlatform_d.lib HINTS ${MYGUI_LIB_DIR} PATH_SUFFIXES "" debug ) -find_library ( MYGUI_LIBRARIES_DBG NAMES -MyGUIEngine_d.lib -MyGUI.OgrePlatform_d.lib -HINTS -${MYGUI_LIB_DIR} -PATH_SUFFIXES "" debug ) + find_library ( MYGUI_PLATFORM_LIBRARIES_REL NAMES MyGUI.OgrePlatform.lib HINTS ${MYGUI_LIB_DIR} PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + find_library ( MYGUI_PLATFORM_LIBRARIES_DBG NAMES MyGUI.OgrePlatform_d.lib HINTS ${MYGUI_LIB_DIR} PATH_SUFFIXES "" debug ) -find_library ( MYGUI_PLATFORM_LIBRARIES_REL NAMES -MyGUI.OgrePlatform.lib -HINTS -${MYGUI_LIB_DIR} -PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + make_library_set ( MYGUI_LIBRARIES ) + make_library_set ( MYGUI_PLATFORM_LIBRARIES ) -find_library ( MYGUI_PLATFORM_LIBRARIES_DBG NAMES -MyGUI.OgrePlatform_d.lib -HINTS -${MYGUI_LIB_DIR} -PATH_SUFFIXES "" debug ) - -make_library_set ( MYGUI_LIBRARIES ) -make_library_set ( MYGUI_PLATFORM_LIBRARIES ) - -MESSAGE ("${MYGUI_LIBRARIES}") -MESSAGE ("${MYGUI_PLATFORM_LIBRARIES}") - -#findpkg_finish ( "MYGUI" ) + MESSAGE ("${MYGUI_LIBRARIES}") + MESSAGE ("${MYGUI_PLATFORM_LIBRARIES}") + #findpkg_finish ( "MYGUI" ) ENDIF (MYGUISDK) IF (OGRESOURCE) MESSAGE(STATUS "Using MyGUI in OGRE dependencies") diff --git a/cmake/FindOGRE.cmake b/cmake/FindOGRE.cmake index 96f93cf34a..81b52b1b77 100644 --- a/cmake/FindOGRE.cmake +++ b/cmake/FindOGRE.cmake @@ -493,14 +493,18 @@ ogre_find_plugin(RenderSystem_Direct3D11 OgreD3D11RenderSystem.h RenderSystems/D if (OGRE_STATIC) # check if dependencies for plugins are met - if (NOT DirectX_FOUND) + if (NOT DirectX9_FOUND) set(OGRE_RenderSystem_Direct3D9_FOUND FALSE) + else () + set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} ${DirectX9_INCLUDE_DIR}) endif () if (NOT DirectX_D3D10_FOUND) set(OGRE_RenderSystem_Direct3D10_FOUND FALSE) endif () if (NOT DirectX_D3D11_FOUND) set(OGRE_RenderSystem_Direct3D11_FOUND FALSE) + else () + set(OGRE_INCLUDE_DIRS ${OGRE_INCLUDE_DIRS} ${DirectX_D3D11_INCLUDE_DIR}) endif () if (NOT OPENGL_FOUND) set(OGRE_RenderSystem_GL_FOUND FALSE) @@ -513,7 +517,7 @@ if (OGRE_STATIC) endif () set(OGRE_RenderSystem_Direct3D9_LIBRARIES ${OGRE_RenderSystem_Direct3D9_LIBRARIES} - ${DirectX_LIBRARIES} + ${DirectX9_LIBRARIES} ) set(OGRE_RenderSystem_Direct3D10_LIBRARIES ${OGRE_RenderSystem_Direct3D10_LIBRARIES} ${DirectX_D3D10_LIBRARIES} diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake index 70e607a89f..163abf4639 100644 --- a/cmake/FindSDL2.cmake +++ b/cmake/FindSDL2.cmake @@ -87,7 +87,7 @@ FIND_PATH(SDL2_INCLUDE_DIR SDL.h ) #MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}") -FIND_LIBRARY(SDL2_LIBRARY_TEMP +FIND_LIBRARY(SDL2_LIBRARY_PATH NAMES SDL2 HINTS $ENV{SDL2DIR} @@ -99,6 +99,9 @@ FIND_LIBRARY(SDL2_LIBRARY_TEMP /opt ) +set(SDL2_LIBRARY_ONLY ${SDL2_LIBRARY_PATH} CACHE STRING "The SDL2 library, with no other libraries.") +set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_PATH}) + #MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}") IF(NOT SDL2_BUILDING_LIBRARY) From 929aae68696b3251155959cfe18312fa56ff625a Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 1 Jun 2014 22:21:52 +0200 Subject: [PATCH 478/545] Silence a clang warning warning: pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression [-Waddress-of-array-temporary] --- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 548a871ce1..f9927537cd 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2057,8 +2057,8 @@ namespace MWWorld // door to exterior if (it->mRef.getDestCell().empty()) { int x, y; - const float *pos = it->mRef.getDoorDest().pos; - positionToIndex(pos[0], pos[1], x, y); + ESM::Position doorDest = it->mRef.getDoorDest(); + positionToIndex(doorDest.pos[0], doorDest.pos[1], x, y); source = getExterior(x, y); } // door to interior From 8b33c087e0da487d8307a9c0f417bbaf22774614 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 14:46:41 +0200 Subject: [PATCH 479/545] Properly handle exceptions when saving the game Add message boxes when an exception occurs while loading or saving the game --- apps/openmw/mwstate/statemanagerimp.cpp | 149 ++++++++++++++---------- 1 file changed, 85 insertions(+), 64 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index dafb8323aa..29b5318d74 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -149,91 +149,105 @@ void MWState::StateManager::endGame() void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) { - ESM::SavedGame profile; + try + { + ESM::SavedGame profile; - MWBase::World& world = *MWBase::Environment::get().getWorld(); + MWBase::World& world = *MWBase::Environment::get().getWorld(); - MWWorld::Ptr player = world.getPlayerPtr(); + MWWorld::Ptr player = world.getPlayerPtr(); - profile.mContentFiles = world.getContentFiles(); + profile.mContentFiles = world.getContentFiles(); - profile.mPlayerName = player.getClass().getName (player); - profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); + profile.mPlayerName = player.getClass().getName (player); + profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); - std::string classId = player.get()->mBase->mClass; - if (world.getStore().get().isDynamic(classId)) - profile.mPlayerClassName = world.getStore().get().find(classId)->mName; - else - profile.mPlayerClassId = classId; + std::string classId = player.get()->mBase->mClass; + if (world.getStore().get().isDynamic(classId)) + profile.mPlayerClassName = world.getStore().get().find(classId)->mName; + else + profile.mPlayerClassId = classId; - profile.mPlayerCell = world.getCellName(); + profile.mPlayerCell = world.getCellName(); - profile.mInGameTime.mGameHour = world.getTimeStamp().getHour(); - profile.mInGameTime.mDay = world.getDay(); - profile.mInGameTime.mMonth = world.getMonth(); - profile.mInGameTime.mYear = world.getYear(); - profile.mTimePlayed = mTimePlayed; - profile.mDescription = description; + profile.mInGameTime.mGameHour = world.getTimeStamp().getHour(); + profile.mInGameTime.mDay = world.getDay(); + profile.mInGameTime.mMonth = world.getMonth(); + profile.mInGameTime.mYear = world.getYear(); + profile.mTimePlayed = mTimePlayed; + profile.mDescription = description; - int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing - Ogre::Image screenshot; - world.screenshot(screenshot, screenshotW, screenshotH); - Ogre::DataStreamPtr encoded = screenshot.encode("jpg"); - profile.mScreenshot.resize(encoded->size()); - encoded->read(&profile.mScreenshot[0], encoded->size()); + int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing + Ogre::Image screenshot; + world.screenshot(screenshot, screenshotW, screenshotH); + Ogre::DataStreamPtr encoded = screenshot.encode("jpg"); + profile.mScreenshot.resize(encoded->size()); + encoded->read(&profile.mScreenshot[0], encoded->size()); - if (!slot) - slot = mCharacterManager.getCurrentCharacter()->createSlot (profile); - else - slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile); + if (!slot) + slot = mCharacterManager.getCurrentCharacter()->createSlot (profile); + else + slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile); - boost::filesystem::ofstream stream (slot->mPath, std::ios::binary); + boost::filesystem::ofstream stream (slot->mPath, std::ios::binary); - ESM::ESMWriter writer; + ESM::ESMWriter writer; - const std::vector& current = - MWBase::Environment::get().getWorld()->getContentFiles(); + const std::vector& current = + MWBase::Environment::get().getWorld()->getContentFiles(); - for (std::vector::const_iterator iter (current.begin()); iter!=current.end(); - ++iter) - writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 + for (std::vector::const_iterator iter (current.begin()); iter!=current.end(); + ++iter) + writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 - writer.setFormat (ESM::Header::CurrentFormat); - int recordCount = 1 // saved game header - +MWBase::Environment::get().getJournal()->countSavedGameRecords() - +MWBase::Environment::get().getWorld()->countSavedGameRecords() - +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() - +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() - +MWBase::Environment::get().getWindowManager()->countSavedGameRecords(); - writer.setRecordCount (recordCount); + writer.setFormat (ESM::Header::CurrentFormat); + int recordCount = 1 // saved game header + +MWBase::Environment::get().getJournal()->countSavedGameRecords() + +MWBase::Environment::get().getWorld()->countSavedGameRecords() + +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() + +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() + +MWBase::Environment::get().getWindowManager()->countSavedGameRecords(); + writer.setRecordCount (recordCount); - writer.save (stream); + writer.save (stream); - Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); - listener.setProgressRange(recordCount); - listener.setLabel("#{sNotifyMessage4}"); + Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + listener.setProgressRange(recordCount); + listener.setLabel("#{sNotifyMessage4}"); - Loading::ScopedLoad load(&listener); + Loading::ScopedLoad load(&listener); - writer.startRecord (ESM::REC_SAVE); - slot->mProfile.save (writer); - writer.endRecord (ESM::REC_SAVE); - listener.increaseProgress(); + writer.startRecord (ESM::REC_SAVE); + slot->mProfile.save (writer); + writer.endRecord (ESM::REC_SAVE); + listener.increaseProgress(); - MWBase::Environment::get().getJournal()->write (writer, listener); - MWBase::Environment::get().getDialogueManager()->write (writer, listener); - MWBase::Environment::get().getWorld()->write (writer, listener); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener); - MWBase::Environment::get().getWindowManager()->write(writer, listener); + MWBase::Environment::get().getJournal()->write (writer, listener); + MWBase::Environment::get().getDialogueManager()->write (writer, listener); + MWBase::Environment::get().getWorld()->write (writer, listener); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener); + MWBase::Environment::get().getWindowManager()->write(writer, listener); - // Ensure we have written the number of records that was estimated - if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record - std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl; + // Ensure we have written the number of records that was estimated + if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record + std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl; - writer.close(); + writer.close(); - Settings::Manager::setString ("character", "Saves", - slot->mPath.parent_path().filename().string()); + Settings::Manager::setString ("character", "Saves", + slot->mPath.parent_path().filename().string()); + } + catch (const std::exception& e) + { + std::stringstream error; + error << "Failed to save game: " << e.what(); + + std::cerr << error.str() << std::endl; + + std::vector buttons; + buttons.push_back("#{sOk}"); + MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); + } } void MWState::StateManager::quickSave (std::string name) @@ -371,10 +385,17 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl } catch (const std::exception& e) { - std::cerr << "failed to load saved game: " << e.what() << std::endl; + std::stringstream error; + error << "Failed to load saved game: " << e.what(); + + std::cerr << error.str() << std::endl; cleanup (true); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); + + std::vector buttons; + buttons.push_back("#{sOk}"); + MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); } } From 68afac6a190066b5dea06d028418f6153b350c1a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 19:47:39 +0200 Subject: [PATCH 480/545] Fix large size_t being truncated to int --- apps/openmw/mwgui/savegamedialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 348b7c1df9..ef5d5858b6 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -117,7 +117,7 @@ namespace MWGui std::string directory = Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves")); - int selectedIndex = MyGUI::ITEM_NONE; + size_t selectedIndex = MyGUI::ITEM_NONE; for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it) { From 996e49c534f3f9fdc0efe860e8ebd74a51cb0458 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 20:24:35 +0200 Subject: [PATCH 481/545] Change CharacterManager to use list instead of vector Solves a crash when deleting all savegames of a character due to mCurrent being invalidated --- apps/openmw/mwbase/statemanager.hpp | 4 +-- apps/openmw/mwstate/charactermanager.cpp | 37 ++++++++++++++---------- apps/openmw/mwstate/charactermanager.hpp | 11 +++++-- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwbase/statemanager.hpp b/apps/openmw/mwbase/statemanager.hpp index 121a73a485..006be921b1 100644 --- a/apps/openmw/mwbase/statemanager.hpp +++ b/apps/openmw/mwbase/statemanager.hpp @@ -1,7 +1,7 @@ #ifndef GAME_MWSTATE_STATEMANAGER_H #define GAME_MWSTATE_STATEMANAGER_H -#include +#include #include namespace MWState @@ -24,7 +24,7 @@ namespace MWBase State_Running }; - typedef std::vector::const_iterator CharacterIterator; + typedef std::list::const_iterator CharacterIterator; private: diff --git a/apps/openmw/mwstate/charactermanager.cpp b/apps/openmw/mwstate/charactermanager.cpp index 822e2d88e1..d773904db2 100644 --- a/apps/openmw/mwstate/charactermanager.cpp +++ b/apps/openmw/mwstate/charactermanager.cpp @@ -49,20 +49,17 @@ MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create) void MWState::CharacterManager::deleteSlot(const MWState::Character *character, const MWState::Slot *slot) { - int index = character - &mCharacters[0]; + std::list::iterator it = findCharacter(character); - if (index<0 || index>=static_cast (mCharacters.size())) - throw std::logic_error ("invalid character"); + it->deleteSlot(slot); - mCharacters[index].deleteSlot(slot); - - if (mCharacters[index].begin() == mCharacters[index].end()) + if (character->begin() == character->end()) { // All slots deleted, cleanup and remove this character - mCharacters[index].cleanup(); + it->cleanup(); if (character == mCurrent) mCurrent = NULL; - mCharacters.erase(mCharacters.begin() + index); + mCharacters.erase(it); } } @@ -78,14 +75,24 @@ void MWState::CharacterManager::createCharacter() mCurrent = &mCharacters.back(); } +std::list::iterator MWState::CharacterManager::findCharacter(const MWState::Character* character) +{ + std::list::iterator it = mCharacters.begin(); + for (; it != mCharacters.end(); ++it) + { + if (&*it == character) + break; + } + if (it == mCharacters.end()) + throw std::logic_error ("invalid character"); + return it; +} + void MWState::CharacterManager::setCurrentCharacter (const Character *character) { - int index = character - &mCharacters[0]; + std::list::iterator it = findCharacter(character); - if (index<0 || index>=static_cast (mCharacters.size())) - throw std::logic_error ("invalid character"); - - mCurrent = &mCharacters[index]; + mCurrent = &*it; } void MWState::CharacterManager::clearCurrentCharacter() @@ -93,12 +100,12 @@ void MWState::CharacterManager::clearCurrentCharacter() mCurrent = 0; } -std::vector::const_iterator MWState::CharacterManager::begin() const +std::list::const_iterator MWState::CharacterManager::begin() const { return mCharacters.begin(); } -std::vector::const_iterator MWState::CharacterManager::end() const +std::list::const_iterator MWState::CharacterManager::end() const { return mCharacters.end(); } diff --git a/apps/openmw/mwstate/charactermanager.hpp b/apps/openmw/mwstate/charactermanager.hpp index 869d34f21c..adf9d2ef44 100644 --- a/apps/openmw/mwstate/charactermanager.hpp +++ b/apps/openmw/mwstate/charactermanager.hpp @@ -11,7 +11,10 @@ namespace MWState { boost::filesystem::path mPath; int mNext; - std::vector mCharacters; + + // Uses std::list, so that mCurrent stays valid when characters are deleted + std::list mCharacters; + Character *mCurrent; std::string mGame; @@ -23,6 +26,8 @@ namespace MWState CharacterManager& operator= (const CharacterManager&); ///< Not implemented + std::list::iterator findCharacter(const MWState::Character* character); + public: CharacterManager (const boost::filesystem::path& saves, const std::string& game); @@ -39,9 +44,9 @@ namespace MWState void clearCurrentCharacter(); - std::vector::const_iterator begin() const; + std::list::const_iterator begin() const; - std::vector::const_iterator end() const; + std::list::const_iterator end() const; }; } From 16ceb382f4aa6c52e1976f8db8a307e9676d0349 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 20:40:06 +0200 Subject: [PATCH 482/545] Ignore raycasting shapes for weapon collision tests Fixes dead bodies being in the way when they shouldn't. --- libs/openengine/bullet/physic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 235300b438..8d9ac3c228 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -615,6 +615,7 @@ namespace Physic btCollisionObject *object) { DeepestNotMeContactTestResultCallback callback(filter, origin); + callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor; dynamicsWorld->contactTest(object, callback); return std::make_pair(callback.mObject, callback.mContactPoint); } From 55d451febef1d0e204d5782b71c9330a2f8cd2d7 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 2 Jun 2014 20:41:37 +0200 Subject: [PATCH 483/545] changes in the model (idtable) to support nested data --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/collection.hpp | 8 +++ apps/opencs/model/world/collectionbase.cpp | 1 + apps/opencs/model/world/collectionbase.hpp | 2 + apps/opencs/model/world/columnbase.hpp | 10 +++- apps/opencs/model/world/idtable.cpp | 54 ++++++++++++++++++--- apps/opencs/model/world/idtable.hpp | 11 +++++ apps/opencs/model/world/refidadapter.cpp | 4 +- apps/opencs/model/world/refidadapter.hpp | 4 +- apps/opencs/model/world/refidadapterimp.cpp | 7 ++- apps/opencs/model/world/refidadapterimp.hpp | 6 +-- apps/opencs/model/world/refidcollection.cpp | 12 ++++- apps/opencs/model/world/refidcollection.hpp | 2 + apps/opencs/view/world/dialoguesubview.cpp | 46 ++++++++++-------- apps/opencs/view/world/util.cpp | 3 +- 15 files changed, 133 insertions(+), 39 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cbe90b1d3e..d41a015ca5 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world - idtable idtableproxymodel regionmap data + idtable idtableproxymodel regionmap data nestedtablemodel ) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 1fb3e1f1db..88ef59ace4 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -82,6 +82,8 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const; + virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + virtual void setData (int index, int column, const QVariant& data); virtual const ColumnBase& getColumn (int column) const; @@ -277,6 +279,12 @@ namespace CSMWorld return mColumns.at (column)->get (mRecords.at (index)); } + template + QVariant Collection::getNestedData(int row, int column, int subRow, int subColumn) const + { + return 10; //TODO + } + template void Collection::setData (int index, int column, const QVariant& data) { diff --git a/apps/opencs/model/world/collectionbase.cpp b/apps/opencs/model/world/collectionbase.cpp index 241f198cb2..7b69125750 100644 --- a/apps/opencs/model/world/collectionbase.cpp +++ b/apps/opencs/model/world/collectionbase.cpp @@ -2,6 +2,7 @@ #include "collectionbase.hpp" #include +#include #include "columnbase.hpp" diff --git a/apps/opencs/model/world/collectionbase.hpp b/apps/opencs/model/world/collectionbase.hpp index 442055d5f3..19017047b4 100644 --- a/apps/opencs/model/world/collectionbase.hpp +++ b/apps/opencs/model/world/collectionbase.hpp @@ -44,6 +44,8 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const = 0; + virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0; + virtual void setData (int index, int column, const QVariant& data) = 0; // Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index fe310d0aa4..c8670a03b8 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -89,7 +89,9 @@ namespace CSMWorld Display_RefRecordType, Display_DialogueType, Display_QuestStatusType, - Display_Gender + Display_Gender, + + Display_Nested }; int mColumnId; @@ -125,6 +127,12 @@ namespace CSMWorld throw std::logic_error ("Column " + getTitle() + " is not editable"); } }; + + template + struct NestedColumn + { + virtual QVariant getNested(const Record& record, int subColumn, int subSow) const = 0; + }; } #endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 31797d0812..04d1b333b4 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -36,7 +36,13 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) return QVariant(); - return mIdCollection->getData (index.row(), index.column()); + if (index.internalId() != 0) + { + std::pair parentAdress(unfoldIndexAdress(index.internalId())); + return mIdCollection->getNestedData(index.row(), index.column(), parentAdress.first, parentAdress.second); + } else { + return mIdCollection->getData (index.row(), index.column()); + } } QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const @@ -97,8 +103,11 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const { + unsigned int encodedId = 0; if (parent.isValid()) - return QModelIndex(); + { + encodedId = this->foldIndexAdress(parent); + } if (row<0 || row>=mIdCollection->getSize()) return QModelIndex(); @@ -106,12 +115,24 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa if (column<0 || column>=mIdCollection->getColumns()) return QModelIndex(); - return createIndex (row, column); + return createIndex(row, column, encodedId); } QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const { - return QModelIndex(); + if (index.internalId() == 0) //0 is used for indexs with invalid parent (top level data) + { + return QModelIndex(); + } + + unsigned int id = index.internalId(); + const std::pair& adress(unfoldIndexAdress(id)); + + if (adress.first >= this->rowCount() || adress.second >= this->columnCount()) + { + throw "Parent index is not present in the model"; + } + return createIndex(adress.first, adress.second); } void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type) @@ -136,10 +157,10 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin, endInsertRows(); } - +///This method can return only indexes to the top level table cells QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const { - return index (mIdCollection->getIndex (id), column); + return index(mIdCollection->getIndex (id), column); } void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record) @@ -238,7 +259,28 @@ std::pair CSMWorld::IdTable::view (int row) return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint); } +///For top level data/columns int CSMWorld::IdTable::getColumnId(int column) const { return mIdCollection->getColumn(column).getId(); +} + +unsigned int CSMWorld::IdTable::foldIndexAdress (const QModelIndex& index) const +{ + unsigned int out = index.row() * this->columnCount(); + out += index.column(); + return ++out; +} + +std::pair< int, int > CSMWorld::IdTable::unfoldIndexAdress (unsigned int id) const +{ + if (id == 0) + { + throw "Attempt to unfold index id of the top level data cell"; + } + + --id; + int row = id / this->columnCount(); + int column = id - row * this->columnCount(); + return std::make_pair(row, column); } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 8b54628256..deb07a1b24 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -8,6 +8,15 @@ #include "universalid.hpp" #include "columns.hpp" +/*! \brief + * Clas for holding the model. Uses typical qt table abstraction/interface for granting access to the individiual fields of the records, + * Some records are holding nested data (for instance inventory list of the npc). In casses like this, table model offers interface + * to access nested data in the qt way – that is specify parent. Since some of those nested data require multiple columns to + * represent informations, single int (default way to index model in the qmodelindex) is not sufficiant. Therefore tablemodelindex class + * can hold two ints for the sake of indexing two dimensions of the table. This model does not support multiple levels of the nested + * data. Vast majority of methods makes sense only for the top level data. + */ + namespace CSMWorld { class CollectionBase; @@ -44,6 +53,8 @@ namespace CSMWorld // not implemented IdTable (const IdTable&); IdTable& operator= (const IdTable&); + unsigned int foldIndexAdress(const QModelIndex& index) const; + std::pair unfoldIndexAdress(unsigned int id) const; public: diff --git a/apps/opencs/model/world/refidadapter.cpp b/apps/opencs/model/world/refidadapter.cpp index 283f062feb..2259a6e445 100644 --- a/apps/opencs/model/world/refidadapter.cpp +++ b/apps/opencs/model/world/refidadapter.cpp @@ -8,13 +8,13 @@ CSMWorld::RefIdAdapter::RefIdAdapter() {} CSMWorld::RefIdAdapter::~RefIdAdapter() {} -QVariant CSMWorld::RefIdAdapter::getData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int idnex, int subRowIndex, int subColIndex) const +QVariant CSMWorld::RefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int idnex, int subRowIndex, int subColIndex) const { assert(false); return QVariant(); } -void CSMWorld::RefIdAdapter::setData (const CSMWorld::RefIdColumn* column, CSMWorld::RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const +void CSMWorld::RefIdAdapter::setNestedData (const CSMWorld::RefIdColumn* column, CSMWorld::RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const { assert(false); } diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 673b1f5a44..c9c7780202 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -30,10 +30,10 @@ namespace CSMWorld const QVariant& value) const = 0; ///< If the data type does not match an exception is thrown. - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, + virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, int idnex, int subRowIndex, int subColIndex) const; - virtual void setData (const RefIdColumn *column, RefIdData& data, + virtual void setNestedData (const RefIdColumn *column, RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const; diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 8c98e18082..750e4af876 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -222,7 +222,7 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD NameRefIdAdapter::setData (column, data, index, value); } -void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdData& data, +void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, RefIdData& data, int index, const QVariant& value, int subRowIndex, @@ -242,6 +242,9 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa case 1: record.get().mInventory.mList.at(subRowIndex).mCount = value.toInt(); break; + + default: + throw "Trying to access non-existing column in the nested table!"; } } else { @@ -249,7 +252,7 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa } } -QVariant CSMWorld::ContainerRefIdAdapter::getData (const CSMWorld::RefIdColumn* column, +QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int index, int subRowIndex, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index f295016985..eab0151b59 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -617,15 +617,13 @@ namespace CSMWorld ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); - using RefIdAdapter::getData; - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index, + virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, int index, int subRowIndex, int subColIndex) const; virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const; - using RefIdAdapter::setData; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, + virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index, const QVariant& value, int subRowIndex, int subColIndex) const; virtual void setData (const RefIdColumn *column, RefIdData& data, int index, diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 1745ce957f..74aa67e3bf 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -165,7 +165,7 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean)); const RefIdColumn *respawn = &mColumns.back(); - mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_None, ColumnBase::Flag_Dialogue, false, false)); + mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_Nested, ColumnBase::Flag_Dialogue, false, false)); const RefIdColumn *content = &mColumns.back(); CreatureColumns creatureColumns (actorsColumns); @@ -419,6 +419,16 @@ QVariant CSMWorld::RefIdCollection::getData (int index, int column) const return adaptor.getData (&mColumns.at (column), mData, localIndex.first); } +QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subRow, int subColumn) const +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); + + const RefIdAdapter& adaptor = findAdaptor (localIndex.second); + + //if this overloaded, base class method was not overriden, crash will happen (assert(false)) Don't try to use this method for non-nested columns! + return adaptor.getNestedData(&mColumns.at(column), mData, localIndex.first, subRow, subColumn); +} + void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index); diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index dd6213677e..d03b458143 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -65,6 +65,8 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const; + virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + virtual void setData (int index, int column, const QVariant& data); virtual void removeRows (int index, int count); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index abdc331039..4ac8e87806 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -295,7 +295,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); skip = true; - } + } //lisp cond pairs would be nice in the C++ connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); mProxys.push_back(proxy); //deleted in the destructor @@ -361,6 +361,7 @@ void CSVWorld::EditWidget::remake(int row) int unlocked = 0; int locked = 0; const int columns = mTable->columnCount(); + for (int i=0; iheaderData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); @@ -368,28 +369,35 @@ void CSVWorld::EditWidget::remake(int row) if (flags & CSMWorld::ColumnBase::Flag_Dialogue) { CSMWorld::ColumnBase::Display display = static_cast - (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); + (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - mDispatcher.makeDelegate(display); - QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i))); - - if (editor) + if (display != CSMWorld::ColumnBase::Display_Nested) { - mWidgetMapper->addMapping (editor, i); - QLabel* label = new QLabel(mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget); - label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable)) + mDispatcher.makeDelegate (display); + QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i))); + + if (editor) { - lockedLayout->addWidget (label, locked, 0); - lockedLayout->addWidget (editor, locked, 1); - ++locked; - } else - { - unlockedLayout->addWidget (label, unlocked, 0); - unlockedLayout->addWidget (editor, unlocked, 1); - ++unlocked; + mWidgetMapper->addMapping (editor, i); + QLabel* label = new QLabel (mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget); + label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + editor->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable)) + { + lockedLayout->addWidget (label, locked, 0); + lockedLayout->addWidget (editor, locked, 1); + ++locked; + } else + { + unlockedLayout->addWidget (label, unlocked, 0); + unlockedLayout->addWidget (editor, unlocked, 1); + ++unlocked; + } } + } else + { + //TODO } } } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index b2a32b551c..5fa93fe797 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -172,7 +172,8 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO display == CSMWorld::ColumnBase::Display_Class || display == CSMWorld::ColumnBase::Display_Faction || display == CSMWorld::ColumnBase::Display_Miscellaneous || - display == CSMWorld::ColumnBase::Display_Sound) + display == CSMWorld::ColumnBase::Display_Sound || + display == CSMWorld::ColumnBase::Display_Region) { return new DropLineEdit(parent); } From d2ad2e0f31fcc6b269d35e5e42de74535dd16d38 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 20:44:59 +0200 Subject: [PATCH 484/545] Re-enable collision when an actor is resurrected --- apps/openmw/mwmechanics/actors.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8dcccfdb35..3d7e7e283a 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -989,7 +989,11 @@ namespace MWMechanics if(!stats.isDead()) { if(iter->second->isDead()) + { + // Actor has been resurrected. Notify the CharacterController and re-enable collision. + MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true); iter->second->resurrect(); + } if(!stats.isDead()) continue; From 577ed3943b3f0edfd22741eaa694fe74b76bad41 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Jun 2014 23:26:43 +0200 Subject: [PATCH 485/545] Show wallpaper when loading a savegame --- apps/openmw/mwgui/loadingscreen.cpp | 22 ++++++++++--------- apps/openmw/mwgui/loadingscreen.hpp | 4 ---- apps/openmw/mwworld/scene.cpp | 4 ---- .../loadinglistener/loadinglistener.hpp | 3 --- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 7c915ebebf..f1bbc68cdf 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -11,6 +11,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/statemanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/inputmanager.hpp" @@ -26,7 +27,6 @@ namespace MWGui , WindowBase("openmw_loading_screen.layout") , mLastRenderTime(0.f) , mLastWallpaperChangeTime(0.f) - , mFirstLoad(true) , mProgress(0) , mVSyncWasEnabled(false) { @@ -77,7 +77,11 @@ namespace MWGui mWindow->setVSyncEnabled(false); #endif - if (!mFirstLoad) + bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() + == MWBase::StateManager::State_NoGame); + + + if (!showWallpaper) { mBackgroundImage->setImageTexture(""); int width = mWindow->getWidth(); @@ -103,12 +107,12 @@ namespace MWGui setVisible(true); - if (mFirstLoad) + if (showWallpaper) { changeWallpaper(); } - MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading); + MWBase::Environment::get().getWindowManager()->pushGuiMode(showWallpaper ? GM_LoadingWallpaper : GM_Loading); } void LoadingScreen::loadingOff() @@ -188,11 +192,6 @@ namespace MWGui draw(); } - void LoadingScreen::removeWallpaper() - { - mFirstLoad = false; - } - void LoadingScreen::draw() { const float loadingScreenFps = 20.f; @@ -201,7 +200,10 @@ namespace MWGui { mLastRenderTime = mTimer.getMilliseconds (); - if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1) + bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() + == MWBase::StateManager::State_NoGame); + + if (showWallpaper && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1) { mLastWallpaperChangeTime = mTimer.getMilliseconds (); changeWallpaper(); diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 96e0e1ed47..f198d625d7 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -29,8 +29,6 @@ namespace MWGui virtual void setVisible(bool visible); - virtual void removeWallpaper(); - LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw); virtual ~LoadingScreen(); @@ -42,8 +40,6 @@ namespace MWGui void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; } private: - bool mFirstLoad; - Ogre::SceneManager* mSceneMgr; Ogre::RenderWindow* mWindow; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 32bf773bd5..f753ae1f45 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -347,8 +347,6 @@ namespace MWWorld MWBase::Environment::get().getWorld()->adjustSky(); mCellChanged = true; - - loadingListener->removeWallpaper(); } //We need the ogre renderer and a scene node. @@ -449,8 +447,6 @@ namespace MWWorld mCellChanged = true; MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5); - - loadingListener->removeWallpaper(); } void Scene::changeToExteriorCell (const ESM::Position& position) diff --git a/components/loadinglistener/loadinglistener.hpp b/components/loadinglistener/loadinglistener.hpp index f6a7b71e9d..47962015c2 100644 --- a/components/loadinglistener/loadinglistener.hpp +++ b/components/loadinglistener/loadinglistener.hpp @@ -18,9 +18,6 @@ namespace Loading virtual void setProgressRange (size_t range) = 0; virtual void setProgress (size_t value) = 0; virtual void increaseProgress (size_t increase = 1) = 0; - - /// Indicate the scene is now ready to be shown - virtual void removeWallpaper() = 0; }; // Used for stopping a loading sequence when the object goes out of scope From 281d3b4c95218da2f5cee37817e89c8a697081e6 Mon Sep 17 00:00:00 2001 From: slothlife Date: Mon, 2 Jun 2014 17:21:13 -0500 Subject: [PATCH 486/545] Fix for dereferencing past end of mGuiModes. --- apps/openmw/mwgui/windowmanagerimp.cpp | 241 +++++++++++++------------ 1 file changed, 122 insertions(+), 119 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 4de3028ed4..0e4ac22a62 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -442,128 +442,131 @@ namespace MWGui return; } - GuiMode mode = mGuiModes.back(); + if(mGuiModes.size() != 0) + { + GuiMode mode = mGuiModes.back(); - switch(mode) { - case GM_QuickKeysMenu: - mQuickKeysMenu->setVisible (true); - break; - case GM_MainMenu: - mMenu->setVisible(true); - break; - case GM_Settings: - mSettingsWindow->setVisible(true); - break; - case GM_Console: - mConsole->setVisible(true); - break; - case GM_Scroll: - mScrollWindow->setVisible(true); - break; - case GM_Book: - mBookWindow->setVisible(true); - break; - case GM_Alchemy: - mAlchemyWindow->setVisible(true); - break; - case GM_Rest: - mWaitDialog->setVisible(true); - break; - case GM_RestBed: - mWaitDialog->setVisible(true); - mWaitDialog->bedActivated(); - break; - case GM_Levelup: - mLevelupDialog->setVisible(true); - break; - case GM_Name: - case GM_Race: - case GM_Class: - case GM_ClassPick: - case GM_ClassCreate: - case GM_Birth: - case GM_ClassGenerate: - case GM_Review: - mCharGen->spawnDialog(mode); - break; - case GM_Inventory: - { - // First, compute the effective set of windows to show. - // This is controlled both by what windows the - // user has opened/closed (the 'shown' variable) and by what - // windows we are allowed to show (the 'allowed' var.) - int eff = mShown & mAllowed & ~mForceHidden; + switch(mode) { + case GM_QuickKeysMenu: + mQuickKeysMenu->setVisible (true); + break; + case GM_MainMenu: + mMenu->setVisible(true); + break; + case GM_Settings: + mSettingsWindow->setVisible(true); + break; + case GM_Console: + mConsole->setVisible(true); + break; + case GM_Scroll: + mScrollWindow->setVisible(true); + break; + case GM_Book: + mBookWindow->setVisible(true); + break; + case GM_Alchemy: + mAlchemyWindow->setVisible(true); + break; + case GM_Rest: + mWaitDialog->setVisible(true); + break; + case GM_RestBed: + mWaitDialog->setVisible(true); + mWaitDialog->bedActivated(); + break; + case GM_Levelup: + mLevelupDialog->setVisible(true); + break; + case GM_Name: + case GM_Race: + case GM_Class: + case GM_ClassPick: + case GM_ClassCreate: + case GM_Birth: + case GM_ClassGenerate: + case GM_Review: + mCharGen->spawnDialog(mode); + break; + case GM_Inventory: + { + // First, compute the effective set of windows to show. + // This is controlled both by what windows the + // user has opened/closed (the 'shown' variable) and by what + // windows we are allowed to show (the 'allowed' var.) + int eff = mShown & mAllowed & ~mForceHidden; - // Show the windows we want - mMap ->setVisible(eff & GW_Map); - mStatsWindow ->setVisible(eff & GW_Stats); - mInventoryWindow->setVisible(eff & GW_Inventory); - mInventoryWindow->setGuiMode(mode); - mSpellWindow ->setVisible(eff & GW_Magic); - break; + // Show the windows we want + mMap ->setVisible(eff & GW_Map); + mStatsWindow ->setVisible(eff & GW_Stats); + mInventoryWindow->setVisible(eff & GW_Inventory); + mInventoryWindow->setGuiMode(mode); + mSpellWindow ->setVisible(eff & GW_Magic); + break; + } + case GM_Container: + mContainerWindow->setVisible(true); + mInventoryWindow->setVisible(true); + mInventoryWindow->setGuiMode(mode); + break; + case GM_Companion: + mCompanionWindow->setVisible(true); + mInventoryWindow->setVisible(true); + mInventoryWindow->setGuiMode(mode); + break; + case GM_Dialogue: + mDialogueWindow->setVisible(true); + break; + case GM_Barter: + mInventoryWindow->setVisible(true); + mInventoryWindow->setTrading(true); + mInventoryWindow->setGuiMode(mode); + mTradeWindow->setVisible(true); + break; + case GM_SpellBuying: + mSpellBuyingWindow->setVisible(true); + break; + case GM_Travel: + mTravelWindow->setVisible(true); + break; + case GM_SpellCreation: + mSpellCreationDialog->setVisible(true); + break; + case GM_Recharge: + mRecharge->setVisible(true); + break; + case GM_Enchanting: + mEnchantingDialog->setVisible(true); + break; + case GM_Training: + mTrainingWindow->setVisible(true); + break; + case GM_MerchantRepair: + mMerchantRepair->setVisible(true); + break; + case GM_Repair: + mRepair->setVisible(true); + break; + case GM_Journal: + mJournal->setVisible(true); + break; + case GM_LoadingWallpaper: + mHud->setVisible(false); + setCursorVisible(false); + break; + case GM_Loading: + // Show the pinned windows + mMap->setVisible(mMap->pinned() && !(mForceHidden & GW_Map)); + mStatsWindow->setVisible(mStatsWindow->pinned() && !(mForceHidden & GW_Stats)); + mInventoryWindow->setVisible(mInventoryWindow->pinned() && !(mForceHidden & GW_Inventory)); + mSpellWindow->setVisible(mSpellWindow->pinned() && !(mForceHidden & GW_Magic)); + + setCursorVisible(false); + break; + default: + // Unsupported mode, switch back to game + break; } - case GM_Container: - mContainerWindow->setVisible(true); - mInventoryWindow->setVisible(true); - mInventoryWindow->setGuiMode(mode); - break; - case GM_Companion: - mCompanionWindow->setVisible(true); - mInventoryWindow->setVisible(true); - mInventoryWindow->setGuiMode(mode); - break; - case GM_Dialogue: - mDialogueWindow->setVisible(true); - break; - case GM_Barter: - mInventoryWindow->setVisible(true); - mInventoryWindow->setTrading(true); - mInventoryWindow->setGuiMode(mode); - mTradeWindow->setVisible(true); - break; - case GM_SpellBuying: - mSpellBuyingWindow->setVisible(true); - break; - case GM_Travel: - mTravelWindow->setVisible(true); - break; - case GM_SpellCreation: - mSpellCreationDialog->setVisible(true); - break; - case GM_Recharge: - mRecharge->setVisible(true); - break; - case GM_Enchanting: - mEnchantingDialog->setVisible(true); - break; - case GM_Training: - mTrainingWindow->setVisible(true); - break; - case GM_MerchantRepair: - mMerchantRepair->setVisible(true); - break; - case GM_Repair: - mRepair->setVisible(true); - break; - case GM_Journal: - mJournal->setVisible(true); - break; - case GM_LoadingWallpaper: - mHud->setVisible(false); - setCursorVisible(false); - break; - case GM_Loading: - // Show the pinned windows - mMap->setVisible(mMap->pinned() && !(mForceHidden & GW_Map)); - mStatsWindow->setVisible(mStatsWindow->pinned() && !(mForceHidden & GW_Stats)); - mInventoryWindow->setVisible(mInventoryWindow->pinned() && !(mForceHidden & GW_Inventory)); - mSpellWindow->setVisible(mSpellWindow->pinned() && !(mForceHidden & GW_Magic)); - - setCursorVisible(false); - break; - default: - // Unsupported mode, switch back to game - break; } } From bbc5b125abd7ccaafe7a0ce206a7c8229685f840 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 00:16:32 +0200 Subject: [PATCH 487/545] Rewrite journal GUI quest index - Use quest names as identifiers, not quest IDs. This ensures that quests with different IDs, but the same name (e.g. A2_4_MiloCaiusGone and A2_4_MiloGone) are merged properly, as they should. - Switch display from BookPage to MWList. Handles word-wrapping and scrolling properly. - Fixes a bug where the quest index would not be updated when opened. --- apps/openmw/mwgui/journalbooks.cpp | 35 +++--------------- apps/openmw/mwgui/journalbooks.hpp | 3 +- apps/openmw/mwgui/journalviewmodel.cpp | 35 +++++++++++++----- apps/openmw/mwgui/journalviewmodel.hpp | 9 ++--- apps/openmw/mwgui/journalwindow.cpp | 50 ++++++++++++++++---------- apps/openmw/mwgui/list.cpp | 12 ++++++- apps/openmw/mwgui/list.hpp | 5 ++- files/mygui/openmw_journal.layout | 4 +-- files/mygui/openmw_journal_skin.xml | 24 +++++++++++++ files/mygui/openmw_list.skin.xml | 1 + 10 files changed, 111 insertions(+), 67 deletions(-) diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index 683fe9208f..70f1569225 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -148,22 +148,6 @@ namespace mTypesetter->lineBreak (); } }; - - struct AddQuestLink : AddContent - { - AddQuestLink (MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* style) : - AddContent (typesetter, style) - { - } - - void operator () (MWGui::JournalViewModel::QuestId id, MWGui::JournalViewModel::Utf8Span name) - { - MWGui::BookTypesetter::Style* style = mTypesetter->createHotStyle (mBodyStyle, MyGUI::Colour::Black, linkHot, linkActive, id); - - mTypesetter->write (style, name); - mTypesetter->lineBreak (); - } - }; } namespace MWGui @@ -206,7 +190,7 @@ book JournalBooks::createJournalBook () BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f)); BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black); - mModel->visitJournalEntries (0, AddJournalEntry (typesetter, body, header, true)); + mModel->visitJournalEntries ("", AddJournalEntry (typesetter, body, header, true)); return typesetter->complete (); } @@ -227,16 +211,17 @@ book JournalBooks::createTopicBook (uintptr_t topicId) return typesetter->complete (); } -book JournalBooks::createQuestBook (uintptr_t questId) +book JournalBooks::createQuestBook (const std::string& questName) { BookTypesetter::Ptr typesetter = createTypesetter (); BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f)); BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black); - mModel->visitQuestName (questId, AddQuestName (typesetter, header)); + AddQuestName addName (typesetter, header); + addName(to_utf8_span(questName.c_str())); - mModel->visitJournalEntries (questId, AddJournalEntry (typesetter, body, header, false)); + mModel->visitJournalEntries (questName, AddJournalEntry (typesetter, body, header, false)); return typesetter->complete (); } @@ -279,16 +264,6 @@ book JournalBooks::createTopicIndexBook (char character) return typesetter->complete (); } -book JournalBooks::createQuestIndexBook (bool activeOnly) -{ - BookTypesetter::Ptr typesetter = BookTypesetter::create (0x7FFFFFFF, 0x7FFFFFFF); - BookTypesetter::Style* base = typesetter->createStyle ("", MyGUI::Colour::Black); - - mModel->visitQuestNames (activeOnly, AddQuestLink (typesetter, base)); - - return typesetter->complete (); -} - BookTypesetter::Ptr JournalBooks::createTypesetter () { //TODO: determine page size from layout... diff --git a/apps/openmw/mwgui/journalbooks.hpp b/apps/openmw/mwgui/journalbooks.hpp index 819bda0fd2..6ae2ba82a0 100644 --- a/apps/openmw/mwgui/journalbooks.hpp +++ b/apps/openmw/mwgui/journalbooks.hpp @@ -18,10 +18,9 @@ namespace MWGui Book createEmptyJournalBook (); Book createJournalBook (); Book createTopicBook (uintptr_t topicId); - Book createQuestBook (uintptr_t questId); + Book createQuestBook (const std::string& questName); Book createTopicIndexBook (); Book createTopicIndexBook (char character); - Book createQuestIndexBook (bool showAll); private: BookTypesetter::Ptr createTypesetter (); diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 5994c6e211..1feb92b02e 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -195,10 +195,12 @@ struct JournalViewModelImpl : JournalViewModel }; - void visitQuestNames (bool active_only, boost::function visitor) const + void visitQuestNames (bool active_only, boost::function visitor) const { MWBase::Journal * journal = MWBase::Environment::get ().getJournal (); + std::set visitedQuests; + for (MWBase::Journal::TQuestIter i = journal->questBegin (); i != journal->questEnd (); ++i) { if (active_only && i->second.isFinished ()) @@ -209,7 +211,15 @@ struct JournalViewModelImpl : JournalViewModel // Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed // to appear in the quest book. if (!quest.getName().empty()) - visitor (reinterpret_cast (&i->second), toUtf8Span (quest.getName())); + { + // Don't list the same quest name twice + if (visitedQuests.find(quest.getName()) != visitedQuests.end()) + continue; + + visitor (quest.getName()); + + visitedQuests.insert(quest.getName()); + } } } @@ -258,20 +268,29 @@ struct JournalViewModelImpl : JournalViewModel } }; - void visitJournalEntries (QuestId questId, boost::function visitor) const + void visitJournalEntries (const std::string& questName, boost::function visitor) const { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); - if (questId != 0) + if (!questName.empty()) { - MWDialogue::Quest const * quest = reinterpret_cast (questId); + std::vector quests; + for (MWBase::Journal::TQuestIter questIt = journal->questBegin(); questIt != journal->questEnd(); ++questIt) + { + if (Misc::StringUtils::ciEqual(questIt->second.getName(), questName)) + quests.push_back(&questIt->second); + } for(MWBase::Journal::TEntryIter i = journal->begin(); i != journal->end (); ++i) { - for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j) + for (std::vector::iterator questIt = quests.begin(); questIt != quests.end(); ++questIt) { - if (i->mInfoId == j->mInfoId) - visitor (JournalEntryImpl (this, i)); + MWDialogue::Quest const* quest = *questIt; + for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j) + { + if (i->mInfoId == j->mInfoId) + visitor (JournalEntryImpl (this, i)); + } } } } diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index 9efdeae546..feb9457c64 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -70,11 +70,12 @@ namespace MWGui /// provides access to the name of the quest with the specified identifier virtual void visitQuestName (TopicId topicId, boost::function visitor) const = 0; - /// walks the active and optionally completed, quests providing the quest id and name - virtual void visitQuestNames (bool active_only, boost::function visitor) const = 0; + /// walks the active and optionally completed, quests providing the name + virtual void visitQuestNames (bool active_only, boost::function visitor) const = 0; - /// walks over the journal entries related to the specified quest identified by its id - virtual void visitJournalEntries (QuestId questId, boost::function visitor) const = 0; + /// walks over the journal entries related to all quests with the given name + /// If \a questName is empty, simply visits all journal entries + virtual void visitJournalEntries (const std::string& questName, boost::function visitor) const = 0; /// provides the name of the topic specified by its id virtual void visitTopicName (TopicId topicId, boost::function visitor) const = 0; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index f3c9e9c73a..0940b7fefa 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -19,6 +19,7 @@ #include "imagebutton.hpp" #include "journalviewmodel.hpp" #include "journalbooks.hpp" +#include "list.hpp" namespace { @@ -38,7 +39,6 @@ namespace static char const TopicsList [] = "TopicsList"; static char const TopicsPage [] = "TopicsPage"; static char const QuestsList [] = "QuestsList"; - static char const QuestsPage [] = "QuestsPage"; static char const LeftBookPage [] = "LeftBookPage"; static char const RightBookPage [] = "RightBookPage"; static char const LeftTopicIndex [] = "LeftTopicIndex"; @@ -110,6 +110,9 @@ namespace adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll ); adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive); + MWGui::Widgets::MWList* list = getWidget(QuestsList); + list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked); + { MWGui::BookPage::ClickCallback callback; @@ -129,14 +132,6 @@ namespace getPage (RightTopicIndex)->adviseLinkClicked (callback); } - { - MWGui::BookPage::ClickCallback callback; - - callback = boost::bind (&JournalWindowImpl::notifyQuestClicked, this, _1); - - getPage (QuestsPage)->adviseLinkClicked (callback); - } - adjustButton(OptionsBTN, true); adjustButton(PrevPageBTN); adjustButton(NextPageBTN); @@ -271,6 +266,10 @@ namespace //TODO: figure out how to make "options" page overlay book page // correctly, so that text may show underneath getPage (RightBookPage)->showPage (Book (), 0); + + // If in quest mode, ensure the quest list is updated + if (mQuestMode) + notifyQuests(getWidget(QuestsList)); } void pushBook (Book book, unsigned int page) @@ -349,9 +348,9 @@ namespace setVisible (JournalBTN, true); } - void notifyQuestClicked (intptr_t questId) + void notifyQuestClicked (const std::string& name, int id) { - Book book = createQuestBook (questId); + Book book = createQuestBook (name); if (mStates.size () > 1) replaceBook (book, 0); @@ -409,9 +408,21 @@ namespace setVisible (ShowActiveBTN, false); } + struct AddQuestNamesToList + { + AddQuestNamesToList(MWGui::Widgets::MWList* list) : mList(list) {} + + MWGui::Widgets::MWList* mList; + void operator () (const std::string& name) + { + mList->addItem(name); + } + }; + void notifyQuests(MyGUI::Widget* _sender) { mQuestMode = true; + setVisible (LeftTopicIndex, false); setVisible (RightTopicIndex, false); setVisible (TopicsList, false); @@ -419,23 +430,26 @@ namespace setVisible (ShowAllBTN, !mAllQuests); setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + MWGui::Widgets::MWList* list = getWidget(QuestsList); + list->clear(); + + AddQuestNamesToList add(list); + + mModel->visitQuestNames(!mAllQuests, add); + + list->adjustSize(); } void notifyShowAll(MyGUI::Widget* _sender) { mAllQuests = true; - setVisible (ShowAllBTN, !mAllQuests); - setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + notifyQuests(_sender); } void notifyShowActive(MyGUI::Widget* _sender) { mAllQuests = false; - setVisible (ShowAllBTN, !mAllQuests); - setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + notifyQuests(_sender); } void notifyCancel(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index 19f20eeee7..ca2989646c 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -65,8 +65,10 @@ namespace MWGui { if (*it != "") { + if (mListItemSkin.empty()) + throw std::runtime_error("MWList needs a ListItemSkin property"); MyGUI::Button* button = mScrollView->createWidget( - "MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), + mListItemSkin, MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it)); button->setCaption((*it)); button->getSubWidgetText()->setWordWrap(true); @@ -102,6 +104,14 @@ namespace MWGui mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition)); } + void MWList::setPropertyOverride(const std::string &_key, const std::string &_value) + { + if (_key == "ListItemSkin") + mListItemSkin = _value; + else + Base::setPropertyOverride(_key, _value); + } + bool MWList::hasItem(const std::string& name) { return (std::find(mItems.begin(), mItems.end(), name) != mItems.end()); diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index dcfe7931a0..acf078a2c2 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -22,7 +22,7 @@ namespace MWGui /** * Event: Item selected with the mouse. - * signature: void method(std::string itemName) + * signature: void method(std::string itemName, int index) */ EventHandle_StringInt eventItemSelected; @@ -49,6 +49,8 @@ namespace MWGui MyGUI::Widget* getItemWidget(const std::string& name); ///< get widget for an item name, useful to set up tooltip + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); + protected: void initialiseOverride(); @@ -60,6 +62,7 @@ namespace MWGui private: MyGUI::ScrollView* mScrollView; MyGUI::Widget* mClient; + std::string mListItemSkin; std::vector mItems; diff --git a/files/mygui/openmw_journal.layout b/files/mygui/openmw_journal.layout index 34421d4313..c460aa41ad 100644 --- a/files/mygui/openmw_journal.layout +++ b/files/mygui/openmw_journal.layout @@ -82,9 +82,7 @@ - - - + diff --git a/files/mygui/openmw_journal_skin.xml b/files/mygui/openmw_journal_skin.xml index ca6d309d79..71a2a7865b 100644 --- a/files/mygui/openmw_journal_skin.xml +++ b/files/mygui/openmw_journal_skin.xml @@ -12,4 +12,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 4dbc3da45c..b2f9c1bef6 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -157,6 +157,7 @@ + From d777739425772b9a16a880e1daac5b96c3f510d4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 00:44:32 +0200 Subject: [PATCH 488/545] Fix a crash on exit when projectiles were active --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 548a871ce1..52ca17314e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -368,6 +368,9 @@ namespace MWWorld World::~World() { + // Must be cleared before mRendering is destroyed + mProjectileManager->clear(); + delete mWeatherManager; delete mWorldScene; delete mRendering; From 17b15a6f4f69330669d82007d79340cbe0338852 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 01:12:31 +0200 Subject: [PATCH 489/545] Fix overlapping text in SpellWindow when the window is too small --- apps/openmw/mwgui/spellwindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index fb5a80cc7d..77da56fa4f 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -190,6 +190,7 @@ namespace MWGui costChance->setNeedMouseFocus(false); costChance->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell()); + t->setSize(mWidth-12-costChance->getTextSize().width, t->getHeight()); mHeight += spellHeight; } @@ -255,6 +256,8 @@ namespace MWGui if (store.getSelectedEnchantItem() != store.end()) costCharge->setStateSelected(item == *store.getSelectedEnchantItem()); + t->setSize(mWidth-12-costCharge->getTextSize().width, t->getHeight()); + mHeight += spellHeight; } @@ -287,6 +290,8 @@ namespace MWGui groupWidget2->setCaptionWithReplacing(label2); groupWidget2->setTextAlign(MyGUI::Align::Right); groupWidget2->setNeedMouseFocus(false); + + groupWidget->setSize(mWidth-8-groupWidget2->getTextSize().width, groupWidget->getHeight()); } mHeight += 24; From d7f3cd75ac736f93e1fd9a251e073a26bd35e47f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 16:04:18 +0200 Subject: [PATCH 490/545] Rewrite journal GUI topic list to use MWList --- apps/openmw/mwgui/journalbooks.cpp | 10 -------- apps/openmw/mwgui/journalbooks.hpp | 2 +- apps/openmw/mwgui/journalviewmodel.cpp | 4 +-- apps/openmw/mwgui/journalviewmodel.hpp | 4 +-- apps/openmw/mwgui/journalwindow.cpp | 34 +++++++++++++++++++++----- files/mygui/openmw_journal.layout | 4 +-- 6 files changed, 34 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index 70f1569225..7ffe9e6a42 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -254,16 +254,6 @@ book JournalBooks::createTopicIndexBook () return typesetter->complete (); } -book JournalBooks::createTopicIndexBook (char character) -{ - BookTypesetter::Ptr typesetter = BookTypesetter::create (0x7FFFFFFF, 0x7FFFFFFF); - BookTypesetter::Style* style = typesetter->createStyle ("", MyGUI::Colour::Black); - - mModel->visitTopicNamesStartingWith (character, AddTopicLink (typesetter, style)); - - return typesetter->complete (); -} - BookTypesetter::Ptr JournalBooks::createTypesetter () { //TODO: determine page size from layout... diff --git a/apps/openmw/mwgui/journalbooks.hpp b/apps/openmw/mwgui/journalbooks.hpp index 6ae2ba82a0..8f87825f09 100644 --- a/apps/openmw/mwgui/journalbooks.hpp +++ b/apps/openmw/mwgui/journalbooks.hpp @@ -18,9 +18,9 @@ namespace MWGui Book createEmptyJournalBook (); Book createJournalBook (); Book createTopicBook (uintptr_t topicId); + Book createTopicBook (const std::string& topicId); Book createQuestBook (const std::string& questName); Book createTopicIndexBook (); - Book createTopicIndexBook (char character); private: BookTypesetter::Ptr createTypesetter (); diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 1feb92b02e..b9ddb7daa9 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -312,7 +312,7 @@ struct JournalViewModelImpl : JournalViewModel visitor (toUtf8Span (topic.getName())); } - void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const + void visitTopicNamesStartingWith (char character, boost::function < void (const std::string&) > visitor) const { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); @@ -321,7 +321,7 @@ struct JournalViewModelImpl : JournalViewModel if (i->first [0] != std::tolower (character, mLocale)) continue; - visitor (TopicId (&i->second), toUtf8Span (i->second.getName())); + visitor (i->second.getName()); } } diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index feb9457c64..4b827d1aba 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -80,8 +80,8 @@ namespace MWGui /// provides the name of the topic specified by its id virtual void visitTopicName (TopicId topicId, boost::function visitor) const = 0; - /// walks over the topics whose names start with the specified character providing the topics id and name - virtual void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const = 0; + /// walks over the topics whose names start with the specified character providing the topics name + virtual void visitTopicNamesStartingWith (char character, boost::function < void (const std::string&) > visitor) const = 0; /// walks over the topic entries for the topic specified by its identifier virtual void visitTopicEntries (TopicId topicId, boost::function visitor) const = 0; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 0940b7fefa..fa27b4ef06 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -3,6 +3,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/journal.hpp" #include "list.hpp" #include @@ -37,7 +38,6 @@ namespace static char const PageOneNum [] = "PageOneNum"; static char const PageTwoNum [] = "PageTwoNum"; static char const TopicsList [] = "TopicsList"; - static char const TopicsPage [] = "TopicsPage"; static char const QuestsList [] = "QuestsList"; static char const LeftBookPage [] = "LeftBookPage"; static char const RightBookPage [] = "RightBookPage"; @@ -113,12 +113,14 @@ namespace MWGui::Widgets::MWList* list = getWidget(QuestsList); list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked); + MWGui::Widgets::MWList* topicsList = getWidget(TopicsList); + topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected); + { MWGui::BookPage::ClickCallback callback; callback = boost::bind (&JournalWindowImpl::notifyTopicClicked, this, _1); - getPage (TopicsPage)->adviseLinkClicked (callback); getPage (LeftBookPage)->adviseLinkClicked (callback); getPage (RightBookPage)->adviseLinkClicked (callback); } @@ -348,6 +350,19 @@ namespace setVisible (JournalBTN, true); } + void notifyTopicSelected (const std::string& topic, int id) + { + const MWBase::Journal* journal = MWBase::Environment::get().getJournal(); + intptr_t topicId = 0; /// \todo get rid of intptr ids + for(MWBase::Journal::TTopicIter i = journal->topicBegin(); i != journal->topicEnd (); ++i) + { + if (Misc::StringUtils::ciEqual(i->first, topic)) + topicId = intptr_t (&i->second); + } + + notifyTopicClicked(topicId); + } + void notifyQuestClicked (const std::string& name, int id) { Book book = createQuestBook (name); @@ -394,7 +409,14 @@ namespace setVisible (RightTopicIndex, false); setVisible (TopicsList, true); - showList (TopicsList, TopicsPage, createTopicIndexBook ((char)character)); + MWGui::Widgets::MWList* list = getWidget(TopicsList); + list->clear(); + + AddNamesToList add(list); + + mModel->visitTopicNamesStartingWith((char) character, add); + + list->adjustSize(); } void notifyTopics(MyGUI::Widget* _sender) @@ -408,9 +430,9 @@ namespace setVisible (ShowActiveBTN, false); } - struct AddQuestNamesToList + struct AddNamesToList { - AddQuestNamesToList(MWGui::Widgets::MWList* list) : mList(list) {} + AddNamesToList(MWGui::Widgets::MWList* list) : mList(list) {} MWGui::Widgets::MWList* mList; void operator () (const std::string& name) @@ -433,7 +455,7 @@ namespace MWGui::Widgets::MWList* list = getWidget(QuestsList); list->clear(); - AddQuestNamesToList add(list); + AddNamesToList add(list); mModel->visitQuestNames(!mAllQuests, add); diff --git a/files/mygui/openmw_journal.layout b/files/mygui/openmw_journal.layout index c460aa41ad..5524f55202 100644 --- a/files/mygui/openmw_journal.layout +++ b/files/mygui/openmw_journal.layout @@ -77,9 +77,7 @@ - - - + From ce14a6413b8f9b3dc2066815e86abc1c4506895a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 22:35:26 +0200 Subject: [PATCH 491/545] Small optimization to ESM::Variant --- components/esm/variant.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp index a7859d1283..217ec4407e 100644 --- a/components/esm/variant.cpp +++ b/components/esm/variant.cpp @@ -6,6 +6,15 @@ #include "esmreader.hpp" #include "variantimp.hpp" +#include "defs.hpp" + +namespace +{ + const uint32_t STRV = ESM::FourCC<'S','T','R','V'>::value; + const uint32_t INTV = ESM::FourCC<'I','N','T','V'>::value; + const uint32_t FLTV = ESM::FourCC<'F','L','T','V'>::value; +} + ESM::Variant::Variant() : mType (VT_None), mData (0) {} ESM::Variant::~Variant() @@ -90,15 +99,17 @@ void ESM::Variant::read (ESMReader& esm, Format format) esm.getSubName(); NAME name = esm.retSubName(); - if (name=="STRV") + + + if (name==STRV) { type = VT_String; } - else if (name=="INTV") + else if (name==INTV) { type = VT_Int; } - else if (name=="FLTV") + else if (name==FLTV) { type = VT_Float; } @@ -111,11 +122,11 @@ void ESM::Variant::read (ESMReader& esm, Format format) esm.getSubName(); NAME name = esm.retSubName(); - if (name=="INTV") + if (name==INTV) { type = VT_Int; } - else if (name=="FLTV") + else if (name==FLTV) { type = VT_Float; } @@ -279,4 +290,4 @@ bool ESM::operator== (const Variant& left, const Variant& right) bool ESM::operator!= (const Variant& left, const Variant& right) { return !(left==right); -} \ No newline at end of file +} From 7376cb9b61f63a1f9f02c31227faeca96abcbd9f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Jun 2014 22:49:37 +0200 Subject: [PATCH 492/545] Fix loading ESX files cleaned with testool (Fixes #1382) --- components/esm/loadregn.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/components/esm/loadregn.cpp b/components/esm/loadregn.cpp index da03e009f2..0c3ccbffbf 100644 --- a/components/esm/loadregn.cpp +++ b/components/esm/loadregn.cpp @@ -12,10 +12,26 @@ void Region::load(ESMReader &esm) { mName = esm.getHNOString("FNAM"); + esm.getSubNameIs("WEAT"); + esm.getSubHeader(); if (esm.getVer() == VER_12) - esm.getHNExact(&mData, sizeof(mData) - 2, "WEAT"); + { + mData.mA = 0; + mData.mB = 0; + esm.getExact(&mData, sizeof(mData) - 2); + } else if (esm.getVer() == VER_13) - esm.getHNExact(&mData, sizeof(mData), "WEAT"); + { + // May include the additional two bytes (but not necessarily) + if (esm.getSubSize() == sizeof(mData)) + esm.getExact(&mData, sizeof(mData)); + else + { + mData.mA = 0; + mData.mB = 0; + esm.getExact(&mData, sizeof(mData)-2); + } + } else esm.fail("Don't know what to do in this version"); From 00775035af1fbf562b1a6d4e4735ce352c0974ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 4 Jun 2014 01:03:12 +0200 Subject: [PATCH 493/545] Add missing hasItemHealth for lockpicks/probes (Fixes #1385) --- apps/openmw/mwclass/lockpick.hpp | 3 +++ apps/openmw/mwclass/probe.hpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index a7cf3791fc..8f5a699d9d 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -64,6 +64,9 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const { return true; } + ///< \return Item health data available? (default implementation: false) }; } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 832169f8b7..a959e6c42e 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -64,6 +64,9 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const { return true; } + ///< \return Item health data available? (default implementation: false) }; } From c4e738677032425b6dcc0daf2db78cb6b081e5c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 4 Jun 2014 21:12:23 +0200 Subject: [PATCH 494/545] Revert "added changed reference tracking for cells" This reverts commit f4334da42ec0076c073aed1a3aec6a4a17f1ba5a. --- apps/opencs/model/world/cell.hpp | 7 ++-- apps/opencs/model/world/columnimp.hpp | 40 ----------------------- apps/opencs/model/world/refcollection.cpp | 6 ---- 3 files changed, 2 insertions(+), 51 deletions(-) diff --git a/apps/opencs/model/world/cell.hpp b/apps/opencs/model/world/cell.hpp index 8a2781590d..a47dbf45df 100644 --- a/apps/opencs/model/world/cell.hpp +++ b/apps/opencs/model/world/cell.hpp @@ -1,7 +1,7 @@ #ifndef CSM_WOLRD_CELL_H #define CSM_WOLRD_CELL_H -#include +#include #include #include @@ -16,11 +16,8 @@ namespace CSMWorld { std::string mId; - /// These are the references modified by the edited content file. These are stored in - /// mModified only. - std::set mTouchedRefs; - void load (ESM::ESMReader &esm); + }; } diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6b276d1517..6976b454d9 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -10,7 +10,6 @@ #include "columnbase.hpp" #include "columns.hpp" #include "info.hpp" -#include "cell.hpp" namespace CSMWorld { @@ -88,45 +87,6 @@ namespace CSMWorld } }; - /// \brief Specialisation that takes care of the modified reference tracking - template<> - struct RecordStateColumn : public Column - { - RecordStateColumn() - : Column (Columns::ColumnId_Modification, ColumnBase::Display_RecordState) - {} - - virtual QVariant get (const Record& record) const - { - if (record.mState==Record::State_Erased) - return static_cast (Record::State_Deleted); - - if (!record.mModified.mTouchedRefs.empty() && - !record.mState==Record::State_Deleted && - !record.mState==Record::State_ModifiedOnly) - { - static_cast (Record::State_Modified); - } - - return static_cast (record.mState); - } - - virtual void set (Record& record, const QVariant& data) - { - record.mState = static_cast (data.toInt()); - } - - virtual bool isEditable() const - { - return true; - } - - virtual bool isUserEditable() const - { - return false; - } - }; - template struct FixedRecordTypeColumn : public Column { diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 36518f0fa4..c516e2c3ec 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -53,8 +53,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool } else { - cell.mModified.mTouchedRefs.insert (Misc::StringUtils::lowerCase ( - mCells.getId (cellIndex))); record.mState = RecordBase::State_Deleted; setRecord (index, record); } @@ -62,10 +60,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - if (!base) - cell.mModified.mTouchedRefs.insert (Misc::StringUtils::lowerCase ( - mCells.getId (cellIndex))); - if (iter==cache.end()) { // new reference From a28a2bc2fe256ef5626701eab7c205a1ea720c9e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Jun 2014 10:28:10 +0200 Subject: [PATCH 495/545] simplified feature management for record tables --- apps/opencs/model/world/data.cpp | 10 +++--- apps/opencs/model/world/idtable.cpp | 23 ++++---------- apps/opencs/model/world/idtable.hpp | 36 ++++++++++------------ apps/opencs/view/world/dialoguesubview.cpp | 7 +++-- apps/opencs/view/world/table.cpp | 8 ++--- 5 files changed, 35 insertions(+), 49 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 442e73e511..f448f5bfa1 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -248,12 +248,12 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding) addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell); addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic); addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal); - addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); - addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo); - addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell); - addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true), + addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); + addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo); + addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cells, UniversalId::Type_Cell); + addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), UniversalId::Type_Referenceables, UniversalId::Type_Referenceable); - addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false); + addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_References, UniversalId::Type_Reference, false); addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false); } diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 50998c36f1..a481ce143a 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -4,9 +4,8 @@ #include "collectionbase.hpp" #include "columnbase.hpp" -CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering, - Viewing viewing, bool preview) -: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview) +CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features) +: mIdCollection (idCollection), mFeatures (features) {} CSMWorld::IdTable::~IdTable() @@ -186,19 +185,9 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector& newO index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1)); } -CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const +unsigned int CSMWorld::IdTable::getFeatures() const { - return mReordering; -} - -CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const -{ - return mViewing; -} - -bool CSMWorld::IdTable::hasPreview() const -{ - return mPreview; + return mFeatures; } std::pair CSMWorld::IdTable::view (int row) const @@ -206,7 +195,7 @@ std::pair CSMWorld::IdTable::view (int row) std::string id; std::string hint; - if (mViewing==Viewing_Cell) + if (mFeatures & Feature_ViewCell) { int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell); int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id); @@ -217,7 +206,7 @@ std::pair CSMWorld::IdTable::view (int row) hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData()); } } - else if (mViewing==Viewing_Id) + else if (mFeatures & Feature_ViewId) { int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id); diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 8b54628256..5500d40b8a 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -19,26 +19,27 @@ namespace CSMWorld public: - enum Reordering + enum Features { - Reordering_None, - Reordering_WithinTopic - }; + Feature_ReorderWithinTopic = 1, - enum Viewing - { - Viewing_None, - Viewing_Id, // use ID column to generate view request (ID is transformed into - // worldspace and original ID is passed as hint with c: prefix) - Viewing_Cell // use cell column to generate view request (cell ID is transformed - // into worldspace and record ID is passed as hint with r: prefix) + /// Use ID column to generate view request (ID is transformed into + /// worldspace and original ID is passed as hint with c: prefix). + Feature_ViewId = 2, + + /// Use cell column to generate view request (cell ID is transformed + /// into worldspace and record ID is passed as hint with r: prefix). + Feature_ViewCell = 4, + + Feature_View = Feature_ViewId | Feature_ViewCell, + + Feature_Preview = 8 }; private: CollectionBase *mIdCollection; - Reordering mReordering; - Viewing mViewing; + unsigned int mFeatures; bool mPreview; // not implemented @@ -47,8 +48,7 @@ namespace CSMWorld public: - IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None, - Viewing viewing = Viewing_None, bool preview = false); + IdTable (CollectionBase *idCollection, unsigned int features = 0); ///< The ownership of \a idCollection is not transferred. virtual ~IdTable(); @@ -97,11 +97,7 @@ namespace CSMWorld ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). - Reordering getReordering() const; - - Viewing getViewing() const; - - bool hasPreview() const; + unsigned int getFeatures() const; std::pair view (int row) const; ///< Return the UniversalId and the hint for viewing \a row. If viewing is not diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index d03bf3f80e..6b57f26855 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -440,7 +440,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM QToolButton* revertButton = new QToolButton(mainWidget); revertButton->setIcon(QIcon(":/edit-undo.png")); - if (mTable->hasPreview()) + if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview) { QToolButton* previewButton = new QToolButton(mainWidget); previewButton->setIcon(QIcon(":/edit-preview.png")); @@ -448,7 +448,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); } - if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None) + if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View) { QToolButton* viewButton = new QToolButton(mainWidget); viewButton->setIcon(QIcon(":/cell.png")); @@ -671,7 +671,8 @@ void CSVWorld::DialogueSubView::cloneRequest () void CSVWorld::DialogueSubView::showPreview () { - if (mTable->hasPreview() && mRow < mTable->rowCount()) + if ((mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview) && + mRow < mTable->rowCount()) { emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()), ""); } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 3d4b02c9cc..912cd2183e 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -46,14 +46,14 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) /// \todo Reverting temporarily disabled on tables that support reordering, because /// revert logic currently can not handle reordering. - if (mModel->getReordering()==CSMWorld::IdTable::Reordering_None) + if (!(mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)) if (listRevertableSelectedIds().size()>0) menu.addAction (mRevertAction); if (listDeletableSelectedIds().size()>0) menu.addAction (mDeleteAction); - if (mModel->getReordering()==CSMWorld::IdTable::Reordering_WithinTopic) + if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic) { /// \todo allow reordering of multiple rows if (selectedRows.size()==1) @@ -85,7 +85,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) if (selectedRows.size()==1) { - if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None) + if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View) { int row = selectedRows.begin()->row(); @@ -101,7 +101,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) menu.addAction (mViewAction); } - if (mModel->hasPreview()) + if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview) menu.addAction (mPreviewAction); } From 1b9b275f30f105ea69bceec1f944b6a5afbb6147 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Jun 2014 13:39:56 +0200 Subject: [PATCH 496/545] fix for bug #1369 --- apps/opencs/model/world/refidcollection.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index f515e34d8e..cb2027880c 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -304,10 +304,17 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float)); weaponColumns.mReach = &mColumns.back(); - for (int i=0; i<6; ++i) + for (int i=0; i<3; ++i) { - mColumns.push_back (RefIdColumn (Columns::ColumnId_MinChop + i, ColumnBase::Display_Integer)); - weaponColumns.mChop[i] = &mColumns.back(); + const RefIdColumn **column = + i==0 ? weaponColumns.mChop : (i==1 ? weaponColumns.mSlash : weaponColumns.mThrust); + + for (int j=0; j<2; ++j) + { + mColumns.push_back ( + RefIdColumn (Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer)); + column[j] = &mColumns.back(); + } } static const struct From c0f1449004c8a609d50e5f94f0192831d3b58c0d Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 14:54:07 +0200 Subject: [PATCH 497/545] Cycle with equipped items if all slots are occupied (Fixes #1395) --- apps/openmw/mwworld/actionequip.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 05677cdc7f..50da1e5e5d 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -41,6 +41,8 @@ namespace MWWorld // slots that this item can be equipped in std::pair, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget()); + if (slots_.first.empty()) + return; // retrieve ContainerStoreIterator to the item MWWorld::ContainerStoreIterator it = invStore.begin(); @@ -55,20 +57,13 @@ namespace MWWorld assert(it != invStore.end()); // equip the item in the first free slot - for (std::vector::const_iterator slot=slots_.first.begin(); - slot!=slots_.first.end(); ++slot) + std::vector::const_iterator slot=slots_.first.begin(); + for (;slot!=slots_.first.end(); ++slot) { // if the item is equipped already, nothing to do if (invStore.getSlot(*slot) == it) return; - // if all slots are occupied, replace the last slot - if (slot == --slots_.first.end()) - { - invStore.equip(*slot, it, actor); - break; - } - if (invStore.getSlot(*slot) == invStore.end()) { // slot is not occupied @@ -76,5 +71,19 @@ namespace MWWorld break; } } + + // all slots are occupied -> cycle + // move all slots one towards begin(), then equip the item in the slot that is now free + if (slot == slots_.first.end()) + { + for (slot=slots_.first.begin();slot!=slots_.first.end(); ++slot) + { + invStore.unequipSlot(*slot, actor); + if (slot+1 != slots_.first.end()) + invStore.equip(*slot, invStore.getSlot(*(slot+1)), actor); + else + invStore.equip(*slot, it, actor); + } + } } } From cefa20bfb94a8d5d8301bdc0f8aca5109a655c53 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 15:39:08 +0200 Subject: [PATCH 498/545] Fix not reacting to quit request while video is playing --- apps/openmw/mwgui/videowidget.cpp | 5 +++++ apps/openmw/mwgui/videowidget.hpp | 3 +++ apps/openmw/mwgui/windowmanagerimp.cpp | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp index 566c7cadbb..8430c1c7bc 100644 --- a/apps/openmw/mwgui/videowidget.cpp +++ b/apps/openmw/mwgui/videowidget.cpp @@ -42,4 +42,9 @@ bool VideoWidget::update() return mPlayer.isPlaying(); } +void VideoWidget::cleanup() +{ + mPlayer.close(); +} + } diff --git a/apps/openmw/mwgui/videowidget.hpp b/apps/openmw/mwgui/videowidget.hpp index 16a71d367d..9360c8359f 100644 --- a/apps/openmw/mwgui/videowidget.hpp +++ b/apps/openmw/mwgui/videowidget.hpp @@ -26,6 +26,9 @@ namespace MWGui /// @return Is the video still playing? bool update(); + /// Free video player resources (done automatically on destruction) + void cleanup(); + private: bool mAllowSkipping; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 4de3028ed4..94001d8777 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1576,12 +1576,13 @@ namespace MWGui bool cursorWasVisible = mCursorVisible; setCursorVisible(false); - while (mVideoWidget->update()) + while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) { MWBase::Environment::get().getInputManager()->update(0, true, false); mRendering->getWindow()->update(); } + mVideoWidget->cleanup(); setCursorVisible(cursorWasVisible); From 85c98711788cc68c8c1a787043b3e9c8b80152d7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 16:15:47 +0200 Subject: [PATCH 499/545] Use question mark for not found glyphs in the font --- apps/openmw/mwgui/fontloader.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/fontloader.cpp b/apps/openmw/mwgui/fontloader.cpp index 59c2e7ca68..13270b797e 100644 --- a/apps/openmw/mwgui/fontloader.cpp +++ b/apps/openmw/mwgui/fontloader.cpp @@ -265,18 +265,30 @@ namespace MWGui cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + MyGUI::utility::toString((fontSize-data[i].ascent))); } + + // Question mark, use for NotDefined marker (used for glyphs not existing in the font) + if (i == 63) + { + MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code"); + cursorCode->addAttribute("index", MyGUI::FontCodeType::NotDefined); + cursorCode->addAttribute("coord", MyGUI::utility::toString(x1) + " " + + MyGUI::utility::toString(y1) + " " + + MyGUI::utility::toString(w) + " " + + MyGUI::utility::toString(h)); + cursorCode->addAttribute("advance", data[i].width); + cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + + MyGUI::utility::toString((fontSize-data[i].ascent))); + } } // These are required as well, but the fonts don't provide them - for (int i=0; i<3; ++i) + for (int i=0; i<2; ++i) { MyGUI::FontCodeType::Enum type; if(i == 0) type = MyGUI::FontCodeType::Selected; else if (i == 1) type = MyGUI::FontCodeType::SelectedBack; - else if (i == 2) - type = MyGUI::FontCodeType::NotDefined; MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code"); cursorCode->addAttribute("index", type); From 4e235516c3811f1b2f3125ff7b52e160de73257f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 16:16:16 +0200 Subject: [PATCH 500/545] Work around missing character in french morrowind font (Bug #1390) --- apps/openmw/mwgui/fontloader.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/fontloader.cpp b/apps/openmw/mwgui/fontloader.cpp index 13270b797e..9d47bc38d1 100644 --- a/apps/openmw/mwgui/fontloader.cpp +++ b/apps/openmw/mwgui/fontloader.cpp @@ -64,10 +64,15 @@ namespace return unicode; } + // getUtf8, aka the worst function ever written. + // This includes various hacks for dealing with Morrowind's .fnt files that are *mostly* + // in the expected win12XX encoding, but also have randomly swapped characters sometimes. + // Looks like the Morrowind developers found standard encodings too boring and threw in some twists for fun. std::string getUtf8 (unsigned char c, ToUTF8::Utf8Encoder& encoder, ToUTF8::FromType encoding) { if (encoding == ToUTF8::WINDOWS_1250) { + // Hacks for polish font unsigned char win1250; std::map conv; conv[0x80] = 0xc6; @@ -101,7 +106,8 @@ namespace conv[0xa3] = 0xbf; conv[0xa4] = 0x0; // not contained in win1250 conv[0xe1] = 0x8c; - conv[0xe1] = 0x8c; + // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? + //conv[0xe1] = 0x8c; conv[0xe3] = 0x0; // not contained in win1250 conv[0xf5] = 0x0; // not contained in win1250 @@ -252,6 +258,21 @@ namespace MWGui code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + MyGUI::utility::toString((fontSize-data[i].ascent))); + // More hacks! The french game uses U+2019, which is nowhere to be found in + // the CP437 encoding of the font. Fall back to 39 (regular apostrophe) + if (i == 39 && mEncoding == ToUTF8::CP437) + { + MyGUI::xml::ElementPtr code = codes->createChild("Code"); + code->addAttribute("index", 0x2019); + code->addAttribute("coord", MyGUI::utility::toString(x1) + " " + + MyGUI::utility::toString(y1) + " " + + MyGUI::utility::toString(w) + " " + + MyGUI::utility::toString(h)); + code->addAttribute("advance", data[i].width); + code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + + MyGUI::utility::toString((fontSize-data[i].ascent))); + } + // ASCII vertical bar, use this as text input cursor if (i == 124) { From b6e52ae8ab53b89635928b9def716c0b51fa0f1c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 17:01:22 +0200 Subject: [PATCH 501/545] Fix crash when loading a savegame after dying (Fixes #1389) --- apps/openmw/mwworld/worldimp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 52ca17314e..5cde556ec1 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1851,7 +1851,12 @@ namespace MWWorld if (!mPlayer) mPlayer = new MWWorld::Player(player, *this); else + { + // Remove the old CharacterController + MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr()); + mPlayer->set(player); + } Ptr ptr = mPlayer->getPlayer(); mRendering->setupPlayer(ptr); From d2e98c4de1732107a75ee93690eea4a995987b73 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 17:21:02 +0200 Subject: [PATCH 502/545] Fix forced switch to third person on death not always working For instance, when dying from fall damage --- apps/openmw/mwmechanics/character.cpp | 7 +++++++ apps/openmw/mwrender/camera.cpp | 4 ++-- apps/openmw/mwrender/camera.hpp | 3 ++- apps/openmw/mwstate/statemanagerimp.cpp | 1 - apps/openmw/mwworld/worldimp.cpp | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c9da912dd2..db4e599291 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -409,6 +409,13 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I void CharacterController::playDeath(float startpoint, CharacterState death) { + if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) + { + // The first-person animations do not include death, so we need to + // force-switch to third person before playing the death animation. + MWBase::Environment::get().getWorld()->useDeathCamera(); + } + switch (death) { case CharState_SwimDeath: diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 2942649512..9e683cc159 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -140,11 +140,11 @@ namespace MWRender } } - void Camera::toggleViewMode() + void Camera::toggleViewMode(bool force) { // Changing the view will stop all playing animations, so if we are playing // anything important, queue the view change for later - if (!mAnimation->allowSwitchViewMode()) + if (!mAnimation->allowSwitchViewMode() && !force) { mViewModeToggleQueued = true; return; diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 808f817cf5..1e86bfb481 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -75,7 +75,8 @@ namespace MWRender /// Attach camera to object void attachTo(const MWWorld::Ptr &); - void toggleViewMode(); + /// @param Force view mode switch, even if currently not allowed by the animation. + void toggleViewMode(bool force=false); bool toggleVanityMode(bool enable); void allowVanityMode(bool allow); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 29b5318d74..0e56365d60 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -144,7 +144,6 @@ void MWState::StateManager::newGame (bool bypass) void MWState::StateManager::endGame() { mState = State_Ended; - MWBase::Environment::get().getWorld()->useDeathCamera(); } void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5cde556ec1..2bd835561d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -432,7 +432,7 @@ namespace MWWorld mRendering->getCamera()->toggleVanityMode(false); } if(mRendering->getCamera()->isFirstPerson()) - togglePOV(); + mRendering->getCamera()->toggleViewMode(true); } MWWorld::Player& World::getPlayer() From 17f8b49db640f3739c613c3eac40fb7bdd197ff1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 17:43:12 +0200 Subject: [PATCH 503/545] Add missing padding for item tooltip magic effects --- apps/openmw/mwgui/tooltips.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index aeb79a9381..faa3f5befd 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -400,7 +400,7 @@ namespace MWGui if (!info.effects.empty()) { MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget("", - MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height), + MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height), MyGUI::Align::Stretch, "ToolTipEffectArea"); MyGUI::IntCoord coord(0, 6, totalSize.width, 24); @@ -419,7 +419,7 @@ namespace MWGui { assert(enchant); MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget("", - MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height), + MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height), MyGUI::Align::Stretch, "ToolTipEnchantArea"); MyGUI::IntCoord coord(0, 6, totalSize.width, 24); From 1173957e563ea49bc94f0babcd7bfa833b3f880f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 18:15:48 +0200 Subject: [PATCH 504/545] Fix item weight displaying as 1e+3 for Stendarr's Hammer --- apps/openmw/mwgui/tooltips.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index faa3f5befd..16b010908a 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -512,7 +512,11 @@ namespace MWGui std::string ToolTips::toString(const float value) { std::ostringstream stream; - stream << std::setprecision(3) << value; + + if (value != int(value)) + stream << std::setprecision(3); + + stream << value; return stream.str(); } From e772bb88da9ddb977844116286fb827bf33a8664 Mon Sep 17 00:00:00 2001 From: dreamer-dead Date: Thu, 5 Jun 2014 18:53:12 +0400 Subject: [PATCH 505/545] Remove RTTI usage in NIF reader. --- components/nif/niffile.hpp | 111 ++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 45 deletions(-) diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 29fa3951e7..6fa98c6101 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -113,24 +113,24 @@ public: }; /// Get a given record - Record *getRecord(size_t index) + Record *getRecord(size_t index) const { Record *res = records.at(index); assert(res != NULL); return res; } /// Number of records - size_t numRecords() { return records.size(); } + size_t numRecords() const { return records.size(); } /// Get a given root - Record *getRoot(size_t index=0) + Record *getRoot(size_t index=0) const { Record *res = roots.at(index); assert(res != NULL); return res; } /// Number of roots - size_t numRoots() { return roots.size(); } + size_t numRoots() const { return roots.size(); } }; @@ -163,45 +163,33 @@ struct KeyListT { void read(NIFStream *nif, bool force=false) { + assert(nif); size_t count = nif->getInt(); if(count == 0 && !force) return; mInterpolationType = nif->getInt(); mKeys.resize(count); + NIFStream &nifReference = *nif; if(mInterpolationType == sLinearInterpolation) { for(size_t i = 0;i < count;i++) { - KeyT &key = mKeys[i]; - key.mTime = nif->getFloat(); - key.mValue = (nif->*getValue)(); + readTimeAndValue(nifReference, mKeys[i]); } } else if(mInterpolationType == sQuadraticInterpolation) { for(size_t i = 0;i < count;i++) { - KeyT &key = mKeys[i]; - key.mTime = nif->getFloat(); - key.mValue = (nif->*getValue)(); - if( typeid(Ogre::Quaternion) != typeid(T) ) - { - key.mForwardValue = (nif->*getValue)(); - key.mBackwardValue = (nif->*getValue)(); - } + readQuadratic(nifReference, mKeys[i]); } } else if(mInterpolationType == sTBCInterpolation) { for(size_t i = 0;i < count;i++) { - KeyT &key = mKeys[i]; - key.mTime = nif->getFloat(); - key.mValue = (nif->*getValue)(); - key.mTension = nif->getFloat(); - key.mBias = nif->getFloat(); - key.mContinuity = nif->getFloat(); + readTBC(nifReference, mKeys[i]); } } //\FIXME This now reads the correct amount of data in the file, but doesn't actually do anything with it. @@ -212,30 +200,8 @@ struct KeyListT { nif->file->fail("count should always be '1' for XYZ_ROTATION_KEY. Retrieved Value: "+Ogre::StringConverter::toString(count)); return; } - //KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) - //Chomp unknown and possibly unused float - nif->getFloat(); - for(size_t i=0;i<3;++i) - { - unsigned int numKeys = nif->getInt(); - if(numKeys != 0) - { - int interpolationTypeAgain = nif->getInt(); - if( interpolationTypeAgain != sLinearInterpolation) - { - nif->file->fail("XYZ_ROTATION_KEY's KeyGroup keyType must be '1' (Linear Interpolation). Retrieved Value: "+Ogre::StringConverter::toString(interpolationTypeAgain)); - return; - } - for(size_t j = 0;j < numKeys;j++) - { - //For now just chomp these - nif->getFloat(); - nif->getFloat(); - } - } - nif->file->warn("XYZ_ROTATION_KEY read, but not used!"); - } - } + readXYZ(nifReference); + } else if (mInterpolationType == 0) { if (count != 0) @@ -244,6 +210,61 @@ struct KeyListT { else nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } + +private: + static void readTimeAndValue(NIFStream &nif, KeyT &key) + { + key.mTime = nif.getFloat(); + key.mValue = (nif.*getValue)(); + } + + static void readQuadratic(NIFStream &nif, KeyT &key) + { + readTimeAndValue(nif, key); + } + + template + static void readQuadratic(NIFStream &nif, KeyT &key) + { + readTimeAndValue(nif, key); + key.mForwardValue = (nif.*getValue)(); + key.mBackwardValue = (nif.*getValue)(); + } + + static void readTBC(NIFStream &nif, KeyT &key) + { + readTimeAndValue(nif, key); + key.mTension = nif.getFloat(); + key.mBias = nif.getFloat(); + key.mContinuity = nif.getFloat(); + } + + static void readXYZ(NIFStream &nif) + { + //KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) + //Chomp unknown and possibly unused float + nif.getFloat(); + for(size_t i=0;i<3;++i) + { + const unsigned int numKeys = nif.getInt(); + if(numKeys != 0) + { + const int interpolationTypeAgain = nif.getInt(); + if( interpolationTypeAgain != sLinearInterpolation) + { + nif.file->fail("XYZ_ROTATION_KEY's KeyGroup keyType must be '1' (Linear Interpolation). Retrieved Value: "+Ogre::StringConverter::toString(interpolationTypeAgain)); + return; + } + for(size_t j = 0;j < numKeys;++j) + { + //For now just chomp these + nif.getFloat(); + nif.getFloat(); + } + } + nif.file->warn("XYZ_ROTATION_KEY read, but not used!"); + } + } }; typedef KeyListT FloatKeyList; typedef KeyListT Vector3KeyList; From f53e86cad9d1375cac64f4306245c89a49e390ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 21:51:57 +0200 Subject: [PATCH 506/545] Fix AiCombat being incorrectly added to player (Fixes #1356) --- apps/openmw/mwmechanics/actors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3d7e7e283a..8fe8e19240 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -932,7 +932,7 @@ namespace MWMechanics for (std::list::iterator it = listGuards.begin(); it != listGuards.end(); ++it) { - engageCombat(iter->first, *it, false); + engageCombat(iter->first, *it, *it == player); } } From 6db936bb3a14893e9a70abd85708be3d250e976b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 22:13:18 +0200 Subject: [PATCH 507/545] Refactor item icon code into ItemWidget (Fixes #1391) - Removed duplicate code - Fixed missing magic backgrounds during item drag&drop - Change background texture used for HUD icons --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/alchemywindow.cpp | 23 +--- apps/openmw/mwgui/alchemywindow.hpp | 5 +- apps/openmw/mwgui/container.cpp | 20 +-- apps/openmw/mwgui/enchantingdialog.cpp | 144 ++++++++++---------- apps/openmw/mwgui/enchantingdialog.hpp | 10 +- apps/openmw/mwgui/hud.cpp | 51 ++----- apps/openmw/mwgui/hud.hpp | 3 +- apps/openmw/mwgui/itemview.cpp | 58 ++------ apps/openmw/mwgui/itemwidget.cpp | 105 ++++++++++++++ apps/openmw/mwgui/itemwidget.hpp | 49 +++++++ apps/openmw/mwgui/quickkeysmenu.cpp | 125 +++++++---------- apps/openmw/mwgui/quickkeysmenu.hpp | 6 +- apps/openmw/mwgui/recharge.cpp | 19 +-- apps/openmw/mwgui/recharge.hpp | 4 +- apps/openmw/mwgui/repair.cpp | 20 +-- apps/openmw/mwgui/repair.hpp | 4 +- apps/openmw/mwgui/windowmanagerimp.cpp | 2 + files/mygui/openmw_alchemy_window.layout | 34 ++--- files/mygui/openmw_box.skin.xml | 5 + files/mygui/openmw_enchanting_dialog.layout | 6 +- files/mygui/openmw_hud.layout | 4 +- files/mygui/openmw_quickkeys_menu.layout | 20 +-- files/mygui/openmw_recharge_dialog.layout | 2 +- files/mygui/openmw_repair.layout | 2 +- files/mygui/openmw_resources.xml | 26 ++++ 26 files changed, 408 insertions(+), 341 deletions(-) create mode 100644 apps/openmw/mwgui/itemwidget.cpp create mode 100644 apps/openmw/mwgui/itemwidget.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8496b47a4a..d81276b72d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -33,7 +33,7 @@ add_openmw_dir (mwgui merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog - recharge mode videowidget backgroundimage + recharge mode videowidget backgroundimage itemwidget ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index ab04189a68..0b3e3c1684 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -13,20 +13,7 @@ #include "inventoryitemmodel.hpp" #include "sortfilteritemmodel.hpp" #include "itemview.hpp" - -namespace -{ - std::string getIconPath(MWWorld::Ptr ptr) - { - std::string path = std::string("icons\\"); - path += ptr.getClass().getInventoryIcon(ptr); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - return path; - } - -} +#include "itemwidget.hpp" namespace MWGui { @@ -149,7 +136,7 @@ namespace MWGui { mApparatus.at (index)->setUserString ("ToolTipType", "ItemPtr"); mApparatus.at (index)->setUserData (*iter); - mApparatus.at (index)->setImageTexture (getIconPath (*iter)); + mApparatus.at (index)->setItem(*iter); } } @@ -189,7 +176,7 @@ namespace MWGui MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients (); for (int i=0; i<4; ++i) { - MyGUI::ImageBox* ingredient = mIngredients[i]; + ItemWidget* ingredient = mIngredients[i]; MWWorld::Ptr item; if (it != mAlchemy.endIngredients ()) @@ -204,15 +191,15 @@ namespace MWGui if (ingredient->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); - ingredient->setImageTexture(""); ingredient->clearUserStrings (); + ingredient->setItem(item); + if (item.isEmpty ()) continue; ingredient->setUserString("ToolTipType", "ItemPtr"); ingredient->setUserData(item); - ingredient->setImageTexture(getIconPath(item)); MyGUI::TextBox* text = ingredient->createWidget("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); text->setTextAlign(MyGUI::Align::Right); diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 4fd4b825c0..b538a1f808 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -11,6 +11,7 @@ namespace MWGui { class ItemView; + class ItemWidget; class SortFilterItemModel; class AlchemyWindow : public WindowBase @@ -44,8 +45,8 @@ namespace MWGui MWMechanics::Alchemy mAlchemy; - std::vector mApparatus; - std::vector mIngredients; + std::vector mApparatus; + std::vector mIngredients; }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 609dea3857..4ba454a1ca 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -20,6 +20,7 @@ #include "inventorywindow.hpp" #include "itemview.hpp" +#include "itemwidget.hpp" #include "inventoryitemmodel.hpp" #include "sortfilteritemmodel.hpp" #include "pickpocketitemmodel.hpp" @@ -46,22 +47,15 @@ namespace MWGui mSourceSortModel->addDragItem(mItem.mBase, count); } - std::string path = std::string("icons\\"); - path += mItem.mBase.getClass().getInventoryIcon(mItem.mBase); - MyGUI::ImageBox* baseWidget = mDragAndDropWidget->createWidget - ("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); + ItemWidget* baseWidget = mDragAndDropWidget->createWidget + ("MW_ItemIcon", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); mDraggedWidget = baseWidget; - MyGUI::ImageBox* image = baseWidget->createWidget("ImageBox", - MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); - size_t pos = path.rfind("."); - if (pos != std::string::npos) - path.erase(pos); - path.append(".dds"); - image->setImageTexture(path); - image->setNeedMouseFocus(false); + baseWidget->setItem(mItem.mBase); + baseWidget->setNeedMouseFocus(false); // text widget that shows item count - MyGUI::TextBox* text = image->createWidget("SandBrightText", + // TODO: move to ItemWidget + MyGUI::TextBox* text = baseWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); text->setTextAlign(MyGUI::Align::Right); text->setNeedMouseFocus(false); diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index ccb1fab682..92221977b1 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -14,6 +14,7 @@ #include "itemselection.hpp" #include "container.hpp" +#include "itemwidget.hpp" #include "sortfilteritemmodel.hpp" @@ -57,8 +58,45 @@ namespace MWGui void EnchantingDialog::open() { center(); - onRemoveItem(NULL); - onRemoveSoul(NULL); + + setSoulGem(MWWorld::Ptr()); + setItem(MWWorld::Ptr()); + } + + void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem) + { + if (gem.isEmpty()) + { + mSoulBox->setItem(MWWorld::Ptr()); + mSoulBox->clearUserStrings(); + mEnchanting.setSoulGem(MWWorld::Ptr()); + } + else + { + mSoulBox->setItem(gem); + mSoulBox->setUserString ("ToolTipType", "ItemPtr"); + mSoulBox->setUserData(gem); + mEnchanting.setSoulGem(gem); + } + updateLabels(); + } + + void EnchantingDialog::setItem(const MWWorld::Ptr &item) + { + if (item.isEmpty()) + { + mItemBox->setItem(MWWorld::Ptr()); + mItemBox->clearUserStrings(); + mEnchanting.setOldItem(MWWorld::Ptr()); + } + else + { + mItemBox->setItem(item); + mItemBox->setUserString ("ToolTipType", "ItemPtr"); + mItemBox->setUserData(item); + mEnchanting.setOldItem(item); + } + updateLabels(); } void EnchantingDialog::exit() @@ -122,16 +160,7 @@ namespace MWGui startEditing(); mEnchanting.setSoulGem(soulgem); - MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += soulgem.getClass().getInventoryIcon(soulgem); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture (path); - image->setUserString ("ToolTipType", "ItemPtr"); - image->setUserData(soulgem); - image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul); + setSoulGem(soulgem); mPrice->setVisible(false); mPriceText->setVisible(false); @@ -151,46 +180,31 @@ namespace MWGui void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) { - delete mItemSelectionDialog; - mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}"); - mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); - mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); - mItemSelectionDialog->setVisible(true); - mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); - mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable); + if (mEnchanting.getOldItem().isEmpty()) + { + delete mItemSelectionDialog; + mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}"); + mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); + mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); + mItemSelectionDialog->setVisible(true); + mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); + mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable); + } + else + { + setItem(MWWorld::Ptr()); + } } void EnchantingDialog::onItemSelected(MWWorld::Ptr item) { mItemSelectionDialog->setVisible(false); - while (mItemBox->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0)); - - MyGUI::ImageBox* image = mItemBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture (path); - image->setUserString ("ToolTipType", "ItemPtr"); - image->setUserData(item); - image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem); - - mEnchanting.setOldItem(item); + setItem(item); mEnchanting.nextCastStyle(); updateLabels(); } - void EnchantingDialog::onRemoveItem(MyGUI::Widget *sender) - { - while (mItemBox->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0)); - mEnchanting.setOldItem(MWWorld::Ptr()); - updateLabels(); - } - void EnchantingDialog::onItemCancel() { mItemSelectionDialog->setVisible(false); @@ -207,28 +221,7 @@ namespace MWGui return; } - while (mSoulBox->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); - - MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture (path); - image->setUserString ("ToolTipType", "ItemPtr"); - image->setUserData(item); - image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul); - updateLabels(); - } - - void EnchantingDialog::onRemoveSoul(MyGUI::Widget *sender) - { - while (mSoulBox->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); - mEnchanting.setSoulGem(MWWorld::Ptr()); - updateLabels(); + setSoulGem(item); } void EnchantingDialog::onSoulCancel() @@ -238,15 +231,22 @@ namespace MWGui void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender) { - delete mItemSelectionDialog; - mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}"); - mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); - mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); - mItemSelectionDialog->setVisible(true); - mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); - mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones); + if (mEnchanting.getGem().isEmpty()) + { + delete mItemSelectionDialog; + mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}"); + mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); + mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); + mItemSelectionDialog->setVisible(true); + mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); + mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones); - //MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}"); + //MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}"); + } + else + { + setSoulGem(MWWorld::Ptr()); + } } void EnchantingDialog::notifyEffectsChanged () diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 7e641702e1..b75ae82803 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -11,6 +11,7 @@ namespace MWGui { class ItemSelectionDialog; + class ItemWidget; class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase { @@ -22,6 +23,9 @@ namespace MWGui virtual void exit(); + void setSoulGem (const MWWorld::Ptr& gem); + void setItem (const MWWorld::Ptr& item); + void startEnchanting(MWWorld::Ptr actor); void startSelfEnchanting(MWWorld::Ptr soulgem); @@ -32,8 +36,6 @@ namespace MWGui void onCancelButtonClicked(MyGUI::Widget* sender); void onSelectItem (MyGUI::Widget* sender); void onSelectSoul (MyGUI::Widget* sender); - void onRemoveItem (MyGUI::Widget* sender); - void onRemoveSoul (MyGUI::Widget* sender); void onItemSelected(MWWorld::Ptr item); void onItemCancel(); @@ -46,8 +48,8 @@ namespace MWGui ItemSelectionDialog* mItemSelectionDialog; MyGUI::Button* mCancelButton; - MyGUI::ImageBox* mItemBox; - MyGUI::ImageBox* mSoulBox; + ItemWidget* mItemBox; + ItemWidget* mSoulBox; MyGUI::Button* mTypeButton; MyGUI::Button* mBuyButton; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index ede5750a56..d87ac7ec59 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -18,6 +18,7 @@ #include "container.hpp" #include "itemmodel.hpp" +#include "itemwidget.hpp" namespace MWGui { @@ -423,9 +424,6 @@ namespace MWGui mSpellStatus->setProgressRange(100); mSpellStatus->setProgressPosition(successChancePercent); - if (mSpellImage->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0)); - mSpellBox->setUserString("ToolTipType", "Spell"); mSpellBox->setUserString("Spell", spellId); @@ -438,7 +436,9 @@ namespace MWGui icon.insert(slashPos+1, "b_"); icon = std::string("icons\\") + icon; Widgets::fixTexturePath(icon); - mSpellImage->setImageTexture(icon); + + mSpellImage->setItem(MWWorld::Ptr()); + mSpellImage->setIcon(icon); } void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) @@ -455,21 +455,10 @@ namespace MWGui mSpellStatus->setProgressRange(100); mSpellStatus->setProgressPosition(chargePercent); - if (mSpellImage->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0)); - mSpellBox->setUserString("ToolTipType", "ItemPtr"); mSpellBox->setUserData(item); - mSpellImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); - MyGUI::ImageBox* itemBox = mSpellImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) - , MyGUI::Align::Stretch); - - std::string path = std::string("icons\\"); - path+=item.getClass().getInventoryIcon(item); - Widgets::fixTexturePath(path); - itemBox->setImageTexture(path); - itemBox->setNeedMouseFocus(false); + mSpellImage->setItem(item); } void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) @@ -489,23 +478,7 @@ namespace MWGui mWeapStatus->setProgressRange(100); mWeapStatus->setProgressPosition(durabilityPercent); - if (mWeapImage->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mWeapImage->getChildAt(0)); - - std::string path = std::string("icons\\"); - path+=item.getClass().getInventoryIcon(item); - Widgets::fixTexturePath(path); - - if (item.getClass().getEnchantment(item) != "") - { - mWeapImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); - MyGUI::ImageBox* itemBox = mWeapImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) - , MyGUI::Align::Stretch); - itemBox->setImageTexture(path); - itemBox->setNeedMouseFocus(false); - } - else - mWeapImage->setImageTexture(path); + mWeapImage->setItem(item); } void HUD::unsetSelectedSpell() @@ -519,11 +492,9 @@ namespace MWGui mWeaponSpellBox->setVisible(true); } - if (mSpellImage->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0)); mSpellStatus->setProgressRange(100); mSpellStatus->setProgressPosition(0); - mSpellImage->setImageTexture(""); + mSpellImage->setItem(MWWorld::Ptr()); mSpellBox->clearUserStrings(); } @@ -538,17 +509,17 @@ namespace MWGui mWeaponSpellBox->setVisible(true); } - if (mWeapImage->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(mWeapImage->getChildAt(0)); mWeapStatus->setProgressRange(100); mWeapStatus->setProgressPosition(0); MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); + + mWeapImage->setItem(MWWorld::Ptr()); if (player.getClass().getNpcStats(player).isWerewolf()) - mWeapImage->setImageTexture("icons\\k\\tx_werewolf_hand.dds"); + mWeapImage->setIcon("icons\\k\\tx_werewolf_hand.dds"); else - mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); + mWeapImage->setIcon("icons\\k\\stealth_handtohand.dds"); mWeapBox->clearUserStrings(); } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 973ac07457..f451ea4d2d 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -10,6 +10,7 @@ namespace MWGui { class DragAndDrop; class SpellIcons; + class ItemWidget; class HUD : public OEngine::GUI::Layout, public LocalMapBase { @@ -63,7 +64,7 @@ namespace MWGui MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning; MyGUI::Widget* mHealthFrame; MyGUI::Widget *mWeapBox, *mSpellBox, *mSneakBox; - MyGUI::ImageBox *mWeapImage, *mSpellImage; + ItemWidget *mWeapImage, *mSpellImage; MyGUI::ProgressBar *mWeapStatus, *mSpellStatus; MyGUI::Widget *mEffectBox, *mMinimapBox; MyGUI::Button* mMinimapButton; diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index 24bc3fd630..fdaf930399 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -12,6 +12,7 @@ #include "../mwworld/class.hpp" #include "itemmodel.hpp" +#include "itemwidget.hpp" namespace MWGui { @@ -80,53 +81,24 @@ void ItemView::update() const ItemStack& item = mModel->getItem(i); /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them - std::string path = std::string("icons\\"); - path += item.mBase.getClass().getInventoryIcon(item.mBase); - - // background widget (for the "equipped" frame and magic item background image) - bool isMagic = (item.mFlags & ItemStack::Flag_Enchanted); - MyGUI::ImageBox* backgroundWidget = dragArea->createWidget("ImageBox", + ItemWidget* itemWidget = dragArea->createWidget("MW_ItemIcon", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); - backgroundWidget->setUserString("ToolTipType", "ItemModelIndex"); - backgroundWidget->setUserData(std::make_pair(i, mModel)); + itemWidget->setUserString("ToolTipType", "ItemModelIndex"); + itemWidget->setUserData(std::make_pair(i, mModel)); + ItemWidget::ItemState state = ItemWidget::None; + if (item.mType == ItemStack::Type_Barter) + state = ItemWidget::Barter; + if (item.mType == ItemStack::Type_Equipped) + state = ItemWidget::Equip; + itemWidget->setItem(item.mBase, state); - std::string backgroundTex = "textures\\menu_icon"; - if (isMagic) - backgroundTex += "_magic"; - if (item.mType == ItemStack::Type_Normal) - { - if (!isMagic) - backgroundTex = ""; - } - else if (item.mType == ItemStack::Type_Equipped) - backgroundTex += "_equip"; - else if (item.mType == ItemStack::Type_Barter) - backgroundTex += "_barter"; - - if (backgroundTex != "") - backgroundTex += ".dds"; - - backgroundWidget->setImageTexture(backgroundTex); - if ((item.mType == ItemStack::Type_Barter) && !isMagic) - backgroundWidget->setProperty("ImageCoord", "2 2 42 42"); - else - backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); - backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedItem); - backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel); - - // image - MyGUI::ImageBox* image = backgroundWidget->createWidget("ImageBox", - MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); - std::string::size_type pos = path.rfind("."); - if(pos != std::string::npos) - path.erase(pos); - path.append(".dds"); - image->setImageTexture(path); - image->setNeedMouseFocus(false); + itemWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedItem); + itemWidget->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel); // text widget that shows item count - MyGUI::TextBox* text = image->createWidget("SandBrightText", - MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); + // TODO: move to ItemWidget + MyGUI::TextBox* text = itemWidget->createWidget("SandBrightText", + MyGUI::IntCoord(5, 19, 32, 18), MyGUI::Align::Default, std::string("Label")); text->setTextAlign(MyGUI::Align::Right); text->setNeedMouseFocus(false); text->setTextShadow(true); diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp new file mode 100644 index 0000000000..a1ca5cb6c9 --- /dev/null +++ b/apps/openmw/mwgui/itemwidget.cpp @@ -0,0 +1,105 @@ +#include "itemwidget.hpp" + +#include +#include + +#include "../mwworld/class.hpp" + +namespace MWGui +{ + + ItemWidget::ItemWidget() + : mItem(NULL) + { + + } + + void ItemWidget::registerComponents() + { + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + } + + void ItemWidget::initialiseOverride() + { + assignWidget(mItem, "Item"); + if (mItem) + mItem->setNeedMouseFocus(false); + assignWidget(mFrame, "Frame"); + if (mFrame) + mFrame->setNeedMouseFocus(false); + + Base::initialiseOverride(); + } + + void ItemWidget::setIcon(const std::string &icon) + { + if (mItem) + mItem->setImageTexture(icon); + } + + void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord) + { + if (mFrame) + { + mFrame->setImageTexture(frame); + mFrame->setImageTile(MyGUI::IntSize(coord.width, coord.height)); // Why is this needed? MyGUI bug? + mFrame->setImageCoord(coord); + } + } + + void ItemWidget::setIcon(const MWWorld::Ptr &ptr) + { + // image + std::string path = std::string("icons\\"); + path += ptr.getClass().getInventoryIcon(ptr); + + std::string::size_type pos = path.rfind("."); + if(pos != std::string::npos) + path.erase(pos); + path.append(".dds"); + setIcon(path); + } + + + void ItemWidget::setItem(const MWWorld::Ptr &ptr, ItemState state) + { + if (!mItem) + return; + + if (ptr.isEmpty()) + { + if (mFrame) + mFrame->setImageTexture(""); + mItem->setImageTexture(""); + return; + } + + bool isMagic = !ptr.getClass().getEnchantment(ptr).empty(); + + std::string backgroundTex = "textures\\menu_icon"; + if (isMagic) + backgroundTex += "_magic"; + if (state == None) + { + if (!isMagic) + backgroundTex = ""; + } + else if (state == Equip) + { + backgroundTex += "_equip"; + } + else if (state == Barter) + backgroundTex += "_barter"; + + if (backgroundTex != "") + backgroundTex += ".dds"; + + if (state == Barter && !isMagic) + setFrame(backgroundTex, MyGUI::IntCoord(2,2,42,42)); + else + setFrame(backgroundTex, MyGUI::IntCoord(0,0,42,42)); + + setIcon(ptr); + } + +} diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp new file mode 100644 index 0000000000..3de98489d0 --- /dev/null +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -0,0 +1,49 @@ +#ifndef OPENMW_MWGUI_ITEMWIDGET_H +#define OPENMW_MWGUI_ITEMWIDGET_H + +#include + +namespace MWWorld +{ + class Ptr; +} + +namespace MWGui +{ + + /// @brief A widget that shows an icon for an MWWorld::Ptr + class ItemWidget : public MyGUI::Widget + { + MYGUI_RTTI_DERIVED(ItemWidget) + public: + ItemWidget(); + + /// Register needed components with MyGUI's factory manager + static void registerComponents (); + + enum ItemState + { + None, + Equip, + Barter, + Magic + }; + + /// \a ptr may be empty + void setItem (const MWWorld::Ptr& ptr, ItemState state = None); + + // Set icon and frame manually + void setIcon (const std::string& icon); + void setIcon (const MWWorld::Ptr& ptr); + void setFrame (const std::string& frame, const MyGUI::IntCoord& coord); + + private: + virtual void initialiseOverride(); + + MyGUI::ImageBox* mItem; + MyGUI::ImageBox* mFrame; + }; + +} + +#endif diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index af4e20ca4a..e142171770 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -23,6 +23,8 @@ #include "spellwindow.hpp" +#include "itemwidget.hpp" + namespace MWGui { @@ -46,14 +48,16 @@ namespace MWGui for (int i = 0; i < 10; ++i) { - MyGUI::Button* button; + ItemWidget* button; getWidget(button, "QuickKey" + boost::lexical_cast(i+1)); button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); - unassign(button, i); - mQuickKeyButtons.push_back(button); + + mAssigned.push_back(Type_Unassigned); + + unassign(button, i); } } @@ -77,12 +81,14 @@ namespace MWGui delete mMagicSelectionDialog; } - void QuickKeysMenu::unassign(MyGUI::Widget* key, int index) + void QuickKeysMenu::unassign(ItemWidget* key, int index) { - while (key->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (key->getChildAt(0)); + key->clearUserStrings(); + key->setItem(MWWorld::Ptr()); + while (key->getChildCount()) // Destroy number label + MyGUI::Gui::getInstance().destroyWidget(key->getChildAt(0)); - key->setUserData(Type_Unassigned); + mAssigned[index] = Type_Unassigned; MyGUI::TextBox* textBox = key->createWidgetReal("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default); textBox->setTextAlign (MyGUI::Align::Center); @@ -156,27 +162,16 @@ namespace MWGui void QuickKeysMenu::onAssignItem(MWWorld::Ptr item) { - MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; - while (button->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + assert (mSelectedIndex > 0); + ItemWidget* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount()) // Destroy number label + MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0)); - button->setUserData(Type_Item); + mAssigned[mSelectedIndex] = Type_Item; - MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); - std::string backgroundTex = "textures\\menu_icon_barter.dds"; - frame->setImageTexture (backgroundTex); - frame->setImageCoord (MyGUI::IntCoord(4, 4, 40, 40)); - frame->setUserString ("ToolTipType", "ItemPtr"); - frame->setUserData(item); - frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); - MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture (path); - image->setNeedMouseFocus (false); + button->setItem(item, ItemWidget::Barter); + button->setUserString ("ToolTipType", "ItemPtr"); + button->setUserData(item); if (mItemSelectionDialog) mItemSelectionDialog->setVisible(false); @@ -189,28 +184,18 @@ namespace MWGui void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item) { - MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; - while (button->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + assert (mSelectedIndex > 0); + ItemWidget* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount()) // Destroy number label + MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0)); - button->setUserData(Type_MagicItem); + mAssigned[mSelectedIndex] = Type_MagicItem; - MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); - std::string backgroundTex = "textures\\menu_icon_select_magic_magic.dds"; - frame->setImageTexture (backgroundTex); - frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40)); - frame->setUserString ("ToolTipType", "ItemPtr"); - frame->setUserData(item); - frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); + button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40)); + button->setIcon(item); - MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - image->setImageTexture (path); - image->setNeedMouseFocus (false); + button->setUserString ("ToolTipType", "ItemPtr"); + button->setUserData(item); if (mMagicSelectionDialog) mMagicSelectionDialog->setVisible(false); @@ -218,21 +203,16 @@ namespace MWGui void QuickKeysMenu::onAssignMagic (const std::string& spellId) { - MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; - while (button->getChildCount ()) - MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); + assert (mSelectedIndex > 0); + ItemWidget* button = mQuickKeyButtons[mSelectedIndex]; + while (button->getChildCount()) // Destroy number label + MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0)); - button->setUserData(Type_Magic); + mAssigned[mSelectedIndex] = Type_Magic; - MyGUI::ImageBox* frame = button->createWidget("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); - std::string backgroundTex = "textures\\menu_icon_select_magic.dds"; - frame->setImageTexture (backgroundTex); - frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40)); - frame->setUserString ("ToolTipType", "Spell"); - frame->setUserString ("Spell", spellId); - frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); - - MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + button->setItem(MWWorld::Ptr()); + button->setUserString ("ToolTipType", "Spell"); + button->setUserString ("Spell", spellId); const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); @@ -251,8 +231,8 @@ namespace MWGui path.erase(pos); path.append(".dds"); - image->setImageTexture (path); - image->setNeedMouseFocus (false); + button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40)); + button->setIcon(path); if (mMagicSelectionDialog) mMagicSelectionDialog->setVisible(false); @@ -265,16 +245,17 @@ namespace MWGui void QuickKeysMenu::activateQuickKey(int index) { - MyGUI::Button* button = mQuickKeyButtons[index-1]; + assert (index-1 > 0); + ItemWidget* button = mQuickKeyButtons[index-1]; - QuickKeyType type = *button->getUserData(); + QuickKeyType type = mAssigned[index-1]; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); if (type == Type_Item || type == Type_MagicItem) { - MWWorld::Ptr item = *button->getChildAt (0)->getUserData(); + MWWorld::Ptr item = *button->getUserData(); // make sure the item is available if (item.getRefData ().getCount() < 1) { @@ -286,7 +267,7 @@ namespace MWGui if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id)) { item = *it; - button->getChildAt(0)->setUserData(item); + button->setUserData(item); break; } } @@ -303,7 +284,7 @@ namespace MWGui if (type == Type_Magic) { - std::string spellId = button->getChildAt(0)->getUserString("Spell"); + std::string spellId = button->getUserString("Spell"); // Make sure the player still has this spell MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); @@ -315,13 +296,13 @@ namespace MWGui } else if (type == Type_Item) { - MWWorld::Ptr item = *button->getChildAt (0)->getUserData(); + MWWorld::Ptr item = *button->getUserData(); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item); } else if (type == Type_MagicItem) { - MWWorld::Ptr item = *button->getChildAt (0)->getUserData(); + MWWorld::Ptr item = *button->getUserData(); // retrieve ContainerStoreIterator to the item MWWorld::ContainerStoreIterator it = store.begin(); @@ -403,9 +384,9 @@ namespace MWGui for (int i=0; i<10; ++i) { - MyGUI::Button* button = mQuickKeyButtons[i]; + ItemWidget* button = mQuickKeyButtons[i]; - int type = *button->getUserData(); + int type = mAssigned[i]; ESM::QuickKeys::QuickKey key; key.mType = type; @@ -417,12 +398,12 @@ namespace MWGui case Type_Item: case Type_MagicItem: { - MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); + MWWorld::Ptr item = *button->getUserData(); key.mId = item.getCellRef().getRefId(); break; } case Type_Magic: - std::string spellId = button->getChildAt(0)->getUserString("Spell"); + std::string spellId = button->getUserString("Spell"); key.mId = spellId; break; } @@ -452,7 +433,7 @@ namespace MWGui mSelectedIndex = i; int keyType = it->mType; std::string id = it->mId; - MyGUI::Button* button = mQuickKeyButtons[i]; + ItemWidget* button = mQuickKeyButtons[i]; switch (keyType) { diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 40c5dab565..dc088d3c9a 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -11,6 +11,7 @@ namespace MWGui class QuickKeysMenuAssign; class ItemSelectionDialog; class MagicSelectionDialog; + class ItemWidget; class QuickKeysMenu : public WindowBase { @@ -51,7 +52,8 @@ namespace MWGui MyGUI::EditBox* mInstructionLabel; MyGUI::Button* mOkButton; - std::vector mQuickKeyButtons; + std::vector mQuickKeyButtons; + std::vector mAssigned; QuickKeysMenuAssign* mAssignDialog; ItemSelectionDialog* mItemSelectionDialog; @@ -63,7 +65,7 @@ namespace MWGui void onQuickKeyButtonClicked(MyGUI::Widget* sender); void onOkButtonClicked(MyGUI::Widget* sender); - void unassign(MyGUI::Widget* key, int index); + void unassign(ItemWidget* key, int index); }; class QuickKeysMenuAssign : public WindowModal diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index e5ea545917..0795642736 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -14,6 +14,7 @@ #include "../mwmechanics/npcstats.hpp" #include "widgets.hpp" +#include "itemwidget.hpp" namespace MWGui { @@ -45,12 +46,7 @@ void Recharge::exit() void Recharge::start (const MWWorld::Ptr &item) { - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - mGemIcon->setImageTexture (path); + mGemIcon->setItem(item); mGemIcon->setUserString("ToolTipType", "ItemPtr"); mGemIcon->setUserData(item); @@ -108,14 +104,9 @@ void Recharge::updateView() text->setNeedMouseFocus(false); currentY += 19; - MyGUI::ImageBox* icon = mView->createWidget ( - "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += iter->getClass().getInventoryIcon(*iter); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - icon->setImageTexture (path); + ItemWidget* icon = mView->createWidget ( + "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); + icon->setItem(*iter); icon->setUserString("ToolTipType", "ItemPtr"); icon->setUserData(*iter); icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked); diff --git a/apps/openmw/mwgui/recharge.hpp b/apps/openmw/mwgui/recharge.hpp index 5558b197e0..17d700649b 100644 --- a/apps/openmw/mwgui/recharge.hpp +++ b/apps/openmw/mwgui/recharge.hpp @@ -8,6 +8,8 @@ namespace MWGui { +class ItemWidget; + class Recharge : public WindowBase { public: @@ -25,7 +27,7 @@ protected: MyGUI::Widget* mGemBox; - MyGUI::ImageBox* mGemIcon; + ItemWidget* mGemIcon; MyGUI::TextBox* mChargeLabel; diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index 29ec62887a..986e27243a 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -13,6 +13,8 @@ #include "widgets.hpp" +#include "itemwidget.hpp" + namespace MWGui { @@ -44,12 +46,7 @@ void Repair::startRepairItem(const MWWorld::Ptr &item) { mRepair.setTool(item); - std::string path = std::string("icons\\"); - path += item.getClass().getInventoryIcon(item); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - mToolIcon->setImageTexture (path); + mToolIcon->setItem(item); mToolIcon->setUserString("ToolTipType", "ItemPtr"); mToolIcon->setUserData(item); @@ -113,14 +110,9 @@ void Repair::updateRepairView() text->setNeedMouseFocus(false); currentY += 19; - MyGUI::ImageBox* icon = mRepairView->createWidget ( - "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); - std::string path = std::string("icons\\"); - path += iter->getClass().getInventoryIcon(*iter); - int pos = path.rfind("."); - path.erase(pos); - path.append(".dds"); - icon->setImageTexture (path); + ItemWidget* icon = mRepairView->createWidget ( + "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); + icon->setItem(*iter); icon->setUserString("ToolTipType", "ItemPtr"); icon->setUserData(*iter); icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem); diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index 42539ad9e0..439ee1169a 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -8,6 +8,8 @@ namespace MWGui { +class ItemWidget; + class Repair : public WindowBase { public: @@ -25,7 +27,7 @@ protected: MyGUI::Widget* mToolBox; - MyGUI::ImageBox* mToolIcon; + ItemWidget* mToolIcon; MyGUI::TextBox* mUsesLabel; MyGUI::TextBox* mQualityLabel; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 94001d8777..588235db96 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -64,6 +64,7 @@ #include "fontloader.hpp" #include "videowidget.hpp" #include "backgroundimage.hpp" +#include "itemwidget.hpp" namespace MWGui { @@ -166,6 +167,7 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); + ItemWidget::registerComponents(); MyGUI::FactoryManager::getInstance().registerFactory("Controller"); diff --git a/files/mygui/openmw_alchemy_window.layout b/files/mygui/openmw_alchemy_window.layout index 4b15ac1bd5..e098800afb 100644 --- a/files/mygui/openmw_alchemy_window.layout +++ b/files/mygui/openmw_alchemy_window.layout @@ -23,21 +23,13 @@ - - - + - - - + - - - + - - - + @@ -51,21 +43,13 @@ - - - + - - - + - - - + - - - + @@ -106,4 +90,4 @@ - \ No newline at end of file + diff --git a/files/mygui/openmw_box.skin.xml b/files/mygui/openmw_box.skin.xml index 620f49e2b3..af3a05d31b 100644 --- a/files/mygui/openmw_box.skin.xml +++ b/files/mygui/openmw_box.skin.xml @@ -73,4 +73,9 @@ as around the sections of the stats window, or around popup info windows --> + + + + + diff --git a/files/mygui/openmw_enchanting_dialog.layout b/files/mygui/openmw_enchanting_dialog.layout index f64d21deaa..2a3cb7c1db 100644 --- a/files/mygui/openmw_enchanting_dialog.layout +++ b/files/mygui/openmw_enchanting_dialog.layout @@ -26,8 +26,7 @@ - - + @@ -35,8 +34,7 @@ - - + diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index 90fa1c8a56..e1f8af7bf3 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -59,7 +59,7 @@ - + @@ -71,7 +71,7 @@ - + diff --git a/files/mygui/openmw_quickkeys_menu.layout b/files/mygui/openmw_quickkeys_menu.layout index dcb10404df..d7e976d455 100644 --- a/files/mygui/openmw_quickkeys_menu.layout +++ b/files/mygui/openmw_quickkeys_menu.layout @@ -17,16 +17,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/files/mygui/openmw_recharge_dialog.layout b/files/mygui/openmw_recharge_dialog.layout index 49e7357645..1b2ad947bf 100644 --- a/files/mygui/openmw_recharge_dialog.layout +++ b/files/mygui/openmw_recharge_dialog.layout @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_repair.layout b/files/mygui/openmw_repair.layout index 2881a5853a..09a3724408 100644 --- a/files/mygui/openmw_repair.layout +++ b/files/mygui/openmw_repair.layout @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index 3901ab8252..a37d3335c2 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -319,4 +319,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From 0063b63ae441edeed34258e40d81b1fcf22a47ba Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 22:23:57 +0200 Subject: [PATCH 508/545] Don't use armor mitigation for fall damage --- apps/openmw/mwclass/npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 7405292b4b..5ec192ab20 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -680,7 +680,7 @@ namespace MWClass else getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur? - if(ishealth) + if(ishealth && !attacker.isEmpty()) // Don't use armor mitigation for fall damage { // Hit percentages: // cuirass = 30% From 3d103f37856074052e3047fa4bbd8d6e02165a4e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Jun 2014 22:27:46 +0200 Subject: [PATCH 509/545] Don't block hits when in hand-to-hand combat (shield not visible) --- apps/openmw/mwmechanics/combat.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 69c3c08f76..be62e8315f 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -73,9 +73,16 @@ namespace MWMechanics return false; MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); + + // Don't block when in spellcasting state (shield is equipped, but not visible) if (blockerStats.getDrawState() == DrawState_Spell) return false; + // Don't block when in hand-to-hand combat (shield is equipped, but not visible) + if (blockerStats.getDrawState() == DrawState_Weapon && + inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight) == inv.end()) + return false; + MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() From c36decb8555aa7c0d755628ad6f67efde572932e Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 00:43:07 +0200 Subject: [PATCH 510/545] Fix being able to place items on top of actors (Fixes #1403) --- apps/openmw/mwworld/physicssystem.cpp | 4 +++- apps/openmw/mwworld/physicssystem.hpp | 3 ++- apps/openmw/mwworld/worldimp.cpp | 12 ++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e93d9e640f..b0b00c6dbd 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -492,7 +492,7 @@ namespace MWWorld return std::make_pair(true, ray.getPoint(len * test.second)); } - std::pair PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal) + std::pair PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal, std::string* hit) { Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay( mouseX, @@ -510,6 +510,8 @@ namespace MWWorld return std::make_pair(false, Ogre::Vector3()); else { + if (hit != NULL) + *hit = result.first; return std::make_pair(true, ray.getPoint(200*result.second)); /// \todo make this distance (ray length) configurable } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 899d7144d9..c590b40c87 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -70,9 +70,10 @@ namespace MWWorld std::pair castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); - std::pair castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL); + std::pair castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL, std::string* hit = NULL); ///< cast ray from the mouse, return true if it hit something and the first result /// @param normal if non-NULL, the hit normal will be written there (if there is a hit) + /// @param hit if non-NULL, the string handle of the hit object will be written there (if there is a hit) OEngine::Physic::PhysicEngine* getEngine(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2bd835561d..0939f01be5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1624,12 +1624,20 @@ namespace MWWorld bool World::canPlaceObject(float cursorX, float cursorY) { Ogre::Vector3 normal(0,0,0); - std::pair result = mPhysics->castRay(cursorX, cursorY, &normal); + std::string handle; + std::pair result = mPhysics->castRay(cursorX, cursorY, &normal, &handle); if (result.first) { // check if the wanted position is on a flat surface, and not e.g. against a vertical wall - return (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() < 30); + if (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() >= 30) + return false; + + MWWorld::Ptr hitObject = searchPtrViaHandle(handle); + if (!hitObject.isEmpty() && hitObject.getClass().isActor()) + return false; + + return true; } else return false; From d442853b3e67b6f0cde3fb28382b83060b14a24b Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 01:30:23 +0200 Subject: [PATCH 511/545] Allow opposite gender's parts as fallback (Fixes #1404) --- apps/openmw/mwrender/npcanimation.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 03ccde388b..fcbf3805b9 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -408,8 +408,6 @@ void NpcAnimation::updateParts() if (bodypart.mData.mType != ESM::BodyPart::MT_Skin) continue; - if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female)) - continue; if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace)) continue; @@ -435,6 +433,20 @@ void NpcAnimation::updateParts() } continue; } + + if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female)) + { + // Allow opposite gender's parts as fallback if parts for our gender are missing + BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart)); + while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart) + { + if(!parts[bIt->second]) + parts[bIt->second] = &*it; + ++bIt; + } + continue; + } + BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart)); while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart) { From 40d6c8abf717b3112cc26c8d7be016974deb6a0f Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 02:24:51 +0200 Subject: [PATCH 512/545] Remove horizontal messagebox layout, not used in vanilla (Fixes #1402) --- apps/openmw/mwgui/messagebox.cpp | 132 ++++++++++--------------------- 1 file changed, 41 insertions(+), 91 deletions(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 1ce167c339..c5c46cba8e 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -232,102 +232,52 @@ namespace MWGui buttonsWidth += buttonLeftPadding; MyGUI::IntSize mainWidgetSize; - if(buttonsWidth < fixedWidth) - { - // on one line - if(textSize.width + 2*textPadding < buttonsWidth) - { - mainWidgetSize.width = buttonsWidth; - } - else - { - mainWidgetSize.width = textSize.width + 3*textPadding; - } - mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding; - - MyGUI::IntPoint absPos; - absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2; - absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2; - - mMainWidget->setPosition(absPos); - 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::IntSize buttonSize(0, buttonHeight); - int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding; - - std::vector::const_iterator button; - for(button = mButtons.begin(); button != mButtons.end(); ++button) - { - buttonCord.left = left; - buttonCord.top = textSize.height + textButtonPadding; - - buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding; - buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding; - - (*button)->setCoord(buttonCord); - (*button)->setSize(buttonSize); - - left += buttonSize.width + buttonLeftPadding; - } + // among each other + if(biggestButtonWidth > textSize.width) { + mainWidgetSize.width = biggestButtonWidth + buttonTopPadding; } - else - { - // among each other - if(biggestButtonWidth > textSize.width) { - mainWidgetSize.width = biggestButtonWidth + buttonTopPadding; - } - else { - mainWidgetSize.width = textSize.width + 3*textPadding; - } - - MyGUI::IntCoord buttonCord; - MyGUI::IntSize buttonSize(0, buttonHeight); - - int top = textButtonPadding + buttonTopPadding + textSize.height; - - std::vector::const_iterator button; - for(button = mButtons.begin(); button != mButtons.end(); ++button) - { - buttonSize.width = (*button)->getTextSize().width + buttonPadding*2; - buttonSize.height = (*button)->getTextSize().height + buttonPadding*2; - - buttonCord.top = top; - buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/ - - (*button)->setCoord(buttonCord); - (*button)->setSize(buttonSize); - - 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); + else { + mainWidgetSize.width = textSize.width + 3*textPadding; } + MyGUI::IntCoord buttonCord; + MyGUI::IntSize buttonSize(0, buttonHeight); + + int top = textButtonPadding + buttonTopPadding + textSize.height; + + std::vector::const_iterator button; + for(button = mButtons.begin(); button != mButtons.end(); ++button) + { + buttonSize.width = (*button)->getTextSize().width + buttonPadding*2; + buttonSize.height = (*button)->getTextSize().height + buttonPadding*2; + + buttonCord.top = top; + buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/ + + (*button)->setCoord(buttonCord); + (*button)->setSize(buttonSize); + + 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 std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); - std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) { if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok)) From b90e4db8718b0a41de179214a9c7b0cb9f9b7440 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Fri, 6 Jun 2014 01:26:28 -0400 Subject: [PATCH 513/545] Actually read in XYZ_ROTATION_KEY data instead of discarding it. --- components/nif/data.hpp | 13 ++++++ components/nif/niffile.hpp | 92 ++++++++++++++------------------------ 2 files changed, 46 insertions(+), 59 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index f1f34184ba..998c887486 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -413,12 +413,25 @@ struct NiMorphData : public Record struct NiKeyframeData : public Record { QuaternionKeyList mRotations; + //\FIXME mXYZ_Keys are read, but not used. + FloatKeyList mXYZ_Keys; Vector3KeyList mTranslations; FloatKeyList mScales; void read(NIFStream *nif) { mRotations.read(nif); + if(mRotations.mInterpolationType == mRotations.sXYZInterpolation) + { + //Chomp unused float + nif->getFloat(); + for(size_t i=0;i<3;++i) + { + //Read concatenates items together. + mXYZ_keys.read(nif,true); + } + nif->file->warn("XYZ_ROTATION_KEY read, but not used!"); + } mTranslations.read(nif); mScales.read(nif); } diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 6fa98c6101..5ef8179d5c 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -158,57 +158,58 @@ struct KeyListT { static const int sTBCInterpolation = 3; static const int sXYZInterpolation = 4; - int mInterpolationType; + unsigned int mInterpolationType; VecType mKeys; void read(NIFStream *nif, bool force=false) { assert(nif); - size_t count = nif->getInt(); + size_t count = nif->getUInt(); if(count == 0 && !force) return; - mInterpolationType = nif->getInt(); - mKeys.resize(count); + //If we aren't forcing things, make sure that read clears any previous keys + if(!force) + mKeys.clear(); + + mInterpolationType = nif->getUInt(); + + KeyT key; NIFStream &nifReference = *nif; - if(mInterpolationType == sLinearInterpolation) + for(size_t i = 0;i < count;i++) { - for(size_t i = 0;i < count;i++) + if(mInterpolationType == sLinearInterpolation) { - readTimeAndValue(nifReference, mKeys[i]); + readTimeAndValue(nifReference, key); + mKeys.push_back(key); } - } - else if(mInterpolationType == sQuadraticInterpolation) - { - for(size_t i = 0;i < count;i++) + else if(mInterpolationType == sQuadraticInterpolation) { - readQuadratic(nifReference, mKeys[i]); + readQuadratic(nifReference, key); + mKeys.push_back(key); } - } - else if(mInterpolationType == sTBCInterpolation) - { - for(size_t i = 0;i < count;i++) + else if(mInterpolationType == sTBCInterpolation) { - readTBC(nifReference, mKeys[i]); + readTBC(nifReference, key); + mKeys.push_back(key); } - } - //\FIXME This now reads the correct amount of data in the file, but doesn't actually do anything with it. - else if(mInterpolationType == sXYZInterpolation) - { - if (count != 1) + else if(mInterpolationType == sXYZInterpolation) { - nif->file->fail("count should always be '1' for XYZ_ROTATION_KEY. Retrieved Value: "+Ogre::StringConverter::toString(count)); - return; + //Don't try to read XYZ keys into the wrong part + if(force) + { + readTimeAndValue(nifReference, key); + mKeys.push_back(key); + } + else if ( count != 1 ) + nif->file->fail("XYZ_ROTATION_KEY count should always be '1' . Retrieved Value: "+Ogre::StringConverter::toString(count)); } - readXYZ(nifReference); + else if ((0 == mInterpolationType)) + if (count != 0) + nif->file->fail("Interpolation type 0 doesn't work with keys"); + else + nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } - else if (mInterpolationType == 0) - { - if (count != 0) - nif->file->fail("Interpolation type 0 doesn't work with keys"); - } - else - nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } private: @@ -238,33 +239,6 @@ private: key.mBias = nif.getFloat(); key.mContinuity = nif.getFloat(); } - - static void readXYZ(NIFStream &nif) - { - //KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) - //Chomp unknown and possibly unused float - nif.getFloat(); - for(size_t i=0;i<3;++i) - { - const unsigned int numKeys = nif.getInt(); - if(numKeys != 0) - { - const int interpolationTypeAgain = nif.getInt(); - if( interpolationTypeAgain != sLinearInterpolation) - { - nif.file->fail("XYZ_ROTATION_KEY's KeyGroup keyType must be '1' (Linear Interpolation). Retrieved Value: "+Ogre::StringConverter::toString(interpolationTypeAgain)); - return; - } - for(size_t j = 0;j < numKeys;++j) - { - //For now just chomp these - nif.getFloat(); - nif.getFloat(); - } - } - nif.file->warn("XYZ_ROTATION_KEY read, but not used!"); - } - } }; typedef KeyListT FloatKeyList; typedef KeyListT Vector3KeyList; From 83d5f2aaebebac558a45f68fdf71b8646cfc56f0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Jun 2014 12:43:21 +0200 Subject: [PATCH 514/545] factored out command creation from table view into a separate class --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/commanddispatcher.cpp | 157 ++++++++++++++++++ apps/opencs/model/world/commanddispatcher.hpp | 53 ++++++ apps/opencs/view/world/table.cpp | 148 +++-------------- apps/opencs/view/world/table.hpp | 10 +- 5 files changed, 235 insertions(+), 135 deletions(-) create mode 100644 apps/opencs/model/world/commanddispatcher.cpp create mode 100644 apps/opencs/model/world/commanddispatcher.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f18ac0bcab..d9cac95f33 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world - idtable idtableproxymodel regionmap data + idtable idtableproxymodel regionmap data commanddispatcher ) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp new file mode 100644 index 0000000000..1e27157446 --- /dev/null +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -0,0 +1,157 @@ + +#include "commanddispatcher.hpp" + +#include "../doc/document.hpp" + +#include "idtable.hpp" +#include "record.hpp" +#include "commands.hpp" + +std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const +{ + std::vector result; + + IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + for (std::vector::const_iterator iter (mSelection.begin()); + iter!=mSelection.end(); ++iter) + { + // check record state + RecordBase::State state = + static_cast (model.data (model.index (*iter, 1)).toInt()); + + if (state==RecordBase::State_Deleted) + continue; + + // check other columns (only relevant for a subset of the tables) + int dialogueTypeIndex = model.searchColumnIndex (Columns::ColumnId_DialogueType); + + if (dialogueTypeIndex!=-1) + { + int type = model.data (model.index (*iter, dialogueTypeIndex)).toInt(); + + if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal) + continue; + } + + result.push_back (*iter); + } + + return result; +} + +std::vector CSMWorld::CommandDispatcher::getRevertableRecords() const +{ + std::vector result; + + IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + /// \todo Reverting temporarily disabled on tables that support reordering, because + /// revert logic currently can not handle reordering. + if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic) + return result; + + for (std::vector::const_iterator iter (mSelection.begin()); + iter!=mSelection.end(); ++iter) + { + // check record state + RecordBase::State state = + static_cast (model.data (model.index (*iter, 1)).toInt()); + + if (state==RecordBase::State_BaseOnly) + continue; + + result.push_back (*iter); + } + + return result; +} + +CSMWorld::CommandDispatcher::CommandDispatcher (CSMDoc::Document& document, + const CSMWorld::UniversalId& id, QObject *parent) +: QObject (parent), mDocument (document), mId (id), mLocked (false) +{} + +void CSMWorld::CommandDispatcher::setEditLock (bool locked) +{ + mLocked = locked; +} + +void CSMWorld::CommandDispatcher::setSelection (const std::vector& selection) +{ + mSelection = selection; +} + +bool CSMWorld::CommandDispatcher::canDelete() const +{ + if (mLocked) + return false; + + return getDeletableRecords().size()!=0; +} + +bool CSMWorld::CommandDispatcher::canRevert() const +{ + if (mLocked) + return false; + + return getRevertableRecords().size()!=0; +} + +void CSMWorld::CommandDispatcher::executeDelete() +{ + if (mLocked) + return; + + std::vector rows = getDeletableRecords(); + + if (rows.empty()) + return; + + IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + int columnIndex = model.findColumnIndex (Columns::ColumnId_Id); + + if (rows.size()>1) + mDocument.getUndoStack().beginMacro (tr ("Delete multiple records")); + + for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) + { + std::string id = model.data (model.index (*iter, columnIndex)). + toString().toUtf8().constData(); + + mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id)); + } + + if (rows.size()>1) + mDocument.getUndoStack().endMacro(); +} + +void CSMWorld::CommandDispatcher::executeRevert() +{ + if (mLocked) + return; + + std::vector rows = getRevertableRecords(); + + if (rows.empty()) + return; + + IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + int columnIndex = model.findColumnIndex (Columns::ColumnId_Id); + + if (rows.size()>1) + mDocument.getUndoStack().beginMacro (tr ("Revert multiple records")); + + for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) + { + std::string id = model.data (model.index (*iter, columnIndex)). + toString().toUtf8().constData(); + + mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id)); + } + + if (rows.size()>1) + mDocument.getUndoStack().endMacro(); +} diff --git a/apps/opencs/model/world/commanddispatcher.hpp b/apps/opencs/model/world/commanddispatcher.hpp new file mode 100644 index 0000000000..a976df46b0 --- /dev/null +++ b/apps/opencs/model/world/commanddispatcher.hpp @@ -0,0 +1,53 @@ +#ifndef CSM_WOLRD_COMMANDDISPATCHER_H +#define CSM_WOLRD_COMMANDDISPATCHER_H + +#include + +#include + +#include "universalid.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class CommandDispatcher : public QObject + { + Q_OBJECT + + bool mLocked; + CSMDoc::Document& mDocument; + UniversalId mId; + std::vector mSelection; + + std::vector getDeletableRecords() const; + + std::vector getRevertableRecords() const; + + public: + + CommandDispatcher (CSMDoc::Document& document, const CSMWorld::UniversalId& id, + QObject *parent = 0); + ///< \param id ID of the table the commands should operate on primarily. + + void setEditLock (bool locked); + + void setSelection (const std::vector& selection); + + bool canDelete() const; + + bool canRevert() const; + + public slots: + + void executeDelete(); + + void executeRevert(); + + }; +} + +#endif diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 912cd2183e..5a2d2e5367 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -19,14 +19,28 @@ #include "../../model/world/columns.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp" +#include "../../model/world/commanddispatcher.hpp" #include "recordstatusdelegate.hpp" #include "util.hpp" void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { + // configure dispatcher QModelIndexList selectedRows = selectionModel()->selectedRows(); + std::vector rows; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); + ++iter) + { + QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); + rows.push_back (index.row()); + } + + mDispatcher->setSelection (rows); + + // create context menu QMenu menu (this); /// \todo add menu items for select all and clear selection @@ -44,13 +58,10 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) if (mCreateAction) menu.addAction (mCreateAction); - /// \todo Reverting temporarily disabled on tables that support reordering, because - /// revert logic currently can not handle reordering. - if (!(mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)) - if (listRevertableSelectedIds().size()>0) - menu.addAction (mRevertAction); + if (mDispatcher->canRevert()) + menu.addAction (mRevertAction); - if (listDeletableSelectedIds().size()>0) + if (mDispatcher->canDelete()) menu.addAction (mDeleteAction); if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic) @@ -108,84 +119,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) menu.exec (event->globalPos()); } -std::vector CSVWorld::Table::listRevertableSelectedIds() const -{ - std::vector revertableIds; - - if (mProxyModel->columnCount()>0) - { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); - ++iter) - { - QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); - - CSMWorld::RecordBase::State state = - static_cast ( - mModel->data (mModel->index (index.row(), 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_BaseOnly) - { - int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); - - std::string id = mModel->data (mModel->index (index.row(), columnIndex)). - toString().toUtf8().constData(); - - revertableIds.push_back (id); - } - } - } - - return revertableIds; -} - -std::vector CSVWorld::Table::listDeletableSelectedIds() const -{ - std::vector deletableIds; - - if (mProxyModel->columnCount()>0) - { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); - ++iter) - { - QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); - - // check record state - CSMWorld::RecordBase::State state = - static_cast ( - mModel->data (mModel->index (index.row(), 1)).toInt()); - - if (state==CSMWorld::RecordBase::State_Deleted) - continue; - - // check other columns (only relevant for a subset of the tables) - int dialogueTypeIndex = - mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType); - - if (dialogueTypeIndex!=-1) - { - int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt(); - - if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal) - continue; - } - - // add the id to the collection - int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); - - std::string id = mModel->data (mModel->index (index.row(), columnIndex)). - toString().toUtf8().constData(); - - deletableIds.push_back (id); - } - } - - return deletableIds; -} - CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) : mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0), @@ -196,6 +129,8 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, mProxyModel = new CSMWorld::IdTableProxyModel (this); mProxyModel->setSourceModel (mModel); + mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); + setModel (mProxyModel); horizontalHeader()->setResizeMode (QHeaderView::Interactive); verticalHeader()->hide(); @@ -240,11 +175,11 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, } mRevertAction = new QAction (tr ("Revert Record"), this); - connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord())); + connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert())); addAction (mRevertAction); mDeleteAction = new QAction (tr ("Delete Record"), this); - connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord())); + connect (mDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeDelete())); addAction (mDeleteAction); mMoveUpAction = new QAction (tr ("Move Up"), this); @@ -283,6 +218,7 @@ void CSVWorld::Table::setEditLock (bool locked) (*iter)->setEditLock (locked); DragRecordTable::setEditLock(locked); + mDispatcher->setEditLock (locked); } CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const @@ -292,46 +228,6 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const mProxyModel->data (mProxyModel->index (row, 0)).toString().toUtf8().constData()); } -void CSVWorld::Table::revertRecord() -{ - if (!mEditLock) - { - std::vector revertableIds = listRevertableSelectedIds(); - - if (!revertableIds.empty()) - { - if (revertableIds.size()>1) - mDocument.getUndoStack().beginMacro (tr ("Revert multiple records")); - - for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) - mDocument.getUndoStack().push (new CSMWorld::RevertCommand (*mModel, *iter)); - - if (revertableIds.size()>1) - mDocument.getUndoStack().endMacro(); - } - } -} - -void CSVWorld::Table::deleteRecord() -{ - if (!mEditLock) - { - std::vector deletableIds = listDeletableSelectedIds(); - - if (!deletableIds.empty()) - { - if (deletableIds.size()>1) - mDocument.getUndoStack().beginMacro (tr ("Delete multiple records")); - - for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) - mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (*mModel, *iter)); - - if (deletableIds.size()>1) - mDocument.getUndoStack().endMacro(); - } - } -} - void CSVWorld::Table::editRecord() { if (!mEditLock) diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 3b1d40e781..54971fb668 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -24,6 +24,7 @@ namespace CSMWorld class UniversalId; class IdTableProxyModel; class IdTable; + class CommandDispatcher; } namespace CSVWorld @@ -48,15 +49,12 @@ namespace CSVWorld CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; int mRecordStatusDisplay; + CSMWorld::CommandDispatcher *mDispatcher; private: void contextMenuEvent (QContextMenuEvent *event); - std::vector listRevertableSelectedIds() const; - - std::vector listDeletableSelectedIds() const; - void mouseMoveEvent(QMouseEvent *event); void dropEvent(QDropEvent *event); @@ -93,10 +91,6 @@ namespace CSVWorld private slots: - void revertRecord(); - - void deleteRecord(); - void editRecord(); void cloneRecord(); From f9f278f6450a80bebbc50cc459054a4e113d2677 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Fri, 6 Jun 2014 07:00:04 -0400 Subject: [PATCH 515/545] Fixed a capitalization error. Changed Interpolations to unsigned. Also explained what's happening in the comments. --- components/nif/data.hpp | 2 +- components/nif/niffile.hpp | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 998c887486..e943887682 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -428,7 +428,7 @@ struct NiKeyframeData : public Record for(size_t i=0;i<3;++i) { //Read concatenates items together. - mXYZ_keys.read(nif,true); + mXYZ_Keys.read(nif,true); } nif->file->warn("XYZ_ROTATION_KEY read, but not used!"); } diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 5ef8179d5c..daec80ea1c 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -153,14 +153,15 @@ template struct KeyListT { typedef std::vector< KeyT > VecType; - static const int sLinearInterpolation = 1; - static const int sQuadraticInterpolation = 2; - static const int sTBCInterpolation = 3; - static const int sXYZInterpolation = 4; + static const unsigned int sLinearInterpolation = 1; + static const unsigned int sQuadraticInterpolation = 2; + static const unsigned int sTBCInterpolation = 3; + static const unsigned int sXYZInterpolation = 4; unsigned int mInterpolationType; VecType mKeys; + //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) void read(NIFStream *nif, bool force=false) { assert(nif); @@ -193,20 +194,22 @@ struct KeyListT { readTBC(nifReference, key); mKeys.push_back(key); } + //XYZ keys aren't actually read here. + //data.hpp sees that the last type read was sXYZInterpolation and: + // Eats a floating point number, then + // Re-runs the read function 3 more times, with force enabled so that the previous values aren't cleared. + // When it does that it's reading in a bunch of sLinearInterpolation keys, not sXYZInterpolation. else if(mInterpolationType == sXYZInterpolation) { //Don't try to read XYZ keys into the wrong part - if(force) - { - readTimeAndValue(nifReference, key); - mKeys.push_back(key); - } - else if ( count != 1 ) + if ( count != 1 ) nif->file->fail("XYZ_ROTATION_KEY count should always be '1' . Retrieved Value: "+Ogre::StringConverter::toString(count)); } - else if ((0 == mInterpolationType)) + else if (0 == mInterpolationType) + { if (count != 0) nif->file->fail("Interpolation type 0 doesn't work with keys"); + } else nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } From 3e0c6ec732e660da413ba8e52843fbebfef637ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Jun 2014 13:09:17 +0200 Subject: [PATCH 516/545] some general cleanup; fixed two cases of dialogue subviews that allowed creating records where they shouldn't have --- apps/opencs/view/world/subviews.cpp | 57 +++++++++++++---------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 75f391699e..022d5d02e4 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -80,49 +80,42 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory); - //edit subviews - manager.add (CSMWorld::UniversalId::Type_Region, - new CSVDoc::SubViewFactoryWithCreator > (false)); + // Dialogue subviews + static const CSMWorld::UniversalId::Type sTableTypes2[] = + { + CSMWorld::UniversalId::Type_Region, + CSMWorld::UniversalId::Type_Spell, + CSMWorld::UniversalId::Type_Birthsign, + CSMWorld::UniversalId::Type_Global, + CSMWorld::UniversalId::Type_Race, + CSMWorld::UniversalId::Type_Class, + CSMWorld::UniversalId::Type_Filter, + CSMWorld::UniversalId::Type_Sound, + CSMWorld::UniversalId::Type_Faction, - manager.add (CSMWorld::UniversalId::Type_Spell, - new CSVDoc::SubViewFactoryWithCreator > (false)); + CSMWorld::UniversalId::Type_None // end marker + }; + + for (int i=0; sTableTypes2[i]!=CSMWorld::UniversalId::Type_None; ++i) + manager.add (sTableTypes2[i], + new CSVDoc::SubViewFactoryWithCreator > (false)); + + manager.add (CSMWorld::UniversalId::Type_Skill, + new CSVDoc::SubViewFactoryWithCreator (false)); + + manager.add (CSMWorld::UniversalId::Type_Gmst, + new CSVDoc::SubViewFactoryWithCreator (false)); manager.add (CSMWorld::UniversalId::Type_Referenceable, new CSVDoc::SubViewFactoryWithCreator > (false)); - manager.add (CSMWorld::UniversalId::Type_Birthsign, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Global, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Gmst, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Race, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Class, - new CSVDoc::SubViewFactoryWithCreator > (false)); - manager.add (CSMWorld::UniversalId::Type_Reference, new CSVDoc::SubViewFactoryWithCreator > (false)); manager.add (CSMWorld::UniversalId::Type_Cell, new CSVDoc::SubViewFactoryWithCreator > (false)); - manager.add (CSMWorld::UniversalId::Type_Filter, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Sound, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Faction, - new CSVDoc::SubViewFactoryWithCreator > (false)); - - manager.add (CSMWorld::UniversalId::Type_Skill, - new CSVDoc::SubViewFactoryWithCreator > (false)); - manager.add (CSMWorld::UniversalId::Type_JournalInfo, new CSVDoc::SubViewFactoryWithCreator > (false)); From f3cece8dec04e230bc6a3cf91b8a1c4b0ca383a3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 14:12:50 +0200 Subject: [PATCH 517/545] Fix alchemy allowing same item ID in different slots (Fixes #1407) --- apps/openmw/mwmechanics/alchemy.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 64b358b96c..2e03122d5b 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -395,7 +395,8 @@ int MWMechanics::Alchemy::addIngredient (const MWWorld::Ptr& ingredient) return -1; for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter) - if (!iter->isEmpty() && ingredient.get()==iter->get()) + if (!iter->isEmpty() && Misc::StringUtils::ciEqual(ingredient.getClass().getId(ingredient), + iter->getClass().getId(*iter))) return -1; mIngredients[slot] = ingredient; From c6557e1ade35b5eddccc26ba987c15115944d137 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Jun 2014 14:25:06 +0200 Subject: [PATCH 518/545] some UniversalId cleanup and enhancements --- apps/opencs/model/world/universalid.cpp | 28 ++++++++++++++++++++++--- apps/opencs/model/world/universalid.hpp | 9 +++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 140a410c06..88e649ace4 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -61,8 +61,8 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, @@ -90,7 +90,7 @@ namespace { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 }, - { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 }, @@ -320,6 +320,28 @@ std::vector CSMWorld::UniversalId::listReferenceabl return list; } +CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type) +{ + for (int i=0; sIdArg[i].mType; ++i) + if (type==sIdArg[i].mType) + { + if (sIdArg[i].mClass==Class_RefRecord) + return Type_Referenceables; + + if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record) + { + if (type==Type_Cell_Missing) + return Type_Cells; + + return static_cast (type-1); + } + + break; + } + + return Type_None; +} + bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) { return left.isEqual (right); diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 22779b2638..3bef71c75f 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -32,6 +32,8 @@ namespace CSMWorld ArgumentType_Index }; + /// \note A record list type must always be immediately followed by the matching + /// record type, if this type is of class SubRecord or Record. enum Type { Type_None = 0, @@ -86,8 +88,8 @@ namespace CSMWorld Type_References, Type_Reference, Type_RegionMap, - Type_Filter, Type_Filters, + Type_Filter, Type_Topics, Type_Topic, Type_Journals, @@ -147,6 +149,11 @@ namespace CSMWorld ///< Will return an empty string, if no icon is available. static std::vector listReferenceableTypes(); + + /// If \a type is a SubRecord, RefRecord or Record type return the type of the table + /// that contains records of type \a type. + /// Otherwise return Type_None. + static Type getParentType (Type type); }; bool operator== (const UniversalId& left, const UniversalId& right); From 9627146bf49c99ba5e4e99f871fb182f468b3e88 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 15:08:44 +0200 Subject: [PATCH 519/545] Another fix for trade exploit (hopefully the last: Fixes #1408) --- apps/openmw/mwgui/tradewindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 73f48c8cf4..7ef472282f 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -345,7 +345,7 @@ namespace MWGui x += abs(int(npcTerm - pcTerm)); int roll = std::rand()%100 + 1; - if(roll > x) //trade refused + if(roll > x || (mCurrentMerchantOffer < 0) != (mCurrentBalance < 0)) //trade refused { MWBase::Environment::get().getWindowManager()-> messageBox("#{sNotifyMessage9}"); From 01283f531eeb71cbef1a01b7e1a0da41a895520e Mon Sep 17 00:00:00 2001 From: Hallfaer Tuilinn Date: Fri, 6 Jun 2014 15:13:25 +0200 Subject: [PATCH 520/545] Fix for Bug #1409 --- apps/openmw/mwmechanics/actors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3d7e7e283a..48218f9de6 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1088,10 +1088,10 @@ namespace MWMechanics CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - float healthHours = healthPerHour >= 0 + float healthHours = healthPerHour > 0 ? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour : 1.0f; - float magickaHours = magickaPerHour >= 0 + float magickaHours = magickaPerHour > 0 ? (stats.getMagicka().getModified() - stats.getMagicka().getCurrent()) / magickaPerHour : 1.0f; From 54a5dba3f546cad38af44707a8f5fb7f106df72a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 15:20:56 +0200 Subject: [PATCH 521/545] Don't reserve Pauldron parts for robes (Fixes #1396) --- apps/openmw/mwrender/npcanimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fcbf3805b9..7277cc1872 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -308,7 +308,7 @@ void NpcAnimation::updateParts() ESM::PartReferenceType parts[] = { ESM::PRT_Groin, ESM::PRT_Skirt, ESM::PRT_RLeg, ESM::PRT_LLeg, ESM::PRT_RUpperarm, ESM::PRT_LUpperarm, ESM::PRT_RKnee, ESM::PRT_LKnee, - ESM::PRT_RForearm, ESM::PRT_LForearm, ESM::PRT_RPauldron, ESM::PRT_LPauldron + ESM::PRT_RForearm, ESM::PRT_LForearm }; size_t parts_size = sizeof(parts)/sizeof(parts[0]); for(size_t p = 0;p < parts_size;++p) From b68a8e38cdbbd04fb6e89c8231c00005ac851c23 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 15:24:06 +0200 Subject: [PATCH 522/545] Remove unused map --- apps/openmw/mwrender/npcanimation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 7277cc1872..be2b262fc2 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -351,8 +351,6 @@ void NpcAnimation::updateParts() // Remember body parts so we only have to search through the store once for each race/gender/viewmode combination static std::map< std::pair,std::vector > sRaceMapping; - static std::map , std::vector > sVampireMapping; - static const int Flag_Female = 1<<0; static const int Flag_FirstPerson = 1<<1; From 58d963d6e665de48300dc4ebdc3725a5fe61c495 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 6 Jun 2014 18:43:30 +0200 Subject: [PATCH 523/545] Fix warning --- apps/openmw/mwgui/messagebox.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index c5c46cba8e..d73a0e1223 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -179,7 +179,6 @@ namespace MWGui { WindowModal::open(); - int fixedWidth = 500; int textPadding = 10; // padding between text-widget and main-widget int textButtonPadding = 20; // padding between the text-widget und the button-widget int buttonLeftPadding = 10; // padding between the buttons if horizontal From f6ae967ba03bdc32b9526391e565baa3e951869a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Jun 2014 20:47:31 +0200 Subject: [PATCH 524/545] simplified Data constructor --- apps/opencs/model/world/data.cpp | 48 ++++++++++++++++---------------- apps/opencs/model/world/data.hpp | 4 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f448f5bfa1..7f2eac20dc 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -16,11 +16,12 @@ #include "regionmap.hpp" #include "columns.hpp" -void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1, - UniversalId::Type type2, bool update) +void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update) { mModels.push_back (model); - mModelIndex.insert (std::make_pair (type1, model)); + mModelIndex.insert (std::make_pair (type, model)); + + UniversalId::Type type2 = UniversalId::getParentType (type); if (type2!=UniversalId::Type_None) mModelIndex.insert (std::make_pair (type2, model)); @@ -235,26 +236,26 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding) mFilters.addColumn (new DescriptionColumn); mFilters.addColumn (new ScopeColumn); - addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); - addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); - addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false); - addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); - addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); - addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); - addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); - addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); - addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region); - addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign); - addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell); - addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic); - addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal); - addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); - addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo); - addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cells, UniversalId::Type_Cell); + addModel (new IdTable (&mGlobals), UniversalId::Type_Global); + addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); + addModel (new IdTable (&mSkills), UniversalId::Type_Skill); + addModel (new IdTable (&mClasses), UniversalId::Type_Class); + addModel (new IdTable (&mFactions), UniversalId::Type_Faction); + addModel (new IdTable (&mRaces), UniversalId::Type_Race); + addModel (new IdTable (&mSounds), UniversalId::Type_Sound); + addModel (new IdTable (&mScripts), UniversalId::Type_Script); + addModel (new IdTable (&mRegions), UniversalId::Type_Region); + addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsign); + addModel (new IdTable (&mSpells), UniversalId::Type_Spell); + addModel (new IdTable (&mTopics), UniversalId::Type_Topic); + addModel (new IdTable (&mJournals), UniversalId::Type_Journal); + addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo); + addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo); + addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell); addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), - UniversalId::Type_Referenceables, UniversalId::Type_Referenceable); - addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_References, UniversalId::Type_Reference, false); - addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false); + UniversalId::Type_Referenceable); + addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); + addModel (new IdTable (&mFilters), UniversalId::Type_Filter); } CSMWorld::Data::~Data() @@ -469,8 +470,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& if (id.getType()==UniversalId::Type_RegionMap) { RegionMap *table = 0; - addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, - UniversalId::Type_None, false); + addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, false); return table; } throw std::logic_error ("No table model available for " + id.toString()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 9a842878a8..edca9fdbcf 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -83,8 +83,8 @@ namespace CSMWorld Data (const Data&); Data& operator= (const Data&); - void addModel (QAbstractItemModel *model, UniversalId::Type type1, - UniversalId::Type type2 = UniversalId::Type_None, bool update = true); + void addModel (QAbstractItemModel *model, UniversalId::Type type, + bool update = true); static void appendIds (std::vector& ids, const CollectionBase& collection, bool listDeleted); From 13c953cbb290433b7f9dbbd04e5191b67a84f60a Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Fri, 6 Jun 2014 16:21:28 -0400 Subject: [PATCH 525/545] Made recommended changes Maybe introduced a bug not allowing punching. Testing. --- apps/openmw/mwinput/inputmanagerimp.cpp | 46 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 80cd834d5d..12e3cdbf78 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -168,11 +168,12 @@ namespace MWInput void InputManager::setPlayerControlsEnabled(bool enabled) { - int nPlayerChannels = 15; + int nPlayerChannels = 17; int playerChannels[] = {A_Activate, A_AutoMove, A_AlwaysRun, A_ToggleWeapon, A_ToggleSpell, A_Rest, A_QuickKey1, A_QuickKey2, A_QuickKey3, A_QuickKey4, A_QuickKey5, A_QuickKey6, - A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10}; + A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10, + A_Use}; for(int i = 0; i < nPlayerChannels; i++) { int pc = playerChannels[i]; @@ -558,41 +559,49 @@ namespace MWInput void InputManager::keyReleased(const SDL_KeyboardEvent &arg ) { - mInputBinder->keyReleased (arg); - OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); - MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)); + if (kc != OIS::KC_UNASSIGNED) + { + bool guiFocus = MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)); + setPlayerControlsEnabled(!guiFocus); + } + mInputBinder->keyReleased (arg); + } void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) { - mInputBinder->mousePressed (arg, id); + bool guiFocus = false; - if (id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT) - return; // MyGUI has no use for these events - - MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); - if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) + if (!(id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT)) // MyGUI has no use for these events { - MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); - if (b && b->getEnabled()) + guiFocus = MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); + if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) { - MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); + if (b && b->getEnabled()) + { + MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + } } } + setPlayerControlsEnabled(!guiFocus); + + mInputBinder->mousePressed (arg, id); } void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) { + bool guiFocus = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); + setPlayerControlsEnabled(!guiFocus); mInputBinder->mouseReleased (arg, id); - MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); } void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg ) { - mInputBinder->mouseMoved (arg); + bool guiFocus = false; resetIdleTime (); @@ -610,7 +619,7 @@ namespace MWInput mMouseWheel = int(arg.z); - MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); + guiFocus = MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); } if (mMouseLookEnabled) @@ -638,6 +647,9 @@ namespace MWInput MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true); } } + + setPlayerControlsEnabled(!guiFocus); + mInputBinder->mouseMoved (arg); } void InputManager::windowFocusChange(bool have_focus) From 97caa1f8a40d2b94046198c9216dca160c5f3a5f Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Fri, 6 Jun 2014 22:25:23 -0400 Subject: [PATCH 526/545] Alternative fix strategy by checking for binding state --- apps/openmw/mwinput/inputmanagerimp.cpp | 45 ++++++++++++++++--------- extern/oics/ICSInputControlSystem.cpp | 5 +++ extern/oics/ICSInputControlSystem.h | 1 + 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 80cd834d5d..ec1c0aa92a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -558,36 +558,51 @@ namespace MWInput void InputManager::keyReleased(const SDL_KeyboardEvent &arg ) { - mInputBinder->keyReleased (arg); - OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); - MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)); + setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc))); + mInputBinder->keyReleased (arg); } void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) { - mInputBinder->mousePressed (arg, id); + bool guiMode = false; - if (id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT) - return; // MyGUI has no use for these events - - MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); - if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) + if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI has no use for these events { - MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); - if (b && b->getEnabled()) + MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); + guiMode = guiMode && MWBase::Environment::get().getWindowManager()->isGuiMode(); + if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) { - MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); + if (b && b->getEnabled()) + { + MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + } } } + + setPlayerControlsEnabled(!guiMode); + mInputBinder->mousePressed (arg, id); + + } void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) - { - mInputBinder->mouseReleased (arg, id); + { - MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); + if(mInputBinder->detectingBindingState()) + { + mInputBinder->mouseReleased (arg, id); + } else { + bool guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); + guiMode = guiMode && MWBase::Environment::get().getWindowManager()->isGuiMode(); + + if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind + + setPlayerControlsEnabled(!guiMode); + mInputBinder->mouseReleased (arg, id); + } } void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg ) diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index cdf8fbfe2f..a053bbab4e 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -796,6 +796,11 @@ namespace ICS mMouseAxisBindingInitialValues[0] = ICS_MOUSE_AXIS_BINDING_NULL_VALUE; } + bool InputControlSystem::detectingBindingState() + { + return mDetectingBindingControl != NULL; + } + void InputControlSystem::cancelDetectingBindingState() { mDetectingBindingControl = NULL; diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index a83ae539ef..4aaecdea9f 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -146,6 +146,7 @@ namespace ICS void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction); void cancelDetectingBindingState(); + bool detectingBindingState(); bool save(std::string fileName = ""); From 1d3a220d947a6cf44f5e3dfc7c588a53f3aec232 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Fri, 6 Jun 2014 22:35:16 -0400 Subject: [PATCH 527/545] Added A_Use command to player controls. --- apps/openmw/mwinput/inputmanagerimp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index ec1c0aa92a..0ca55ea580 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -168,11 +168,12 @@ namespace MWInput void InputManager::setPlayerControlsEnabled(bool enabled) { - int nPlayerChannels = 15; + int nPlayerChannels = 17; int playerChannels[] = {A_Activate, A_AutoMove, A_AlwaysRun, A_ToggleWeapon, A_ToggleSpell, A_Rest, A_QuickKey1, A_QuickKey2, A_QuickKey3, A_QuickKey4, A_QuickKey5, A_QuickKey6, - A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10}; + A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10, + A_Use}; for(int i = 0; i < nPlayerChannels; i++) { int pc = playerChannels[i]; From 85fca19fd940876f980387dc42a8c6708d2824dd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Jun 2014 13:02:45 +0200 Subject: [PATCH 528/545] replaced selection model in CommandDispatcher with a slightly slower but more robust implementation --- apps/opencs/model/world/commanddispatcher.cpp | 36 ++++++++++--------- apps/opencs/model/world/commanddispatcher.hpp | 8 ++--- apps/opencs/view/world/table.cpp | 10 +++--- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 1e27157446..2b4c3109f5 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -7,18 +7,20 @@ #include "record.hpp" #include "commands.hpp" -std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const +std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const { - std::vector result; + std::vector result; IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); - for (std::vector::const_iterator iter (mSelection.begin()); + for (std::vector::const_iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) { + int row = model.getModelIndex (*iter, 0).row(); + // check record state RecordBase::State state = - static_cast (model.data (model.index (*iter, 1)).toInt()); + static_cast (model.data (model.index (row, 1)).toInt()); if (state==RecordBase::State_Deleted) continue; @@ -28,7 +30,7 @@ std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const if (dialogueTypeIndex!=-1) { - int type = model.data (model.index (*iter, dialogueTypeIndex)).toInt(); + int type = model.data (model.index (row, dialogueTypeIndex)).toInt(); if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal) continue; @@ -40,9 +42,9 @@ std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const return result; } -std::vector CSMWorld::CommandDispatcher::getRevertableRecords() const +std::vector CSMWorld::CommandDispatcher::getRevertableRecords() const { - std::vector result; + std::vector result; IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); @@ -51,12 +53,14 @@ std::vector CSMWorld::CommandDispatcher::getRevertableRecords() const if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic) return result; - for (std::vector::const_iterator iter (mSelection.begin()); + for (std::vector::const_iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) { + int row = model.getModelIndex (*iter, 0).row(); + // check record state RecordBase::State state = - static_cast (model.data (model.index (*iter, 1)).toInt()); + static_cast (model.data (model.index (row, 1)).toInt()); if (state==RecordBase::State_BaseOnly) continue; @@ -77,7 +81,7 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked) mLocked = locked; } -void CSMWorld::CommandDispatcher::setSelection (const std::vector& selection) +void CSMWorld::CommandDispatcher::setSelection (const std::vector& selection) { mSelection = selection; } @@ -103,7 +107,7 @@ void CSMWorld::CommandDispatcher::executeDelete() if (mLocked) return; - std::vector rows = getDeletableRecords(); + std::vector rows = getDeletableRecords(); if (rows.empty()) return; @@ -115,9 +119,9 @@ void CSMWorld::CommandDispatcher::executeDelete() if (rows.size()>1) mDocument.getUndoStack().beginMacro (tr ("Delete multiple records")); - for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) + for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) { - std::string id = model.data (model.index (*iter, columnIndex)). + std::string id = model.data (model.getModelIndex (*iter, columnIndex)). toString().toUtf8().constData(); mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id)); @@ -132,7 +136,7 @@ void CSMWorld::CommandDispatcher::executeRevert() if (mLocked) return; - std::vector rows = getRevertableRecords(); + std::vector rows = getRevertableRecords(); if (rows.empty()) return; @@ -144,9 +148,9 @@ void CSMWorld::CommandDispatcher::executeRevert() if (rows.size()>1) mDocument.getUndoStack().beginMacro (tr ("Revert multiple records")); - for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) + for (std::vector::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter) { - std::string id = model.data (model.index (*iter, columnIndex)). + std::string id = model.data (model.getModelIndex (*iter, columnIndex)). toString().toUtf8().constData(); mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id)); diff --git a/apps/opencs/model/world/commanddispatcher.hpp b/apps/opencs/model/world/commanddispatcher.hpp index a976df46b0..3bf81f0683 100644 --- a/apps/opencs/model/world/commanddispatcher.hpp +++ b/apps/opencs/model/world/commanddispatcher.hpp @@ -21,11 +21,11 @@ namespace CSMWorld bool mLocked; CSMDoc::Document& mDocument; UniversalId mId; - std::vector mSelection; + std::vector mSelection; - std::vector getDeletableRecords() const; + std::vector getDeletableRecords() const; - std::vector getRevertableRecords() const; + std::vector getRevertableRecords() const; public: @@ -35,7 +35,7 @@ namespace CSMWorld void setEditLock (bool locked); - void setSelection (const std::vector& selection); + void setSelection (const std::vector& selection); bool canDelete() const; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 5a2d2e5367..7599c8341b 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -29,16 +29,18 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) // configure dispatcher QModelIndexList selectedRows = selectionModel()->selectedRows(); - std::vector rows; + std::vector records; + + int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) { - QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); - rows.push_back (index.row()); + records.push_back (mProxyModel->data ( + mProxyModel->index (iter->row(), columnIndex)).toString().toUtf8().constData()); } - mDispatcher->setSelection (rows); + mDispatcher->setSelection (records); // create context menu QMenu menu (this); From e4a37ef7097d22e388c5c3809052190e4cc5ecef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Jun 2014 13:06:19 +0200 Subject: [PATCH 529/545] removed some hardcoded column numbers --- apps/opencs/model/world/commanddispatcher.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 2b4c3109f5..ce6d1e3982 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -13,14 +13,16 @@ std::vector CSMWorld::CommandDispatcher::getDeletableRecords() cons IdTable& model = dynamic_cast (*mDocument.getData().getTableModel (mId)); + int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification); + for (std::vector::const_iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) { int row = model.getModelIndex (*iter, 0).row(); // check record state - RecordBase::State state = - static_cast (model.data (model.index (row, 1)).toInt()); + RecordBase::State state = static_cast ( + model.data (model.index (row, stateColumnIndex)).toInt()); if (state==RecordBase::State_Deleted) continue; @@ -53,14 +55,16 @@ std::vector CSMWorld::CommandDispatcher::getRevertableRecords() con if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic) return result; + int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification); + for (std::vector::const_iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) { int row = model.getModelIndex (*iter, 0).row(); // check record state - RecordBase::State state = - static_cast (model.data (model.index (row, 1)).toInt()); + RecordBase::State state = static_cast ( + model.data (model.index (row, stateColumnIndex)).toInt()); if (state==RecordBase::State_BaseOnly) continue; From 302e2f8e9a7ad6d7deab6a0f66bb230677221a41 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Jun 2014 14:32:12 +0200 Subject: [PATCH 530/545] fixed some proxy model problems related to column numbers --- apps/opencs/view/world/table.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 7599c8341b..217d52ec14 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -36,8 +36,10 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) { - records.push_back (mProxyModel->data ( - mProxyModel->index (iter->row(), columnIndex)).toString().toUtf8().constData()); + int row = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)).row(); + + records.push_back (mModel->data ( + mModel->index (row, columnIndex)).toString().toUtf8().constData()); } mDispatcher->setSelection (records); @@ -71,8 +73,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) /// \todo allow reordering of multiple rows if (selectedRows.size()==1) { - int row =selectedRows.begin()->row(); - int column = mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_Topic); if (column==-1) @@ -80,14 +80,17 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) if (column!=-1) { - if (row>0 && mProxyModel->data (mProxyModel->index (row, column))== - mProxyModel->data (mProxyModel->index (row-1, column))) + int row = mProxyModel->mapToSource ( + mProxyModel->index (selectedRows.begin()->row(), 0)).row(); + + if (row>0 && mModel->data (mModel->index (row, column))== + mModel->data (mModel->index (row-1, column))) { menu.addAction (mMoveUpAction); } - if (rowrowCount()-1 && mProxyModel->data (mProxyModel->index (row, column))== - mProxyModel->data (mProxyModel->index (row+1, column))) + if (rowrowCount()-1 && mModel->data (mModel->index (row, column))== + mModel->data (mModel->index (row+1, column))) { menu.addAction (mMoveDownAction); } @@ -225,9 +228,11 @@ void CSVWorld::Table::setEditLock (bool locked) CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const { + row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row(); + return CSMWorld::UniversalId ( - static_cast (mProxyModel->data (mProxyModel->index (row, 2)).toInt()), - mProxyModel->data (mProxyModel->index (row, 0)).toString().toUtf8().constData()); + static_cast (mModel->data (mModel->index (row, 2)).toInt()), + mModel->data (mModel->index (row, 0)).toString().toUtf8().constData()); } void CSVWorld::Table::editRecord() From 7ede6573ebc825bc2a1e71c985536981fa7636e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Jun 2014 14:39:34 +0200 Subject: [PATCH 531/545] removed more hardcoded column numbers --- apps/opencs/view/world/table.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 217d52ec14..0fc7dd4b2f 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -230,9 +230,12 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const { row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row(); + int idColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); + int typeColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); + return CSMWorld::UniversalId ( - static_cast (mModel->data (mModel->index (row, 2)).toInt()), - mModel->data (mModel->index (row, 0)).toString().toUtf8().constData()); + static_cast (mModel->data (mModel->index (row, typeColumn)).toInt()), + mModel->data (mModel->index (row, idColumn)).toString().toUtf8().constData()); } void CSVWorld::Table::editRecord() From cd693b6d37dc6a5b0413e500d0fb1570449156e6 Mon Sep 17 00:00:00 2001 From: Fil Krynicki Date: Sat, 7 Jun 2014 20:08:29 -0400 Subject: [PATCH 532/545] Fixed mouse closing containers, and injection/gui test order Called setEnabled on channels now effects whether those channels notify listeners, rather than whether they register changes to their controls. This was making channels get stuck on "1" when the GUI was activated. Also ensured GUI activity can invalidate player controls even if that activity is closing the GUI, by re-ordering a check. And fixed a comment. --- apps/openmw/mwinput/inputmanagerimp.cpp | 10 +++++----- extern/oics/ICSChannel.cpp | 5 +---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 0ca55ea580..85d5cdb8e1 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -569,10 +569,10 @@ namespace MWInput { bool guiMode = false; - if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI has no use for these events + if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events { - MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); - guiMode = guiMode && MWBase::Environment::get().getWindowManager()->isGuiMode(); + guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); + guiMode = MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode; if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) { MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); @@ -596,8 +596,8 @@ namespace MWInput { mInputBinder->mouseReleased (arg, id); } else { - bool guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); - guiMode = guiMode && MWBase::Environment::get().getWindowManager()->isGuiMode(); + bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); + guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode; if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind diff --git a/extern/oics/ICSChannel.cpp b/extern/oics/ICSChannel.cpp index 268615c920..178fe5aa35 100644 --- a/extern/oics/ICSChannel.cpp +++ b/extern/oics/ICSChannel.cpp @@ -84,7 +84,7 @@ namespace ICS mValue = value; - if(previousValue != value) + if(previousValue != value && mEnabled) { notifyListeners(previousValue); } @@ -130,9 +130,6 @@ namespace ICS void Channel::update() { - if(!mEnabled) - return; - if(this->getControlsCount() == 1) { ControlChannelBinderItem ccBinderItem = mAttachedControls.back(); From 51c45796b183a5b4d71323602045674a0c4be71c Mon Sep 17 00:00:00 2001 From: slothlife Date: Sat, 7 Jun 2014 19:26:12 -0500 Subject: [PATCH 533/545] Fix physics to not trigger Bullet assert in Debug When physics attempts to move by a very small amount, precision losses caused Bullet to trigger an assert in debug from normalizing a zero length vector. --- apps/openmw/mwworld/physicssystem.cpp | 28 +++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index b0b00c6dbd..fde774662e 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -299,17 +299,33 @@ namespace MWWorld continue; // velocity updated, calculate nextpos again } - // trace to where character would go if there were no obstructions - tracer.doTrace(colobj, newPosition, nextpos, engine); - - // check for obstructions - if(tracer.mFraction >= 1.0f) + if(!newPosition.positionCloses(nextpos, 0.00000001)) { - newPosition = tracer.mEndPos; // ok to move, so set newPosition + // trace to where character would go if there were no obstructions + tracer.doTrace(colobj, newPosition, nextpos, engine); + + // check for obstructions + if(tracer.mFraction >= 1.0f) + { + newPosition = tracer.mEndPos; // ok to move, so set newPosition + remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it? + break; + } + } + else + { + // The current position and next position are nearly the same, so just exit. + // Note: Bullet can trigger an assert in debug modes if the positions + // are the same, since that causes it to attempt to normalize a zero + // length vector (which can also happen with nearly identical vectors, since + // precision can be lost due to any math Bullet does internally). Since we + // aren't performing any collision detection, we want to reject the next + // position, so that we don't slowly move inside another object. remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it? break; } + Ogre::Vector3 oldPosition = newPosition; // We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over) // NOTE: stepMove modifies newPosition if successful From 803a7514dfbfabd58678ad3a551deebb0c6f628e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Jun 2014 11:33:39 +0200 Subject: [PATCH 534/545] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index da54170345..092f5c15e8 100644 --- a/credits.txt +++ b/credits.txt @@ -36,6 +36,7 @@ Eli2 Emanuel Guével (potatoesmaster) Fil Krynicki (filkry) gugus/gus +Hallfaer Tuilinn Jacob Essex (Yacoby) Jannik Heller (scrawl) Jason Hooks (jhooks) From 48468b7d0ca5db689ca0b6d1141f8a4119a5b35f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 8 Jun 2014 14:10:08 +0200 Subject: [PATCH 535/545] some dialogue subview cleanup and start of command dispatching refactoring --- apps/opencs/view/world/dialoguesubview.cpp | 30 +++++++++------------- apps/opencs/view/world/dialoguesubview.hpp | 3 +++ 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 6b57f26855..ad2db87231 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -332,6 +332,7 @@ void CSVWorld::EditWidget::remake(int row) if (mMainWidget) { delete mMainWidget; + mMainWidget = 0; } mMainWidget = new QWidget (this); @@ -339,6 +340,7 @@ void CSVWorld::EditWidget::remake(int row) if (mWidgetMapper) { delete mWidgetMapper; + mWidgetMapper = 0; } mWidgetMapper = new QDataWidgetMapper (this); mWidgetMapper->setModel(mTable); @@ -396,7 +398,7 @@ void CSVWorld::EditWidget::remake(int row) mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0)); - this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable + this->setMinimumWidth(325); /// \todo replace hardcoded value with a user setting this->setWidget(mMainWidget); this->setWidgetResizable(true); } @@ -407,7 +409,6 @@ void CSVWorld::EditWidget::remake(int row) CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting) : - SubView (id), mEditWidget(0), mMainLayout(NULL), @@ -415,8 +416,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mTable(dynamic_cast(document.getData().getTableModel(id))), mRow (-1), mLocked(false), - mDocument(document) - + mDocument(document), + mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType())) { connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); mRow = mTable->getModelIndex (id.getId(), 0).row(); @@ -560,14 +561,12 @@ void CSVWorld::DialogueSubView::nextId() void CSVWorld::DialogueSubView::setEditLock (bool locked) { mLocked = locked; + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased) - { - mEditWidget->setDisabled(true); - } else - { - mEditWidget->setDisabled(mLocked); - } + + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); + + mCommandDispatcher.setEditLock (locked); } void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) @@ -575,13 +574,8 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) if (index.row() == mRow) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased) - { - mEditWidget->setDisabled(true); - } else - { - mEditWidget->setDisabled(mLocked); - } + + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); } } diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 5642f46a0b..cbca0159cf 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -8,7 +8,9 @@ #include #include "../doc/subview.hpp" + #include "../../model/world/columnbase.hpp" +#include "../../model/world/commanddispatcher.hpp" class QDataWidgetMapper; class QSize; @@ -169,6 +171,7 @@ namespace CSVWorld bool mLocked; const CSMDoc::Document& mDocument; TableBottomBox* mBottom; + CSMWorld::CommandDispatcher mCommandDispatcher; public: From 29231b8fc9a10fc3e4122bd70cfa88e571ad3ad2 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 10:26:53 +0200 Subject: [PATCH 536/545] starting new branch --- apps/opencs/view/world/dialoguesubview.cpp | 39 +++++++++++++++------- apps/opencs/view/world/dialoguesubview.hpp | 4 +-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 4ac8e87806..d537ac4f14 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "../../model/world/columnbase.hpp" #include "../../model/world/idtable.hpp" @@ -261,6 +263,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: } std::map::iterator delegateIt(mDelegates.find(display)); + if (delegateIt != mDelegates.end()) { editor = delegateIt->second->createEditor(qobject_cast(mParent), QStyleOptionViewItem(), index, display); @@ -371,7 +374,20 @@ void CSVWorld::EditWidget::remake(int row) CSMWorld::ColumnBase::Display display = static_cast (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - if (display != CSMWorld::ColumnBase::Display_Nested) + if (display == CSMWorld::ColumnBase::Display_Nested) + { + const QModelIndex& parent = mTable->index(row, i); + if (parent.data().isValid() && mTable->hasChildren(parent)) + { + qDebug()<setModel(mTable); + table->setRootIndex(mTable->index(row, i)); + } + //TODO + } else { mDispatcher.makeDelegate (display); QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i))); @@ -394,10 +410,9 @@ void CSVWorld::EditWidget::remake(int row) unlockedLayout->addWidget (editor, unlocked, 1); ++unlocked; } - } - } else - { - //TODO + } else { + qDebug()<<"No edit widget"; + } } } } @@ -421,13 +436,12 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout(NULL), mUndoStack(document.getUndoStack()), mTable(dynamic_cast(document.getData().getTableModel(id))), - mRow (-1), mLocked(false), mDocument(document) { connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); - mRow = mTable->getModelIndex (id.getId(), 0).row(); + mCurrentId(id.getId()); QWidget *mainWidget = new QWidget(this); QHBoxLayout *buttonsLayout = new QHBoxLayout; @@ -477,7 +491,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout = new QVBoxLayout(mainWidget); - mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false); + mEditWidget = new EditWidget(mainWidget, mCurrentId, mTable, mUndoStack, false); connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); @@ -498,14 +512,15 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM deleteButton->setDisabled(true); } - dataChanged(mTable->index(mRow, 0)); + dataChanged(getModelIndex(mCurrentId, 0)); mMainLayout->addLayout(buttonsLayout); setWidget(mainWidget); } void CSVWorld::DialogueSubView::prevId() { - int newRow = mRow - 1; + int new Row = getModelIndex(mCurrentId, 0).row() - 1; + if (newRow < 0) { return; @@ -552,12 +567,12 @@ void CSVWorld::DialogueSubView::nextId() } CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (newRow, 1)).toInt()); - if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)) + if (!(state == CSMWorld::RecordBase::State_Deleted)) { mEditWidget->remake(newRow); setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - mRow = newRow; + mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); mEditWidget->setDisabled(mLocked); return; } diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 5642f46a0b..dd14b3095a 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -165,7 +165,7 @@ namespace CSVWorld QVBoxLayout* mMainLayout; CSMWorld::IdTable* mTable; QUndoStack& mUndoStack; - int mRow; + std::string mCurrentId; bool mLocked; const CSMDoc::Document& mDocument; TableBottomBox* mBottom; @@ -206,4 +206,4 @@ namespace CSVWorld }; } -#endif \ No newline at end of file +#endif From 6f5935edb38dd30e00360053b9d1fd8b26b28b05 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 11:37:48 +0200 Subject: [PATCH 537/545] subview does not store row number anymore --- apps/opencs/view/world/dialoguesubview.cpp | 93 +++++++++++++--------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index d537ac4f14..03321728ba 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -379,14 +379,15 @@ void CSVWorld::EditWidget::remake(int row) const QModelIndex& parent = mTable->index(row, i); if (parent.data().isValid() && mTable->hasChildren(parent)) { + /* qDebug()<setModel(mTable); table->setRootIndex(mTable->index(row, i)); + */ } - //TODO } else { mDispatcher.makeDelegate (display); @@ -410,9 +411,7 @@ void CSVWorld::EditWidget::remake(int row) unlockedLayout->addWidget (editor, unlocked, 1); ++unlocked; } - } else { - qDebug()<<"No edit widget"; - } + } } } } @@ -441,7 +440,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM { connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); - mCurrentId(id.getId()); + mCurrentId = id.getId(); QWidget *mainWidget = new QWidget(this); QHBoxLayout *buttonsLayout = new QHBoxLayout; @@ -491,7 +490,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout = new QVBoxLayout(mainWidget); - mEditWidget = new EditWidget(mainWidget, mCurrentId, mTable, mUndoStack, false); + mEditWidget = new EditWidget(mainWidget, mTable->getModelIndex(mCurrentId, 0).row(), mTable, mUndoStack, false); connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); @@ -512,14 +511,14 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM deleteButton->setDisabled(true); } - dataChanged(getModelIndex(mCurrentId, 0)); + dataChanged(mTable->getModelIndex(mCurrentId, 0)); mMainLayout->addLayout(buttonsLayout); setWidget(mainWidget); } void CSVWorld::DialogueSubView::prevId() { - int new Row = getModelIndex(mCurrentId, 0).row() - 1; + int newRow = mTable->getModelIndex(mCurrentId, 0).row() - 1; if (newRow < 0) { @@ -540,7 +539,7 @@ void CSVWorld::DialogueSubView::prevId() mEditWidget->remake(newRow); setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - mRow = newRow; + mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); mEditWidget->setDisabled(mLocked); return; } @@ -550,7 +549,7 @@ void CSVWorld::DialogueSubView::prevId() void CSVWorld::DialogueSubView::nextId() { - int newRow = mRow + 1; + int newRow = mTable->getModelIndex(mCurrentId, 0).row() + 1; if (newRow >= mTable->rowCount()) { @@ -571,7 +570,7 @@ void CSVWorld::DialogueSubView::nextId() { mEditWidget->remake(newRow); setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), - mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); mEditWidget->setDisabled(mLocked); return; @@ -583,8 +582,10 @@ void CSVWorld::DialogueSubView::nextId() void CSVWorld::DialogueSubView::setEditLock (bool locked) { mLocked = locked; - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased) + QModelIndex index(mTable->getModelIndex(mCurrentId, 0)); + + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (index.row(), 1)).toInt()); + if (state == CSMWorld::RecordBase::State_Deleted) { mEditWidget->setDisabled(true); } else @@ -595,10 +596,12 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) { - if (index.row() == mRow) + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (!currentIndex.isValid() && index.row() == currentIndex.row()) { - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased) + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + if (state == CSMWorld::RecordBase::State_Deleted) { mEditWidget->setDisabled(true); } else @@ -621,15 +624,24 @@ void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor, void CSVWorld::DialogueSubView::revertRecord() { - int rows = mTable->rowCount(); - if (!mLocked && mTable->columnCount() > 0 && mRow < mTable->rowCount() ) + const int rows = mTable->rowCount(); + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (!currentIndex.isValid()) + { + return; + } + + const int currentRow = currentIndex.row(); + + if (!mLocked && mTable->columnCount() > 0 && currentRow < mTable->rowCount() ) { CSMWorld::RecordBase::State state = - static_cast (mTable->data (mTable->index (mRow, 1)).toInt()); + static_cast (mTable->data (mTable->index (currentRow, 1)).toInt()); if (state!=CSMWorld::RecordBase::State_BaseOnly) { - mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData())); + mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mCurrentId)); } if (rows != mTable->rowCount()) { @@ -638,11 +650,11 @@ void CSVWorld::DialogueSubView::revertRecord() mEditWidget->setDisabled(true); //closing the editor is other option return; } - if (mRow >= mTable->rowCount()) + if (currentIndex.row() >= mTable->rowCount()) { prevId(); } else { - dataChanged(mTable->index(mRow, 0)); + dataChanged(currentIndex); } } } @@ -650,19 +662,20 @@ void CSVWorld::DialogueSubView::revertRecord() void CSVWorld::DialogueSubView::deleteRecord() { - int rows = mTable->rowCount(); + const int rows = mTable->rowCount(); + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); //easier than disabling the button - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); - bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased); + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted); if (!mLocked && mTable->columnCount() > 0 && !deledetedOrErased && - mRow < rows && + currentIndex.row() < rows && mBottom->canCreateAndDelete()) { - mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData())); + mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mCurrentId)); if (rows != mTable->rowCount()) { if (mTable->rowCount() == 0) @@ -670,11 +683,11 @@ void CSVWorld::DialogueSubView::deleteRecord() mEditWidget->setDisabled(true); //closing the editor is other option return; } - if (mRow >= mTable->rowCount()) + if (currentIndex.row() >= mTable->rowCount()) { prevId(); } else { - dataChanged(mTable->index(mRow, 0)); + dataChanged(currentIndex); } } } @@ -682,29 +695,35 @@ void CSVWorld::DialogueSubView::deleteRecord() void CSVWorld::DialogueSubView::requestFocus (const std::string& id) { - mRow = mTable->getModelIndex (id, 0).row(); - mEditWidget->remake(mRow); + mCurrentId = std::string(id); + mEditWidget->remake(mTable->getModelIndex (id, 0).row()); } void CSVWorld::DialogueSubView::cloneRequest () { - mBottom->cloneRequest(mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData(), - static_cast(mTable->data(mTable->index(mRow, 2)).toInt())); + mBottom->cloneRequest(mCurrentId, static_cast(mTable->data(mTable->getModelIndex(mCurrentId, 2)).toInt())); } void CSVWorld::DialogueSubView::showPreview () { - if (mTable->hasPreview() && mRow < mTable->rowCount()) + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid() && + mTable->hasPreview() && + currentIndex.row() < mTable->rowCount()) { - emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()), ""); + emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), ""); } } void CSVWorld::DialogueSubView::viewRecord() { - if (mRow < mTable->rowCount()) + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid() && + currentIndex.row() < mTable->rowCount()) { - std::pair params = mTable->view (mRow); + std::pair params = mTable->view (currentIndex.row()); if (params.first.getType()!=CSMWorld::UniversalId::Type_None) emit focusId (params.first, params.second); From 649ce543698db2f87460f9b26c0d84c9b48606a2 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 11:53:06 +0200 Subject: [PATCH 538/545] merging --- CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 874d65af3d..3632f1e080 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,19 +36,8 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/.git) string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}") string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}") -<<<<<<< HEAD - set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}") - - set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR}) - set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR}) - set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE}) - - set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}") - set(OPENMW_VERSION_TAGHASH "${TAGHASH}") -======= set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}") set(OPENMW_VERSION_TAGHASH "${TAGHASH}") ->>>>>>> master/refs message(STATUS "OpenMW version ${OPENMW_VERSION}") else(MATCH) From c8458654ac19121fdf2851658a3737121829bf94 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 13:16:10 +0200 Subject: [PATCH 539/545] correcting problems --- apps/opencs/view/world/dialoguesubview.cpp | 43 +++++++--------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 523b358aef..db80af0258 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include "../../model/world/columnbase.hpp" #include "../../model/world/idtable.hpp" @@ -375,22 +374,21 @@ void CSVWorld::EditWidget::remake(int row) { CSMWorld::ColumnBase::Display display = static_cast (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - +/* commented out for now TODO if (display == CSMWorld::ColumnBase::Display_Nested) { const QModelIndex& parent = mTable->index(row, i); if (parent.data().isValid() && mTable->hasChildren(parent)) { - /* qDebug()<setModel(mTable); table->setRootIndex(mTable->index(row, i)); - */ + } - } else + } else */ { mDispatcher.makeDelegate (display); QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i))); @@ -583,40 +581,28 @@ void CSVWorld::DialogueSubView::nextId() void CSVWorld::DialogueSubView::setEditLock (bool locked) { mLocked = locked; - QModelIndex index(mTable->getModelIndex(mCurrentId, 0)); - - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (index.row(), 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted) - { - mEditWidget->setDisabled(true); - } else - { - mEditWidget->setDisabled(mLocked); - } - - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (mRow, 1)).toInt()); + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); + + if (currentIndex.isValid()) + { + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + + mCommandDispatcher.setEditLock (locked); + } - mCommandDispatcher.setEditLock (locked); } void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - if (!currentIndex.isValid() && index.row() == currentIndex.row()) + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); + + if (currentIndex.isValid() && index.row() == currentIndex.row()) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); - if (state == CSMWorld::RecordBase::State_Deleted) - { - mEditWidget->setDisabled(true); - } else - { - mEditWidget->setDisabled(mLocked); - } - - mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); } } @@ -719,7 +705,6 @@ void CSVWorld::DialogueSubView::showPreview () if (currentIndex.isValid() && mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview && - mTable->hasPreview() && currentIndex.row() < mTable->rowCount()) { emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), ""); From 9ee00534b9818226232bc7b7aaf832b37cbcd4b0 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 13:18:17 +0200 Subject: [PATCH 540/545] check if index is valid before attempting to use it --- apps/opencs/view/world/dialoguesubview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index db80af0258..8ffc0da563 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -660,11 +660,11 @@ void CSVWorld::DialogueSubView::deleteRecord() const int rows = mTable->rowCount(); QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - //easier than disabling the button CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted); if (!mLocked && + currentIndex.isValid() && mTable->columnCount() > 0 && !deledetedOrErased && currentIndex.row() < rows && From 8763309a1bdc0e15839cdfd3509ed68e28fc0917 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 13:31:15 +0200 Subject: [PATCH 541/545] reformatting to make code easier to read --- apps/opencs/view/world/dialoguesubview.cpp | 63 ++++++++++++++-------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 8ffc0da563..9d6538c1ce 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -133,25 +133,25 @@ void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std:: if (mDisplay == CSMWorld::ColumnBase::Display_Referenceable) { if ( type == CSMWorld::UniversalId::Type_Activator - || type == CSMWorld::UniversalId::Type_Potion - || type == CSMWorld::UniversalId::Type_Apparatus - || type == CSMWorld::UniversalId::Type_Armor - || type == CSMWorld::UniversalId::Type_Book - || type == CSMWorld::UniversalId::Type_Clothing - || type == CSMWorld::UniversalId::Type_Container - || type == CSMWorld::UniversalId::Type_Creature - || type == CSMWorld::UniversalId::Type_Door - || type == CSMWorld::UniversalId::Type_Ingredient - || type == CSMWorld::UniversalId::Type_CreatureLevelledList - || type == CSMWorld::UniversalId::Type_ItemLevelledList - || type == CSMWorld::UniversalId::Type_Light - || type == CSMWorld::UniversalId::Type_Lockpick - || type == CSMWorld::UniversalId::Type_Miscellaneous - || type == CSMWorld::UniversalId::Type_Npc - || type == CSMWorld::UniversalId::Type_Probe - || type == CSMWorld::UniversalId::Type_Repair - || type == CSMWorld::UniversalId::Type_Static - || type == CSMWorld::UniversalId::Type_Weapon) + || type == CSMWorld::UniversalId::Type_Potion + || type == CSMWorld::UniversalId::Type_Apparatus + || type == CSMWorld::UniversalId::Type_Armor + || type == CSMWorld::UniversalId::Type_Book + || type == CSMWorld::UniversalId::Type_Clothing + || type == CSMWorld::UniversalId::Type_Container + || type == CSMWorld::UniversalId::Type_Creature + || type == CSMWorld::UniversalId::Type_Door + || type == CSMWorld::UniversalId::Type_Ingredient + || type == CSMWorld::UniversalId::Type_CreatureLevelledList + || type == CSMWorld::UniversalId::Type_ItemLevelledList + || type == CSMWorld::UniversalId::Type_Light + || type == CSMWorld::UniversalId::Type_Lockpick + || type == CSMWorld::UniversalId::Type_Miscellaneous + || type == CSMWorld::UniversalId::Type_Npc + || type == CSMWorld::UniversalId::Type_Probe + || type == CSMWorld::UniversalId::Type_Repair + || type == CSMWorld::UniversalId::Type_Static + || type == CSMWorld::UniversalId::Type_Weapon) { type = CSMWorld::UniversalId::Type_Referenceable; } @@ -266,16 +266,20 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: if (delegateIt != mDelegates.end()) { editor = delegateIt->second->createEditor(qobject_cast(mParent), QStyleOptionViewItem(), index, display); + DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display); bool skip = false; if (qobject_cast(editor)) { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); + connect(editor, SIGNAL(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*)), proxy, SLOT(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*))); + connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); + skip = true; } if(!skip && qobject_cast(editor)) @@ -299,7 +303,9 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: skip = true; } //lisp cond pairs would be nice in the C++ - connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); + connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), + this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); + mProxys.push_back(proxy); //deleted in the destructor } return editor; @@ -326,7 +332,9 @@ mUndoStack(undoStack), mTable(table) { remake (row); - connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); + + connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), + this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); } void CSVWorld::EditWidget::remake(int row) @@ -345,6 +353,7 @@ void CSVWorld::EditWidget::remake(int row) mWidgetMapper = 0; } mWidgetMapper = new QDataWidgetMapper (this); + mWidgetMapper->setModel(mTable); mWidgetMapper->setItemDelegate(&mDispatcher); @@ -536,10 +545,14 @@ void CSVWorld::DialogueSubView::prevId() if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)) { mEditWidget->remake(newRow); + setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); + mEditWidget->setDisabled(mLocked); + return; } --newRow; @@ -568,10 +581,14 @@ void CSVWorld::DialogueSubView::nextId() if (!(state == CSMWorld::RecordBase::State_Deleted)) { mEditWidget->remake(newRow); + setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); + mEditWidget->setDisabled(mLocked); + return; } ++newRow; @@ -620,6 +637,7 @@ void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor, void CSVWorld::DialogueSubView::revertRecord() { const int rows = mTable->rowCount(); + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); if (!currentIndex.isValid()) @@ -643,6 +661,7 @@ void CSVWorld::DialogueSubView::revertRecord() if (mTable->rowCount() == 0) { mEditWidget->setDisabled(true); //closing the editor is other option + return; } if (currentIndex.row() >= mTable->rowCount()) @@ -676,6 +695,7 @@ void CSVWorld::DialogueSubView::deleteRecord() if (mTable->rowCount() == 0) { mEditWidget->setDisabled(true); //closing the editor is other option + return; } if (currentIndex.row() >= mTable->rowCount()) @@ -691,6 +711,7 @@ void CSVWorld::DialogueSubView::deleteRecord() void CSVWorld::DialogueSubView::requestFocus (const std::string& id) { mCurrentId = std::string(id); + mEditWidget->remake(mTable->getModelIndex (id, 0).row()); } From 7eb82f74aecfc97cadc014c8f13bfaaf50661016 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 16 Jun 2014 10:22:14 +0200 Subject: [PATCH 542/545] Fixed complitaion. --- apps/opencs/view/world/dialoguesubview.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 9d6538c1ce..e9910f42b5 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -600,12 +600,12 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) mLocked = locked; QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); - if (currentIndex.isValid()) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); + mCommandDispatcher.setEditLock (locked); } @@ -615,11 +615,12 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); if (currentIndex.isValid() && index.row() == currentIndex.row()) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); } } From 786c68f09a2f31c699c7753faa785d117f18b0e5 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 16 Jun 2014 11:31:57 +0200 Subject: [PATCH 543/545] refactoring dialogue subview --- apps/opencs/view/world/dialoguesubview.cpp | 20 ++++++++++++++++---- apps/opencs/view/world/dialoguesubview.hpp | 3 +++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index e9910f42b5..0f2ae73dde 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -448,7 +448,9 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType())) { connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); - mCurrentId = id.getId(); + + changeCurrentId(id.getId()); + QWidget *mainWidget = new QWidget(this); QHBoxLayout *buttonsLayout = new QHBoxLayout; @@ -509,7 +511,9 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this)); mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); + connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest())); if(!mBottom->canCreateAndDelete()) @@ -549,7 +553,7 @@ void CSVWorld::DialogueSubView::prevId() setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); + changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); mEditWidget->setDisabled(mLocked); @@ -585,7 +589,7 @@ void CSVWorld::DialogueSubView::nextId() setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - mCurrentId = std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()); + changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); mEditWidget->setDisabled(mLocked); @@ -615,7 +619,6 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - if (currentIndex.isValid() && index.row() == currentIndex.row()) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); @@ -746,3 +749,12 @@ void CSVWorld::DialogueSubView::viewRecord() emit focusId (params.first, params.second); } } + +void CSVWorld::DialogueSubView::changeCurrentId(const std::string& newId) +{ + std::vector selection; + mCurrentId = std::string(newId); + + selection.push_back(mCurrentId); + mCommandDispatcher.setSelection(selection); +} diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 2a9dd2e4f6..2fdceacb1e 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -181,6 +181,9 @@ namespace CSVWorld bool sorting = false); virtual void setEditLock (bool locked); + + private: + void changeCurrentId(const std::string& newCurrent); private slots: From d6288a805512b1113896c8f2d09b052045af7369 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 16 Jun 2014 11:58:55 +0200 Subject: [PATCH 544/545] Remove unneded revert and delete slots --- apps/opencs/view/world/dialoguesubview.cpp | 80 +--------------------- apps/opencs/view/world/dialoguesubview.hpp | 4 -- 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 0f2ae73dde..e798c83200 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -495,8 +495,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId())); connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId())); connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest())); - connect(revertButton, SIGNAL(clicked()), this, SLOT(revertRecord())); - connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteRecord())); + connect(revertButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeRevert())); + connect(deleteButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeDelete())); mMainLayout = new QVBoxLayout(mainWidget); @@ -638,83 +638,9 @@ void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor, } } -void CSVWorld::DialogueSubView::revertRecord() -{ - const int rows = mTable->rowCount(); - - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - if (!currentIndex.isValid()) - { - return; - } - - const int currentRow = currentIndex.row(); - - if (!mLocked && mTable->columnCount() > 0 && currentRow < mTable->rowCount() ) - { - CSMWorld::RecordBase::State state = - static_cast (mTable->data (mTable->index (currentRow, 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_BaseOnly) - { - mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mCurrentId)); - } - if (rows != mTable->rowCount()) - { - if (mTable->rowCount() == 0) - { - mEditWidget->setDisabled(true); //closing the editor is other option - - return; - } - if (currentIndex.row() >= mTable->rowCount()) - { - prevId(); - } else { - dataChanged(currentIndex); - } - } - } -} - -void CSVWorld::DialogueSubView::deleteRecord() -{ - const int rows = mTable->rowCount(); - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); - bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted); - - if (!mLocked && - currentIndex.isValid() && - mTable->columnCount() > 0 && - !deledetedOrErased && - currentIndex.row() < rows && - mBottom->canCreateAndDelete()) - { - mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mCurrentId)); - if (rows != mTable->rowCount()) - { - if (mTable->rowCount() == 0) - { - mEditWidget->setDisabled(true); //closing the editor is other option - - return; - } - if (currentIndex.row() >= mTable->rowCount()) - { - prevId(); - } else { - dataChanged(currentIndex); - } - } - } -} - void CSVWorld::DialogueSubView::requestFocus (const std::string& id) { - mCurrentId = std::string(id); + changeCurrentId(id); mEditWidget->remake(mTable->getModelIndex (id, 0).row()); } diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 2fdceacb1e..050aad947f 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -195,10 +195,6 @@ namespace CSVWorld void viewRecord(); - void revertRecord(); - - void deleteRecord(); - void cloneRequest(); void dataChanged(const QModelIndex & index); From bbe7854968d5ecb44b767bc1b64963fd8bceddcc Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Tue, 17 Jun 2014 10:46:54 +0200 Subject: [PATCH 545/545] Corrected formatting to follow our standard better. --- apps/opencs/view/world/dialoguesubview.cpp | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index e798c83200..bc2a6048ad 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -518,17 +518,17 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM if(!mBottom->canCreateAndDelete()) { - cloneButton->setDisabled(true); - addButton->setDisabled(true); - deleteButton->setDisabled(true); + cloneButton->setDisabled (true); + addButton->setDisabled (true); + deleteButton->setDisabled (true); } - dataChanged(mTable->getModelIndex(mCurrentId, 0)); - mMainLayout->addLayout(buttonsLayout); - setWidget(mainWidget); + dataChanged(mTable->getModelIndex (mCurrentId, 0)); + mMainLayout->addLayout (buttonsLayout); + setWidget (mainWidget); } -void CSVWorld::DialogueSubView::prevId() +void CSVWorld::DialogueSubView::prevId () { int newRow = mTable->getModelIndex(mCurrentId, 0).row() - 1; @@ -563,7 +563,7 @@ void CSVWorld::DialogueSubView::prevId() } } -void CSVWorld::DialogueSubView::nextId() +void CSVWorld::DialogueSubView::nextId () { int newRow = mTable->getModelIndex(mCurrentId, 0).row() + 1; @@ -615,7 +615,7 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) } -void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) +void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); @@ -627,10 +627,10 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) } } -void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor, - const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document) +void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, + const QModelIndex& index, + const CSMWorld::UniversalId& id, + const CSMDoc::Document* document) { if (document == &mDocument) { @@ -662,9 +662,9 @@ void CSVWorld::DialogueSubView::showPreview () } } -void CSVWorld::DialogueSubView::viewRecord() +void CSVWorld::DialogueSubView::viewRecord () { - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + QModelIndex currentIndex(mTable->getModelIndex (mCurrentId, 0)); if (currentIndex.isValid() && currentIndex.row() < mTable->rowCount()) @@ -676,7 +676,7 @@ void CSVWorld::DialogueSubView::viewRecord() } } -void CSVWorld::DialogueSubView::changeCurrentId(const std::string& newId) +void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId) { std::vector selection; mCurrentId = std::string(newId);