From 4e7ee970504334321c15654ce2ecceddcebfe783 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Mon, 14 Apr 2014 17:18:29 +0400 Subject: [PATCH 001/484] 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 caa082646..3ff583264 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 1ceeeb4a224753c6df6fae64c3bf2f6d9929fa74 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 13 Apr 2014 07:35:26 +1000 Subject: [PATCH 002/484] Fix movement glitches for actors with low speeds (e.g. a rat). Was caused by false detection of being stuck. --- apps/openmw/mwmechanics/aiwander.cpp | 30 ++++++++++++++++++---------- apps/openmw/mwmechanics/aiwander.hpp | 3 ++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index e89d43ca4..c50506c75 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -35,6 +35,7 @@ namespace MWMechanics , mPrevX(0) , mPrevY(0) , mWalkState(State_Norm) + , mDistSameSpot(0) , mStuckCount(0) , mEvadeDuration(0) , mStuckDuration(0) @@ -71,7 +72,6 @@ namespace MWMechanics return new AiWander(*this); } - // TODO: duration is passed in but never used, check if it is needed bool AiWander::execute (const MWWorld::Ptr& actor,float duration) { actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); @@ -113,7 +113,9 @@ namespace MWMechanics mCellX = actor.getCell()->getCell()->mData.mX; mCellY = actor.getCell()->getCell()->mData.mY; - // TODO: If there is no path does this actor get stuck forever? + // If there is no path this actor doesn't go anywhere. See: + // https://forum.openmw.org/viewtopic.php?t=1556 + // http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833 if(!mPathgrid) mDistance = 0; else if(mPathgrid->mPoints.empty()) @@ -166,7 +168,7 @@ namespace MWMechanics } } - // TODO: Does this actor stay in one spot forever while in AiWander? + // Actor becomes stationary - see above URL's for previous research if(mAllowedNodes.empty()) mDistance = 0; @@ -277,8 +279,10 @@ namespace MWMechanics { assert(mAllowedNodes.size()); unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size()); + // NOTE: destNodePos initially constructed with local (i.e. cell) co-ordinates Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ); + // convert dest to use world co-ordinates ESM::Pathgrid::Point dest; dest.mX = destNodePos[0] + mXCell; dest.mY = destNodePos[1] + mYCell; @@ -338,9 +342,15 @@ namespace MWMechanics * f = one frame * t = how long before considered stuck * u = how long to move sideways + * + * DIST_SAME_SPOT is calibrated for movement speed of around 150. + * A rat has walking speed of around 30, so we need to adjust for + * that. */ - bool samePosition = (abs(pos.pos[0] - mPrevX) < DIST_SAME_SPOT) && - (abs(pos.pos[1] - mPrevY) < DIST_SAME_SPOT); + if(!mDistSameSpot) + mDistSameSpot = DIST_SAME_SPOT * (actor.getClass().getSpeed(actor) / 150); + bool samePosition = (abs(pos.pos[0] - mPrevX) < mDistSameSpot) && + (abs(pos.pos[1] - mPrevY) < mDistSameSpot); switch(mWalkState) { @@ -364,14 +374,14 @@ namespace MWMechanics { mStuckDuration += duration; // consider stuck only if position unchanges for a period - if(mStuckDuration > DURATION_SAME_SPOT) + if(mStuckDuration < DURATION_SAME_SPOT) + break; // still checking, note duration added to timer + else { - mWalkState = State_Evade; mStuckDuration = 0; mStuckCount++; + mWalkState = State_Evade; } - else - break; // still in the same state, but duration added to timer } } /* FALL THROUGH */ @@ -395,7 +405,7 @@ namespace MWMechanics // diagonal should have same animation as walk forward actor.getClass().getMovementSettings(actor).mPosition[0] = 1; - actor.getClass().getMovementSettings(actor).mPosition[1] = 0.01f; + 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]))); } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 75621911e..dd718a677 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -58,8 +58,9 @@ namespace MWMechanics WalkState mWalkState; int mStuckCount; - float mStuckDuration; + float mStuckDuration; // accumulate time here while in same spot float mEvadeDuration; + float mDistSameSpot; // take account of actor's speed bool mStoredAvailableNodes; bool mChooseAction; From d3be725ee72f157afe14524e7955b885b46a4499 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 18 Apr 2014 09:03:36 +1000 Subject: [PATCH 003/484] Actors are moved on if idling near a closed interior door. Unreachable pathgrid points due to a closed door are removed from the allowed set of points. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 415 ++++++++++++++++----------- apps/openmw/mwmechanics/aiwander.hpp | 39 ++- apps/openmw/mwmechanics/obstacle.cpp | 176 ++++++++++++ apps/openmw/mwmechanics/obstacle.hpp | 52 ++++ 5 files changed, 487 insertions(+), 197 deletions(-) create mode 100644 apps/openmw/mwmechanics/obstacle.cpp create mode 100644 apps/openmw/mwmechanics/obstacle.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9fabb2080..e83ae2d8d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -69,7 +69,7 @@ add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting - disease pickpocket levelledlist combat steering + disease pickpocket levelledlist combat steering obstacle ) add_openmw_dir (mwstate diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index c50506c75..029be2fb8 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -17,11 +17,8 @@ namespace MWMechanics { - // NOTE: determined empirically but probably need further tweaking - static const int COUNT_BEFORE_RESET = 200; - static const float DIST_SAME_SPOT = 1.8f; - static const float DURATION_SAME_SPOT = 1.0f; - static const float DURATION_TO_EVADE = 0.4f; + static const int COUNT_BEFORE_RESET = 200; // TODO: maybe no longer needed + static const float DOOR_CHECK_INTERVAL = 1.5f; AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat) @@ -29,16 +26,10 @@ namespace MWMechanics , mCellY(std::numeric_limits::max()) , mXCell(0) , mYCell(0) - , mX(0) - , mY(0) - , mZ(0) - , mPrevX(0) - , mPrevY(0) - , mWalkState(State_Norm) - , mDistSameSpot(0) - , mStuckCount(0) - , mEvadeDuration(0) - , mStuckDuration(0) + , mCell(NULL) + , mStuckCount(0) // TODO: maybe no longer needed + , mDoorCheckDuration(0) + , mTrimCurrentNode(false) , mSaidGreeting(false) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) @@ -56,7 +47,7 @@ namespace MWMechanics mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); mPlayedIdle = 0; - mPathgrid = NULL; + //mPathgrid = NULL; mIdleChanceMultiplier = MWBase::Environment::get().getWorld()->getStore().get().find("fIdleChanceMultiplier")->getFloat(); @@ -72,10 +63,71 @@ namespace MWMechanics return new AiWander(*this); } + /* + * AiWander high level states (0.29.0). Not entirely accurate in some cases + * e.g. non-NPC actors do not greet and some creatures may be moving even in + * the IdleNow state. + * + * [select node, + * build path] + * +---------->MoveNow----------->Walking + * | | + * [allowed | | + * nodes] | [hello if near] | + * start--->ChooseAction----->IdleNow | + * ^ ^ | | + * | | | | + * | +-----------+ | + * | | + * +----------------------------------+ + * + * + * New high level states. Not exactly as per vanilla (e.g. door stuff) + * but the differences are required because our physics does not work like + * vanilla and therefore have to compensate/work around. Note also many of + * the actions now have reaction times. + * + * [select node, [if stuck evade + * build path] or remove nodes if near door] + * +---------->MoveNow<---------->Walking + * | ^ | | + * | |(near door) | | + * [allowed | | | | + * nodes] | [hello if near] | | + * start--->ChooseAction----->IdleNow | | + * ^ ^ | ^ | | + * | | | | (stuck near | | + * | +-----------+ +---------------+ | + * | player) | + * +----------------------------------+ + * + * TODO: non-time critical operations should be run once every 250ms or so. + * + * TODO: It would be great if door opening/closing can be detected and pathgrid + * links dynamically updated. Currently (0.29.0) AiWander allows destination + * beyond closed doors which sometimes makes the actors stuck at the door and + * impossible for the player to open the door. + * + * For now detect being stuck at the door and simply delete the nodes from the + * allowed set. The issue is when the door opens the allowed set is not + * re-calculated. Normally this would not be an issue since hostile actors will + * enter combat (i.e. no longer wandering) + * + * FIXME: Sometimes allowed nodes that shouldn't be deleted are deleted. + */ bool AiWander::execute (const MWWorld::Ptr& actor,float duration) { - actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); - actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); + bool cellChange = mCell && (actor.getCell() != mCell); + if(!mCell || cellChange) + { + mCell = actor.getCell(); + mStoredAvailableNodes = false; // prob. not needed since mDistance = 0 + } + const ESM::Cell *cell = mCell->getCell(); + + MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor); + cStats.setDrawState(DrawState_Nothing); + cStats.setMovementFlag(CreatureStats::Flag_Run, false); MWBase::World *world = MWBase::Environment::get().getWorld(); if(mDuration) { @@ -105,65 +157,76 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); - // Once off initialization to discover & store allowed node points for this actor. + // Initialization to discover & store allowed node points for this actor. if(!mStoredAvailableNodes) { - mPathgrid = world->getStore().get().search(*actor.getCell()->getCell()); + // infrequently used, therefore no benefit in caching it as a member + const ESM::Pathgrid * + pathgrid = world->getStore().get().search(*cell); - mCellX = actor.getCell()->getCell()->mData.mX; - mCellY = actor.getCell()->getCell()->mData.mY; + // cache the current cell location + mCellX = cell->mData.mX; + mCellY = cell->mData.mY; // If there is no path this actor doesn't go anywhere. See: // https://forum.openmw.org/viewtopic.php?t=1556 // http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833 - if(!mPathgrid) - mDistance = 0; - else if(mPathgrid->mPoints.empty()) + if(!pathgrid || pathgrid->mPoints.empty()) mDistance = 0; - if(mDistance) // A distance value is initially passed into the constructor. + // A distance value passed into the constructor indicates how far the + // actor can wander from the spawn position. AiWander assumes that + // pathgrid points are available, and uses them to randomly select wander + // destinations within the allowed set of pathgrid points (nodes). + if(mDistance) { mXCell = 0; mYCell = 0; - if(actor.getCell()->getCell()->isExterior()) + if(cell->isExterior()) { mXCell = mCellX * ESM::Land::REAL_SIZE; mYCell = mCellY * ESM::Land::REAL_SIZE; } - // convert npcPos to local (i.e. cell) co-ordinates - Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos); - npcPos[0] = npcPos[0] - mXCell; - npcPos[1] = npcPos[1] - mYCell; - - // populate mAllowedNodes for this actor with pathgrid point indexes based on mDistance - // NOTE: mPoints and mAllowedNodes contain points in local co-ordinates - for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++) + // convert actorPos to local (i.e. cell) co-ordinates + Ogre::Vector3 actorPos(pos.pos); + actorPos[0] = actorPos[0] - mXCell; + actorPos[1] = actorPos[1] - mYCell; + + // mAllowedNodes for this actor with pathgrid point indexes + // based on mDistance + // NOTE: mPoints and mAllowedNodes are in local co-ordinates + float closestNodeDist = -1; + unsigned int closestIndex = 0; + unsigned int indexAllowedNodes = 0; + for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) { - Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, - mPathgrid->mPoints[counter].mY, - mPathgrid->mPoints[counter].mZ); - if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance) - mAllowedNodes.push_back(mPathgrid->mPoints[counter]); + float sqrDist = actorPos.squaredDistance(Ogre::Vector3( + pathgrid->mPoints[counter].mX, + pathgrid->mPoints[counter].mY, + pathgrid->mPoints[counter].mZ)); + if(sqrDist <= (mDistance * mDistance)) + { + mAllowedNodes.push_back(pathgrid->mPoints[counter]); + // keep track of the closest node + if(closestNodeDist == -1 || sqrDist < closestNodeDist) + { + closestNodeDist = sqrDist; + closestIndex = indexAllowedNodes; + } + indexAllowedNodes++; + } } if(!mAllowedNodes.empty()) { - Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ); - float closestNode = npcPos.squaredDistance(firstNodePos); - unsigned int index = 0; - for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++) - { - Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, - mAllowedNodes[counterThree].mY, - mAllowedNodes[counterThree].mZ); - float tempDist = npcPos.squaredDistance(nodePos); - if(tempDist < closestNode) - index = counterThree; - } - mCurrentNode = mAllowedNodes[index]; - mAllowedNodes.erase(mAllowedNodes.begin() + index); - - mStoredAvailableNodes = true; // set only if successful in finding allowed nodes + // Start with the closest node and remove it from the allowed set + // so that it does not get selected again. The removed node will + // later be put in the back of the queue, unless it gets removed + // due to inaccessibility (e.g. a closed door) + mCurrentNode = mAllowedNodes[closestIndex]; + mAllowedNodes.erase(mAllowedNodes.begin() + closestIndex); + // set only if successful in finding allowed nodes + mStoredAvailableNodes = true; } } } @@ -173,10 +236,10 @@ namespace MWMechanics mDistance = 0; // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles. - if(mDistance && (mCellX != actor.getCell()->getCell()->mData.mX || mCellY != actor.getCell()->getCell()->mData.mY)) + if(mDistance && cellChange) mDistance = 0; - if(mChooseAction) // Initially set true by the constructor. + if(mChooseAction) { mPlayedIdle = 0; unsigned short idleRoll = 0; @@ -207,7 +270,7 @@ namespace MWMechanics mIdleNow = true; // Play idle voiced dialogue entries randomly - int hello = actor.getClass().getCreatureStats(actor).getAiSetting(CreatureStats::AI_Hello).getModified(); + int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); if (hello > 0) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -216,19 +279,38 @@ namespace MWMechanics MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); // Don't bother if the player is out of hearing range - if (roll < chance && Ogre::Vector3(player.getRefData().getPosition().pos).distance(Ogre::Vector3(actor.getRefData().getPosition().pos)) < 1500) + if (roll < chance && Ogre::Vector3(player.getRefData().getPosition().pos).distance(Ogre::Vector3(pos.pos)) < 1500) MWBase::Environment::get().getDialogueManager()->say(actor, "idle"); } } } + // Check if an idle actor is too close to a door - if so start walking + mDoorCheckDuration += duration; + if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL) + { + mDoorCheckDuration = 0; // restart timer + if(mDistance && // actor is not intended to be stationary + mIdleNow && // but is in idle + !mWalking && // FIXME: some actors are idle while walking + proximityToDoor(actor)) // NOTE: checks interior cells only + { + mIdleNow = false; + mMoveNow = true; + mTrimCurrentNode = false; // just in case +//#if 0 + std::cout << "idle door \""+actor.getClass().getName(actor)+"\" "<< std::endl; +//#endif + } + } + // Allow interrupting a walking actor to trigger a greeting - if(mIdleNow || (mWalking && (mWalkState != State_Norm))) + if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState())) { // Play a random voice greeting if the player gets too close const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - int hello = actor.getClass().getCreatureStats(actor).getAiSetting(CreatureStats::AI_Hello).getModified(); + int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); float helloDistance = hello; int iGreetDistanceMultiplier = store.get().find("iGreetDistanceMultiplier")->getInt(); helloDistance *= iGreetDistanceMultiplier; @@ -242,7 +324,7 @@ namespace MWMechanics stopWalking(actor); mMoveNow = false; mWalking = false; - mWalkState = State_Norm; + mObstacleCheck.clear(); } if (!mSaidGreeting) @@ -275,12 +357,15 @@ namespace MWMechanics if(mMoveNow && mDistance) { + // Construct a new path if there isn't one if(!mPathFinder.isPathConstructed()) { assert(mAllowedNodes.size()); unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size()); - // NOTE: destNodePos initially constructed with local (i.e. cell) co-ordinates - Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ); + // NOTE: initially constructed with local (i.e. cell) co-ordinates + Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, + mAllowedNodes[randNode].mY, + mAllowedNodes[randNode].mZ); // convert dest to use world co-ordinates ESM::Pathgrid::Point dest; @@ -299,16 +384,27 @@ namespace MWMechanics if(mPathFinder.isPathConstructed()) { - // buildPath inserts dest in case it is not a pathgraph point index - // which is a duplicate for AiWander + // buildPath inserts dest in case it is not a pathgraph point + // index which is a duplicate for AiWander. However below code + // does not work since getPath() returns a copy of path not a + // reference //if(mPathFinder.getPathSize() > 1) //mPathFinder.getPath().pop_back(); - // Remove this node as an option and add back the previously used node - // (stops NPC from picking the same node): + // Remove this node as an option and add back the previously used node (stops NPC from picking the same node): ESM::Pathgrid::Point temp = mAllowedNodes[randNode]; mAllowedNodes.erase(mAllowedNodes.begin() + randNode); - mAllowedNodes.push_back(mCurrentNode); + // check if mCurrentNode was taken out of mAllowedNodes + if(mTrimCurrentNode && mAllowedNodes.size() > 1) + { + mTrimCurrentNode = false; +#if 0 + std::cout << "deleted "<< std::to_string(mCurrentNode.mX) + +", "+std::to_string(mCurrentNode.mY) << std::endl; +#endif + } + else + mAllowedNodes.push_back(mCurrentNode); mCurrentNode = temp; mMoveNow = false; @@ -320,124 +416,97 @@ namespace MWMechanics } } - if(mWalking) + // Are we there yet? + if(mWalking && + mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - stopWalking(actor); - mMoveNow = false; - mWalking = false; - mChooseAction = true; - } - else + stopWalking(actor); + mMoveNow = false; + mWalking = false; + mChooseAction = true; + } + else if(mWalking) // have not yet reached the destination + { + // turn towards the next point in mPath + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + + // Returns true if evasive action needs to be taken + if(mObstacleCheck.check(actor, duration)) { - /* f t - * State_Norm <---> State_CheckStuck --> State_Evade - * ^ ^ | ^ | ^ | | - * | | | | | | | | - * | +---+ +---+ +---+ | u - * | any < t < u | - * +--------------------------------------------+ - * - * f = one frame - * t = how long before considered stuck - * u = how long to move sideways - * - * DIST_SAME_SPOT is calibrated for movement speed of around 150. - * A rat has walking speed of around 30, so we need to adjust for - * that. - */ - if(!mDistSameSpot) - mDistSameSpot = DIST_SAME_SPOT * (actor.getClass().getSpeed(actor) / 150); - bool samePosition = (abs(pos.pos[0] - mPrevX) < mDistSameSpot) && - (abs(pos.pos[1] - mPrevY) < mDistSameSpot); - - switch(mWalkState) + // first check if we're walking into a door + if(proximityToDoor(actor)) // NOTE: checks interior cells only { - case State_Norm: - { - if(!samePosition) - break; - else - mWalkState = State_CheckStuck; - } - /* FALL THROUGH */ - case State_CheckStuck: - { - if(!samePosition) - { - mWalkState = State_Norm; - mStuckDuration = 0; - break; - } - else - { - mStuckDuration += duration; - // consider stuck only if position unchanges for a period - if(mStuckDuration < DURATION_SAME_SPOT) - break; // still checking, note duration added to timer - else - { - mStuckDuration = 0; - mStuckCount++; - mWalkState = State_Evade; - } - } - } - /* FALL THROUGH */ - case State_Evade: - { - mEvadeDuration += duration; - if(mEvadeDuration < DURATION_TO_EVADE) - break; - else - { - mWalkState = State_Norm; // tried to evade, assume all is ok and start again - mEvadeDuration = 0; - } - } - /* NO DEFAULT CASE */ + // remove allowed points then select another random destination + mTrimCurrentNode = true; + trimAllowedNodes(mAllowedNodes, mPathFinder); + mObstacleCheck.clear(); + mPathFinder.clearPath(); + mWalking = false; + mMoveNow = true; } - - if(mWalkState == State_Evade) + else // probably walking into another NPC { - //std::cout << "Stuck \""<= COUNT_BEFORE_RESET) // something has gone wrong, reset + { + //std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl; + mObstacleCheck.clear(); - if(mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset - { - //std::cout << "Reset \""<& nodes, + const PathFinder& pathfinder) + { +//#if 0 + std::cout << "allowed size "<< std::to_string(nodes.size()) << std::endl; +//#endif + // TODO: how to add these back in once the door opens? + std::list paths = pathfinder.getPath(); + while(paths.size() >= 2) + { + ESM::Pathgrid::Point pt = paths.back(); +#if 0 + std::cout << "looking for "<< + "pt "+std::to_string(pt.mX)+", "+std::to_string(pt.mY) + < #include "pathfinding.hpp" +#include "obstacle.hpp" #include "../mwworld/timestamp.hpp" @@ -26,7 +27,7 @@ namespace MWMechanics void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect); - int mDistance; + int mDistance; // how far the actor can wander from the spawn point int mDuration; int mTimeOfDay; std::vector mIdle; @@ -34,35 +35,18 @@ namespace MWMechanics bool mSaidGreeting; - float mX; - float mY; - float mZ; - - // Cell location + // Cached current cell location int mCellX; int mCellY; // Cell location multiplied by ESM::Land::REAL_SIZE float mXCell; float mYCell; - // for checking if we're stuck (but don't check Z axis) - float mPrevX; - float mPrevY; - - enum WalkState - { - State_Norm, - State_CheckStuck, - State_Evade - }; - WalkState mWalkState; - - int mStuckCount; - float mStuckDuration; // accumulate time here while in same spot - float mEvadeDuration; - float mDistSameSpot; // take account of actor's speed + const MWWorld::CellStore* mCell; // for detecting cell change + // if false triggers calculating allowed nodes based on mDistance bool mStoredAvailableNodes; + // AiWander states bool mChooseAction; bool mIdleNow; bool mMoveNow; @@ -73,12 +57,21 @@ namespace MWMechanics MWWorld::TimeStamp mStartTime; + // allowed pathgrid nodes based on mDistance from the spawn point std::vector mAllowedNodes; ESM::Pathgrid::Point mCurrentNode; + bool mTrimCurrentNode; + void trimAllowedNodes(std::vector& nodes, + const PathFinder& pathfinder); PathFinder mPathFinder; - const ESM::Pathgrid *mPathgrid; + //const ESM::Pathgrid *mPathgrid; + + ObstacleCheck mObstacleCheck; + float mDoorCheckDuration; + int mStuckCount; + //float mReaction; }; } diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp new file mode 100644 index 000000000..00f97ae01 --- /dev/null +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -0,0 +1,176 @@ +#include "obstacle.hpp" + +#include + +#include "../mwbase/world.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" + +namespace MWMechanics +{ + // NOTE: determined empirically but probably need further tweaking + static const float DIST_SAME_SPOT = 1.8f; + static const float DURATION_SAME_SPOT = 1.0f; + static const float DURATION_TO_EVADE = 0.4f; + + // Proximity check function for interior doors. Given that most interior cells + // do not have many doors performance shouldn't be too much of an issue. + // + // 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) + { + MWWorld::CellStore *cell = actor.getCell(); + + if(cell->getCell()->isExterior()) + return false; // check interior cells only + + // Check all the doors in this cell + MWWorld::CellRefList& doors = cell->get(); + MWWorld::CellRefList::List& refList = doors.mList; + 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. + //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:: + for (; it != refList.end(); ++it) + { + MWWorld::LiveCellRef& ref = *it; + if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && + ref.mData.getLocalRotation().rot[2] == (closed ? 0 : 1)) + { +//#if 0 + std::cout << "\""+actor.getClass().getName(actor)+"\" " + <<"next to door "+ref.mRef.mRefID + //+", enabled? "+std::to_string(ref.mData.isEnabled()) + +", dist "+std::to_string(sqrt(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)))) + << std::endl; +//#endif + return true; // found, stop searching + } + } + return false; // none found + } + + ObstacleCheck::ObstacleCheck(): + mPrevX(0) // to see if the moved since last time + , mPrevY(0) + , mDistSameSpot(-1) // avoid calculating it each time + , mWalkState(State_Norm) + , mStuckDuration(0) + , mEvadeDuration(0) + { + } + + void ObstacleCheck::clear() + { + mWalkState = State_Norm; + mStuckDuration = 0; + mEvadeDuration = 0; + } + + bool ObstacleCheck::isNormalState() const + { + return mWalkState == State_Norm; + } + + /* + * input - actor, duration (time since last check) + * output - true if evasive action needs to be taken + * + * Walking state transitions (player greeting check not shown): + * + * MoveNow <------------------------------------+ + * | d| + * | | + * +-> State_Norm <---> State_CheckStuck --> State_Evade + * ^ ^ | f ^ | t ^ | | + * | | | | | | | | + * | +---+ +---+ +---+ | u + * | any < t < u | + * +--------------------------------------------+ + * + * f = one reaction time + * d = proximity to a closed door + * t = how long before considered stuck + * u = how long to move sideways + * + * DIST_SAME_SPOT is calibrated for movement speed of around 150. + * A rat has walking speed of around 30, so we need to adjust for + * that. + */ + bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration) + { + const MWWorld::Class& cls = actor.getClass(); + ESM::Position pos = actor.getRefData().getPosition(); + + if(mDistSameSpot == -1) + mDistSameSpot = DIST_SAME_SPOT * (cls.getSpeed(actor) / 150); + + bool samePosition = (abs(pos.pos[0] - mPrevX) < mDistSameSpot) && + (abs(pos.pos[1] - mPrevY) < mDistSameSpot); + // update position + mPrevX = pos.pos[0]; + mPrevY = pos.pos[1]; + + switch(mWalkState) + { + case State_Norm: + { + if(!samePosition) + break; + else + mWalkState = State_CheckStuck; + } + /* FALL THROUGH */ + case State_CheckStuck: + { + if(!samePosition) + { + mWalkState = State_Norm; + mStuckDuration = 0; + break; + } + else + { + mStuckDuration += duration; + // consider stuck only if position unchanges for a period + if(mStuckDuration < DURATION_SAME_SPOT) + break; // still checking, note duration added to timer + else + { + mStuckDuration = 0; + mWalkState = State_Evade; + } + } + } + /* FALL THROUGH */ + case State_Evade: + { + mEvadeDuration += duration; + if(mEvadeDuration < DURATION_TO_EVADE) + return true; + else + { +//#if 0 + std::cout << "evade \""+actor.getClass().getName(actor)+"\" " + //<<"dist spot "+std::to_string(mDistSameSpot) + //+", speed "+std::to_string(cls.getSpeed(actor)) + << std::endl; +//#endif + // tried to evade, assume all is ok and start again + mWalkState = State_Norm; + mEvadeDuration = 0; + } + } + /* NO DEFAULT CASE */ + } + return false; // no obstacles to evade (yet) + } +} diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp new file mode 100644 index 000000000..920e2e794 --- /dev/null +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -0,0 +1,52 @@ +#ifndef OPENMW_MECHANICS_OBSTACLE_H + +namespace MWWorld +{ + class Ptr; +} + +namespace MWMechanics +{ + // 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 + bool proximityToDoor(const MWWorld::Ptr& actor, + float minSqr = MIN_DIST_TO_DOOR_SQUARED, + bool closed = true); + + class ObstacleCheck + { + public: + ObstacleCheck(); + + // Clear the timers and set the state machine to default + void clear(); + + bool isNormalState() const; + + // Returns true if there is an obstacle and an evasive action + // should be taken + bool check(const MWWorld::Ptr& actor, float duration); + + private: + + // for checking if we're stuck (ignoring Z axis) + float mPrevX; + float mPrevY; + + enum WalkState + { + State_Norm, + State_CheckStuck, + State_Evade + }; + WalkState mWalkState; + + float mStuckDuration; // accumulate time here while in same spot + float mEvadeDuration; + float mDistSameSpot; // take account of actor's speed + }; +} + +#endif From aad13d315c4a19d8dc55be4ca4f7f1483373ee18 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 18 Apr 2014 14:25:08 +1000 Subject: [PATCH 004/484] Fixed issue where allowed nodes were being erased. PathFinder was returning an empty path if the closest pathgrid point to the start was also the closest pathgrid point to the goal. Still need to clean up and remove logging statements. --- apps/openmw/mwmechanics/aiwander.cpp | 101 ++++++++++++++---------- apps/openmw/mwmechanics/pathfinding.cpp | 42 +++++++++- apps/openmw/mwmechanics/pathgrid.cpp | 14 ++++ 3 files changed, 115 insertions(+), 42 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 029be2fb8..c25821b4e 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -112,11 +112,13 @@ namespace MWMechanics * allowed set. The issue is when the door opens the allowed set is not * re-calculated. Normally this would not be an issue since hostile actors will * enter combat (i.e. no longer wandering) - * - * FIXME: Sometimes allowed nodes that shouldn't be deleted are deleted. */ bool AiWander::execute (const MWWorld::Ptr& actor,float duration) { + MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor); + if(cStats.isDead() || cStats.getHealth().getCurrent() <= 0) + return true; // Don't bother with dead actors + bool cellChange = mCell && (actor.getCell() != mCell); if(!mCell || cellChange) { @@ -125,7 +127,6 @@ namespace MWMechanics } const ESM::Cell *cell = mCell->getCell(); - MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor); cStats.setDrawState(DrawState_Nothing); cStats.setMovementFlag(CreatureStats::Flag_Run, false); MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -188,45 +189,56 @@ namespace MWMechanics mYCell = mCellY * ESM::Land::REAL_SIZE; } - // convert actorPos to local (i.e. cell) co-ordinates - Ogre::Vector3 actorPos(pos.pos); - actorPos[0] = actorPos[0] - mXCell; - actorPos[1] = actorPos[1] - mYCell; - - // mAllowedNodes for this actor with pathgrid point indexes - // based on mDistance + // FIXME: There might be a bug here. The allowed node points are + // based on the actor's current position rather than the actor's + // spawn point. As a result the allowed nodes for wander can change + // between saves, for example. + // + // convert npcPos to local (i.e. cell) co-ordinates + Ogre::Vector3 npcPos(pos.pos); + npcPos[0] = npcPos[0] - mXCell; + npcPos[1] = npcPos[1] - mYCell; + + // mAllowedNodes for this actor with pathgrid point indexes based on mDistance // NOTE: mPoints and mAllowedNodes are in local co-ordinates - float closestNodeDist = -1; - unsigned int closestIndex = 0; - unsigned int indexAllowedNodes = 0; for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) { - float sqrDist = actorPos.squaredDistance(Ogre::Vector3( - pathgrid->mPoints[counter].mX, - pathgrid->mPoints[counter].mY, - pathgrid->mPoints[counter].mZ)); - if(sqrDist <= (mDistance * mDistance)) - { + Ogre::Vector3 nodePos(pathgrid->mPoints[counter].mX, pathgrid->mPoints[counter].mY, + pathgrid->mPoints[counter].mZ); + if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance) mAllowedNodes.push_back(pathgrid->mPoints[counter]); - // keep track of the closest node - if(closestNodeDist == -1 || sqrDist < closestNodeDist) - { - closestNodeDist = sqrDist; - closestIndex = indexAllowedNodes; - } - indexAllowedNodes++; - } } if(!mAllowedNodes.empty()) { - // Start with the closest node and remove it from the allowed set - // so that it does not get selected again. The removed node will - // later be put in the back of the queue, unless it gets removed - // due to inaccessibility (e.g. a closed door) - mCurrentNode = mAllowedNodes[closestIndex]; - mAllowedNodes.erase(mAllowedNodes.begin() + closestIndex); - // set only if successful in finding allowed nodes - mStoredAvailableNodes = true; + Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ); + float closestNode = npcPos.squaredDistance(firstNodePos); + unsigned int index = 0; + for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++) + { + Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY, + mAllowedNodes[counterThree].mZ); + float tempDist = npcPos.squaredDistance(nodePos); + if(tempDist < closestNode) + index = counterThree; + } +#if 0 + if(actor.getClass().getName(actor) == "Rat") + { + std::cout << "rat allowed "<< std::to_string(mAllowedNodes.size()) + +" mDist "+std::to_string(mDistance) + +" pos "+std::to_string(static_cast(npcPos[0])) + +", "+std::to_string(static_cast(npcPos[1])) + < 1) { mTrimCurrentNode = false; -#if 0 +//#if 0 std::cout << "deleted "<< std::to_string(mCurrentNode.mX) +", "+std::to_string(mCurrentNode.mY) << std::endl; -#endif +//#endif +//#if 0 + std::cout << "allowed size "<< + std::to_string(mAllowedNodes.size()) << std::endl; +//#endif } else mAllowedNodes.push_back(mCurrentNode); @@ -412,7 +428,15 @@ namespace MWMechanics } // Choose a different node and delete this one from possible nodes because it is uncreachable: else + { mAllowedNodes.erase(mAllowedNodes.begin() + randNode); +//#if 0 + //std::cout << "actor \""<< actor.getClass().getName(actor) << "\"" << std::endl; + if(actor.getClass().getName(actor) == "Rat") + std::cout << "erase no path "<< std::to_string(mAllowedNodes[randNode].mX) + +", "+std::to_string(mAllowedNodes[randNode].mY) << std::endl; +//#endif + } } } @@ -477,9 +501,6 @@ namespace MWMechanics void AiWander::trimAllowedNodes(std::vector& nodes, const PathFinder& pathfinder) { -//#if 0 - std::cout << "allowed size "<< std::to_string(nodes.size()) << std::endl; -//#endif // TODO: how to add these back in once the door opens? std::list paths = pathfinder.getPath(); while(paths.size() >= 2) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 730b8cb92..3a67a9b72 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -100,8 +100,11 @@ namespace } } } - if(start == closestReachableIndex) - closestReachableIndex = -1; // couldn't find anyting other than start + // AiWander has logic that depends on whether a path was created, deleting + // allowed nodes if not. Hence a path needs to be created even if the start + // and the end points are the same. + //if(start == closestReachableIndex) + //closestReachableIndex = -1; // couldn't find anyting other than start return std::pair (closestReachableIndex, closestReachableIndex == closestIndex); @@ -224,6 +227,18 @@ namespace MWMechanics // this shouldn't really happen, but just in case if(endNode.first != -1) { + // AiWander has logic that depends on whether a path was created, + // deleting allowed nodes if not. Hence a path needs to be created + // even if the start and the end points are the same. + // NOTE: aStarSearch will return an empty path if the start and end + // nodes are the same + if(startNode == endNode.first) + { + mPath.push_back(endPoint); + mIsPathConstructed = true; + return; + } + mPath = mCell->aStarSearch(startNode, endNode.first); if(!mPath.empty()) @@ -243,9 +258,32 @@ namespace MWMechanics } else mIsPathConstructed = false; +#if 0 + { + mIsPathConstructed = false; + std::cout << "no path "<< + std::to_string(startPoint.mX-xCell) + +", "+std::to_string(startPoint.mY-yCell) + +", "+std::to_string(startNode) + +", "+std::to_string(endPoint.mX-xCell) + +", "+std::to_string(endPoint.mY-yCell) + +", "+std::to_string(endNode.first)<mName == "Gnisis, Arvs-Drelen") + for(unsigned int v = 0; v < mPathgrid->mPoints.size(); v++) + { + std::cout << "SCC \"X:" << + std::to_string(mPathgrid->mPoints[v].mX) + +", Y:"+std::to_string(mPathgrid->mPoints[v].mY) + +", Num:"+std::to_string(mSCCId) + +", Point:"+std::to_string(v) + +", Group:"+std::to_string(mGraph[v].componentId) + <<"\""< Date: Fri, 18 Apr 2014 14:35:27 +1000 Subject: [PATCH 005/484] Cleaned up logging statements. --- apps/openmw/mwmechanics/aiwander.cpp | 45 ------------------------- apps/openmw/mwmechanics/pathfinding.cpp | 23 ------------- apps/openmw/mwmechanics/pathgrid.cpp | 14 -------- 3 files changed, 82 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index c25821b4e..276d1fac6 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -221,21 +221,7 @@ namespace MWMechanics if(tempDist < closestNode) index = counterThree; } -#if 0 - if(actor.getClass().getName(actor) == "Rat") - { - std::cout << "rat allowed "<< std::to_string(mAllowedNodes.size()) - +" mDist "+std::to_string(mDistance) - +" pos "+std::to_string(static_cast(npcPos[0])) - +", "+std::to_string(static_cast(npcPos[1])) - < 1) - { mTrimCurrentNode = false; -//#if 0 - std::cout << "deleted "<< std::to_string(mCurrentNode.mX) - +", "+std::to_string(mCurrentNode.mY) << std::endl; -//#endif -//#if 0 - std::cout << "allowed size "<< - std::to_string(mAllowedNodes.size()) << std::endl; -//#endif - } else mAllowedNodes.push_back(mCurrentNode); mCurrentNode = temp; @@ -428,15 +401,7 @@ namespace MWMechanics } // Choose a different node and delete this one from possible nodes because it is uncreachable: else - { mAllowedNodes.erase(mAllowedNodes.begin() + randNode); -//#if 0 - //std::cout << "actor \""<< actor.getClass().getName(actor) << "\"" << std::endl; - if(actor.getClass().getName(actor) == "Rat") - std::cout << "erase no path "<< std::to_string(mAllowedNodes[randNode].mX) - +", "+std::to_string(mAllowedNodes[randNode].mY) << std::endl; -//#endif - } } } @@ -506,11 +471,6 @@ namespace MWMechanics while(paths.size() >= 2) { ESM::Pathgrid::Point pt = paths.back(); -#if 0 - std::cout << "looking for "<< - "pt "+std::to_string(pt.mX)+", "+std::to_string(pt.mY) - <mName == "Gnisis, Arvs-Drelen") - for(unsigned int v = 0; v < mPathgrid->mPoints.size(); v++) - { - std::cout << "SCC \"X:" << - std::to_string(mPathgrid->mPoints[v].mX) - +", Y:"+std::to_string(mPathgrid->mPoints[v].mY) - +", Num:"+std::to_string(mSCCId) - +", Point:"+std::to_string(v) - +", Group:"+std::to_string(mGraph[v].componentId) - <<"\""< Date: Fri, 18 Apr 2014 15:19:22 +1000 Subject: [PATCH 006/484] More cleaning up. --- apps/openmw/mwmechanics/aiwander.cpp | 16 ++++++++-------- apps/openmw/mwmechanics/aiwander.hpp | 3 --- apps/openmw/mwmechanics/obstacle.cpp | 15 --------------- apps/openmw/mwmechanics/pathfinding.cpp | 2 +- 4 files changed, 9 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 276d1fac6..260aa72cf 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -47,7 +47,6 @@ namespace MWMechanics mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); mPlayedIdle = 0; - //mPathgrid = NULL; mIdleChanceMultiplier = MWBase::Environment::get().getWorld()->getStore().get().find("fIdleChanceMultiplier")->getFloat(); @@ -104,14 +103,15 @@ namespace MWMechanics * TODO: non-time critical operations should be run once every 250ms or so. * * TODO: It would be great if door opening/closing can be detected and pathgrid - * links dynamically updated. Currently (0.29.0) AiWander allows destination - * beyond closed doors which sometimes makes the actors stuck at the door and - * impossible for the player to open the door. + * links dynamically updated. Currently (0.29.0) AiWander allows choosing a + * destination beyond closed doors which sometimes makes the actors stuck at the + * door and impossible for the player to open the door. * * For now detect being stuck at the door and simply delete the nodes from the * allowed set. The issue is when the door opens the allowed set is not - * re-calculated. Normally this would not be an issue since hostile actors will - * enter combat (i.e. no longer wandering) + * re-calculated. However this would not be an issue in most cases since hostile + * actors will enter combat (i.e. no longer wandering) and different pathfinding + * will kick in. */ bool AiWander::execute (const MWWorld::Ptr& actor,float duration) { @@ -473,8 +473,8 @@ namespace MWMechanics ESM::Pathgrid::Point pt = paths.back(); for(int j = 0; j < nodes.size(); j++) { - // NOTE: doesn't hadle a door with the same X/Y - // coordinates but with a different Z + // FIXME: doesn't hadle a door with the same X/Y + // co-ordinates but with a different Z if(nodes[j].mX == pt.mX && nodes[j].mY == pt.mY) { nodes.erase(nodes.begin() + j); diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 8fe35e53d..59c21de89 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -65,13 +65,10 @@ namespace MWMechanics const PathFinder& pathfinder); PathFinder mPathFinder; - //const ESM::Pathgrid *mPathgrid; ObstacleCheck mObstacleCheck; float mDoorCheckDuration; int mStuckCount; - - //float mReaction; }; } diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 00f97ae01..9a748c052 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -44,16 +44,7 @@ namespace MWMechanics MWWorld::LiveCellRef& ref = *it; if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && ref.mData.getLocalRotation().rot[2] == (closed ? 0 : 1)) - { -//#if 0 - std::cout << "\""+actor.getClass().getName(actor)+"\" " - <<"next to door "+ref.mRef.mRefID - //+", enabled? "+std::to_string(ref.mData.isEnabled()) - +", dist "+std::to_string(sqrt(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)))) - << std::endl; -//#endif return true; // found, stop searching - } } return false; // none found } @@ -158,12 +149,6 @@ namespace MWMechanics return true; else { -//#if 0 - std::cout << "evade \""+actor.getClass().getName(actor)+"\" " - //<<"dist spot "+std::to_string(mDistSameSpot) - //+", speed "+std::to_string(cls.getSpeed(actor)) - << std::endl; -//#endif // tried to evade, assume all is ok and start again mWalkState = State_Norm; mEvadeDuration = 0; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 139553556..11d436700 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -231,7 +231,7 @@ namespace MWMechanics // deleting allowed nodes if not. Hence a path needs to be created // even if the start and the end points are the same. // NOTE: aStarSearch will return an empty path if the start and end - // nodes are the same + // nodes are the same if(startNode == endNode.first) { mPath.push_back(endPoint); From a0fc514df78d605b9b4db6d89eb8fb0f9115ebb0 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 18 Apr 2014 15:45:39 +1000 Subject: [PATCH 007/484] Suppress compiler warning. --- apps/openmw/mwmechanics/aiwander.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 260aa72cf..988da4eb4 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -471,7 +471,7 @@ namespace MWMechanics while(paths.size() >= 2) { ESM::Pathgrid::Point pt = paths.back(); - for(int j = 0; j < nodes.size(); j++) + for(unsigned int j = 0; j < nodes.size(); j++) { // FIXME: doesn't hadle a door with the same X/Y // co-ordinates but with a different Z From 7437647f70fad054793b0bf649a4b1484cf0d0c9 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 18 Apr 2014 16:45:31 +1000 Subject: [PATCH 008/484] Forgot to add a guard :-( --- apps/openmw/mwmechanics/obstacle.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index 920e2e794..12030b2be 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -1,4 +1,5 @@ #ifndef OPENMW_MECHANICS_OBSTACLE_H +#define OPENMW_MECHANICS_OBSTACLE_H namespace MWWorld { From 4625adfb7fdc85d5f83d9f1adf8c0ad00762daa6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 Apr 2014 11:43:37 +0200 Subject: [PATCH 009/484] Fix typo in a condition. --- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 7f5a7fac5..6ea3f5472 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -714,7 +714,7 @@ namespace MWMechanics effect.mDuration = 1; if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { - if (!magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) + if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) magnitude = int((0.05 * y) / (0.1 * magicEffect->mData.mBaseCost)); else magnitude = int(y / (0.1 * magicEffect->mData.mBaseCost)); From d3d0b7362f1d4b0c1945116e88e041b2e8b92ad4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 Apr 2014 12:34:12 +0200 Subject: [PATCH 010/484] Fix older savegame compatibility regarding new crime feature. --- components/esm/player.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/esm/player.cpp b/components/esm/player.cpp index e41cc535e..7a2c03b48 100644 --- a/components/esm/player.cpp +++ b/components/esm/player.cpp @@ -26,8 +26,10 @@ void ESM::Player::load (ESMReader &esm) mBirthsign = esm.getHNString ("SIGN"); - esm.getHNT (mCurrentCrimeId, "CURD"); - esm.getHNT (mPayedCrimeId, "PAYD"); + mCurrentCrimeId = 0; + esm.getHNOT (mCurrentCrimeId, "CURD"); + mPayedCrimeId = 0; + esm.getHNOT (mPayedCrimeId, "PAYD"); } void ESM::Player::save (ESMWriter &esm) const @@ -51,4 +53,4 @@ void ESM::Player::save (ESMWriter &esm) const esm.writeHNT ("CURD", mCurrentCrimeId); esm.writeHNT ("PAYD", mPayedCrimeId); -} \ No newline at end of file +} From b3916e77448eb65dd54434113cf5f55491edc83a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 Apr 2014 13:44:09 +0200 Subject: [PATCH 011/484] Crime: mark witnesses as alarmed. Fixes guard dialogue to properly detect if the player turned himself in. --- apps/openmw/mwmechanics/actors.cpp | 1 + apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f7478e22c..7b83ff1f1 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -763,6 +763,7 @@ namespace MWMechanics // TODO: Not a complete list, disposition changes? creatureStats.setHostile(false); creatureStats.setAttacked(false); + creatureStats.setAlarmed(false); // Update witness crime id npcStats.setCrimeId(-1); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 3a26ea7dc..a44d1a2ba 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -866,6 +866,9 @@ namespace MWMechanics { it1->getClass().getNpcStats(*it1).setCrimeId(id); } + + // Mark as Alarmed for dialogue + it1->getClass().getCreatureStats(*it1).setAlarmed(true); } break; // Someone saw the crime and everyone has been told } From a3dffd5d57d272e95ad6875e8c3fccb2195db7d9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 Apr 2014 14:13:29 +0200 Subject: [PATCH 012/484] Add some missing SDL to MyGUI key translations. Most importantly to allow numpad enter as alternative to return key. --- extern/sdl4ogre/sdlinputwrapper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index d48e43c01..c3ea2fd74 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -443,5 +443,10 @@ namespace SFO mKeyMap.insert( KeyMap::value_type(SDLK_PAGEDOWN, OIS::KC_PGDOWN) ); mKeyMap.insert( KeyMap::value_type(SDLK_INSERT, OIS::KC_INSERT) ); mKeyMap.insert( KeyMap::value_type(SDLK_DELETE, OIS::KC_DELETE) ); + mKeyMap.insert( KeyMap::value_type(SDLK_KP_ENTER, OIS::KC_NUMPADENTER) ); + mKeyMap.insert( KeyMap::value_type(SDLK_RCTRL, OIS::KC_RCONTROL) ); + mKeyMap.insert( KeyMap::value_type(SDLK_LGUI, OIS::KC_LWIN) ); + mKeyMap.insert( KeyMap::value_type(SDLK_RGUI, OIS::KC_RWIN) ); + mKeyMap.insert( KeyMap::value_type(SDLK_APPLICATION, OIS::KC_APPS) ); } } From 479a94b35df7f825a50ae2ede32a7c291d1840b2 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 19 Apr 2014 08:16:56 +1000 Subject: [PATCH 013/484] Backing off closed doors working, needs cleanup and tweaking. --- apps/openmw/mwmechanics/aicombat.cpp | 209 ++++++++++++++++++++++++++- apps/openmw/mwmechanics/aicombat.hpp | 10 ++ apps/openmw/mwmechanics/aiwander.cpp | 7 +- apps/openmw/mwmechanics/obstacle.cpp | 9 +- apps/openmw/mwmechanics/pathgrid.cpp | 6 +- 5 files changed, 231 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index fd2fa61ba..e94899359 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -35,6 +35,9 @@ namespace namespace MWMechanics { + static const float DOOR_CHECK_INTERVAL = 1.5f; + // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp + AiCombat::AiCombat(const MWWorld::Ptr& actor) : mTarget(actor), mTimerAttack(0), @@ -44,12 +47,104 @@ namespace MWMechanics mReadyToAttack(false), mStrike(false), mCombatMove(false), + mBackOffDoor(false), mRotate(false), mMovement(), + mDoorIter(actor.getCell()->get().mList.end()), + mDoors(actor.getCell()->get().mList), + mDoorCheckDuration(0), mTargetAngle(0) { } + /* + * The 'pursuit' part of AiCombat now has some memory to allow backtracking. + * The intention is to allow actors to detect being 'stuck' somewhere, whether + * in a river or facing a door, to go back to a known 'good' position. + * + * Each actor goes through these states of movement once alerted and an AiCombat + * package is queued (FIXME: below is a DRAFT proposal only): + * + * - Maybe remember the starting position so that the actor can return if + * lose sight of the target? Last Known Target Location Tracking - keep track + * of target positions every sec, paired with actor's location at the time + * + * - Get to the target if far away (need path finding), how close depends on + * the current best (selected?) weapon. As the actor moves, some breadcrumb + * is left (e.g. every second store a position in a FIFO) so that the actor + * can back track if necessary. + * + * - If the actor gets stuck (need a way of detecting this) then decide what + * to do next. For example, if next to a door then maybe back track one or + * two positions and check LOS of the target every x frames (reaction time?). + * Or maybe back track then look for a new path. + * + * - Once in weapon range, may need a strategy to get to the target for a + * strike (maybe there are others nearby attacking the same target). + * + * + * Current AiCombat movement states (as of 0.29.0), ignoring the details of the + * attack states such as CombatMove, Strike and ReadyToAttack: + * + * +-----(within strike range)----->attack--(beyond strike range)-->follow + * | | ^ | | + * | | | | | + * pursue<----(beyond follow range)-----+ +----(within strike range)---+ | + * ^ | + * | | + * +--------------------------(beyond follow range)--------------------+ + * + * + * Below diagram is high level only, FIXME: code detail may be different: + * + * +-----------(same)-------------->attack---------(same)---------->follow + * | |^^ | | + * | ||| | | + * | +--(same)-----------------+|+----------(same)------------+ | + * | | | in range | + * | | too far | | + * | | +---------------got hit or LOS<---+ | + * | <----+ | | | + * pursue<---------+ door | | + * ^^ <--> maybe stuck, check --------------> back up and wait | + * || | ^ | | ^ | | + * || | | | stuck | | | waited | + * || +---+ | +---+ | too long | + * || backtrack | | | + * |+----------------------+ go back? <-----------+ | + * | | + * +----------------------------(same)---------------------------------+ + * + * FIXME: + * + * The new scheme is way too complicated, should really be implemented as a + * proper state machine. + * + * TODO: + * + * Use the Observer Pattern to co-ordinate attacks, provide intelligence on + * whether the target was hit, etc. + * + * TODO: + * + * Auto-generate large cubes or squares as a poor-man's navmesh? Many + * external cells do not have any pathgrids, and certainly none for flying + * or swimming. + * + * + * Called from: (check Doxygen as this comment could be out of date) + * + * OMW::Engine::go() | + * Ogre::Root::renderOneFrame() | + * Ogre::Root::... | ... detail omitted + * Ogre::Root::fireFrameRenderingQueued() | + * OMW::Engine::frameRenderingQueued() | virtual Ogre::FrameListener + * MWMechanics::MechanicsManager::update() | + * MWMechanics::Actors::update() | + * MWMechanics::Actors::updateActor() | + * MWMechanics::AiSequence::execute() | from priority queue mPackages + * MWMechanics::AiCombat::execute() | virtual MWMechanics::AiPackage + */ bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description @@ -168,6 +263,43 @@ namespace MWMechanics ESM::Position pos = actor.getRefData().getPosition(); + /* + * Some notes on meanings of variables: + * + * rangeMelee: + * + * - Distance where attack using the actor's weapon is possible + * - longer for ranged weapons (obviously?) vs. melee weapons + * - 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: + * + * - 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) + * - 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: + * + * - Once triggered, the actor follows the target with LOS shortcut + * (the shortcut really only applies to cells where pathgrids are + * available, since the default path without pathgrids is direct to + * target even if LOS is not achieved) + * + */ float rangeMelee; float rangeCloseUp; bool distantCombat = false; @@ -189,6 +321,7 @@ namespace MWMechanics Ogre::Vector3 vDir = vDest - vStart; float distBetween = vDir.length(); + // (within strike dist) || (not quite strike dist while following) if(distBetween < rangeMelee || (distBetween <= rangeCloseUp && mFollowTarget) ) { //Melee and Close-up combat @@ -198,12 +331,13 @@ namespace MWMechanics mRotate = true; //bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget); + // (not quite strike dist while following) if (mFollowTarget && distBetween > rangeMelee) { //Close-up combat: just run up on target mMovement.mPosition[1] = 1; } - else + else // (within strike dist) { //Melee: stop running and attack mMovement.mPosition[1] = 0; @@ -240,7 +374,7 @@ namespace MWMechanics } else { - //target is at far distance: build path to target OR follow target (if previously actor had reached it once) + //target is at far distance: build path to target mFollowTarget = false; buildNewPath(actor); //may fail to build a path, check before use @@ -261,6 +395,55 @@ namespace MWMechanics mMovement.mPosition[1] = 1; mReadyToAttack = false; + + // remember that this section gets updated every tReaction, which is + // currently hard coded at 250ms or 1/4 second + if(mObstacleCheck.check(actor, tReaction)) // true if evasive action needed + { + std::cout<<"found obstacle"<getCell()->isExterior()) + { + // Check all the doors in this cell + mDoors = cell->get().mList; // update list member + mDoorIter = mDoors.begin(); + Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); + for (; mDoorIter != mDoors.end(); ++mDoorIter) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + if(actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED && + ref.mData.getLocalRotation().rot[2] == 0) + { + std::cout<<"closed door id \""< rangeMelee) @@ -293,6 +476,28 @@ namespace MWMechanics } } + MWWorld::LiveCellRef& ref = *mDoorIter; + Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); + if(mBackOffDoor && + actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < 1.5*1.5*MIN_DIST_TO_DOOR_SQUARED) + { + mMovement.mPosition[1] = -0.2; // back off, but slowly + if(mDoorIter != mDoors.end() && ref.mData.getLocalRotation().rot[2] >= 1) // open + { + mDoorIter = mDoors.end(); + mBackOffDoor = false; + std::cout<<"open door id \""<::List::iterator mDoorIter; + MWWorld::CellRefList::List& mDoors; + void buildNewPath(const MWWorld::Ptr& actor); }; } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 988da4eb4..5d165488c 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -83,8 +83,7 @@ namespace MWMechanics * * New high level states. Not exactly as per vanilla (e.g. door stuff) * but the differences are required because our physics does not work like - * vanilla and therefore have to compensate/work around. Note also many of - * the actions now have reaction times. + * vanilla and therefore have to compensate/work around. * * [select node, [if stuck evade * build path] or remove nodes if near door] @@ -467,6 +466,10 @@ namespace MWMechanics 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(); while(paths.size() >= 2) { diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 9a748c052..6694de096 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -42,9 +42,12 @@ namespace MWMechanics for (; it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; - if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && - ref.mData.getLocalRotation().rot[2] == (closed ? 0 : 1)) - return true; // found, stop searching + if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) + if(closed && ref.mData.getLocalRotation().rot[2] == 0 || + !closed && ref.mData.getLocalRotation().rot[2] >= 1) + { + return true; // found, stop searching + } } return false; // none found } diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index ec647c1cb..cb9f051e3 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -197,11 +197,11 @@ namespace MWMechanics // both of these are set to zero in the constructor //mSCCId = 0; // how many strongly connected components in this cell //mSCCIndex = 0; - int pointsSize = mPathgrid->mPoints.size(); + int pointsSize = static_cast (mPathgrid->mPoints.size()); mSCCPoint.resize(pointsSize, std::pair (-1, -1)); mSCCStack.reserve(pointsSize); - for(int v = 0; v < static_cast (pointsSize); v++) + for(int v = 0; v < pointsSize; v++) { if(mSCCPoint[v].first == -1) // undefined (haven't visited) recursiveStrongConnect(v); @@ -249,7 +249,7 @@ namespace MWMechanics return path; // there is no path, return an empty path } - int graphSize = mGraph.size(); + int graphSize = static_cast (mGraph.size()); std::vector gScore (graphSize, -1); std::vector fScore (graphSize, -1); std::vector graphParent (graphSize, -1); From 3dfd08cf2de36dd081c25a75b1c637e9ede987ea Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 08:31:02 +1000 Subject: [PATCH 014/484] Cleanup and little tweaking. --- apps/openmw/mwmechanics/aicombat.cpp | 235 ++++++++++++--------------- apps/openmw/mwmechanics/aicombat.hpp | 5 +- apps/openmw/mwmechanics/pathgrid.hpp | 2 + apps/openmw/mwworld/cellstore.hpp | 2 +- 4 files changed, 107 insertions(+), 137 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index e94899359..335bc8702 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -35,7 +35,7 @@ namespace namespace MWMechanics { - static const float DOOR_CHECK_INTERVAL = 1.5f; + static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander // NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp AiCombat::AiCombat(const MWWorld::Ptr& actor) : @@ -50,70 +50,49 @@ namespace MWMechanics mBackOffDoor(false), mRotate(false), mMovement(), + mCell(NULL), mDoorIter(actor.getCell()->get().mList.end()), - mDoors(actor.getCell()->get().mList), + mDoors(actor.getCell()->get()), mDoorCheckDuration(0), mTargetAngle(0) { } /* - * The 'pursuit' part of AiCombat now has some memory to allow backtracking. - * The intention is to allow actors to detect being 'stuck' somewhere, whether - * in a river or facing a door, to go back to a known 'good' position. - * - * Each actor goes through these states of movement once alerted and an AiCombat - * package is queued (FIXME: below is a DRAFT proposal only): - * - * - Maybe remember the starting position so that the actor can return if - * lose sight of the target? Last Known Target Location Tracking - keep track - * of target positions every sec, paired with actor's location at the time - * - * - Get to the target if far away (need path finding), how close depends on - * the current best (selected?) weapon. As the actor moves, some breadcrumb - * is left (e.g. every second store a position in a FIFO) so that the actor - * can back track if necessary. - * - * - If the actor gets stuck (need a way of detecting this) then decide what - * to do next. For example, if next to a door then maybe back track one or - * two positions and check LOS of the target every x frames (reaction time?). - * Or maybe back track then look for a new path. - * - * - Once in weapon range, may need a strategy to get to the target for a - * strike (maybe there are others nearby attacking the same target). - * - * * Current AiCombat movement states (as of 0.29.0), ignoring the details of the * attack states such as CombatMove, Strike and ReadyToAttack: * - * +-----(within strike range)----->attack--(beyond strike range)-->follow - * | | ^ | | - * | | | | | - * pursue<----(beyond follow range)-----+ +----(within strike range)---+ | - * ^ | - * | | - * +--------------------------(beyond follow range)--------------------+ + * +----(within strike range)----->attack--(beyond strike range)-->follow + * | | ^ | | + * | | | | | + * pursue<---(beyond follow range)-----+ +----(within strike range)---+ | + * ^ | + * | | + * +-------------------------(beyond follow range)--------------------+ * * - * Below diagram is high level only, FIXME: code detail may be different: + * Below diagram is high level only, the code detail is a little different + * (but including those detail will just complicate the diagram w/o adding much) * - * +-----------(same)-------------->attack---------(same)---------->follow - * | |^^ | | - * | ||| | | - * | +--(same)-----------------+|+----------(same)------------+ | - * | | | in range | - * | | too far | | - * | | +---------------got hit or LOS<---+ | - * | <----+ | | | - * pursue<---------+ door | | - * ^^ <--> maybe stuck, check --------------> back up and wait | - * || | ^ | | ^ | | - * || | | | stuck | | | waited | - * || +---+ | +---+ | too long | - * || backtrack | | | - * |+----------------------+ go back? <-----------+ | - * | | - * +----------------------------(same)---------------------------------+ + * +----------(same)-------------->attack---------(same)---------->follow + * | |^^ ||| + * | ||| ||| + * | +--(same)-----------------+|+----------(same)------------+|| + * | | | || + * | | | (in range) || + * | <---+ (too far) | || + * pursue<-------------------------[door open]<-----+ || + * ^^^ | || + * ||| | || + * ||+----------evade-----+ | || + * || | [closed door] | || + * |+----> maybe stuck, check --------------> back up, check door || + * | ^ | ^ | ^ || + * | | | | | | || + * | | +---+ +---+ || + * | +-------------------------------------------------------+| + * | | + * +---------------------------(same)---------------------------------+ * * FIXME: * @@ -124,26 +103,6 @@ namespace MWMechanics * * Use the Observer Pattern to co-ordinate attacks, provide intelligence on * whether the target was hit, etc. - * - * TODO: - * - * Auto-generate large cubes or squares as a poor-man's navmesh? Many - * external cells do not have any pathgrids, and certainly none for flying - * or swimming. - * - * - * Called from: (check Doxygen as this comment could be out of date) - * - * OMW::Engine::go() | - * Ogre::Root::renderOneFrame() | - * Ogre::Root::... | ... detail omitted - * Ogre::Root::fireFrameRenderingQueued() | - * OMW::Engine::frameRenderingQueued() | virtual Ogre::FrameListener - * MWMechanics::MechanicsManager::update() | - * MWMechanics::Actors::update() | - * MWMechanics::Actors::updateActor() | - * MWMechanics::AiSequence::execute() | from priority queue mPackages - * MWMechanics::AiCombat::execute() | virtual MWMechanics::AiPackage */ bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { @@ -175,7 +134,6 @@ namespace MWMechanics mRotate = false; } - mTimerAttack -= duration; actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike); @@ -190,6 +148,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 attackPeriod = 1.0f; @@ -298,7 +262,6 @@ namespace MWMechanics * (the shortcut really only applies to cells where pathgrids are * available, since the default path without pathgrids is direct to * target even if LOS is not achieved) - * */ float rangeMelee; float rangeCloseUp; @@ -395,55 +358,6 @@ namespace MWMechanics mMovement.mPosition[1] = 1; mReadyToAttack = false; - - // remember that this section gets updated every tReaction, which is - // currently hard coded at 250ms or 1/4 second - if(mObstacleCheck.check(actor, tReaction)) // true if evasive action needed - { - std::cout<<"found obstacle"<getCell()->isExterior()) - { - // Check all the doors in this cell - mDoors = cell->get().mList; // update list member - mDoorIter = mDoors.begin(); - Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); - for (; mDoorIter != mDoors.end(); ++mDoorIter) - { - MWWorld::LiveCellRef& ref = *mDoorIter; - if(actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED && - ref.mData.getLocalRotation().rot[2] == 0) - { - std::cout<<"closed door id \""< rangeMelee) @@ -476,26 +390,77 @@ namespace MWMechanics } } + // NOTE: This section gets updated every tReaction, which is currently hard + // coded at 250ms or 1/4 second + // + // TODO: Add a parameter to vary DURATION_SAME_SPOT? + if((distBetween > rangeMelee || 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; + // Check all the doors in this cell + mDoors = cell->get(); // update + mDoorIter = mDoors.mList.begin(); + Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); + for (; mDoorIter != mDoors.mList.end(); ++mDoorIter) + { + MWWorld::LiveCellRef& ref = *mDoorIter; + float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility + if(actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr && + ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening + { + //std::cout<<"closed door id \""<& ref = *mDoorIter; Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); + float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility + // TODO: add reaction to checking open doors if(mBackOffDoor && - actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < 1.5*1.5*MIN_DIST_TO_DOOR_SQUARED) + actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) { mMovement.mPosition[1] = -0.2; // back off, but slowly - if(mDoorIter != mDoors.end() && ref.mData.getLocalRotation().rot[2] >= 1) // open - { - mDoorIter = mDoors.end(); - mBackOffDoor = false; - std::cout<<"open door id \""<= 1) + { + mDoorIter = mDoors.mList.end(); + mBackOffDoor = false; + //std::cout<<"open door id \""<::List::iterator mDoorIter; - MWWorld::CellRefList::List& mDoors; + MWWorld::CellRefList& mDoors; void buildNewPath(const MWWorld::Ptr& actor); }; diff --git a/apps/openmw/mwmechanics/pathgrid.hpp b/apps/openmw/mwmechanics/pathgrid.hpp index ac545efbc..5d01dca00 100644 --- a/apps/openmw/mwmechanics/pathgrid.hpp +++ b/apps/openmw/mwmechanics/pathgrid.hpp @@ -30,6 +30,8 @@ namespace MWMechanics // the input parameters are pathgrid point indexes // the output list is in local (internal cells) or world (external // cells) co-ordinates + // + // NOTE: if start equals end an empty path is returned std::list aStarSearch(const int start, const int end) const; private: diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index b970afe1b..88b49ed1c 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -8,7 +8,7 @@ #include "esmstore.hpp" #include "cellreflist.hpp" -#include "../mwmechanics/pathgrid.hpp" +#include "../mwmechanics/pathgrid.hpp" // TODO: maybe belongs in mwworld namespace ESM { From 6733a1541efb66ec561c9e619969cb07e912f5d0 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 19 Apr 2014 19:03:31 -0400 Subject: [PATCH 015/484] Fixes to Crime System Victimless crimes were removed because victims may not exist in the case of stealing items. Is class now uses case insensitive comparison. Fixed issue with confiscation of stolen items. --- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- apps/openmw/mwscript/miscextensions.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5a3ff10de..e43bfe40d 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1305,7 +1305,7 @@ namespace MWClass bool Npc::isClass(const MWWorld::Ptr& ptr, const std::string &className) const { - return ptr.get()->mBase->mClass == className; + return Misc::StringUtils::ciEqual(ptr.get()->mBase->mClass, className); } const ESM::GameSetting *Npc::fMinWalkSpeed; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index d162e1037..147f6d03f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -805,8 +805,8 @@ namespace MWMechanics // 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 and no victimless crimes - if (ptr.getRefData().getHandle() != "player" || victim.isEmpty()) + // Only player can commit crime + if (ptr.getRefData().getHandle() != "player") return false; const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index aa554adc3..d8ba3ea22 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -814,6 +814,7 @@ namespace MWScript { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); player.getClass().getNpcStats(player).setBounty(0); + MWBase::Environment::get().getWorld()->confiscateStolenItems(player); MWBase::Environment::get().getWorld()->getPlayer().recordCrimeId(); } }; @@ -825,7 +826,6 @@ namespace MWScript { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); player.getClass().getNpcStats(player).setBounty(0); - MWBase::Environment::get().getWorld()->confiscateStolenItems(player); MWBase::Environment::get().getWorld()->getPlayer().recordCrimeId(); } }; From 3484df0743670e68a70c688922fd55885e1bcb13 Mon Sep 17 00:00:00 2001 From: Jeffrey Haines Date: Sat, 19 Apr 2014 19:42:49 -0400 Subject: [PATCH 016/484] Fixed garage value found in beta's static analysis Source: https://forum.openmw.org/viewtopic.php?f=6&t=2059#p23844 --- 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 147f6d03f..84dc337c9 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -823,6 +823,8 @@ namespace MWMechanics alarm = esmStore.get().find("iAlarmKilling")->getInt(); else if (type == OT_Theft) alarm = esmStore.get().find("iAlarmStealing")->getInt(); + else + return false; // Innocent until proven guilty bool reported = false; From 9bd31b62365a17341ddae54d2ca8af2d2e300125 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 10:06:03 +1000 Subject: [PATCH 017/484] Added reaction time and moved game setting variables init to the constructor. --- apps/openmw/mwmechanics/aiwander.cpp | 173 +++++++++++++++------------ apps/openmw/mwmechanics/aiwander.hpp | 5 + 2 files changed, 101 insertions(+), 77 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 5d165488c..12d86a5dc 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -30,6 +30,10 @@ namespace MWMechanics , mStuckCount(0) // TODO: maybe no longer needed , mDoorCheckDuration(0) , mTrimCurrentNode(false) + , mReaction(0) + , mGreetDistanceMultiplier(0) + , mGreetDistanceReset(0) + , mChance(0) , mSaidGreeting(false) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) @@ -47,8 +51,15 @@ namespace MWMechanics mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); mPlayedIdle = 0; + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); mIdleChanceMultiplier = - MWBase::Environment::get().getWorld()->getStore().get().find("fIdleChanceMultiplier")->getFloat(); + store.get().find("fIdleChanceMultiplier")->getFloat(); + + mGreetDistanceMultiplier = + store.get().find("iGreetDistanceMultiplier")->getInt(); + mGreetDistanceReset = + store.get().find("fGreetDistanceReset")->getFloat(); + mChance = store.get().find("fVoiceIdleOdds")->getFloat(); mStoredAvailableNodes = false; mChooseAction = true; @@ -99,7 +110,7 @@ namespace MWMechanics * | player) | * +----------------------------------+ * - * TODO: non-time critical operations should be run once every 250ms or so. + * NOTE: non-time critical operations are run once every 250ms or so. * * TODO: It would be great if door opening/closing can be detected and pathgrid * links dynamically updated. Currently (0.29.0) AiWander allows choosing a @@ -128,6 +139,83 @@ namespace MWMechanics cStats.setDrawState(DrawState_Nothing); cStats.setMovementFlag(CreatureStats::Flag_Run, false); + + ESM::Position pos = actor.getRefData().getPosition(); + + // Check if an idle actor is too close to a door - if so start walking + mDoorCheckDuration += duration; + if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL) + { + mDoorCheckDuration = 0; // restart timer + if(mDistance && // actor is not intended to be stationary + mIdleNow && // but is in idle + !mWalking && // FIXME: some actors are idle while walking + proximityToDoor(actor)) // NOTE: checks interior cells only + { + mIdleNow = false; + mMoveNow = true; + mTrimCurrentNode = false; // just in case + } + } + + if(mWalking) // have not yet reached the destination + { + // turn towards the next point in mPath + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + + // Returns true if evasive action needs to be taken + if(mObstacleCheck.check(actor, duration)) + { + // first check if we're walking into a door + if(proximityToDoor(actor)) // NOTE: checks interior cells only + { + // remove allowed points then select another random destination + mTrimCurrentNode = true; + trimAllowedNodes(mAllowedNodes, mPathFinder); + mObstacleCheck.clear(); + mPathFinder.clearPath(); + mWalking = false; + mMoveNow = true; + } + 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]))); + } + mStuckCount++; // TODO: maybe no longer needed + } +//#if 0 + // TODO: maybe no longer needed + if(mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset + { + //std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl; + mObstacleCheck.clear(); + + stopWalking(actor); + mMoveNow = false; + mWalking = false; + mChooseAction = true; + } +//#endif + } + + + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); + + mReaction += duration; + if(mReaction > 0.25f) // FIXME: hard coded constant + { + mReaction = 0; + return false; + } + + // NOTE: everything below get updated every mReaction + MWBase::World *world = MWBase::Environment::get().getWorld(); if(mDuration) { @@ -155,8 +243,6 @@ namespace MWMechanics } } - ESM::Position pos = actor.getRefData().getPosition(); - // Initialization to discover & store allowed node points for this actor. if(!mStoredAvailableNodes) { @@ -270,50 +356,29 @@ namespace MWMechanics int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); if (hello > 0) { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - float chance = store.get().find("fVoiceIdleOdds")->getFloat(); int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); // Don't bother if the player is out of hearing range - if (roll < chance && Ogre::Vector3(player.getRefData().getPosition().pos).distance(Ogre::Vector3(pos.pos)) < 1500) + if (roll < mChance && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500) MWBase::Environment::get().getDialogueManager()->say(actor, "idle"); } } } - // Check if an idle actor is too close to a door - if so start walking - mDoorCheckDuration += duration; - if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL) - { - mDoorCheckDuration = 0; // restart timer - if(mDistance && // actor is not intended to be stationary - mIdleNow && // but is in idle - !mWalking && // FIXME: some actors are idle while walking - proximityToDoor(actor)) // NOTE: checks interior cells only - { - mIdleNow = false; - mMoveNow = true; - mTrimCurrentNode = false; // just in case - } - } - // Allow interrupting a walking actor to trigger a greeting if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState())) { // Play a random voice greeting if the player gets too close - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); float helloDistance = hello; - int iGreetDistanceMultiplier = store.get().find("iGreetDistanceMultiplier")->getInt(); - helloDistance *= iGreetDistanceMultiplier; + helloDistance *= mGreetDistanceMultiplier; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - float playerDist = Ogre::Vector3(player.getRefData().getPosition().pos).distance( + float playerDist = Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance( Ogre::Vector3(actor.getRefData().getPosition().pos)); - if(mWalking && playerDist <= helloDistance) + if(mWalking && playerDist <= helloDistance*helloDistance) { stopWalking(actor); mMoveNow = false; @@ -324,7 +389,7 @@ namespace MWMechanics if (!mSaidGreeting) { // TODO: check if actor is aware / has line of sight - if (playerDist <= helloDistance + if (playerDist <= helloDistance*helloDistance // Only play a greeting if the player is not moving && Ogre::Vector3(player.getClass().getMovementSettings(player).mPosition).squaredLength() == 0) { @@ -335,8 +400,7 @@ namespace MWMechanics } else { - float fGreetDistanceReset = store.get().find("fGreetDistanceReset")->getFloat(); - if (playerDist >= fGreetDistanceReset * iGreetDistanceMultiplier) + if (playerDist >= mGreetDistanceReset*mGreetDistanceReset * mGreetDistanceMultiplier*mGreetDistanceMultiplier) mSaidGreeting = false; } @@ -413,51 +477,6 @@ namespace MWMechanics mWalking = false; mChooseAction = true; } - else if(mWalking) // have not yet reached the destination - { - // turn towards the next point in mPath - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; - - // Returns true if evasive action needs to be taken - if(mObstacleCheck.check(actor, duration)) - { - // first check if we're walking into a door - if(proximityToDoor(actor)) // NOTE: checks interior cells only - { - // remove allowed points then select another random destination - mTrimCurrentNode = true; - trimAllowedNodes(mAllowedNodes, mPathFinder); - mObstacleCheck.clear(); - mPathFinder.clearPath(); - mWalking = false; - mMoveNow = true; - } - 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]))); - } - mStuckCount++; // TODO: maybe no longer needed - } -//#if 0 - // TODO: maybe no longer needed - if(mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset - { - //std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl; - mObstacleCheck.clear(); - - stopWalking(actor); - mMoveNow = false; - mWalking = false; - mChooseAction = true; - } -//#endif - } return false; // AiWander package not yet completed } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 59c21de89..a39862135 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -34,6 +34,9 @@ namespace MWMechanics bool mRepeat; bool mSaidGreeting; + int mGreetDistanceMultiplier; + float mGreetDistanceReset; + float mChance; // Cached current cell location int mCellX; @@ -69,6 +72,8 @@ namespace MWMechanics ObstacleCheck mObstacleCheck; float mDoorCheckDuration; int mStuckCount; + + float mReaction; // update some actions infrequently }; } From 3d26702f5e9d8086cba0c4c775dc975b85b94649 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 10:36:01 +1000 Subject: [PATCH 018/484] Make idle actors face the player. Turning animation is not smooth. --- apps/openmw/mwmechanics/aiwander.cpp | 31 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 12d86a5dc..167f61959 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -204,9 +204,6 @@ namespace MWMechanics //#endif } - - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - mReaction += duration; if(mReaction > 0.25f) // FIXME: hard coded constant { @@ -375,32 +372,40 @@ namespace MWMechanics helloDistance *= mGreetDistanceMultiplier; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - float playerDist = Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance( - Ogre::Vector3(actor.getRefData().getPosition().pos)); + Ogre::Vector3 playerPos(player.getRefData().getPosition().pos); + Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); + float playerDistSqr = playerPos.squaredDistance(actorPos); - if(mWalking && playerDist <= helloDistance*helloDistance) + if(playerDistSqr <= helloDistance*helloDistance) { - stopWalking(actor); - mMoveNow = false; - mWalking = false; - mObstacleCheck.clear(); + if(mWalking) + { + stopWalking(actor); + mMoveNow = false; + mWalking = false; + mObstacleCheck.clear(); + } + Ogre::Vector3 dir = playerPos - actorPos; + float length = dir.length(); + + // FIXME: horrible hack, and does not turn smoothly + zTurn(actor, Ogre::Degree(Ogre::Radian(Ogre::Math::ACos(dir.y / length) * ((Ogre::Math::ASin(dir.x / length).valueRadians()>0)?1.0:-1.0)).valueDegrees())); } if (!mSaidGreeting) { // TODO: check if actor is aware / has line of sight - if (playerDist <= helloDistance*helloDistance + if (playerDistSqr <= helloDistance*helloDistance // Only play a greeting if the player is not moving && Ogre::Vector3(player.getClass().getMovementSettings(player).mPosition).squaredLength() == 0) { mSaidGreeting = true; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); - // TODO: turn to face player and interrupt the idle animation? } } else { - if (playerDist >= mGreetDistanceReset*mGreetDistanceReset * mGreetDistanceMultiplier*mGreetDistanceMultiplier) + if (playerDistSqr >= mGreetDistanceReset*mGreetDistanceReset * mGreetDistanceMultiplier*mGreetDistanceMultiplier) mSaidGreeting = false; } From 000afa48b73cad62b3e762998b3ef2042467af74 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 11:59:47 +1000 Subject: [PATCH 019/484] An attempt at making turning animation smoother. Copied some code from AiCombat for rotation. --- apps/openmw/mwmechanics/aiwander.cpp | 34 ++++++++++++++++++++++++---- apps/openmw/mwmechanics/aiwander.hpp | 5 ++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 167f61959..548eb60f6 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -34,6 +34,9 @@ namespace MWMechanics , mGreetDistanceMultiplier(0) , mGreetDistanceReset(0) , mChance(0) + , mRotate(false) + , mTargetAngle(0) + , mOriginalAngle(0) , mSaidGreeting(false) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) @@ -204,6 +207,12 @@ namespace MWMechanics //#endif } + if (mRotate) + { + if (zTurn(actor, Ogre::Degree(mTargetAngle))) + mRotate = false; + } + mReaction += duration; if(mReaction > 0.25f) // FIXME: hard coded constant { @@ -385,11 +394,28 @@ namespace MWMechanics mWalking = false; mObstacleCheck.clear(); } - Ogre::Vector3 dir = playerPos - actorPos; - float length = dir.length(); - // FIXME: horrible hack, and does not turn smoothly - zTurn(actor, Ogre::Degree(Ogre::Radian(Ogre::Math::ACos(dir.y / length) * ((Ogre::Math::ASin(dir.x / length).valueRadians()>0)?1.0:-1.0)).valueDegrees())); + if(!mRotate) + { + 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(); + // an attempt at reducing the turning animation glitch + // TODO: doesn't seem to work very well + if(abs(faceAngle) > 10) + { + mTargetAngle = faceAngle; + mRotate = true; + } + } + } + else if(!mDistance) // FIXME: stationary actors go back to their normal position + { + //mTargetAngle = mOriginalAngle; + //mRotate = true; } if (!mSaidGreeting) diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index a39862135..2ed1af3be 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -73,6 +73,11 @@ namespace MWMechanics float mDoorCheckDuration; int mStuckCount; + // the z rotation angle (degrees) we want to reach + // used every frame when mRotate is true + float mTargetAngle; + float mOriginalAngle; + bool mRotate; float mReaction; // update some actions infrequently }; } From 2b544d550b0844e928b66a69baf5f4117636c4e4 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 14:27:18 +1000 Subject: [PATCH 020/484] Fixed the rotation animation glitch. --- apps/openmw/mwmechanics/aiwander.cpp | 15 ++++++--------- apps/openmw/mwmechanics/steering.cpp | 3 +-- apps/openmw/mwmechanics/steering.hpp | 3 ++- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 548eb60f6..988879379 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -209,7 +209,10 @@ namespace MWMechanics if (mRotate) { - if (zTurn(actor, Ogre::Degree(mTargetAngle))) + // 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))) mRotate = false; } @@ -220,7 +223,7 @@ namespace MWMechanics return false; } - // NOTE: everything below get updated every mReaction + // NOTE: everything below get updated every 0.25 seconds MWBase::World *world = MWBase::Environment::get().getWorld(); if(mDuration) @@ -404,7 +407,6 @@ namespace MWMechanics float faceAngle = Ogre::Radian(Ogre::Math::ACos(dir.y / length) * ((Ogre::Math::ASin(dir.x / length).valueRadians()>0)?1.0:-1.0)).valueDegrees(); // an attempt at reducing the turning animation glitch - // TODO: doesn't seem to work very well if(abs(faceAngle) > 10) { mTargetAngle = faceAngle; @@ -412,11 +414,6 @@ namespace MWMechanics } } } - else if(!mDistance) // FIXME: stationary actors go back to their normal position - { - //mTargetAngle = mOriginalAngle; - //mRotate = true; - } if (!mSaidGreeting) { @@ -436,7 +433,7 @@ namespace MWMechanics } // Check if idle animation finished - if(!checkIdle(actor, mPlayedIdle)) + if(!checkIdle(actor, mPlayedIdle) && !mRotate) { mPlayedIdle = 0; mIdleNow = false; diff --git a/apps/openmw/mwmechanics/steering.cpp b/apps/openmw/mwmechanics/steering.cpp index d911fd81b..054107f73 100644 --- a/apps/openmw/mwmechanics/steering.cpp +++ b/apps/openmw/mwmechanics/steering.cpp @@ -10,7 +10,7 @@ namespace MWMechanics { -bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle) +bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, Ogre::Degree epsilon) { Ogre::Radian currentAngle (actor.getRefData().getPosition().rot[2]); Ogre::Radian diff (targetAngle - currentAngle); @@ -27,7 +27,6 @@ bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle) // 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; diff --git a/apps/openmw/mwmechanics/steering.hpp b/apps/openmw/mwmechanics/steering.hpp index 504dc3ac3..4042b5412 100644 --- a/apps/openmw/mwmechanics/steering.hpp +++ b/apps/openmw/mwmechanics/steering.hpp @@ -12,7 +12,8 @@ namespace MWMechanics /// 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); +bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, + Ogre::Degree epsilon = Ogre::Degree(0.5)); } From 95ef874205ee741360563e9b2c6828a90fce0d4d Mon Sep 17 00:00:00 2001 From: Thomas Luppi Date: Sun, 20 Apr 2014 00:34:58 -0400 Subject: [PATCH 021/484] Gets default keybindings from scancode, not keyvalue. Gives keyboard set-up independant default keybindings; useful for international keyboards or dvorak users --- apps/openmw/mwinput/inputmanagerimp.cpp | 61 +++++++++++++------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index e2d4f8cb2..616d8ae91 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -811,36 +811,37 @@ namespace MWInput // across different versions of OpenMW (in the case where another input action is added) std::map defaultKeyBindings; - defaultKeyBindings[A_Activate] = SDLK_SPACE; - defaultKeyBindings[A_MoveBackward] = SDLK_s; - defaultKeyBindings[A_MoveForward] = SDLK_w; - defaultKeyBindings[A_MoveLeft] = SDLK_a; - defaultKeyBindings[A_MoveRight] = SDLK_d; - defaultKeyBindings[A_ToggleWeapon] = SDLK_f; - defaultKeyBindings[A_ToggleSpell] = SDLK_r; - defaultKeyBindings[A_QuickKeysMenu] = SDLK_F1; - defaultKeyBindings[A_Console] = SDLK_F2; - defaultKeyBindings[A_Run] = SDLK_LSHIFT; - defaultKeyBindings[A_Sneak] = SDLK_LCTRL; - defaultKeyBindings[A_AutoMove] = SDLK_q; - defaultKeyBindings[A_Jump] = SDLK_e; - defaultKeyBindings[A_Journal] = SDLK_j; - defaultKeyBindings[A_Rest] = SDLK_t; - defaultKeyBindings[A_GameMenu] = SDLK_ESCAPE; - defaultKeyBindings[A_TogglePOV] = SDLK_TAB; - defaultKeyBindings[A_QuickKey1] = SDLK_1; - defaultKeyBindings[A_QuickKey2] = SDLK_2; - defaultKeyBindings[A_QuickKey3] = SDLK_3; - defaultKeyBindings[A_QuickKey4] = SDLK_4; - defaultKeyBindings[A_QuickKey5] = SDLK_5; - defaultKeyBindings[A_QuickKey6] = SDLK_6; - defaultKeyBindings[A_QuickKey7] = SDLK_7; - defaultKeyBindings[A_QuickKey8] = SDLK_8; - defaultKeyBindings[A_QuickKey9] = SDLK_9; - defaultKeyBindings[A_QuickKey10] = SDLK_0; - defaultKeyBindings[A_Screenshot] = SDLK_F12; - defaultKeyBindings[A_ToggleHUD] = SDLK_F11; - defaultKeyBindings[A_AlwaysRun] = SDLK_y; + //Gets the Keyvalue from the Scancode; gives the button in the same place reguardless of keyboard format + defaultKeyBindings[A_Activate] = SDL_GetKeyFromScancode(SDL_SCANCODE_SPACE); + defaultKeyBindings[A_MoveBackward] = SDL_GetKeyFromScancode(SDL_SCANCODE_S); + defaultKeyBindings[A_MoveForward] = SDL_GetKeyFromScancode(SDL_SCANCODE_W); + defaultKeyBindings[A_MoveLeft] = SDL_GetKeyFromScancode(SDL_SCANCODE_A); + defaultKeyBindings[A_MoveRight] = SDL_GetKeyFromScancode(SDL_SCANCODE_D); + defaultKeyBindings[A_ToggleWeapon] = SDL_GetKeyFromScancode(SDL_SCANCODE_F); + defaultKeyBindings[A_ToggleSpell] = SDL_GetKeyFromScancode(SDL_SCANCODE_R); + defaultKeyBindings[A_QuickKeysMenu] = SDL_GetKeyFromScancode(SDL_SCANCODE_F1); + defaultKeyBindings[A_Console] = SDL_GetKeyFromScancode(SDL_SCANCODE_F2); + defaultKeyBindings[A_Run] = SDL_GetKeyFromScancode(SDL_SCANCODE_LSHIFT); + defaultKeyBindings[A_Sneak] = SDL_GetKeyFromScancode(SDL_SCANCODE_LCTRL); + defaultKeyBindings[A_AutoMove] = SDL_GetKeyFromScancode(SDL_SCANCODE_Q); + defaultKeyBindings[A_Jump] = SDL_GetKeyFromScancode(SDL_SCANCODE_E); + defaultKeyBindings[A_Journal] = SDL_GetKeyFromScancode(SDL_SCANCODE_J); + defaultKeyBindings[A_Rest] = SDL_GetKeyFromScancode(SDL_SCANCODE_T); + defaultKeyBindings[A_GameMenu] = SDL_GetKeyFromScancode(SDL_SCANCODE_ESCAPE); + defaultKeyBindings[A_TogglePOV] = SDL_GetKeyFromScancode(SDL_SCANCODE_TAB); + defaultKeyBindings[A_QuickKey1] = SDL_GetKeyFromScancode(SDL_SCANCODE_1); + defaultKeyBindings[A_QuickKey2] = SDL_GetKeyFromScancode(SDL_SCANCODE_2); + defaultKeyBindings[A_QuickKey3] = SDL_GetKeyFromScancode(SDL_SCANCODE_3); + defaultKeyBindings[A_QuickKey4] = SDL_GetKeyFromScancode(SDL_SCANCODE_4); + defaultKeyBindings[A_QuickKey5] = SDL_GetKeyFromScancode(SDL_SCANCODE_5); + defaultKeyBindings[A_QuickKey6] = SDL_GetKeyFromScancode(SDL_SCANCODE_6); + defaultKeyBindings[A_QuickKey7] = SDL_GetKeyFromScancode(SDL_SCANCODE_7); + defaultKeyBindings[A_QuickKey8] = SDL_GetKeyFromScancode(SDL_SCANCODE_8); + defaultKeyBindings[A_QuickKey9] = SDL_GetKeyFromScancode(SDL_SCANCODE_9); + defaultKeyBindings[A_QuickKey10] = SDL_GetKeyFromScancode(SDL_SCANCODE_0); + defaultKeyBindings[A_Screenshot] = SDL_GetKeyFromScancode(SDL_SCANCODE_F12); + defaultKeyBindings[A_ToggleHUD] = SDL_GetKeyFromScancode(SDL_SCANCODE_F11); + defaultKeyBindings[A_AlwaysRun] = SDL_GetKeyFromScancode(SDL_SCANCODE_y); std::map defaultMouseButtonBindings; defaultMouseButtonBindings[A_Inventory] = SDL_BUTTON_RIGHT; From d6f1f129eb0df850ecb302dcc264b8f5b71724d9 Mon Sep 17 00:00:00 2001 From: Thomas Luppi Date: Sun, 20 Apr 2014 00:39:50 -0400 Subject: [PATCH 022/484] Forgot to capitalize something. whooooops dat y do --- 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 616d8ae91..1346b9e95 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -841,7 +841,7 @@ namespace MWInput defaultKeyBindings[A_QuickKey10] = SDL_GetKeyFromScancode(SDL_SCANCODE_0); 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_AlwaysRun] = SDL_GetKeyFromScancode(SDL_SCANCODE_Y); std::map defaultMouseButtonBindings; defaultMouseButtonBindings[A_Inventory] = SDL_BUTTON_RIGHT; From e17fab891da936e82c0bf77108bf146b800749cd Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 16:49:57 +1000 Subject: [PATCH 023/484] Suppress travis warning and one more tweak. --- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwmechanics/obstacle.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 988879379..d552e045d 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -153,7 +153,7 @@ namespace MWMechanics if(mDistance && // actor is not intended to be stationary mIdleNow && // but is in idle !mWalking && // FIXME: some actors are idle while walking - proximityToDoor(actor)) // NOTE: checks interior cells only + proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6*1.6)) // NOTE: checks interior cells only { mIdleNow = false; mMoveNow = true; diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 6694de096..181560935 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -43,8 +43,8 @@ namespace MWMechanics { MWWorld::LiveCellRef& ref = *it; if(pos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr) - if(closed && ref.mData.getLocalRotation().rot[2] == 0 || - !closed && ref.mData.getLocalRotation().rot[2] >= 1) + if((closed && ref.mData.getLocalRotation().rot[2] == 0) || + (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { return true; // found, stop searching } From 6a1435c49e7ed6a83bb92801ed6c7303872eb78a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 20 Apr 2014 17:59:08 +1000 Subject: [PATCH 024/484] Remove rotation check that was freezing NPC's. --- apps/openmw/mwmechanics/aiwander.cpp | 3 +-- apps/openmw/mwmechanics/aiwander.hpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index d552e045d..ad94be0eb 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -36,7 +36,6 @@ namespace MWMechanics , mChance(0) , mRotate(false) , mTargetAngle(0) - , mOriginalAngle(0) , mSaidGreeting(false) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) @@ -433,7 +432,7 @@ namespace MWMechanics } // Check if idle animation finished - if(!checkIdle(actor, mPlayedIdle) && !mRotate) + if(!checkIdle(actor, mPlayedIdle)) { mPlayedIdle = 0; mIdleNow = false; diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 2ed1af3be..fe14abeb6 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -76,7 +76,6 @@ namespace MWMechanics // the z rotation angle (degrees) we want to reach // used every frame when mRotate is true float mTargetAngle; - float mOriginalAngle; bool mRotate; float mReaction; // update some actions infrequently }; From 86bd2f48dc08da0878264a57b0204db72304e111 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 20 Apr 2014 17:28:10 +0200 Subject: [PATCH 025/484] removed an unused function --- apps/opencs/model/world/refcollection.cpp | 11 ----------- apps/opencs/model/world/refcollection.hpp | 5 ----- 2 files changed, 16 deletions(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 9ee59bd1e..4fdd97909 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -38,14 +38,3 @@ std::string CSMWorld::RefCollection::getNewId() stream << "ref#" << mNextId++; return stream.str(); } - -void CSMWorld::RefCollection::cloneRecord(const std::string& origin, - const std::string& destination, - const CSMWorld::UniversalId::Type type, - const CSMWorld::UniversalId::ArgumentType argumentType) -{ - Record clone(getRecord(origin)); - clone.mState = CSMWorld::RecordBase::State_ModifiedOnly; - clone.get().mId = destination; - insertRecord(clone, getAppendIndex(destination, type), type); -} \ No newline at end of file diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index dcfd2036c..173efba05 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -26,11 +26,6 @@ namespace CSMWorld ///< Load a sequence of references. std::string getNewId(); - - void cloneRecord(const std::string& origin, - const std::string& destination, - const CSMWorld::UniversalId::Type type, - const CSMWorld::UniversalId::ArgumentType argumentType); }; } From f811abb752efdd8306c081df67d92edd57d86728 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 20 Apr 2014 20:35:07 +0400 Subject: [PATCH 026/484] 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 f03a9197d..98ec9cfce 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 fd2fa61ba..84798ca02 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; + + 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))) + { + 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; + } - buildNewPath(actor); //may fail to build a path, check before use + mFollowTarget = false; - //delete visited path node - mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); + buildNewPath(actor); //may fail to build a path, check before use - //if no new path leave mTargetAngle unchanged - if(!mPathFinder.getPath().empty()) - { - //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; + //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); - - float dist = -1; //hack to indicate first time, to construct a new path + Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos); + + 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 767a36292..b71dd9cf0 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 3ecd40743..4aee6f6e4 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 ecaaef568..86fa3b6bc 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 d911fd81b..7646e832d 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 504dc3ac3..9bdf7d4a3 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 594a9f7f4..47536ab6c 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 f1e89bf6b..0eea3c6a0 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 79f32546e194d435e877f29b6216ea165be1218c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 Apr 2014 19:28:25 +0200 Subject: [PATCH 027/484] Dead link fix --- cmake/FindLIBUNSHIELD.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindLIBUNSHIELD.cmake b/cmake/FindLIBUNSHIELD.cmake index 4f4e98a1c..f0fa4cc82 100644 --- a/cmake/FindLIBUNSHIELD.cmake +++ b/cmake/FindLIBUNSHIELD.cmake @@ -4,7 +4,7 @@ # LIBUNSHIELD_FOUND, if false, do not try to link to LibUnshield # LIBUNSHIELD_INCLUDE_DIR, where to find the headers # -# Created by Tom Mason (wheybags) for OpenMW (http://openmw.com), based on FindMPG123.cmake +# Created by Tom Mason (wheybags) for OpenMW (http://openmw.org), based on FindMPG123.cmake # # 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 From 262e9596996bb29d4e000ded8235682988818613 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 Apr 2014 19:28:39 +0200 Subject: [PATCH 028/484] Remove unused slice_array --- components/CMakeLists.txt | 2 +- components/misc/slice_array.hpp | 82 --------------------------------- 2 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 components/misc/slice_array.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 2b06babe7..38be5b11a 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -49,7 +49,7 @@ add_component_dir (esm ) add_component_dir (misc - slice_array stringops + utf8stream stringops ) add_component_dir (files diff --git a/components/misc/slice_array.hpp b/components/misc/slice_array.hpp deleted file mode 100644 index cd58e7bd6..000000000 --- a/components/misc/slice_array.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ - - This file (slice_array.h) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -#ifndef MISC_SLICE_ARRAY_H -#define MISC_SLICE_ARRAY_H - -// A simple array implementation containing a pointer and a -// length. Used for holding slices into a data buffer. -#include -#include - -namespace Misc -{ - -template -struct SliceArray -{ - const T* ptr; - size_t length; - - /// Initialize to zero length - SliceArray() : ptr(0), length(0) {} - - /// Initialize from pointer + length - SliceArray(const T* _ptr, size_t _length) - : ptr(_ptr), length(_length) {} - - /// Initialize from null-terminated string - SliceArray(const char* str) - { - ptr = str; - length = strlen(str); - } - - bool operator==(SliceArray &t) - { - return - length == t.length && - (memcmp(ptr,t.ptr, length*sizeof(T)) == 0); - } - - /// Only use this for stings - bool operator==(const char* str) - { - return - str[length] == 0 && - (strncmp(ptr, str, length) == 0); - } - - /** This allocates a copy of the data. Only use this for debugging - and error messages. */ - std::string toString() - { return std::string(ptr,length); } -}; - -typedef SliceArray SString; -typedef SliceArray IntArray; -typedef SliceArray FloatArray; - -} - -#endif From 2cb9f38a45596859f2f3dc7fe1db51cf2b78bf36 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 20 Apr 2014 19:34:58 +0200 Subject: [PATCH 029/484] Changed crime IDs for legacy savegames. Not an issue, but it was inconsistent. --- components/esm/player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esm/player.cpp b/components/esm/player.cpp index 7a2c03b48..70f795afe 100644 --- a/components/esm/player.cpp +++ b/components/esm/player.cpp @@ -26,9 +26,9 @@ void ESM::Player::load (ESMReader &esm) mBirthsign = esm.getHNString ("SIGN"); - mCurrentCrimeId = 0; + mCurrentCrimeId = -1; esm.getHNOT (mCurrentCrimeId, "CURD"); - mPayedCrimeId = 0; + mPayedCrimeId = -1; esm.getHNOT (mPayedCrimeId, "PAYD"); } From 6929e541ddd21b211faa2b3817d0a763f0f31777 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 Apr 2014 05:30:14 +0200 Subject: [PATCH 030/484] Fix texture name issue with Vality's Bitter Coast Mod --- components/nifogre/material.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/nifogre/material.cpp b/components/nifogre/material.cpp index 4dae1a93d..3a87e1d52 100644 --- a/components/nifogre/material.cpp +++ b/components/nifogre/material.cpp @@ -67,6 +67,10 @@ std::string NIFMaterialLoader::findTextureName(const std::string &filename) std::string texname = filename; Misc::StringUtils::toLower(texname); + // Apparently, leading separators are allowed + while (texname.size() && (texname[0] == '/' || texname[0] == '\\')) + texname.erase(0, 1); + if(texname.compare(0, sizeof(path)-1, path) != 0 && texname.compare(0, sizeof(path2)-1, path2) != 0) texname = path + texname; From e3244501184f2c0b6e422f6d566f8853fd6d27f1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Apr 2014 09:02:58 +0200 Subject: [PATCH 031/484] 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 cbe90b1d3..1db922afa 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 87660a60b..de6809839 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 164398fb7..53afee048 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 3ff75c9c1..3f19269e7 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 b969862e9..e41c49029 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 032/484] 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 ab63e56c4..000000000 --- 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 033/484] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index eb427a22b..499c55eeb 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 034/484] 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 84798ca02..807e08c1d 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 93c789af1..2c63d5a14 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 035/484] 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 a75a84ec5..000000000 --- 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 5af298a57..000000000 --- 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 5d897448a..000000000 --- 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 87a85e8e4..000000000 --- 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 65825ce8b..000000000 --- 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 361339fe2..000000000 --- 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 e6c605275..000000000 --- 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 77ef4524f..000000000 --- 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 f268d3b27..000000000 --- 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 325de2bd2..000000000 --- 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 837a31bee..000000000 --- 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 07049fb71..000000000 --- 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 bbceafabe..000000000 --- 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 54c50f395..000000000 --- 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 332b68f5c..000000000 --- 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 b785bbd23..000000000 --- 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 153ac1551..000000000 --- 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 85215edab..000000000 --- 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 e31e526c0..000000000 --- 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 5c0754193..000000000 --- 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 da2cc2571..000000000 --- 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 9d3a01936..000000000 --- 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 9cb0ae1a1..000000000 --- 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 2d1d45d41..000000000 --- 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 81cc54fca..000000000 --- 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 90fb9bc97..000000000 --- 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 2c93986e7..000000000 --- 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 9f4513671..000000000 --- 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 3406a62c4..000000000 --- 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 4b6e8e344..000000000 --- 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 e73e24dcb..000000000 --- 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 3b3fa5b79..000000000 --- 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 ae42623b7..000000000 --- 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 2f2830625..000000000 --- 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 036/484] 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 000000000..05a9ba8f9 --- /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 000000000..da4c36d44 --- /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 000000000..6c7e78087 --- /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 000000000..1463e4d7d --- /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 000000000..70b91ee40 --- /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 000000000..8819096ad --- /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 000000000..1c48199d1 --- /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 000000000..52f9e05f1 --- /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 000000000..d9d5830d9 --- /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 000000000..0cfd415ac --- /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 000000000..db5091999 --- /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 000000000..2b52dfd1f --- /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 000000000..b2a47903f --- /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 000000000..c2860d769 --- /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 000000000..665326c2c --- /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 000000000..7f24f6a62 --- /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 000000000..cb127cb76 --- /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 000000000..5e894d8df --- /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 000000000..9283bbf51 --- /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 000000000..35ae4c068 --- /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 000000000..5e10c346f --- /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 000000000..6d718aad8 --- /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 000000000..259dd518b --- /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 000000000..c99879762 --- /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 037/484] relocate support.hpp / remove support.cpp --- apps/opencs/CMakeLists.txt | 31 ++-- apps/opencs/model/settings/support.cpp | 1 - apps/opencs/model/settings/support.hpp | 135 +++++++++++++--- apps/opencs/view/settings/support.cpp | 1 - apps/opencs/view/settings/support.hpp | 206 ------------------------- 5 files changed, 124 insertions(+), 250 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 cbe90b1d3..8ab44243d 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 d79edfdb3..000000000 --- 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 4ffd01b73..abc86a0cb 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 +{ + // 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 { - class SettingContainer; + enum SettingProperty + { + 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, - typedef QList SettingList; - typedef QMap SettingMap; - typedef QMap SectionMap; + //Stringlists should always be the last items + Property_DefaultValues = 12, + Property_DeclaredValues = 13, + Property_DefinedValues = 14, + Property_Proxies = 15 + }; - struct QStringPair + enum SettingType { - QStringPair(): left (""), right ("") - {} + Type_MultiBool = 0, + Type_SingleBool = 1, + Type_MultiList = 2, + Type_SingleList = 3, + Type_MultiRange = 4, + Type_SingleRange = 5, + Type_MultiText = 6, + Type_SingleText = 7 + }; - QStringPair (const QString &leftValue, const QString &rightValue) - : left (leftValue), right(rightValue) - {} + enum MergeMethod + { + Merge_Accept, + Merge_Ignore, + Merge_Overwrite + }; +} - QStringPair (const QStringPair &pair) - : left (pair.left), right (pair.right) - {} +namespace CSVSettings +{ + enum ViewType + { + ViewType_Boolean = 0, + ViewType_List = 1, + ViewType_Range = 2, + ViewType_Text = 3, + ViewType_Undefined = 4 + }; - QString left; - QString right; + enum Alignment + { + Align_Left = Qt::AlignLeft, + Align_Center = Qt::AlignHCenter, + Align_Right = Qt::AlignRight + }; +} - bool isEmpty() const - { return (left.isEmpty() && right.isEmpty()); } +// +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 // MODEL_SUPPORT_HPP + +#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 d79edfdb3..000000000 --- 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 5d954505c..000000000 --- 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 038/484] Re-link user settings to editor main application --- apps/opencs/editor.cpp | 13 + apps/opencs/editor.hpp | 4 +- apps/opencs/model/settings/usersettings.cpp | 455 ++++++++------------ 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 | 41 +- 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, 280 insertions(+), 361 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 87660a60b..2dfdb1de6 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 164398fb7..4c02b462e 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 94cee8a43..db31f4255 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,269 +42,235 @@ 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); - - windowHeight->setObjectName ("Height"); - windowWidth->setObjectName ("Width"); - rsDelegate->setObjectName ("Record Status Display"); - refIdTypeDelegate->setObjectName ("Referenceable ID Type Display"); - - SettingMap *displayFormatMap = new SettingMap; - SettingMap *windowSizeMap = new SettingMap; - - displayFormatMap->insert (rsDelegate->objectName(), rsDelegate ); - displayFormatMap->insert (refIdTypeDelegate->objectName(), refIdTypeDelegate); - - windowSizeMap->insert (windowWidth->objectName(), windowWidth ); - windowSizeMap->insert (windowHeight->objectName(), windowHeight ); - - mEditorSettingDefaults.insert ("Display Format", displayFormatMap); - mEditorSettingDefaults.insert ("Window Size", windowSizeMap); -} - -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)) + QString section = "Window Size"; { - stream = new QTextStream(file); - stream->setCodec(QTextCodec::codecForName("UTF-8")); + Setting *width = createSetting (Type_SingleText, section, "Width"); + Setting *height = createSetting (Type_SingleText, section, "Height"); + + width->setWidgetWidth (5); + height->setWidgetWidth (5); + + width->setDefaultValues (QStringList() << "1024"); + height->setDefaultValues (QStringList() << "768"); + + width->setEditorSetting (true); + height->setEditorSetting (true); + + height->setViewLocation (2,2); + width->setViewLocation (2,1); + + /* + *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" + ); } - return stream; - -} - -bool CSMSettings::UserSettings::writeSettings(QMap &settings) -{ - QTextStream *stream = openFileStream(mUserFilePath); - - bool success = (stream); - - if (success) + section = "Display Format"; { - QList keyList = settings.keys(); + QString defaultValue = "Icon and Text"; - foreach (QString key, keyList) - { - SettingList *sectionSettings = settings[key]; + QStringList values = QStringList() + << defaultValue << "Icon Only" << "Text Only"; - *stream << "[" << key << "]" << '\n'; + Setting *rsd = createSetting (Type_SingleBool, + section, "Record Status Display", + values); - foreach (SettingContainer *item, *sectionSettings) - *stream << item->objectName() << " = " << item->getValue() << '\n'; - } + Setting *ritd = createSetting (Type_SingleBool, + section, "Referenceable ID Type Display", + values); - stream->device()->close(); - delete stream; - stream = 0; + rsd->setEditorSetting (true); + ritd->setEditorSetting (true); } - else + + section = "Proxy Selection Test"; { - displayFileErrorMessage(mReadWriteMessage, false); + //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); } - - return (success); } - -const CSMSettings::SectionMap &CSMSettings::UserSettings::getSectionMap() const +CSMSettings::UserSettings::~UserSettings() { - return mSectionSettings; + mUserSettingsInstance = 0; } -const CSMSettings::SettingMap *CSMSettings::UserSettings::getSettings(const QString §ionName) const +void CSMSettings::UserSettings::loadSettings (const QString &fileName) { - return getValidSettings(sectionName); -} + mUserFilePath = QString::fromUtf8 + (mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8(); -bool CSMSettings::UserSettings::loadFromFile(const QString &filePath) -{ - if (filePath.isEmpty()) - return false; + QString global = QString::fromUtf8 + (mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8(); - SectionMap loadedSettings; + QString local = QString::fromUtf8 + (mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8(); - QTextStream *stream = openFileStream (filePath, true); + //open user and global streams + QTextStream *userStream = openFilestream (mUserFilePath, true); + QTextStream *otherStream = openFilestream (global, true); - bool success = (stream); + //failed stream, try for local + if (!otherStream) + otherStream = openFilestream (local, true); - if (success) + //error condition - notify and return + if (!otherStream || !userStream) { - //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; - } + 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.
"); - 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; - } + message += QObject::tr("
Global filepath: ") + global; + message += QObject::tr("
Local filepath: ") + local; + message += QObject::tr("
User filepath: ") + mUserFilePath; - } - - loadedSettings.insert(section, settings); - - stream->device()->close(); - delete stream; - stream = 0; + displayFileErrorMessage ( message, true); + return; } - mergeMap (loadedSettings); + //success condition - merge the two streams into a single map and save + DefinitionPageMap totalMap = readFilestream (userStream); + DefinitionPageMap otherMap = readFilestream(otherStream); - return success; -} + //merging other settings file in and ignore duplicate settings to + //avoid overwriting user-level settings + mergeSettings (totalMap, otherMap); -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()); - } - } - } - } + if (!totalMap.isEmpty()) + addDefinitions (totalMap); } -void CSMSettings::UserSettings::loadSettings (const QString &fileName) +void CSMSettings::UserSettings::saveSettings + (const QMap &settingMap) { - mSectionSettings.clear(); - - //global - QString globalFilePath = QString::fromStdString(mCfgMgr.getGlobalPath().string()) + fileName; - bool globalOk = loadFromFile(globalFilePath); - - - //local - QString localFilePath = QString::fromStdString(mCfgMgr.getLocalPath().string()) + fileName; - bool localOk = loadFromFile(localFilePath); - - //user - mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName; - loadFromFile(mUserFilePath); - - if (!(localOk || globalOk)) + for (int i = 0; i < settings().size(); i++) { - 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.
"); + Setting* setting = settings().at(i); - message += QObject::tr("
Global filepath: ") + globalFilePath; - message += QObject::tr("
Local filepath: ") + localFilePath; + QString key = setting->page() + '.' + setting->name(); - displayFileErrorMessage ( message, true); + if (!settingMap.keys().contains(key)) + continue; + + setting->setDefinedValues (settingMap.value(key)); } + + writeFilestream (openFilestream (mUserFilePath, false), settingMap); } -void CSMSettings::UserSettings::updateSettings (const QString §ionName, const QString &settingName) +QString CSMSettings::UserSettings::settingValue (const QString §ion, + const QString &name) { + Setting *setting = findSetting(section, name); - SettingMap *settings = getValidSettings(sectionName); - - if (!settings) - return; - - if (settingName.isEmpty()) - { - foreach (const SettingContainer *setting, *settings) - emit signalUpdateEditorSetting (setting->objectName(), setting->getValue()); - } - else + if (setting) { - if (settings->find(settingName) != settings->end()) - { - const SettingContainer *setting = settings->value(settingName); - emit signalUpdateEditorSetting (setting->objectName(), setting->getValue()); - } + if (!setting->definedValues().isEmpty()) + return setting->definedValues().at(0); } -} - -QString CSMSettings::UserSettings::getSetting (const QString §ion, const QString &setting) const -{ - SettingMap *settings = getValidSettings(section); - - QString retVal = ""; - - if (settings->find(setting) != settings->end()) - retVal = settings->value(setting)->getValue(); - - return retVal; + 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 63e78bd61..75a3a0797 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; - - const SettingMap *getSettings (const QString §ionName) const; + /// Writes settings to the user's config file path + void saveSettings (const QMap &settingMap); - /// 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 7fd005717..a80d21cb2 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 85274a18d..52e42cc0e 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 bc34c6118..47e1a80de 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 (subview) - subview->updateEditorSetting (settingName, settingValue); - } - } - else if (settingName == "Width") - resizeViewWidth (settingValue.toInt()); + if (list.isEmpty()) + return; + + int value = list.at(0).toInt(); + + if (name == "Width") + resizeViewWidth (value); - else if (settingName == "Height") - resizeViewHeight (settingValue.toInt()); + 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 ee7380e2b..5e6c9abc4 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 4a4dbc124..2297af0ba 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 01f495186..00e33916d 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 d59f0c234..e84f5cf4b 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 6503ebd27..9f6a4c1da 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 712b8f556..995de21fc 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 4231a4a43..dfc74b3eb 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 a5a7e8252..c193ed32b 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 b344ba1ad..9d86c32e4 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 b2a32b551..16310c8a9 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 7664f3eae..50e2cf858 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 039/484] 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 c3b36516c..161c9700f 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 040/484] 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 604b51990..ee6dba982 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 c97867d35..6945ae441 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 3cd8237e7..2662e1c53 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 2ac342a61..e053136d5 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 edec45e15..ba2a32727 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 6ea3f5472..d861e2032 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 968d3bbd7..f10d1df96 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 99dbcc66c..4b3d40ab7 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 27b842348..dc06bf6c9 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 0e21c55ac..174e34423 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 041/484] 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 f10d1df96..686fa94a7 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 00b15f4a3..c46d83c1b 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 16f6603a2..75122eacb 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 042/484] 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 e3c632512..5b4c2570a 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 043/484] 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 ee6dba982..1847fbd44 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 2662e1c53..e9f384572 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 ba2a32727..3751e5828 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 d861e2032..db8daff15 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 686fa94a7..bc71cc494 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 174e34423..0e21c55ac 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 5b4c2570a..5c9b25d28 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 c46d83c1b..699d326ee 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 75122eacb..16f6603a2 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 044/484] 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 1847fbd44..be76bd0b4 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 6945ae441..f012d675c 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 e9f384572..984e21e72 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 e053136d5..bddc46728 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 db8daff15..9a6cd6b89 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 bc71cc494..20013493f 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 4b3d40ab7..f20c5f6d2 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 dc06bf6c9..27b842348 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 699d326ee..f04e819c8 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 045/484] 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 5c9b25d28..87bdd2f9d 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 046/484] 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 52e42cc0e..733a75bb0 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 047/484] 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 1346b9e95..4bd2a1e65 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 87fbda25c..5eb355566 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 048/484] 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 4bd2a1e65..7fc867186 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 049/484] 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 7fc867186..3d5d2f4a8 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; - } - //If no quicksave works create a new slot with Signature - if(slot == NULL) { - slot = mCurrentCharacter->createSlot(mCurrentCharacter->getSignature()); + //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); } - //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 050/484] 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 3d5d2f4a8..db030c940 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 051/484] 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 9417d2a4b..7e4522de6 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 d96649af6..5a66c3370 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 db030c940..c3f5ff7aa 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 adf9f1557..e348323be 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 6361476e3..f24636d15 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 052/484] 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 7e4522de6..b4dae090f 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 053/484] 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 cd907408a..b9cf6aa7f 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 b4dae090f..023e01b06 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 c3f5ff7aa..bc1aaf8f6 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 6b0871012..19b6ca1f3 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 46ade236b..8082a2c78 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 054/484] 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 b9cf6aa7f..fc4a2d806 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 023e01b06..ed1b9e0a9 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 bc1aaf8f6..51c0a1621 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 19b6ca1f3..a0971b942 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 8082a2c78..2d3ca21fb 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 055/484] 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 a0971b942..56f562e04 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 056/484] 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 51c0a1621..b37813915 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 057/484] 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 56f562e04..e32aad505 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 058/484] 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 1db922afa..f1d50467b 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 3ef14ee7e..20a355d48 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 201fb4342..c7d87e16a 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 3f19269e7..51774e4ff 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 e41c49029..c30c83c06 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 000000000..722e90364 --- /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 000000000..eae0c8001 --- /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 059/484] 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 70b91ee40..450252cd9 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 8819096ad..ca8a2cc7b 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 75a3a0797..63caed923 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 47e1a80de..397567f99 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 b2a47903f..36cdbb0ae 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 665326c2c..a5711c8f8 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 259dd518b..4f93b1c0f 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 995de21fc..902ab268a 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 dfc74b3eb..c2811b893 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 16310c8a9..ea8a7c541 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 50e2cf858..1c7e37818 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 060/484] 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 22dda0ce0..7d27e73bd 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 84dc337c9..868a09e2e 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 761caf586..a00c79525 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 a4a4e9568..9cc873c0f 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 061/484] Reworked the accusation of actors --- apps/openmw/mwbase/mechanicsmanager.hpp | 6 ++---- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 8 ++++---- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 3 +-- apps/openmw/mwworld/player.cpp | 8 +++++--- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 7d27e73bd..d0a0783d3 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 868a09e2e..0ef94c13c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -985,13 +985,13 @@ namespace MWMechanics mObjects.getObjectsInRange(position, radius, objects); } - std::list MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor) + void MechanicsManager::getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) { - return mActors.getActorsFollowing(actor); + mActors.getObjectsInRange(position, radius, objects); } - MWMechanics::Actors& MechanicsManager::getActors() + std::list MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor) { - return *mActors; + return mActors.getActorsFollowing(actor); } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index a00c79525..603815744 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 9cc873c0f..f4ca5ee27 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 062/484] 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 e4c480a8c..44b3d0229 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 51c0a1621..75c9015a0 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 7b83ff1f1..804ec7a41 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 d61d74258..f7dff1058 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 d24191d88..90c00a36e 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 5dd758377..4d59379d6 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 a0971b942..6c834a2be 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 bba75bc49..bbba1081c 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 67755259e..433237e26 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 bd5642116..a86dc38b1 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 6746f692f..7237fd334 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 a4a4e9568..9202118a4 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 7dbaaddb4..7e3f7a3cf 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 063/484] Checks the state of the passed sneak variable --- apps/openmw/mwworld/player.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index f4ca5ee27..8588547d2 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(); - - // 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); + 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(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 064/484] 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 450252cd9..eec4c54cf 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 db31f4255..badb73ece 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 63caed923..f0ed7af41 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 397567f99..acb272553 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 d838395f6..ef0da56ac 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 d23b86631..f11c4a2b9 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 ce4e8f014..485ca57ac 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 d9126fee0..1b42223af 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 065/484] 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 badb73ece..808fbfc70 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 066/484] 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 807e08c1d..8a3c23aef 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 b71dd9cf0..8130df0e8 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 2c63d5a14..21f2ed883 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 86fa3b6bc..ff3bf06fa 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 7646e832d..d10733b36 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 9bdf7d4a3..1c00b508d 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 067/484] 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 06a228a1f..02cc5c6a9 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 1645d8db0..38535630f 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 db19070a6..2b9840876 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 068/484] 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 c62c4e970..024656b38 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 069/484] 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 deeb93440..42362fde7 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 070/484] 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 6bc7657e4..bbd968a7b 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 071/484] 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 508b195e9..03361408c 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 072/484] 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 18ae7dd1b..b1c700e31 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 073/484] 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 a09a58191..14f5cc4e7 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 79e1cc2a5..d4b042726 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 074/484] 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 e11e3b0c4..819c2701c 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 075/484] 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 3d70fdc6a..e1d1246c8 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 88f1302bb..32535f33e 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 b9284dc1a..a2e31e791 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 70186a089..ceea34466 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 80467f58a..36083e4b0 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 78b6409f2..531fe2959 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 1dbdbf7e7..27ee182cf 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 076/484] 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 de6809839..f13c85e73 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 53afee048..d1825e5af 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 51774e4ff..b8372eb4c 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 c30c83c06..1af18a148 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 077/484] 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 | 142 ++++++++++--------------- apps/openmw/mwrender/globalmap.hpp | 7 +- components/esm/globalmap.cpp | 17 +++ components/esm/globalmap.hpp | 3 + 7 files changed, 112 insertions(+), 99 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 1cc9610df..aa48631e4 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 249477551..0b549147c 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 2b9840876..0457fcb59 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 76ad1890f..0537ed516 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; - - 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"); + const ESM::GlobalMap::Bounds& bounds = map.mBounds; - 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); - - // 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"); - - // 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; + if (bounds.mMaxX-bounds.mMinX <= 0) + return; + if (bounds.mMaxY-bounds.mMinY <= 0) + return; - assert(imageX < image.getWidth()); - assert(imageY < image.getHeight()); + if (bounds.mMinX > bounds.mMaxX + || bounds.mMinY > bounds.mMaxY) + throw std::runtime_error("invalid map bounds"); - if (image.getColourAt(imageX, imageY, 0).a > 0) - exploredCells.push_back(std::make_pair(x+bounds.mMinX,y+bounds.mMinY)); - } - } + 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); + + // 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; + + // Completely off-screen? -> no need to blit anything + if (bounds.mMaxX < mMinX + || bounds.mMaxY < mMinY + || bounds.mMinX > mMaxX + || bounds.mMinY > mMaxY) + return; - // 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; - - // Completely off-screen? -> no need to blit anything - if (bounds.mMaxX < mMinX - || bounds.mMaxY < mMinY - || bounds.mMinX > mMaxX - || bounds.mMinY > mMaxY) - return; - - 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"); - } + 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"); } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 5fe878cd4..6075d042e 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 1fa5f907e..f17c071ff 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 5d036c736..158f70a6e 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 078/484] 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 ca37b152c..267170214 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 079/484] 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 267170214..a08cd9c33 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 080/484] 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 42362fde7..8095b0d05 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 5eb355566..3787a9c07 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 081/484] Revert "Checks the state of the passed sneak variable" This reverts commit 4a4c08946c5b75701a5eb9b3e878c0727380909d. --- apps/openmw/mwworld/player.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 8588547d2..f4ca5ee27 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(); - - // 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); - } + 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); } 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 082/484] Revert 4a4c089..f0c5d1a This rolls back to commit 4a4c08946c5b75701a5eb9b3e878c0727380909d. --- apps/openmw/mwmechanics/actors.cpp | 37 +++++++++++++++++++++--------- apps/openmw/mwworld/player.cpp | 30 +++++++++++++++--------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a08cd9c33..ca37b152c 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 f4ca5ee27..8588547d2 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(); - - // 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); + 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(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 083/484] 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 8ab44243d..680c8f8b7 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 52f9e05f1..55ef0bb08 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 000000000..411e12775 --- /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 000000000..1df0c7bd6 --- /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 084/484] 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 4c0faeac1..dc7226909 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 b052739bd..a00c2480e 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 93c789af1..4cabaee09 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 2b1fdd365..ff9bacf7b 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 9a6cd6b89..21aee5b98 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 0b3f3438d..acf1cf3f2 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 e00276293..9610171b2 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 87bdd2f9d..46bb4db58 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 085/484] 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 8a3c23aef..fa7ef28a3 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 d10733b36..0a8a37ecb 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 086/484] 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 804ec7a41..d51b02a15 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 087/484] 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 ad94be0eb..2d1fbdd78 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 fe14abeb6..35ecc83e0 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 088/484] 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 e3bd428e2..eb84741c4 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 02cc5c6a9..946259e10 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 38535630f..973ac0745 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 0457fcb59..2ed113126 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 ab9770a41..074cb3208 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 ff9bacf7b..34402977c 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 089/484] 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 6c7e78087..ca682b454 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 abc86a0cb..ce808587f 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 808fbfc70..2f8e8098d 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 a5711c8f8..e67445873 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 411e12775..12b71d28f 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 9283bbf51..8eccee646 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 090/484] 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 12b71d28f..2bb5863bc 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 8eccee646..7bd0b228e 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 091/484] 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 bb6cf2800..9c4ea2d29 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 c11e11c32..49c58c896 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 34ac8d9f4..585647338 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 bcb8440bf..e702c073d 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 22595582e..4b9b4ff99 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 97e1e9a2b..c0847929b 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 23856395e..78dcc9497 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 58e89c4fc..7b2ea4d4a 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 47aaf79e8..684771b86 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 c9c65a152..ad18a13e8 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 bd0704724..dd2f2f3c1 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 092/484] Fix a stacking issue --- apps/openmw/mwworld/containerstore.cpp | 41 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index dd2f2f3c1..b1cbcc9c2 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -187,31 +187,44 @@ 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); - MWWorld::Ptr item = *it; - - // we may have copied an item from the world, so reset a few things first - item.getRefData().setBaseNode(NULL); - 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; - 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 - item.getCellRef().mOwner = ""; + itemPtr.getCellRef().mOwner = ""; } else - item.getCellRef().mOwner = actorPtr.getCellRef().mRefID; + 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); // 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; 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 093/484] 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 19649cfd2..faa0d8637 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 094/484] 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 e348323be..bcf4374a4 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 15287bc74..d75abc873 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 095/484] 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 433237e26..60af3d9b9 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 096/484] 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 946259e10..be4a9a14e 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 ef223a617..2135f4dde 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 f10908d7b..d5078e994 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 f5418e3f8..a09011e10 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 097/484] 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 804ec7a41..96194d292 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 098/484] 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 34402977c..841f617b7 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 099/484] 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 596bf0e56..4b9c8988e 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 2b612d734..42d963117 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 7d531d6d3..5bf8305ba 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 100/484] 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 2b1fdd365..26c629fb8 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 101/484] 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 26c629fb8..88d07cfa6 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 102/484] 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 88d07cfa6..2b1fdd365 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 103/484] 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 2b1fdd365..03beed5a5 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 104/484] 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 03beed5a5..8b8788741 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 105/484] 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 8b8788741..eca0c2289 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 106/484] 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 3e15bcd78..9cabab3e8 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 0c5bd9afa..86db207a4 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 c67367a6c..294c9b6a1 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 cb9f051e3..82d815d68 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 21aee5b98..e6342e661 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 21781c530..c2bf794f1 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 e62fee6e2..3b8b91b0e 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 ba39d10d5..4f5536ca3 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 9c10ca84b..f1b1325f7 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 0720e798a..33032477f 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 150f0bed2..627c05251 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 bbd968a7b..e5f0c4b88 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 7d531d6d3..d1f328f06 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 5e4211faa..b93632d19 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 107/484] 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 42d963117..e64639c34 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 716101637..30b72acd9 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 108/484] 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 e9731d626..eef96c8c9 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 184d11bb4..25b2a4505 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 8abdf0019..638237f34 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 ef0da56ac..c3ec68b52 --- 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 902ab268a..a5a98aac7 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 109/484] 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 d51b02a15..0b0569376 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 f81613ed1..40ac92251 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 5dc59e5ab..633dc285c 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 ceea34466..bf2273b17 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 36083e4b0..2f584e7ed 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 7e3f7a3cf..638c738bd 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 531fe2959..db1ac1609 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 27ee182cf..9e36cb68d 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 110/484] 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 80704ca7c..82400aac4 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 111/484] 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 5526bd26d..fa1bd28be 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 112/484] 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 96194d292..a0680c037 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 113/484] 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 a09011e10..5ef3d7304 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 d75abc873..b80859ea1 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 114/484] 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 e1d1246c8..f51fba07b 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 8e4e9703f..7f06320aa 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 eb84741c4..4287e466b 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 f03a9197d..d68228904 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 32535f33e..caaf7c91f 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 a2e31e791..6cd2c75af 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 26383b3a7..724d531cf 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 1b4803ba2..00511f47c 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 55235173f..96e0e1ed4 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 aa48631e4..284e5c4e2 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 0b549147c..7f4f18893 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 2ed113126..e2e4e157c 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 074cb3208..064ca89ba 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 527c576cc..8e118e2f8 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 de63b9906..97584a5b8 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 acf1cf3f2..33a78330d 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, 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); - 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); + // 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 acffe20f3..7f2a87eec 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 5209aa51a..a9c17fa93 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 c5c826d47..ebe0aa08a 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 e6730c307..ea6d3d006 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 879ffa8e3..663af640b 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 d8d2cefbf..3ff4a5d6e 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 5e4211faa..0aeb0ae5c 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 7e3f7a3cf..8d27b2712 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 0fc2d547c..0f8ab8682 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 335702c66..3611114a9 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 cad3a4492..3e9df504b 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 46bb4db58..0e825e263 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 f1e89bf6b..40ba8fa82 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 b6c0ebc70..6b0bb9a27 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 33650e678..b385ac067 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 5614d295f..eb5e14daf 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 483d52491..f6a7b71e9 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 115/484] 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 a0680c037..2de5e268f 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 116/484] 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 47e1fd2b8..2bd9d8997 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 117/484] 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 e64639c34..d0555cdc3 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 118/484] 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 7917c75f3..7c915ebeb 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 33a78330d..6fbd4bb23 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 119/484] 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 b79808d08..9a55b3dcf 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; - const MWWorld::ESMStore &store = world->getStore(); - const ESM::Faction *faction = store.get().find(factionId); - 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; - if (!ranks.empty()) - { - std::map::const_iterator it = ranks.begin(); + ++rank; // Next rank - if(it->second < -1 || it->second > 9) - return ""; + // if we are already at max rank, there is no next rank + if (rank > 9) + rank = 9; - 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]; + const MWWorld::ESMStore &store = world->getStore(); + const ESM::Faction *faction = store.get().find(factionId); + + if(rank < 0 || rank > 9) + return ""; + + 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 120/484] 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 9a55b3dcf..b97be61e1 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 121/484] 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 2bd9d8997..b5bf6405d 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 122/484] 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 b6e3915bb..df9c53ea8 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 e8cb23b77..f4c7142ce 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 123/484] 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 b5bf6405d..e299c7b0b 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 124/484] 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 0e825e263..4c1a8b1c0 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 125/484] 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 8dda041ca..eff7aea24 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 b6ed9155f..b5dfd333d 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 126/484] Implemented Scrawls alternative workaround. --- files/mygui/openmw_confirmation_dialog.layout | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index e299c7b0b..edeed539c 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 127/484] Fixes #1187: Make GetDistance handle actors in remote cells gracefully --- apps/openmw/mwscript/interpretercontext.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index b97be61e1..1f5ad5b07 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 ref = MWBase::Environment::get().getWorld()->getPtr (name, true); + 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 = 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 128/484] 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 fc4a2d806..121a73a48 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 bb4373cba..74ccc82f4 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 8d09a1cbc..42c29f4bc 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 304eaddd3..5fe80ce0c 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 61e4e5b25..874533289 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 2a40fb1cc..822e2d88e 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 bc2e23f89..869d34f21 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 6fbd4bb23..635ad1ff4 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 2d3ca21fb..40c36deb5 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 129/484] 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 635ad1ff4..33f2dce7c 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 130/484] 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 2de5e268f..b87bc453c 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 c67367a6c..2581d52c9 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 07b7c898c..cb1b0de02 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 ad94be0eb..972c4553d 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 fe14abeb6..a789a372e 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 a34c5476c..43da111bf 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 131/484] 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 | 42 +++++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 722010686..7120ff5af 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; + if (!mPathFinder.isPathConstructed()) + { + Ogre::Vector3 destNodePos = mReturnPosition; - ESM::Pathgrid::Point dest; - dest.mX = destNodePos[0]; - dest.mY = destNodePos[1]; - dest.mZ = destNodePos[2]; + 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]; + // 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); + // don't take shortcuts for wandering + mPathFinder.buildPath(start, dest, actor.getCell(), false); - if(mPathFinder.isPathConstructed()) - { - mMoveNow = false; - mWalking = true; + 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 132/484] 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 cbe90b1d3..7a9320904 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 d7b7728a5..93810a252 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 adcb147c1..9ca712801 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 000000000..4aa13308a --- /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 000000000..4e5389f06 --- /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 738de89ae..bfce1fce4 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 c3757fe45..d894fd9cc 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 712b8f556..d700d5f2e 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 4231a4a43..926ba0e95 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 133/484] 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 4aa13308a..f962f6f10 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 4e5389f06..7a2b51743 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 bfce1fce4..85b79c3f2 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 d894fd9cc..596ddfaed 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 926ba0e95..30b487ce8 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 134/484] 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 2dfdb1de6..f6370ac51 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 135/484] 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 f1d50467b..e19242e09 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 b8372eb4c..4658667c3 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 1af18a148..63ee5eb68 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 722e90364..53827deb0 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 eae0c8001..af266d52b 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 000000000..f840ab717 --- /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 000000000..4aa497482 --- /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 4a4dbc124..3ca52c452 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 01f495186..cddc1b235 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 136/484] 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 20a355d48..25b48a3c9 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 c7d87e16a..e19efd04e 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 4658667c3..ae6f1103f 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 63ee5eb68..4adc9726c 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 53827deb0..dbaa2b4d5 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 af266d52b..4e3db1815 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 f840ab717..15296d616 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 4aa497482..cb154b13e 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 3ca52c452..c18cca809 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 137/484] 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 2f8e8098d..fa89fceee 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 abdc33103..d03bf3f80 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 138/484] 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 44c8c96be..c397b190f 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 40ac92251..8490226cb 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 633dc285c..23d9303c0 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 e5f0c4b88..7a85623cf 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 88b49ed1c..69d1a53a3 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 3d4413a35..9d456e236 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 16d4877a9..b85a3d7ce 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 de9c8f04a..79c8b38f3 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 645330683..2328e67a8 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 139/484] 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 9d456e236..b277b2494 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 b85a3d7ce..a26ad99de 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 79c8b38f3..6fa182894 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 140/484] 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 c09abcbaf..c2b11c615 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 18bb24ed0..5be81ac08 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 141/484] 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 fe310d0aa..53b55939b 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 93810a252..e0a735e35 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 a62acc02b..94b042ec5 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 34167cd85..24fb54399 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 85b79c3f2..beb2e849e 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 142/484] 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 8490226cb..910760685 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 23d9303c0..aee11a358 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 33f2dce7c..6dcfd9076 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 143/484] 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 f962f6f10..8e283294e 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 7a2b51743..29b590c36 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 beb2e849e..326f3c60d 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 596ddfaed..c8b110f4b 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 d700d5f2e..8e98e93a3 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 30b487ce8..83a294dd8 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 144/484] 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 | 17 +++-- apps/openmw/mwmechanics/aipersue.hpp | 6 +- apps/openmw/mwmechanics/aisequence.hpp | 62 ++++++++++------- apps/openmw/mwmechanics/aitravel.hpp | 7 +- apps/openmw/mwmechanics/aiwander.hpp | 17 +++-- apps/openmw/mwmechanics/alchemy.hpp | 92 ++++++++++++------------- 11 files changed, 146 insertions(+), 101 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 3787a9c07..ace4cc6d0 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 fd54869f6..b6ce9f85d 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 30b72acd9..833b0063c 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 53b57c058..3771417fa 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 48a8eb4c2..4eb3e3757 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 8e015da15..30eab7f8b 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(); - + + ///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; - ///< \return Package completed? - + + /// Returns the TypeID of the AiPackage + /// \see enum TypeId virtual int getTypeId() const = 0; - ///< @see enum TypeId + /// 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 3fd708ab3..bf5410676 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 cb1b0de02..a751e0397 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 72f3e0298..ea7f1dc32 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 2975c8315..6481b2a01 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 + /// 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 31cafa4dc..b2b0fe1ee 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 145/484] 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 8e283294e..d9d891ff1 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 29b590c36..06ee3b9c6 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 326f3c60d..ccd121204 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 c8b110f4b..08744a4a0 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 8e98e93a3..e5cfbe360 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 83a294dd8..cfab486e5 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 146/484] 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 eca0c2289..a16c6588d 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 147/484] 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 5e4211faa..d023d4388 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 148/484] 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 0f23dfe7b..3f40712d2 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 f6ff32dc1..c6fdbf3be 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 ccd121204..de46f175f 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 149/484] 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 3f40712d2..d916e33e9 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 c6fdbf3be..bfcb25e66 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 0bb11ce8c..506a0288d 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 150/484] 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 de46f175f..260b3b825 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 151/484] 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 d0555cdc3..fdaec28b4 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 7120ff5af..f95c858c9 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 2975c8315..3be74010d 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 97bb88c52..ec9c86754 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 152/484] 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 f95c858c9..7120ff5af 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 3be74010d..2975c8315 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 ec9c86754..29577542e 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 153/484] 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 53b55939b..fe310d0aa 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 e0a735e35..6d65d0ff8 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 9ca712801..85c243944 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 d916e33e9..cdbd88278 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 d9d891ff1..c33fa58ad 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 06ee3b9c6..8c5f1b841 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 260b3b825..849a1988a 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 08744a4a0..0097a16dc 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 e5cfbe360..cc51a2213 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 cfab486e5..8e874ec56 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 154/484] 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 25b48a3c9..760c675a0 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 155/484] 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 392fdfc66..bd45a207c 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 156/484] 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 | 74 ++++++++++++++++++- apps/opencs/view/render/worldspacewidget.hpp | 26 ++++++- 6 files changed, 183 insertions(+), 44 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index cdbd88278..3691a7a4d 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 bfcb25e66..f9215f596 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 fb74788cc..43c8dbd8d 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 17dc46918..d5b62b8ed 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 4d2442c89..925dd921b 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -5,15 +5,20 @@ #include #include +#include + #include "../world/scenetoolmode.hpp" +#include -CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) -: SceneWidget (parent) +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 f7208d7a1..83ef593d6 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 157/484] 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 74ccc82f4..a77c625f9 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 3d4c741a3..31a3b6fdd 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 158/484] 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 b1cbcc9c2..eb6760d14 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 159/484] 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 e9efe75e7..2bea088e3 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 7ef168e98..c23a74efa 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 16e6ab017..60312455f 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 f52deedcc..74216c1de 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 1b9a899a0..01b8764c2 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 844144d7c..3d968470f 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 b80859ea1..d4c72c75b 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 160/484] 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 7a6317c16..59c2e7ca6 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 161/484] 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 8ad2b4a67..280639f71 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 162/484] 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 d60dcae11..b71f537f3 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 3691a7a4d..a6bdb5180 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 8df9cf347..7f8f104f1 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 43c8dbd8d..929088789 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 d5b62b8ed..ad1e22e39 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 506a0288d..45cd11618 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&))); + } + + SceneToolMode *navigationTool = mScene->makeNavigationSelector (mToolbar); + mToolbar->addTool (navigationTool); + + SceneToolMode *lightingTool = mScene->makeLightingSelector (mToolbar); + mToolbar->addTool (lightingTool); - layout2->addWidget (toolbar, 0); + mLayout->addWidget (mToolbar, 0); - layout2->addWidget (mScene, 1); + mLayout->addWidget (mScene, 1); - layout->insertLayout (0, layout2, 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 0b15ea541..9af76ef6a 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 163/484] 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 45cd11618..f3807e4e9 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 164/484] 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 4287e466b..c78902a60 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 dc7226909..fb41b3b67 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 058519ece..c0e25a517 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 e2e4e157c..1b4145e5c 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 064ca89ba..44bc56654 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 33f2dce7c..48d12f0a6 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 4d5b36c74..b2a1637f1 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 165/484] 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 c78902a60..9e5230af6 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 df9c53ea8..8b44af2ef 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 39574d0f7..df53a42b7 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 1b4145e5c..d2a31e8d1 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 44bc56654..e31013b45 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 48d12f0a6..c718eeced 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 166/484] 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 a77c625f9..c0daa2c0e 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 167/484] 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 fb41b3b67..51e24e29c 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 38be5b11a..1c60dfb83 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 000000000..ad2b671aa --- /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 000000000..c52466b13 --- /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 168/484] 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 f24636d15..2b44d0f4e 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 169/484] make getDropType static and public. --- apps/opencs/view/render/worldspacewidget.cpp | 2 +- apps/opencs/view/render/worldspacewidget.hpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 925dd921b..16ff0a403 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 83ef593d6..f9d4f9a06 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -30,6 +30,14 @@ namespace CSVRender public: + enum dropType + { + cellsMixed, + cellsInterior, + cellsExterior, + notCells + }; + WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); @@ -38,22 +46,14 @@ namespace CSVRender 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 - enum dropType - { - cellsMixed, - cellsInterior, - cellsExterior, - notCells - }; - - dropType getDropType(const std::vector& data) const; - private: void dragEnterEvent(QDragEnterEvent *event); From 92467ba6bc5b91f5e4487a5bca5100f8d6a13930 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 20:55:58 +0200 Subject: [PATCH 170/484] 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 97283d065..19d26a176 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 3611114a9..25f523bee 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 171/484] 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 01eb770f7..d51d4298f 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 172/484] 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 e43bfe40d..5222eac44 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 173/484] 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 c3ea2fd74..09a244177 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 174/484] 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 247c0d4bd..e30a2bbc1 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 175/484] 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 760c675a0..a441f4ae2 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 e19efd04e..11a4057d1 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 dbaa2b4d5..5277b08d2 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 4e3db1815..dee7d06cb 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 176/484] 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 b0b482cfd..38ebda268 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 6460b0305..acab7c786 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 817c0e43c..e459dded7 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 177/484] 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 e83ae2d8d..0661508b8 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 38ebda268..3c1a75d56 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 8e015da15..bd172c373 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 36e18946c..8da5c640e 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 3fd708ab3..86750acca 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 acab7c786..0b1da180d 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 cb1b0de02..614eb4154 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 c40d47d7f..12809755e 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 b1de3e510..d8cde5952 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 70f795afe..52b44c945 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 377c8547a..440d0a2d9 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 178/484] 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 eded36394..1febb1678 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 ae6f1103f..f102dac70 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 4adc9726c..be9528659 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 5277b08d2..47cac1713 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 dee7d06cb..270aeeb00 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 15296d616..50c29eedb 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 cb154b13e..ad1e3ffb8 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 c18cca809..877bc1dea 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 179/484] 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 | 40 ++-- .../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 | 174 ++++++++++-------- apps/opencs/view/world/scenesubview.hpp | 16 +- 9 files changed, 182 insertions(+), 150 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index a6bdb5180..c9308fbfb 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 bd5d1107c..0a73c791c 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 1aee421ed..8a58b7d32 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 929088789..de4dde9dd 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) +void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) { - const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + mCellId = data.begin()->getId(); + update(); + emit cellChanged(*data.begin()); +} - if (mime->fromDocument (mDocument)) +CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const +{ + switch(type) { - const std::vector& data (mime->getData()); - CSVRender::WorldspaceWidget::dropType whatHappend = getDropType (data); - - switch (whatHappend) - { - case CSVRender::WorldspaceWidget::cellsExterior: - emit exteriorCellsDropped(data); - break; + case cellsInterior: + return canHandle; - case CSVRender::WorldspaceWidget::cellsInterior: - handleDrop(data); - break; + case cellsExterior: + return needPaged; - 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(); + default: + return ignored; + } } diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index ad1e22e39..bb5340845 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 16ff0a403..c83a5a3e1 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 f9d4f9a06..a14e03915 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 f3807e4e9..d411985b3 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(widget, SIGNAL(dataDropped(const std::vector&)), + this, SLOT(handleDrop(const std::vector&))); - connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + 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); - - 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); - - 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())); + CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL; + CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL; + SceneToolbar* toolbar = NULL; - widget->handleDrop (data); + switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data))) + { + case CSVRender::WorldspaceWidget::canHandle: + mScene->handleDrop(data); + break; + + case CSVRender::WorldspaceWidget::needPaged: + pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument); + toolbar = makeToolbar(pagedNewWidget); + makeConnections(pagedNewWidget); + replaceToolbarAndWorldspace(pagedNewWidget, toolbar); + mScene->handleDrop(data); + break; + + 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::changeToUnpaged (const std::vector< CSMWorld::UniversalId >& data) +void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar) { - mLayout->removeWidget(mToolbar); - mLayout->removeWidget(mScene); + assert(mLayout); - delete mScene; - delete mToolbar; + if (mScene) + { + mLayout->removeWidget(mScene); + mScene->deleteLater(); + } - mToolbar = new SceneToolbar (48+6, this); - CSVRender::UnpagedWorldspaceWidget* widget = new CSVRender::UnpagedWorldspaceWidget (data.begin()->getId(), mDocument, this); - setUniversalId(*(data.begin())); + 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 (exteriorCellsDropped (const std::vector&)), - this, SLOT (changeToPaged (const std::vector&))); + mToolbar = toolbar; 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 9af76ef6a..251ddae1f 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 180/484] 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 | 243 +++++++++++++++++-------------- apps/opencs/model/world/data.hpp | 20 ++- 4 files changed, 164 insertions(+), 118 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 47cac1713..85bfececd 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 270aeeb00..5e86e4e67 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 d60dcae11..93b734e27 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; + + mReader = new ESM::ESMReader; + mReader->setEncoder (&mEncoder); + mReader->open (path.string()); - /// \todo set encoding properly, once config implementation has been fixed. - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); - reader.setEncoder (&encoder); + mBase = base; + mProject = project; - reader.open (path.string()); + mAuthor = mReader->getAuthor(); + mDescription = mReader->getDesc(); - const ESM::Dialogue *dialogue = 0; + return mReader->getRecordCount(); +} - mAuthor = reader.getAuthor(); - mDescription = reader.getDesc(); +bool CSMWorld::Data::continueLoading() +{ + if (!mReader) + throw std::logic_error ("can't continue loading, because no load has been started"); - // 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()) + if (!mReader->hasMoreRecs()) { - ESM::NAME n = reader.getRecName(); - reader.getRecHeader(); + delete mReader; + mReader = 0; + mDialogue = 0; + return true; + } + + ESM::NAME n = mReader->getRecName(); + mReader->getRecHeader(); - switch (n.val) + 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: { - 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; + std::string id = mReader->getHNOString ("NAME"); - 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 (*mReader); - ESM::Dialogue record; - record.mId = id; - record.load (reader); + 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 (record.mType==ESM::Dialogue::Journal) + if (mJournals.tryDelete (id)) { - mJournals.load (record, base); - dialogue = &mJournals.getRecord (id).get(); + /// \todo handle info records } - else if (record.mType==ESM::Dialogue::Deleted) + else if (mTopics.tryDelete (id)) { - 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 - } + /// \todo handle info records } else { - mTopics.load (record, base); - dialogue = &mTopics.getRecord (id).get(); + /// \todo report deletion of non-existing record } - - break; } - - case ESM::REC_INFO: + else { - if (!dialogue) - { - /// \todo INFO record without matching DIAL record -> report to user - reader.skipRecord(); - break; - } + mTopics.load (record, mBase); + mDialogue = &mTopics.getRecord (id).get(); + } - if (dialogue->mType==ESM::Dialogue::Journal) - mJournalInfos.load (reader, base, *dialogue); - else - mTopicInfos.load (reader, base, *dialogue); + break; + } + case ESM::REC_INFO: + { + if (!mDialogue) + { + /// \todo INFO record without matching DIAL record -> report to user + mReader->skipRecord(); break; } - case ESM::REC_FILT: + if (mDialogue->mType==ESM::Dialogue::Journal) + mJournalInfos.load (*mReader, mBase, *mDialogue); + else + mTopicInfos.load (*mReader, mBase, *mDialogue); - if (project) - { - mFilters.load (reader, base); - mFilters.setData (mFilters.getSize()-1, - mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope), - static_cast (CSMFilter::Filter::Scope_Project)); - break; - } + 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) + // fall through (filter record in a content file is an error with format 0) - default: + default: - /// \todo throw an exception instead, once all records are implemented - /// or maybe report error and continue? - reader.skipRecord(); - } + /// \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 152c3ac41..234069e3a 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 181/484] 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 f102dac70..f9e6bd96a 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 be9528659..47118a0fb 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 85bfececd..e2cf6684f 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 5e86e4e67..f6cfd2a0b 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 50c29eedb..418dc5638 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, steps); +} + +void CSVDoc::Loader::nextRecord (CSMDoc::Document *document) { std::map::iterator iter = mDocuments.find (document); if (iter!=mDocuments.end()) - iter->second->nextStage (name); + 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 ad1e3ffb8..0c85223c6 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 c7d9ed470..1c5f51129 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 182/484] 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 09a244177..82db5ea99 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 183/484] 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 f9e6bd96a..d44da15c5 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 47118a0fb..d834d85d4 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 e2cf6684f..2ef808dd6 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 f6cfd2a0b..a6bcb6b87 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 418dc5638..a9206ef2b 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 0c85223c6..a251e75d9 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 1c5f51129..b8971a296 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 184/484] 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 a9206ef2b..3b5890479 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 a251e75d9..d1c740011 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 185/484] 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 8da5c640e..0c10bd81d 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 186/484] 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 804ec7a41..f51593088 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 f7dff1058..ddd7a47d3 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 d023d4388..c0f88249c 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 187/484] 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 f51593088..71ccf7ff2 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 c0f88249c..d581a86c0 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 188/484] 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 d411985b3..34008c9a8 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 189/484] 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 79427309c..000000000 --- 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 51e562c91..000000000 --- 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 5c7664b50..000000000 --- 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 190/484] 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 bd45a207c..27007f161 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 191/484] 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 3f3e3a62d..000000000 --- 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 f432c32ec..000000000 --- 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 fb187f844..000000000 --- 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 be52f6f49..000000000 --- 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 33032477f..8ce87a25e 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 192/484] 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 0661508b8..89e40c9b1 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 193/484] 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 000000000..bfb166370 --- /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 000000000..f8e59fa05 --- /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 194/484] 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 | 144 ++++++++++++------ 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 | 139 +++++++++++------ 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, 393 insertions(+), 177 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 680c8f8b7..38075ac53 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 ca682b454..1b265759c 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_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 { - setProperty (Property_ViewType, vType); + 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 1463e4d7d..4e28a2348 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 eec4c54cf..36ca1ae03 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 ca8a2cc7b..2efc2929f 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 ce808587f..be5a407ad 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 2f8e8098d..17448f168 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" - ); - - // 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. + "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"); + 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 1c48199d1..2a3f0cba6 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 d9d5830d9..3ed4d3b09 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 db5091999..019024776 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 e67445873..afd4bff5e 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 2bb5863bc..ac9a5da8b 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) +{ + + mRangeWidget = 0; + + if (isMultiValue()) + return; + + buildSpinBox (setting); + + mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); + mRangeWidget->setObjectName (setting->name()); + + addWidget (mRangeWidget); +} + +void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) { - foreach (const QString &value, setting->declaredValues()) + SpinBox *sb = 0; + + switch (setting->type()) { - QAbstractButton *button = 0; + case CSMSettings::Type_SpinBox: - if (isMultiValue()) - button = new QCheckBox (value, this); - else - button = new QRadioButton (value, this); + sb = new SpinBox (this); - connect (button, SIGNAL (clicked (bool)), - this, SLOT (slotToggled (bool))); + if (!setting->declaredValues().isEmpty()) + sb->setValueList (setting->declaredValues()); - button->setObjectName (value); + mRangeWidget = sb; - addWidget (button); + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); + break; - mButtons[value] = button; + case CSMSettings::Type_DoubleSpinBox: + mRangeWidget = new QDoubleSpinBox (this); + + connect (mRangeWidget, SIGNAL (valueChanged (double)), + this, SLOT (slotUpdateView (double))); + break; + + default: + break; } + + //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::slotToggled (bool state) +void CSVSettings::RangeView::slotUpdateView (int value) { - //test only for true to avoid multiple selection updates with radiobuttons - if (!isMultiValue() && !state) - return; - - QStringList values; + QString textValue = ""; - foreach (QString key, mButtons.keys()) + if (mRangeType == CSMSettings::Type_SpinBox) { - if (mButtons.value(key)->isChecked()) - values.append (key); + QStringList list = + static_cast (mRangeWidget)->valueList(); + if (!list.isEmpty()) + textValue = list.at(value); } - setSelectedValues (values, false); + + if (textValue.isEmpty()) + textValue = QVariant (value).toString(); + + setSelectedValue (textValue, false); View::updateView(); + } -void CSVSettings::RangeView::updateView (bool signalUpdate) const +void CSVSettings::RangeView::slotUpdateView (double value) { + setSelectedValue (QVariant(value).toString(), false); - QStringList values = selectedValues(); - - foreach (const QString &buttonName, mButtons.keys()) - { - QAbstractButton *button = mButtons[buttonName]; + View::updateView(); +} - //if the value is not found in the list, the widget is checked false - bool buttonValue = values.contains(buttonName); +void CSVSettings::RangeView::updateView (bool signalUpdate) const +{ + QString value; - //skip if the butotn value will not change - if (button->isChecked() == buttonValue) - continue; + if (!selectedValues().isEmpty()) + value = selectedValues().at(0); - //disable autoexclusive if it's enabled and we're setting - //the button value to false - bool switchExclusive = (!buttonValue && button->autoExclusive()); + switch (mRangeType) + { + case CSMSettings::Type_SpinBox: + static_cast (mRangeWidget)->setValue (value); + break; - if (switchExclusive) - button->setAutoExclusive (false); + case CSMSettings::Type_DoubleSpinBox: + static_cast (mRangeWidget)->setValue (value.toDouble()); + break; - button->setChecked (buttonValue); + default: + break; - 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 1df0c7bd6..6515c9168 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 5e10c346f..6886732db 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 6d718aad8..c485e7fcf 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 4f93b1c0f..2a70152c2 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 c99879762..23357e45f 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 195/484] 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 6e05e9dff..92ac627c4 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 196/484] 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 6e05e9dff..8bfdadf15 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 197/484] 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 1b265759c..fe5a26bbc 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 4e28a2348..8efe33034 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 be5a407ad..d65de2b91 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 8bfdadf15..787e26650 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 ac9a5da8b..b2701c7bf 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 6515c9168..e8d6df88e 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 198/484] 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 fe5a26bbc..fe15cf7f6 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 8efe33034..cf5dd2a06 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 787e26650..a8fd752e3 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 199/484] 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 34008c9a8..36cce9ecd 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 251ddae1f..b9ecbe931 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 200/484] 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 71ccf7ff2..1d3b45b2d 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 201/484] 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 c9308fbfb..a3f34d218 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 de4dde9dd..166c85f44 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 c83a5a3e1..59b82bb67 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 202/484] 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 8ad2b4a67..42ed235c5 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 247c0d4bd..5b85e203c 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 203/484] #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 bf02a8c30..3693d70b0 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 ddd7a47d3..f7dff1058 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 1ad43e360..1f994d013 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 204/484] 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 3693d70b0..8f6ac5274 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 205/484] 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 8f6ac5274..4f291c36e 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 206/484] 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 | 228 ++---------------- 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, 61 insertions(+), 257 deletions(-) rename files/{opencs.cfg => opencs.conf} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd45a207c..3d5923647 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 f6370ac51..480e91e30 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 fe15cf7f6..2ef829f86 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 36ca1ae03..e48dd6e26 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('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); - foreach (QString settingName, (*settingMap).keys()) + if (!setting) { - QStringList *values = settingMap->value (settingName); - Setting *setting = findSetting (pageName, settingName); + qWarning() << "Found definitions for undeclared setting " + << names.at(0) << "." << names.at(1); + continue; + } - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << pageName << "." << settingName; - continue; - } + QStringList values = settings->value (key).toStringList(); - if (values->size() == 0) - values->append (setting->defaultValues()); + if (values.isEmpty()) + values.append (setting->defaultValues()); - setting->setDefinedValues (*values); - } + 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 2efc2929f..9342c66e4 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 a8fd752e3..bd24b7df0 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); - - QString key = setting->page() + '.' + setting->name(); - - if (!settingMap.keys().contains(key)) - continue; - - setting->setDefinedValues (settingMap.value(key)); - } + foreach (const QString &key, settingMap.keys()) + mSettings->setValue (key, 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 f0ed7af41..ade14c50c 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 7bd0b228e..aeb652b3b 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 2a70152c2..9e595478d 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 23357e45f..4f3af9ae5 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 207/484] 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 e48dd6e26..afb80c206 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 bd24b7df0..7764cc2c2 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 208/484] 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 afb80c206..b0e5cba98 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 9342c66e4..95f55106e 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 7764cc2c2..178104982 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 ade14c50c..826bb6d6b 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 209/484] 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 d2a31e8d1..6a15c8e33 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 210/484] 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 89e40c9b1..7a5283125 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 211/484] 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 d5f9e30cd..f31241bdb 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 bf02a8c30..c3957f72f 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 396e710be..e69f39a19 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 1c9bab25e..dcd12ee14 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 43da111bf..e53b53e58 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 212/484] 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 d44da15c5..fe6aaef27 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 d834d85d4..de4a5e94b 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 3b5890479..1b2ca8ad5 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 d1c740011..ece071755 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 b8971a296..816eff791 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 213/484] 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 d3d8f5fad..8104cc3e6 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 214/484] 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 38075ac53..22db97206 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 480e91e30..f6a13f4f6 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 b0e5cba98..000000000 --- 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 95f55106e..000000000 --- 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 178104982..7e65cb270 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 826bb6d6b..509c06bfa 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 acb272553..95ab6ca27 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 35ae4c068..8354ced7f 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 c3ec68b52..31ec18d52 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 f11c4a2b9..ef453c58f 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 485ca57ac..6b4d442f3 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 206adbdd7..4fe7031ce 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 215/484] 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 3d5923647..ff0916086 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 38075ac53..22db97206 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 480e91e30..f6a13f4f6 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 b0e5cba98..000000000 --- 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 95f55106e..000000000 --- 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 178104982..7e65cb270 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 826bb6d6b..509c06bfa 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 acb272553..95ab6ca27 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 35ae4c068..8354ced7f 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 c3ec68b52..31ec18d52 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 f11c4a2b9..ef453c58f 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 485ca57ac..6b4d442f3 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 206adbdd7..4fe7031ce 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 3faac7c8e..000000000 --- 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 000000000..065f11a88 --- /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 216/484] 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 e69f39a19..dc04f92d4 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 217/484] 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 94238e6d5..4c6ab1c75 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 5222eac44..6a96c955f 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 c3957f72f..295f00d21 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 614eb4154..37e0c7f17 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 dc04f92d4..5381af8da 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 218/484] 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 82d815d68..c3fa0a662 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 219/484] 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 7e65cb270..e26b1de5c 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 509c06bfa..7bb15e598 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 3ed4d3b09..32fc7a46a 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 220/484] 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 da4c36d44..aaf9936d5 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 cf5dd2a06..89d6cc2c4 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 d65de2b91..229e293b8 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 e26b1de5c..8d71dbe82 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 7bb15e598..3ac348760 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 32fc7a46a..4e7b08aff 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 0cfd415ac..b0e12c461 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 2b52dfd1f..bbb92f34f 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 7f24f6a62..877d4bef8 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 b2701c7bf..8ae6caca0 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 e8d6df88e..2ab343f1f 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 5e894d8df..2d0c71a23 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 8354ced7f..071f1b45e 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 bfb166370..4b1447f8f 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 f8e59fa05..e887e8c93 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 c485e7fcf..f4cd03d2f 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 9e595478d..c3b33cf84 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 4f3af9ae5..5106d8d90 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 221/484] updated changelog --- readme.txt | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/readme.txt b/readme.txt index a054626dd..44f15fbcf 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 222/484] 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 | 83 +++++++++------------ 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, 82 insertions(+), 78 deletions(-) diff --git a/apps/opencs/model/settings/connector.cpp b/apps/opencs/model/settings/connector.cpp index 05a9ba8f9..5e1d64544 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 2ef829f86..2f86d4ff8 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 89d6cc2c4..e40302f00 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 8d71dbe82..1a9125439 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(); +bool CSMSettings::UserSettings::hasSettingDefinitions + (const QString &viewKey) const +{ + return (mSettingDefinitions->contains (viewKey)); } -void CSMSettings::UserSettings::saveSettings - (const QMap &settingMap) +void CSMSettings::UserSettings::setDefinitions + (const QString &key, const QStringList &list) { - foreach (const QString &key, settingMap.keys()) - mSettingDefinitions->setValue (key, settingMap.value (key)); + 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 3ac348760..830cc8c69 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; + + ///Test to indicate whether or not a setting has any definitions + bool hasSettingDefinitions (const QString &viewKey) const; - ///add definitions to the settings specified in the page map - void addDefinitions(); + ///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 4e7b08aff..56bc1fdfe 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 aeb652b3b..7cdf2bded 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 071f1b45e..2266f130d 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 c3b33cf84..69109e2b3 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 5106d8d90..84ad62759 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 223/484] 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 | 456 ++++++------------ .../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, 300 insertions(+), 481 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index eded36394..8f5bfbc12 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 3ef14ee7e..bbce7fa3f 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 201fb4342..33378511b 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 d29cc2631..42a432043 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 316eda78f..651283880 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 d7df2117d..eb93d9047 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 b8eb0a3b3..c2f0a150a 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 1f96c60b4..ca34c2229 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 59c65086e..db20ce4bc 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 bdd65b44a..1030e5c02 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 6923b3153..cea4f3a68 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 3604b451c..ec50ba35d 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 c219e5610..42d577163 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 7cd80347d..ccc44e6a9 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 b99abec6d..5f245dd4d 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 5fddf08d3..a8afea62a 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 413de5ef0..47aeda1e6 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 ff9948bf6..c68b283be 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 dab61bfff..488081f46 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"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative value")); -//checking for model + //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) - { - if (someItem.mData.mEnchant < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative enchantment"); - } - } + if (enchantable && someItem.mData.mEnchant < 0) + messages.push_back (std::make_pair (someID, someItem.mId + " has negative enchantment")); } -template void CSMTools::ReferenceableCheckStage::inventoryItemCheck( - const ITEM& someItem, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::inventoryItemCheck ( + const Item& someItem, Messages& messages, const std::string& someID) { 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"); - } + 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")); } -template void CSMTools::ReferenceableCheckStage::toolCheck( - const TOOL& someTool, - std::vector< std::string >& messages, - const std::string& someID, bool canBeBroken) +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 338983cc7..b0129fc2a 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 4398e00ef..07df20470 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 c8c437cbd..a12903e7d 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 d88361746..75545a7c7 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 55c25d907..0f000245e 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 a5154d292..b989e22a2 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 8de8e1a66..ecf8d61b7 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 28fc24fd3..630516c72 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 662bdadee..cf5d53b5c 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 dce2d2b6f..3d222e909 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 00b45cd93..a82a0eb6d 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 a2cc7c8d2..3d0be46fd 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 880ddafcd..182f1888b 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 d3d8f5fad..ea3568fe2 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 0079fab34..3394d3f62 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 224/484] 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 5f245dd4d..412e9f2f0 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 225/484] updated changelog --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 44f15fbcf..7f95003af 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 226/484] 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 6a96c955f..b548e0844 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 227/484] 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 4f93b42f8..90fa1c8a5 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 228/484] 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 fdaec28b4..84a155225 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 - } - else if(mBackOffDoor && - mDoorIter != mDoors.mList.end() && - ref.mData.getLocalRotation().rot[2] >= 1) - { - mDoorIter = mDoors.mList.end(); - mBackOffDoor = false; - //std::cout<<"open door id \""<& 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 \""< Date: Fri, 9 May 2014 08:32:52 -0500 Subject: [PATCH 229/484] 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 bd437ed61..89bf75c6c 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 eef96c8c9..6b67cf7d5 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 364a6b1a4..c2cb8117a 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 3ef14ee7e..72d7f5cd8 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 201fb4342..9f0617eb9 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 b969862e9..6c66f2c0e 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 ec6350658..bc477e26a 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 8b5462825..c5c84eeda 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 ae61f5d39..08024d45d 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 fcf016ee2..4c7699185 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 173efba05..be2f5e579 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 0870a2d3e..74c5dfe58 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 ab0257c0c..fa2656f89 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 516bb3f40..f49171775 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 8a58b7d32..f56ba82ec 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 15ce2dbaf..fc00f4491 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 52682342f..b797a7742 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 a0a34108e..0044583db 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 585647338..8b287a10d 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 6c43f47b4..3c6f99e68 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 2bea088e3..af631a2fe 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 1bb80f3d4..82d8b1f2d 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 cdc12e210..5ffa7a547 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 120616f9f..6888d88a6 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 0f6d782a6..4486559ba 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 67bc75e02..92a49acc0 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 c09aa65d9..cbe910c71 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 1efc79643..705193798 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 c595de5ae..75f7ccae4 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 9a3dd7342..b245b9241 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 8ce87a25e..6854358f5 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 3cfffbccc..21776f683 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 f01c88c65..b5eede9f5 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 6070c43a8..91f3fce95 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 faa73a986..a65b6b3b1 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 230/484] 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 bd437ed61..0c5c156db 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 231/484] 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 5381af8da..eb51ddfc5 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 232/484] 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 caaf7c91f..8c425caa0 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 233/484] 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 0fbb26c84..f312c2159 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 234/484] 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 e5f0c4b88..1c39d2c07 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 235/484] 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 fdaec28b4..08d087069 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 9610171b2..b18bda5e3 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 236/484] 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 284e5c4e2..6a2228c33 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 7f4f18893..a28c71ac9 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 237/484] 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 6a2228c33..89517d7d1 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 238/484] 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 52682342f..6545b5d45 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 239/484] updated changelog --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 7f95003af..4db9425b6 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 240/484] 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 | 14 +++++++++++++- apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/tools/subviews.cpp | 2 ++ 10 files changed, 52 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 2ef808dd6..e2427e62d 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 04e6fae89..6e1a1c4f4 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 a11297b45..2f93db48e 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 885e23033..2de58675f 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 234069e3a..4f7c624e6 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 94b042ec5..7471e5cec 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 24fb54399..22779b263 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 95ab6ca27..e71b8435a 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 "../../model/settings/usersettings.hpp" + #include "../world/subviews.hpp" + #include "../tools/subviews.hpp" -#include "../../model/settings/usersettings.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 5e6c9abc4..686c001dc 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 781cf602e..8b04aca50 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 241/484] 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 fe6aaef27..d4f8eb110 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 de4a5e94b..7b3a811fa 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 e2427e62d..c106c06e8 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 a6bcb6b87..c276e14ff 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 1b2ca8ad5..0a99d434a 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 ece071755..ab2cec548 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 816eff791..02f6a5467 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 242/484] 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 0a99d434a..7e4754ddf 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 ab2cec548..69a8b48ba 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 243/484] 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 2de58675f..3e9fe11eb 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 244/484] 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 7471e5cec..140a410c0 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 245/484] 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 d107b198c..000000000 --- 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 6355aea44..000000000 --- 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 246/484] 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 ad6c4be3d..57d2f4730 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 1a9125439..04f98f0d6 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 830cc8c69..7e553caf6 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 247/484] 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 89517d7d1..a4cd61c84 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 248/484] 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 f312c2159..4a610b45c 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 249/484] 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 6c43f47b4..6ee329aa7 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 a9fb6daab..be118597c 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 250/484] 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 a4cd61c84..b6b1bd89a 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 251/484] 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 6ee329aa7..e5b225791 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 c6bd6d15d..5994c6e21 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 be118597c..4f4459b35 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 252/484] 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 7972527ac..4dbc3da45 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 253/484] 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 ea6d3d006..c6c9c1ffe 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 254/484] 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 c718eeced..c89041710 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 ebe0aa08a..a769e7f67 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 b2a1637f1..5a99d0c2e 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 255/484] 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 b6b1bd89a..dc22dcb22 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 256/484] Savegame: store fog of war (Closes #1177) --- apps/openmw/mwrender/localmap.cpp | 267 ++++++++++++++++------ 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, 380 insertions(+), 86 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 0f6d782a6..41885da33 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() +std::string LocalMap::coordStr(const int x, const int y) { - mBuffers.clear(); + return StringConverter::toString(x) + "_" + StringConverter::toString(y); } -void LocalMap::saveTexture(const std::string& texname, const std::string& filename) +void LocalMap::clear() { - 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); + // 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; + mBounds = bounds; + // 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); + + 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())); - render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, sSize, sSize, - cell->getCell()->mName + "_" + coordStr(x,y)); + 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 638469d2d..1d480872e 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 19d26a176..948f85b5e 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 423a7078a..eb6827292 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 7f2a87eec..3b758f866 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 1c39d2c07..39f6538bb 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 88b49ed1c..cc3036647 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 de9c8f04a..ba36d4a86 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 1c60dfb83..3dd5df295 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 1f7e8197e..541a359c6 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 cd0db3067..88918a3ab 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 000000000..18235066d --- /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 000000000..4a5619e51 --- /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 257/484] 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 9e5230af6..39cfc47ed 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 6a15c8e33..e3baf84fb 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 e31013b45..7617a4463 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 41885da33..e1694d892 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 258/484] 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 e1694d892..56b2326ec 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 1d480872e..941171527 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 259/484] 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 56b2326ec..78d7527f7 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 260/484] 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 dc22dcb22..2bd5e44cb 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 a28c71ac9..5251fac23 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 3d4413a35..49fd8cb89 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 16d4877a9..8d8765378 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 261/484] 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 ba36d4a86..d5da19dfa 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 262/484] 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 948f85b5e..a3c53dc44 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 263/484] 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 78d7527f7..4168127df 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 941171527..babf7224e 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 49fd8cb89..7af926dca 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 264/484] 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 819c2701c..b1d2c75b1 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 265/484] 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 be4a9a14e..ccd4489ba 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 2bea088e3..d6da3b30e 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 f78b8f798..bd3e87548 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 266/484] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 499c55eeb..6f0561490 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 267/484] 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 57d2f4730..b00373587 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 06c4a0988..f452008ac 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 000f6761a..a6f8aaae2 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 d4f8eb110..096864b77 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 7b3a811fa..9b675826a 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 73278ba97..27d21635e 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 cd1bbef98..44239b21b 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 4a1abb888..874214822 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 8cf7883e5..6b4565584 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 3e9fe11eb..ff33b4665 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 4f7c624e6..ab247b6a3 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 268/484] 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 b548e0844..4c9b683a4 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 e3baf84fb..ed6910221 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 40ac92251..1482ee24e 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 5be00505c..7f59d8d78 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 eb51ddfc5..2b1f82b92 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 b1d2c75b1..24e758e32 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 0ae596a54..185a58b94 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 c2bf794f1..a326b7a6d 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 354b1fd0b..6997a9d7a 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 4168127df..0d32dd0ef 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 c89041710..153da1f30 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 a769e7f67..ed140434b 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 b4b275b6a..95b956907 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 126d5490c..a73ed7ca5 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 e2d8b242a..54cd40baf 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 d5da19dfa..b9a8f8dda 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 3dd5df295..533288048 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 fe250089a..5bb6de662 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 540044f38..2cf2c5b4f 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 5a99d0c2e..9ef4dabd2 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 91f123eb7..9d8d943d9 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 b385ac067..57faefdf4 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 80238ad68..21f573bc7 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 504cd0163..ce7c75d2a 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 ad2b671aa..42cd91c5b 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 000000000..2dca2dcec --- /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 000000000..cb5c0ff0d --- /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 269/484] 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 6375bdd1b..6ec2f64d0 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 0c10bd81d..8b71c8072 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 86750acca..4cac6c008 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 0b1da180d..2134b7bba 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 17f118b11..787653f11 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 270/484] 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 afda52448..6eab43a60 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 271/484] 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 6375bdd1b..b935284d3 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 e30a2bbc1..cf2ff87c6 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 b9a8f8dda..538cd17df 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 4484d9862..c10892e52 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 4ef611dc8..4e035446e 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 272/484] 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 161c9700f..98ac5ee14 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]; - - //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()) //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; - } + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - //************************ - // 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]))); - } + pathTo(actor, dest, duration); //Go to the destination - 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 4eb3e3757..531082357 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 8193a670b..afe99e2c0 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 b3a7facee..e36b51f69 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 0c10bd81d..4e0bc7104 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; - } - } - - // 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(); + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist - 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; + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - 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); - } + pathTo(actor, dest, duration); //Go to the destination - 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 8a471228e..7d1ea5bb9 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 cd03939bd..d77a35ea4 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 29577542e..603a04f8c 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 3b5330e9f..5b8ce3eb2 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 9ee49552d..b940c27e6 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 273/484] 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 7a5283125..aee5cbeac 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 44c8c96be..2dfa34ba3 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 eeedc0d7a..1463dff7e 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 b6ce9f85d..f68438872 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 98ac5ee14..8d9e01939 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 531082357..43681c163 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 afe99e2c0..90f0505a4 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 + } } - - //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]))); + else { + actor.getClass().getMovementSettings(actor).mPosition[1] = 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 e36b51f69..37de32d8d 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 4e0bc7104..6e91ccb71 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 7d1ea5bb9..2eb533d62 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 181560935..7cd85685b 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 12030b2be..e737ef9cf 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 ba36d4a86..5d1657a34 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 645330683..d111d0008 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 274/484] 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 90f0505a4..872eecb62 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 275/484] 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 b935284d3..91ef48c09 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 f7dff1058..e42672bad 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 2b1f82b92..5c2ee30e1 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 276/484] 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 000000000..375e8fae7 --- /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 000000000..6c90e36d6 --- /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 277/484] 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 5b8ce3eb2..efdbdd86b 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 b940c27e6..926233444 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 278/484] 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 2b44d0f4e..9eed2c7d9 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 279/484] 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 | 345 ++++++++++++------------ 6 files changed, 223 insertions(+), 226 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index ace4cc6d0..3787a9c07 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 6c90e36d6..6e9a1bdf5 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 43681c163..10a381410 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 37de32d8d..c9c8504aa 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 b2b0fe1ee..31cafa4dc 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 09c995428..5aea0210f 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; - - ///Priority of actions - enum Priority { - Priority_Default, - Priority_Jump, - Priority_Movement, - Priority_Hit, - Priority_Weapon, - Priority_Knockdown, - Priority_Torch, - - Priority_Death, - - Num_Priorities - }; - - /// Current action of the character - 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_WalkForward, - CharState_WalkBack, - CharState_WalkLeft, - CharState_WalkRight, - - CharState_SwimWalkForward, - CharState_SwimWalkBack, - CharState_SwimWalkLeft, - CharState_SwimWalkRight, - - CharState_RunForward, - CharState_RunBack, - CharState_RunLeft, - CharState_RunRight, - - CharState_SwimRunForward, - CharState_SwimRunBack, - CharState_SwimRunLeft, - CharState_SwimRunRight, - - CharState_SneakForward, - CharState_SneakBack, - CharState_SneakLeft, - CharState_SneakRight, - - CharState_TurnLeft, - CharState_TurnRight, - - CharState_Jump, - - CharState_Death1, - CharState_Death2, - CharState_Death3, - CharState_Death4, - CharState_Death5, - CharState_SwimDeath, - CharState_DeathKnockDown, - CharState_DeathKnockOut, - - CharState_Hit, - CharState_KnockDown, - CharState_KnockOut, - CharState_Block - }; - - ///Weapon type - enum WeaponType { - WeapType_None, - - WeapType_HandToHand, - WeapType_OneHand, - WeapType_TwoHand, - WeapType_TwoWide, - WeapType_BowAndArrow, - WeapType_Crossbow, - WeapType_Thrown, - WeapType_PickProbe, - - 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 - }; - - ///Current jumping state - enum JumpingState { - JumpState_None, - JumpState_Falling, - JumpState_Landing - }; - - class CharacterController - { - MWWorld::Ptr mPtr; - MWRender::Animation *mAnimation; - - typedef std::deque > AnimationQueue; - AnimationQueue mAnimQueue; - - CharacterState mIdleState; - std::string mCurrentIdle; - - CharacterState mMovementState; - std::string mCurrentMovement; - float mMovementSpeed; - float mMovementAnimVelocity; - - CharacterState mDeathState; - std::string mCurrentDeath; - - CharacterState mHitState; - std::string mCurrentHit; +class Movement; +class CreatureStats; + +enum Priority { + Priority_Default, + Priority_Jump, + Priority_Movement, + Priority_Hit, + Priority_Weapon, + Priority_Knockdown, + Priority_Torch, + + Priority_Death, + + Num_Priorities +}; + +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_WalkForward, + CharState_WalkBack, + CharState_WalkLeft, + CharState_WalkRight, + + CharState_SwimWalkForward, + CharState_SwimWalkBack, + CharState_SwimWalkLeft, + CharState_SwimWalkRight, + + CharState_RunForward, + CharState_RunBack, + CharState_RunLeft, + CharState_RunRight, + + CharState_SwimRunForward, + CharState_SwimRunBack, + CharState_SwimRunLeft, + CharState_SwimRunRight, + + CharState_SneakForward, + CharState_SneakBack, + CharState_SneakLeft, + CharState_SneakRight, + + CharState_TurnLeft, + CharState_TurnRight, + + CharState_Jump, + + CharState_Death1, + CharState_Death2, + CharState_Death3, + CharState_Death4, + CharState_Death5, + CharState_SwimDeath, + CharState_DeathKnockDown, + CharState_DeathKnockOut, + + CharState_Hit, + CharState_KnockDown, + CharState_KnockOut, + CharState_Block +}; + +enum WeaponType { + WeapType_None, + + WeapType_HandToHand, + WeapType_OneHand, + WeapType_TwoHand, + WeapType_TwoWide, + WeapType_BowAndArrow, + WeapType_Crossbow, + WeapType_Thrown, + WeapType_PickProbe, + + WeapType_Spell +}; + +enum UpperBodyCharacterState { + UpperCharState_Nothing, + UpperCharState_EquipingWeap, + UpperCharState_UnEquipingWeap, + UpperCharState_WeapEquiped, + UpperCharState_StartToMinAttack, + UpperCharState_MinAttackToMaxAttack, + UpperCharState_MaxAttackToMinHit, + UpperCharState_MinHitToHit, + UpperCharState_FollowStartToFollowStop, + UpperCharState_CastingSpell +}; + +enum JumpingState { + JumpState_None, + JumpState_Falling, + JumpState_Landing +}; + +class CharacterController +{ + MWWorld::Ptr mPtr; + MWRender::Animation *mAnimation; + + typedef std::deque > AnimationQueue; + AnimationQueue mAnimQueue; + + CharacterState mIdleState; + std::string mCurrentIdle; + + CharacterState mMovementState; + std::string mCurrentMovement; + float mMovementSpeed; + float mMovementAnimVelocity; + + CharacterState mDeathState; + std::string mCurrentDeath; + + 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 280/484] 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 5be81ac08..908165ee6 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 281/484] 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 5a4cb743a..8196262f5 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 282/484] 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 6a4e1be2f..93e0d1c36 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 908165ee6..3f91ca357 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 283/484] 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 8196262f5..3d524a686 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 284/484] 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 3d524a686..7ac68dd67 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 285/484] 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 280639f71..2b8b6eccb 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 286/484] 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 f68438872..0e660e967 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 872eecb62..1bc350383 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 287/484] 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 1463dff7e..56c155ded 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 6e9a1bdf5..8d225655a 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 1bc350383..5ccd2c8d8 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 82489adac..96dd91f82 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 288/484] 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 e6342e661..0f5649af2 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 289/484] 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 0f5649af2..d510373ff 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 44402fe7b..a930442fb 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 290/484] 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 5ccd2c8d8..c2e8385b8 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 c9c8504aa..bb62a2543 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 7cd85685b..fc781e637 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 e737ef9cf..76ab9d029 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 291/484] 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 91ef48c09..22d033f40 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 7cec26fb8..79686bb97 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 627c05251..4378e179d 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 292/484] 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 89bf75c6c..bd437ed61 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 6b67cf7d5..eef96c8c9 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 c2cb8117a..364a6b1a4 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 72d7f5cd8..3ef14ee7e 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 9f0617eb9..201fb4342 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 6c66f2c0e..b969862e9 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 bc477e26a..ec6350658 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 c5c84eeda..8b5462825 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 08024d45d..ae61f5d39 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 4c7699185..fcf016ee2 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 be2f5e579..173efba05 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 74c5dfe58..0870a2d3e 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 fa2656f89..ab0257c0c 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 f49171775..516bb3f40 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 f56ba82ec..8a58b7d32 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 fc00f4491..15ce2dbaf 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 b797a7742..52682342f 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 0044583db..a0a34108e 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 8b287a10d..585647338 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 3c6f99e68..6c43f47b4 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 af631a2fe..2bea088e3 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 82d8b1f2d..1bb80f3d4 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 5ffa7a547..cdc12e210 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 6888d88a6..120616f9f 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 4486559ba..0f6d782a6 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 92a49acc0..67bc75e02 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 cbe910c71..c09aa65d9 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 705193798..1efc79643 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 75f7ccae4..c595de5ae 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 b245b9241..9a3dd7342 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 6854358f5..8ce87a25e 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 21776f683..3cfffbccc 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 b5eede9f5..f01c88c65 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 91f3fce95..6070c43a8 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 a65b6b3b1..faa73a986 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 293/484] 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 4c6ab1c75..dc23b63f3 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 4c9b683a4..214e51009 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 c10892e52..6646ce273 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 4e035446e..16eb45306 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 294/484] 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 0cd665a87..d5ece298b 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 1bb80f3d4..6aed8db71 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 86db207a4..95d455edb 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 7a40afb4c..5f36cea2c 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 22d033f40..e0db094d1 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 2b8b6eccb..bf8ce8bdc 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 5aea0210f..1b7caf34d 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 45abda21d..4fd5e159a 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 d510373ff..cb02d4655 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 a326b7a6d..dee1a1b05 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 b18bda5e3..7127c92f3 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 295/484] 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 f27fada39..0430adf06 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 c2e8385b8..5e16ebdc8 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 bb62a2543..055958384 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 926233444..60a736991 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 296/484] 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 57faefdf4..ca4f42217 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 21f573bc7..3fa954182 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 297/484] 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 9bfea41f3..80f81ffd1 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 79686bb97..7d2dc1a62 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 d261fe0c0..f2cda5a01 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 e07ee9df8..e223435dd 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 5bb6de662..e512ca5f8 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 2cf2c5b4f..4c4c44b3f 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 9ef4dabd2..6c388de08 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 298/484] 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 e223435dd..947de0e4d 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 2328e67a8..953045fa2 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 299/484] 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 375e8fae7..c6ecc08bf 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 96dd91f82..99589b610 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 300/484] 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 a5a7e8252..8da300aba 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 301/484] 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 c6ecc08bf..26865aea4 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 8d225655a..85bb09fc8 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 99589b610..a3b9e64d3 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 302/484] 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 56c155ded..4b4b36ed6 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 26865aea4..a206d27ca 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 8d9e01939..f1296a949 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 5e16ebdc8..2a2f4fdc8 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 303/484] 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 214e51009..845fffbc0 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 95d455edb..e64a736c3 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 5f36cea2c..6c4c93128 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 e0db094d1..79a90c4d3 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 80f81ffd1..57618e6e9 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 cb02d4655..553674dd3 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 533288048..90570b260 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 000000000..4f51a619e --- /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 000000000..d9e9a8c63 --- /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 e512ca5f8..66d848124 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 4c4c44b3f..7814d937a 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 304/484] 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 bd437ed61..d60210b21 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 15ce2dbaf..fc00f4491 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 52682342f..2008accc9 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 7fdfc069f..02e3812f0 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 ce4707af6..3aa923a23 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 6c43f47b4..e9c51a7f8 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 c23a74efa..17a25e502 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 1bb80f3d4..82d8b1f2d 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 cdc12e210..5ffa7a547 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 120616f9f..6888d88a6 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 0f6d782a6..a22beff23 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 67bc75e02..92a49acc0 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 c09aa65d9..cbe910c71 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 1efc79643..705193798 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 c595de5ae..75f7ccae4 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 9a3dd7342..b245b9241 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 8ce87a25e..6854358f5 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 faa73a986..b56f70680 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 305/484] Savegame: store levelled creature state and move to actorIds (Closes #1332) --- apps/openmw/mwclass/creaturelevlist.cpp | 57 +++++++++++++++++++------ 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, 99 insertions(+), 17 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 732038b2f..be01b848a 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); + data->mSpawnActorId = -1; - MWWorld::LiveCellRef *ref = - ptr.get(); + ptr.getRefData().setCustomData(data.release()); + } + } - std::string id = MWMechanics::getLevelledItem(ref->mBase, true); + void CreatureLevList::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const + { + const ESM::CreatureLevListState& state2 = dynamic_cast (state); - 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); - } + ensureCustomData(ptr); + CreatureLevListCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); + customData.mSpawnActorId = state2.mSpawnActorId; + } - ptr.getRefData().setCustomData(data.release()); - } + 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 d2c02043e..b67fb5523 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 67ab44b77..3f94a77c4 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 90570b260..0f2ef1301 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 000000000..164dae96e --- /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 000000000..99b5a7fa2 --- /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 306/484] 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 85bb09fc8..c1b326198 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 307/484] 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 5c8a2d2dd..0459d5341 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 984e21e72..06f0619ce 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 bddc46728..12b360aa8 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 a206d27ca..44eacb0d1 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 3f94a77c4..a5f166374 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 f20c5f6d2..951ba7865 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 27b842348..057bc906e 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 4ba3e0009..97b0767fa 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) - { - 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) + void World::activateDoor(const Ptr &door, bool open) { - 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 eee69e81c..7b85c3ed8 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 0f2ef1301..d7bdaf36c 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 000000000..0487be7a4 --- /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 000000000..0df30afb0 --- /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 308/484] 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 553674dd3..3f6cc4103 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 309/484] 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 97b0767fa..2b1cbe4c7 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 310/484] 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 5c2ee30e1..41374c1a3 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 3f6cc4103..0843e3e54 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 a930442fb..dce4b792e 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 311/484] 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 79a90c4d3..af6cac12f 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 8464cc419..72cb8f574 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 833b0063c..9125e2832 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 0430adf06..f3ce7143a 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 3771417fa..b8dc9d6e0 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 f1296a949..d747781a3 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 10a381410..91bdbdac2 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 6e91ccb71..aa71af465 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 2eb533d62..90ff8df93 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 0b1da180d..8afe8402f 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 e53b53e58..8ed19925e 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 312/484] AiCombat: Removed obsolete door back-off code (now handled in AiAvoidDoor) --- apps/openmw/mwmechanics/aicombat.cpp | 85 +++++----------------------- apps/openmw/mwmechanics/aicombat.hpp | 6 -- 2 files changed, 14 insertions(+), 77 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 72cb8f574..ff9c0f8c4 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 313/484] 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 c0847929b..390c0768c 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 314/484] 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 9c4ea2d29..b8be9dcb8 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 49c58c896..172fa9508 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 e702c073d..b5b498e5e 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 4b9b4ff99..7ced6ae34 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 390c0768c..718c6d991 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 78dcc9497..f58ee2939 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 d6da3b30e..4d52d59bb 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 7b2ea4d4a..2cdd8a2e6 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 684771b86..21c5477d0 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 315/484] 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 41374c1a3..bf9a11d6e 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 316/484] 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 a5f166374..5d2d8a517 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 317/484] 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 af6cac12f..a0616258c 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 318/484] 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 | 85 +++++++++++++++++++++++----- apps/openmw/mwmechanics/aicombat.hpp | 6 ++ 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index ff9c0f8c4..72cb8f574 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 - - // 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 - if(mPathFinder.isPathConstructed()) - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); + // 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 319/484] 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 682010340..9fe7890ac 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 2d151988b..000000000 --- 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 63745b625..000000000 --- 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 d7bdaf36c..c7deeadf3 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 8a15af73a..000000000 --- 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 bc3186ce9..000000000 --- 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 4e16fb64a..000000000 --- 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 320/484] Feature 1314: make npc fight creatures --- apps/openmw/mwmechanics/actors.cpp | 149 +++++++++++++++++-------- 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, 181 insertions(+), 56 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6ec2f64d0..d988b9703 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -178,54 +178,65 @@ namespace MWMechanics calculateDynamicStats (ptr); calculateCreatureStatModifiers (ptr, duration); + // fatigue restoration + calculateRestoration(ptr, duration, false); + } + + void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) + { + CreatureStats& creatureStats = MWWorld::Class::get(actor1).getCreatureStats(actor1); + + if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player - // AI - if(MWBase::Environment::get().getMechanicsManager()->isAIActive()) + float fight; + + if (againstPlayer) + fight = actor1.getClass().getCreatureStats(actor1).getAiSetting(CreatureStats::AI_Fight).getModified(); + else { - CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + 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)); - //engage combat or not? - if(ptr != player && !creatureStats.isHostile()) + 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)) { - 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); + bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2); - if (LOS) + 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(ptr, player); + MWBase::Environment::get().getMechanicsManager()->startCombat(actor2, actor1); } } } - 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::updateNpc (const MWWorld::Ptr& ptr, float duration) { - if(!paused) - { - updateDrowning(ptr, duration); - calculateNpcStatModifiers(ptr); - updateEquippedLight(ptr, 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 f7dff1058..c6b72c958 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 8464cc419..9b2e73edb 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 30b72acd9..388e6c348 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 2134b7bba..1ed135a67 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 37e0c7f17..50cd3bea8 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 321/484] 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 03361408c..66c09b6ff 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 322/484] 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 0459d5341..e16f00186 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 585647338..02c4b9356 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 ccd4489ba..dc02f9976 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 2b1cbe4c7..47cb50463 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 7b85c3ed8..490fdf5a7 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 323/484] 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 845fffbc0..6d2eea6af 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 324/484] 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 39cfc47ed..44ebed3e9 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 e16f00186..2ddd01ac4 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 2bd5e44cb..29c065f3d 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 5251fac23..d23b0c228 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 f941c699b..b931966f0 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 be5c63191..4e73cc555 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 ed6910221..3cf7379ff 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 7617a4463..c98c32c52 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 a3c53dc44..9398e033a 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 eb6827292..d59e1e27d 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 5368cbe68..2cbc4462c 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 481a41297..6a7b05a3a 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 57fc2d470..be241a564 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 20013493f..620a0d0c9 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 47cb50463..263478890 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 490fdf5a7..a86cebfd2 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 325/484] 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 a0616258c..108cc8cc5 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 72cb8f574..8464cc419 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 9125e2832..833b0063c 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 f3ce7143a..0430adf06 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 b8dc9d6e0..3771417fa 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 d747781a3..f1296a949 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 91bdbdac2..10a381410 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 aa71af465..6e91ccb71 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 90ff8df93..2eb533d62 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 8afe8402f..0b1da180d 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 8ed19925e..e53b53e58 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 326/484] 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 8464cc419..72cb8f574 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 833b0063c..9125e2832 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 327/484] 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 aee5cbeac..e791ab891 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 f3973153a..15739730b 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 2ddd01ac4..d1ecd11a0 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 0843e3e54..91a81c74b 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 1e6119daa..968be0f9e 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 bc9e68d26..eb6863655 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 8ce87a25e..dc31772c9 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 1454240b4..ab9dcf734 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 000000000..c886908f9 --- /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 000000000..e934bf6ab --- /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 4b92a920b..ecc8bdd02 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 263478890..587fb71f4 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 a86cebfd2..8d2f3a9da 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 328/484] 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 c886908f9..55ecdb569 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 e934bf6ab..c51985a7e 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 329/484] 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 fa1e58b9d..5dc53e505 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 330/484] 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 d1ecd11a0..81bec6fe8 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 108cc8cc5..d54805539 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 9398e033a..991ca690e 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 d59e1e27d..f539f9270 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 f2cda5a01..304228010 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 55ecdb569..266b566f7 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 c51985a7e..da965a4cf 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 587fb71f4..1f645fd86 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 8d2f3a9da..285d5fef6 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 c7deeadf3..e0166138e 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 6c388de08..bdeb95291 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 000000000..85c00025b --- /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 000000000..6e36efb5b --- /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 331/484] 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 d54805539..a3211892e 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 6e91ccb71..aa71af465 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 2eb533d62..90ff8df93 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 332/484] 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 be76bd0b4..f0c71bf53 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 f012d675c..79a801248 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 dc23b63f3..4abc9ea71 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 04c010c83..d3ffb321e 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 be01b848a..fea30735c 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 b67fb5523..6c51a3189 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 6d2eea6af..5b9e26f26 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 4b9c8988e..03c6e234a 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 5d2d8a517..aa247f0b9 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 91c536b43..ba6fad7ba 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 057bc906e..f47b8ace3 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 ecc8bdd02..25ee0c2e8 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 541a359c6..4df04d0e5 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 88918a3ab..55c1e5155 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 164dae96e..21cc73b89 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 99b5a7fa2..da64cd7c2 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 333/484] 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 f0c71bf53..fd8eeb46b 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 79a801248..9fc013e45 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 4abc9ea71..db3a70a6a 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 d3ffb321e..30573cd15 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 5b9e26f26..009559d19 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 03c6e234a..356e358b9 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 9cabab3e8..65ffdb9e1 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 5c154d425..2da58e72e 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 57618e6e9..95e25cba6 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 7d2dc1a62..70a86536a 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 f47b8ace3..0b1eb857c 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 eb6760d14..1cbaa349c 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 334/484] 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 8a58b7d32..52e7afefd 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 335/484] 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 de679e815..aee8628bd 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 336/484] 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 cf2ff87c6..d5433f328 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 337/484] 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 7f06320aa..a49ebb9bc 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 8c425caa0..323b45064 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 5c6d092ad..7e7f2b6f5 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 338/484] 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 a5411b747..8ecb4bd13 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 339/484] 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 6545b5d45..af2fcb46f 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 340/484] 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 eff7aea24..19f20eeee 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 956523c0d..dcfe7931a 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 3cf7379ff..d701e56ab 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 341/484] 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 9eb5f55cc..2c3540462 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 f93dae4d1..b74a5da5a 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 342/484] 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 fd8eeb46b..2d9695c6b 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 db3a70a6a..924021faa 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 009559d19..72505fa08 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 1cbaa349c..8f2a56646 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 dd0c1b002..7c81bdb6e 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 4d8cbc622..1b0bc772e 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 3cfffbccc..f754fb57a 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 343/484] 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 ea1ca56d3..a8cbcb24b 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 344/484] 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 a8cbcb24b..f27c1cc92 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 345/484] 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 5cf8f8a89..fb4c09b91 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 e7e5cf1ea..0a09c5cc0 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 346/484] 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 364a6b1a4..58ae1d593 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 f27c1cc92..41240ae48 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 347/484] 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 648ab3ebe..3226278fe 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 348/484] 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 52f935710..26010faf3 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 d51d4298f..dd3a67e94 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 761b7ca5a..ffa911b44 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 349/484] 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 347de96a6..1abbae3ae 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 350/484] 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 13015e39c..3a3a3dddd 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 d0ea4b7fb..423c3971a 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 351/484] 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 26010faf3..3d0f2e5da 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 dd3a67e94..237d145a2 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 3a3a3dddd..ac09db9d9 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 352/484] 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 b74a5da5a..2da213529 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 353/484] 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 2da213529..f0f6bffc1 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 354/484] 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 25b2a4505..fd4b97acb 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 323b45064..fe37f37ff 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 b1c700e31..8b9ee9184 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 9463e4c45..55574bf3e 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 724d531cf..04aa0534d 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 8ecb4bd13..a699286a1 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 ed140434b..ce8c800b9 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 fb43ee858..4a2f17e26 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 63d78833e..612c4fee6 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 355/484] 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 4a2f17e26..5adf409bb 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()) + { + it = lookup->second; + + mLookup[info.mId] = mInfo.insert(++it, info); + return; + } + + lookup = mLookup.find(info.mNext); + 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.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 612c4fee6..6ec5527f9 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 356/484] 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 ce8c800b9..1fdf3c5a5 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 357/484] 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 f0f6bffc1..9dc2380f8 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 7e977cf58..41a280da8 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 57618e6e9..d8dfa158d 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 8ed19925e..695954bc2 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 358/484] Fix overwriting DialInfo --- components/esm/loaddial.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index 5adf409bb..ee7ddbfad 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -61,29 +61,30 @@ void Dialogue::addInfo(const ESM::DialInfo& info, bool merge) ESM::Dialogue::InfoContainer::iterator it = mInfo.end(); std::map::iterator lookup; - lookup = mLookup.find(info.mPrev); + + lookup = mLookup.find(info.mId); if (lookup != mLookup.end()) { it = lookup->second; - - mLookup[info.mId] = mInfo.insert(++it, info); + *it = info; return; } - lookup = mLookup.find(info.mNext); + lookup = mLookup.find(info.mPrev); if (lookup != mLookup.end()) { it = lookup->second; - mLookup[info.mId] = mInfo.insert(it, info); + mLookup[info.mId] = mInfo.insert(++it, info); return; } - lookup = mLookup.find(info.mId); + lookup = mLookup.find(info.mNext); if (lookup != mLookup.end()) { it = lookup->second; - *it = info; + + mLookup[info.mId] = mInfo.insert(it, info); return; } From a5f0fe7282d200a88f357b1bf9b2cca0743630a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 18 May 2014 20:07:41 +0200 Subject: [PATCH 359/484] 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 0c5c156db..541720f7e 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 4db9425b6..92cb35f31 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 360/484] 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 9dc2380f8..6a5cf572a 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 361/484] 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 bcf4374a4..6119ab7b4 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 362/484] 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 8179021a4..745141502 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 363/484] 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 4d52d59bb..e9a4a18e5 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 17a25e502..df563b3d4 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 364/484] 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 ac09db9d9..56e937c8e 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 365/484] 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 06ee9fb4e..4466e354d 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 56e937c8e..0def0afdb 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 366/484] 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 4466e354d..4cdeec043 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 367/484] 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 25b006fb3..0958c8f0c 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 368/484] 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 304228010..0cd23eb6f 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 369/484] 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 eb93d9047..34d93c49a 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 874214822..07c42a490 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 6b4565584..7b0c37386 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 370/484] 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 903612258..825d62efb 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 705193798..e4c1a2677 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 304228010..48c7508a6 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 1f645fd86..896877dda 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 371/484] 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 3226278fe..3a52592ae 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 784980e09..72b14ba75 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 58ae1d593..d9c1454fc 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 372/484] 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 01b8764c2..5827645f5 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 373/484] 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 caf62546e..ae0d477d2 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 374/484] 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 6a5cf572a..980a23a3e 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 375/484] 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 34d93c49a..066c76734 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 ae0d477d2..64d65ea0d 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 376/484] 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 29a4768aa..2cd42eb30 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 377/484] 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 8179021a4..9abd6ac3f 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 000000000..da36b90a2 --- /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 000000000..20f23cf0c --- /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 91937d24b..fa7419b32 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 cca70dfcf..8923a5cc8 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 378/484] 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 d9c1454fc..a4e5cad4d 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 379/484] 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 cd58fca1e..40520a9ba 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 e6f3c8c35..a47dbf45d 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 ff33b4665..8b9d9f6df 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 ab247b6a3..2b521c548 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 cf9e496ee..44ffa92b9 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 fcf016ee2..b60cbd7e4 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 4fdd97909..db6e294fa 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; - mCells.setRecord (cellIndex, cell); + 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); + } + } } std::string CSMWorld::RefCollection::getNewId() diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 173efba05..45aa5758b 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 f04e819c8..00d7dfc19 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 380/484] 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 8b9d9f6df..442e73e51 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 db6e294fa..3a60c4934 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 45aa5758b..d80ea2469 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 381/484] 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 dc02f9976..079793ee1 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 d701e56ab..81b28aa66 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 896877dda..f8523726e 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 285d5fef6..ca0e63c2d 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 382/484] 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 2cd42eb30..5be99f166 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 383/484] 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 9abd6ac3f..e4d8d1b9f 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 35551f97b..6141790a8 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 e791ab891..cf72cc732 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 384/484] 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 8f1b9f6f3..dcd26d469 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 385/484] 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 c0daa2c0e..16e939eb2 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 48c7508a6..43972e9f9 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 f8523726e..d5e572b13 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 386/484] 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 66c09b6ff..8c817b380 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 387/484] 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 5827645f5..44d5fe3d5 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 388/484] 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 8c817b380..26ff7e96e 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 d5e572b13..9b5f9d9d3 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 ca0e63c2d..0a396ef5c 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 389/484] 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 66c09b6ff..27739fd26 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 390/484] 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 a882ae05e..6958084f4 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 391/484] 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 16e939eb2..6048e49b4 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 392/484] 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 8b44af2ef..bafd04311 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 393/484] 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 1a97668bc..bc2957da1 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 394/484] 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 0a09c5cc0..4ebdb715a 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 395/484] 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 4ebdb715a..2f3dd9a45 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 396/484] 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 ed1b9e0a9..d5b52ebae 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 397/484] 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 d5b52ebae..7eaba9361 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 398/484] 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 8b9ee9184..5bdf80593 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 bf9a11d6e..f5f244330 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 399/484] 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 e4d8d1b9f..b323d4759 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 a4e5cad4d..e9e430275 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 6141790a8..4576432e1 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 cf72cc732..9e959a986 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 400/484] 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 e9e430275..c2408a554 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 41240ae48..6b58304a0 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 44d5fe3d5..77dbcb1ee 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 5be99f166..21b2d9c9a 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 bc2957da1..c03879d46 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 20f23cf0c..47978ba44 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 fa7419b32..383d37640 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 64d65ea0d..8fcf615ba 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 401/484] Remove useless throwing of exception --- apps/openmw/mwmechanics/levelledlist.hpp | 34 +++++++++++------------- apps/openmw/mwworld/esmstore.hpp | 3 ++- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 6888d88a6..5d9e29118 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -53,28 +53,26 @@ namespace MWMechanics return std::string(); std::string item = candidates[std::rand()%candidates.size()]; + // Vanilla doesn't fail on nonexistent items in levelled lists + if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) + { + 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? - try + 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()) { - 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); - } + return item; } - catch (std::logic_error&) + else { - // Vanilla doesn't fail on nonexistent items in levelled lists - std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl; - return std::string(); + 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 c6c9c1ffe..90786acd4 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 402/484] 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 0e21c55ac..99accbb97 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; - - mRef = ref; - mPtr = Ptr (&boost::any_cast&> (mRef), 0); + const T* base = list.find(name); - return true; - } + LiveCellRef ref; + ref.mBase = base; + ref.mRef.mRefNum.mIndex = 0; + ref.mRef.mRefNum.mContentFile = -1; - 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 403/484] 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 4a610b45c..1b13e3803 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 3920a3e79..b047ba47c 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 b83069283..f4696d3b3 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 404/484] 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 26ff7e96e..41977ad7e 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 16ab6321d..fe9368b44 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 550151e43..26d1cab6d 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 ebc3b18e6..183d91ca1 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 18a40d5d3..a174f69a7 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 2d9695c6b..62734c03d 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 924021faa..7e484f9d4 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 06f0619ce..27903c410 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 e15424c38..ebe41bb53 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 bd25b66b2..1b28a8462 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 72505fa08..bca7708ea 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 216f815cd..f9d7947a6 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 e9b0c8f3c..146251ca2 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 fe37f37ff..c7e832e4a 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 8b9ee9184..067862345 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 a6880ffcb..6524c168e 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 fa1bd28be..85f57a1a8 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 a0a34108e..70093049d 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 02c4b9356..a207dec0c 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 b5b498e5e..b2befc3ba 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 dcd26d469..000275794 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 ada004612..b303848df 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 079793ee1..103c48ca1 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 718c6d991..e1bc9d4da 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 e9a4a18e5..788f90f50 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 2cdd8a2e6..55317724e 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 027c3201f..24bc3fd63 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 5a3fc2855..38995ac32 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 2a48e62a9..83527a884 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 51e24e29c..5df2b12b8 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 683406d9e..313650bb6 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 de96bcacd..a3df2dfbe 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 74a4f88e7..475f73a07 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 77df46514..99b85c13c 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 469d7188e..1ec4bd6da 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 d5ece298b..1a9e418de 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 a00c2480e..16e474143 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 31a3b6fdd..6ae44e314 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 b931966f0..dd29f40ce 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 ad18a13e8..18b0d5ae3 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 bee76992a..34873b9bc 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 89d73215d..642e1a644 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 ed1b9e0a9..6c07e14d3 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 81b28aa66..40fcc3530 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 8095b0d05..cf71cc1aa 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 363647467..35667a23c 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 4b4b36ed6..3dfacb853 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 44eacb0d1..504522582 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 0430adf06..07bb9726e 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 7120ff5af..1c870bda4 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 af58e9ee0..64b358b96 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 b6d91db58..60bccb3f7 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 87337cdd7..23246c294 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 bf9a11d6e..5a72c8883 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 48179d344..dc8b567a9 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 3751e5828..bb2e94223 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 013e3daf4..5e88b2250 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 14f5cc4e7..03ccde388 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 991ca690e..882a3d09b 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 ded25479c..cc17905df 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 66c8d4468..6737d6a94 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 a882ae05e..993e99c2e 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 1f5ad5b07..6f7968fac 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 620a0d0c9..b0d73253f 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 e4c1a2677..fb27e73f4 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 bd3e87548..6b12cc3e6 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 020bdb0ff..660915523 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 2a1b7a3aa..05677cdc7 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 60af3d9b9..0a4e2d6c9 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 aa247f0b9..04d733e2c 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 951ba7865..6629f84f9 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 0b1eb857c..b47028e01 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 8f2a56646..d816f993b 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 7127c92f3..78a295030 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 844e2b18b..8a671cea8 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 ced952861..039fce0ca 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 1f994d013..5ca8f2952 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 25ee0c2e8..122a6f9bf 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 9b5f9d9d3..5a83a5bc7 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 405/484] 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 ce8244619..36d750821 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 c0482cf5e..26647e595 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 406/484] 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 5bdf80593..863a0f2ff 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 407/484] 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 266b566f7..bf0fb7579 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 408/484] 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 a47dbf45d..8a2781590 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 6976b454d..6b276d151 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 3a60c4934..1cfa4df76 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 409/484] 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 82400aac4..b1519b9d2 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 410/484] 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 b1519b9d2..9fd1cee96 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 411/484] 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 c2408a554..c10103cd6 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 412/484] 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 bf0fb7579..12cca2754 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 413/484] 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 3648877fd..3ef6ff4df 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 414/484] 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 0d32dd0ef..2b0323675 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 415/484] 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 26d1cab6d..d7dae97a5 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 17cfca453..e9164f920 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 183d91ca1..338a7ba0d 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 79b823fa9..b60ef41d6 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 a174f69a7..f596f60de 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 a73b2c190..052928238 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 146251ca2..5edf22b00 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 db44cd2b7..97ee10291 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 23246c294..9c5c9dbb9 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 ae0b25a4a..01ca1e0e1 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 6629f84f9..100e758f2 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 b47028e01..54cea9ab0 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 416/484] 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 980a23a3e..6d2c15549 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,19 +159,25 @@ 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()) { - mDone = true; - return; + 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 if (mPackages.begin() != itActualCombat) + else { - // move combat package with nearest target to the front - mPackages.splice(mPackages.begin(), mPackages, itActualCombat); + mDone = true; + return; } } From 4f94a31b5422545a8ed7b76920c132192a9c5a9d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 25 May 2014 07:50:19 +1000 Subject: [PATCH 417/484] 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 825d62efb..ac175634b 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 418/484] 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 82400aac4..fe97d77d4 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 419/484] 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 1027cc48a..9fe92f807 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 420/484] 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 | 43 ++-- 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, 718 insertions(+), 405 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 9e959a986..8496b47a4 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 fe9368b44..043aadd35 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 8580d61ce..947a9cb94 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 d7dae97a5..825b14978 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 338a7ba0d..0cc2e6020 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 f596f60de..c0362188b 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 62734c03d..9498ea52d 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 7e484f9d4..1a6e4e321 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 fea30735c..784304804 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 27903c410..12645c9f3 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 ebe41bb53..60c0efeb8 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 1b28a8462..fd45ec859 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 60ffec7b9..19381a3fd 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 e568bf869..1044fb01d 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 bca7708ea..7405292b4 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); - if (!MWBase::Environment::get().getWorld()->getGodModeState()) - weapon.getCellRef().mCharge -= std::min(std::max(1, - (int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge); + damage *= float(weaphealth) / weapmaxhealth; - // Weapon broken? unequip it - if (weapon.getCellRef().mCharge == 0) - weapon = *inv.unequipItem(weapon, ptr); + 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); + } } 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 f9d7947a6..7440617c2 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 d376270cb..5d076a3c5 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 af79a9691..9b528a4fc 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 5edf22b00..26618c021 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 237d145a2..811f93b48 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 b303848df..29fe6f82d 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 103c48ca1..ede5750a5 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 e1bc9d4da..ad1a4e953 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 788f90f50..b1e8052d8 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 83527a884..50e7644fb 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 0196bf02d..230282f15 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 5df2b12b8..90abbb145 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 313650bb6..5c4f3eb5a 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 a3df2dfbe..1ae02599e 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 475f73a07..b8dcbcbbb 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 16e474143..fb5a80cc7 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 dd29f40ce..aeb79a938 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 18b0d5ae3..fe43eb548 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 4baa48e7c..558e955f0 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 40fcc3530..a42dca79e 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 35667a23c..9f141a951 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 504522582..ea6f296cc 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 c1b326198..d2a2e33a1 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 1027cc48a..8ea9be339 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 5ffa7a547..69c3c08f7 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 9c5c9dbb9..f3f6795db 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 d25be1e13..0d5bae42b 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 fc781e637..55ebfeab5 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 dc8b567a9..9f2c851cf 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 bb2e94223..4a049d60f 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 91a81c74b..c996e90d6 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 820ba8acc..a9c9884d5 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 3b8b91b0e..9124e89b8 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 825d62efb..a5bd12152 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 6737d6a94..93711d036 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 b0d73253f..fa17d96af 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 fb27e73f4..a944a31b8 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 bcefb0181..1472afc08 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 000000000..f16d8e3d1 --- /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 000000000..3b0c2251b --- /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 264929bfb..9c3370f08 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 04d733e2c..63cdbfb1a 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 100e758f2..c13ecfab5 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 54cea9ab0..c3f94d7f1 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 d816f993b..2496a6eff 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 78a295030..2eb8aeb46 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 1b13e3803..0921d3a1b 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 b2e4d6d56..3994d8a24 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 99accbb97..3842e7ff1 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 039fce0ca..b8f0f8699 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 5ca8f2952..9913b888b 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 12cca2754..4e4f0b271 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 b047ba47c..1cf22744a 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 f4696d3b3..2f37a1cfd 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 008782130..2e267b37c 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 82371b056..a8ffad684 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 122a6f9bf..32bf773bd 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 5a83a5bc7..727b200f5 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 f04e819c8..84518bed9 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 16f6603a2..5f53eadbe 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 55d043c8a..0830c5de6 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 f01c88c65..28204c9ee 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 421/484] 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 ac175634b..2e2e9b698 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 8fa7fcdbee3d63d61120526b24ef3b104c01e718 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 25 May 2014 21:03:37 +0400 Subject: [PATCH 422/484] 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 35667a23c..fe89fda11 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 9fe92f807..8f8188559 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 5a72c8883..c9a181461 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 423/484] 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 c3f94d7f1..4e36a8da9 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 727b200f5..b8d531a58 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 424/484] 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 9498ea52d..7b62ad04f 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 12645c9f3..078889629 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 425/484] 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 d14251886..9ec770c9d 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 426/484] 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 24e758e32..d50f2c5ae 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 427/484] 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 727b200f5..43153612d 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 428/484] 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 1fdf3c5a5..fc2bd4d77 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 c6195d88c..a933eb682 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 6119ab7b4..9ecae465c 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 429/484] Store death animation index in CreatureStats --- apps/openmw/mwmechanics/character.cpp | 46 ++++++++++++++++------- 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, 61 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 60bccb3f7..c9da912dd 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -407,37 +407,56 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I return inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); } +void CharacterController::playDeath(float startpoint, CharacterState death) +{ + switch (death) + { + case CharState_SwimDeath: + mCurrentDeath = "swimdeath"; + break; + case CharState_DeathKnockDown: + mCurrentDeath = "deathknockdown"; + break; + case CharState_DeathKnockOut: + mCurrentDeath = "deathknockout"; + break; + default: + mCurrentDeath = "death" + Ogre::StringConverter::toString(death - CharState_Death1 + 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; + mAnimation->disable(mCurrentMovement); + mCurrentMovement = ""; + + mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All, + 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; - mCurrentDeath = "swimdeath"; } else if (mHitState == CharState_KnockDown) { mDeathState = CharState_DeathKnockDown; - mCurrentDeath = "deathknockdown"; } else if (mHitState == CharState_KnockOut) { mDeathState = CharState_DeathKnockOut; - mCurrentDeath = "deathknockout"; } else { int selected=0; - mCurrentDeath = chooseRandomGroup("death", &selected); + chooseRandomGroup("death", &selected); 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); + playDeath(startpoint, mDeathState); } CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *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 1b7caf34d..5cefe13bc 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 3ef6ff4df..7fd26c25c 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 70a86536a..8b2398dfb 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 66d848124..3860e9351 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 7814d937a..5ca3d071f 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 430/484] Fix actor models incorrectly being rotated on X/Y axes --- apps/openmw/mwrender/actors.cpp | 13 ++++--------- apps/openmw/mwworld/worldimp.cpp | 16 +++++++++------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index a9c9884d5..b7e9f5730 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 43153612d..435ca8b36 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 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 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::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 431/484] 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 9124e89b8..a2f901b26 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 432/484] 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 fc2bd4d77..03d928d2a 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 433/484] 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 44ebed3e9..9c069cbc2 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 6524c168e..ab04189a6 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 3a58ebf06..4fd4b825c 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 884d567c5..32a5255c9 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 f8821ab50..a944f56e2 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 70093049d..d0ac3e7c3 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 02e3812f0..006d0a3c3 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 811f93b48..db87d0a59 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 890176363..ec699b317 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 a207dec0c..609dea385 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 3aa923a23..5446a4ab7 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 000275794..8f8bab025 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 befbd6eee..9bc40bb6f 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 29fe6f82d..ccb1fab68 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 8bad60c8e..7e641702e 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 50e7644fb..49cc60d8a 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 4cb39fe01..2f1387365 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 90abbb145..9321d2de2 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 c0e25a517..56a04cfbb 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 5c4f3eb5a..e5ea54591 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 2ffc5e10f..5558b197e 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 1ae02599e..29ec62887 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 d0f5c54c4..42539ad9e 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 a084e6453..3d0751114 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 5feaff7bf..17e56f334 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 78adecd3e..4730a7295 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 7a6c1a5ed..37f2c8af0 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 99b85c13c..8d9f35daa 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 f7ea54c89..2a6dcfdcc 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 558e955f0..cb7f3b0bd 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 2da58e72e..420a642e8 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 34873b9bc..9a2c3b805 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 740115cdf..1fc902b20 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 642e1a644..79d50cdc5 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 f2a23b048..5387bd690 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 12bf97f7c..460663682 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 5a66c3370..1cf05bb06 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 48de9ea87..d8bd2bd59 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 a42dca79e..46aa781ac 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 c98c32c52..cd87113ce 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 cf71cc1aa..f020ef9f2 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 434/484] 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 7b62ad04f..940a36b00 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 078889629..12645c9f3 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 4e36a8da9..c3f94d7f1 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 f7297128b..43153612d 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 435/484] 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 940a36b00..9498ea52d 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 8f8bab025..0cea50f1b 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 436/484] 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 fb4c09b91..41d662d30 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 437/484] 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 9c069cbc2..69712ed03 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 f431f2f64..89f477598 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 47b256017..c50873c74 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 0cea50f1b..762c472d8 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 9bc40bb6f..fcb1338b5 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 6048e49b4..b36baf87b 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 42c29f4bc..9f44d5370 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 1ec4bd6da..030b8bf37 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 e424d7395..25c615678 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 87b26b814..15b41813f 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 d8bd2bd59..79ab28299 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 46aa781ac..5a228801a 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 cd87113ce..d14623901 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 f020ef9f2..6206985dd 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 438/484] 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 69712ed03..2dfa50eb5 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 15b41813f..4dcb680ec 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 5a228801a..eb800ef9a 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 d14623901..b1dbf3a24 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 439/484] 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 eb800ef9a..b931cd370 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 6206985dd..2d78e7875 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 440/484] 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 27d21635e..337784765 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 eb93d9047..fc35e21cd 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 c2f0a150a..653f3a957 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 874214822..294f83049 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 6b4565584..64085bf0d 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 44ffa92b9..d1bd771f8 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 b60cbd7e4..eb62434cf 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 441/484] 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 3b0c2251b..4db362b1e 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 442/484] 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 d9c9e5e0b..8b61237a1 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 ad911d4d033926965ed593ede3db3ec6ad6d5782 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 27 May 2014 22:09:08 +1000 Subject: [PATCH 443/484] 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 3b0c2251b..4db362b1e 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 e266c39c5d831a45be5fa9e6df7eef2e11ea925d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 May 2014 14:54:29 +0200 Subject: [PATCH 444/484] 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 | 28 +++++++++++++- components/esm/dialoguestate.hpp | 5 ++- components/esm/loadfact.cpp | 14 +++---- components/esm/loadfact.hpp | 11 ++---- 13 files changed, 137 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index f51fba07b..cab6809aa 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 c7e832e4a..3ca2b8345 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 6cd2c75af..db0b78d59 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 3d67f3bce..d301e88aa 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 1ea4be843..1f9846aa7 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 047c4d92f..19f6ca2df 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 bf2273b17..f81cfb460 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 db1ac1609..24e875173 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 9e36cb68d..381a052ac 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 b3544c85c..14301ac19 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); + } + + 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); + } } -} \ No newline at end of file +} diff --git a/components/esm/dialoguestate.hpp b/components/esm/dialoguestate.hpp index 9aa9eaefd..5e5f602a3 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 84be21938..0924efb17 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 9c257e068..75e30a5bf 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 445/484] 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 19f6ca2df..9dde65ab2 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 f81cfb460..53c80a943 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 24e875173..4ef638ef8 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 381a052ac..1dff04665 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 446/484] 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 fd4b97acb..bcf16091f 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 447/484] 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 cf71cc1aa..8cfe2c2b3 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 448/484] 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 b8f0f8699..e93d9e640 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 3dcd088f5..899d7144d 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 435ca8b36..fdc203182 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); - - /// \todo also check if the wanted position is on a flat surface, and not e.g. against a vertical wall! + Ogre::Vector3 normal(0,0,0); + std::pair result = mPhysics->castRay(cursorX, cursorY, &normal); - 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 6646ce273..235300b43 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 16eb45306..803986d5b 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 449/484] 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 fdc203182..38edd8b8d 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 450/484] 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 3ca2b8345..b6cef2fe7 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 060a50f94a2b4746c69e26c8fec90ceb47031968 Mon Sep 17 00:00:00 2001 From: Digmaster Date: Tue, 27 May 2014 13:50:24 -0400 Subject: [PATCH 451/484] 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 01ea3429c..1b197f6d8 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 c9ec23cfa..28c45c605 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 9321d2de2..af4e20ca4 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 56a04cfbb..40c5dab56 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 2d78e7875..332c8f6a7 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 452/484] 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 1c8cc7840..9f6306830 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 f78f7541b..5c23c834d 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 02ccbbc05..53c33b3c4 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 06de3eb88..a00b0b223 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 4dcb680ec..c2515a6de 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 79ab28299..471d8ac70 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 453/484] 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 0c013b18f..90a294c0c 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 93e0d1c36..e4e385ff0 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 98bd63ba1..f7d2726e3 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 454/484] 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 38edd8b8d..c95a137ec 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 455/484] 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 d4b042726..77e0acb9e 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 456/484] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 6f0561490..da5417034 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 457/484] 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 7a42e6900..ef45989ef 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 90a294c0c..ed628278b 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 15c859958..e8562011c 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 458/484] 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 1f9846aa7..900ea72ca 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 459/484] Fix container scripts not getting removed properly on cell change Broken by f99eda1a543c7 --- apps/openmw/mwworld/containerstore.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 2496a6eff..8a076c3fc 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; - - MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); - - if(&(player.getClass().getContainerStore (player)) == this) + if (actorPtr == player) { - 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 - item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1); + // Items in player's inventory have cell set to 0, so their scripts will never be removed + item.mCell = 0; } else - cell = player.getCell(); + { + // 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.mCell = cell; item.mContainerStore = 0; + + MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); + + // 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); } return it; From e68600eda25d40810f037ec6c44352ba67cb54b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 May 2014 19:23:50 +0200 Subject: [PATCH 460/484] 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 820863cb9..d33e5300e 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 53c80a943..24b0b6f7a 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 6f7968fac..6bf50371b 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 9fb7fa2bf..1137efed3 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 fa17d96af..9d6d5e50d 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 4ef638ef8..0f726a52d 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 1dff04665..8796c53c5 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 461/484] 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 15739730b..68ec2cae8 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 4a3093b10..f7c586380 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 ab9dcf734..3f6490d85 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 462/484] 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 c95a137ec..548a871ce 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 463/484] 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 d64564d77..16101162e 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 464/484] 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 16101162e..97ccb9099 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 465/484] 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 6048e49b4..2b064a603 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 466/484] 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 f7c586380..e778f6e34 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 467/484] 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 569a6b50c..c0b21b2ef 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 468/484] 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 bafd04311..0c0ad53b2 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 469/484] 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 97ccb9099..17ecdf3ae 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 470/484] 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 68ec2cae8..15739730b 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 e778f6e34..4a3093b10 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 3f6490d85..ab9dcf734 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 471/484] 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 811f93b48..57de35fc5 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 472/484] 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 460663682..9c7757af9 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 c2515a6de..cc18e6694 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 471d8ac70..81073d419 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 473/484] 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 762c472d8..5e3f93ab9 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 332c8f6a7..34e026fd7 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 474/484] 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 0f8ab8682..1dfb2f976 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 475/484] Support lights that do not have a model (Fixes #1361) --- apps/openmw/mwclass/light.cpp | 6 +- apps/openmw/mwrender/animation.cpp | 40 ++++++---- apps/openmw/mwrender/objects.cpp | 119 +++++++++++++++-------------- 3 files changed, 88 insertions(+), 77 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index fd45ec859..ef4549268 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 a2f901b26..9ed4cb6d3 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); - - 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; - - 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); + if (!model.empty()) + { + setObjectRoot(model, false); + + 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; + + 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 3101100f2..7953a3117 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; - - if (small) + 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::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()]; } - 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->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); + // 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->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); - sg->setCastShadows(true); + sg->setCastShadows(true); - sg->setRenderQueueGroup(RQG_Main); + 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(); + 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 476/484] 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 d33e5300e..3647f8ccb 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 0c0ad53b2..53ce8f488 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) + { + MyGUI::Gui::getInstance().destroyWidget(mVideo); + mVideo = NULL; + } + if (mBackground && !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(mBackground); + mBackground = NULL; } - if (mBackground) - mBackground->setVisible(show); + + 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 c27442536..ccd8df4b0 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 a42dca79e..53752fc99 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 477/484] 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 337784765..45b53f4fe 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 fc35e21cd..4846d6c73 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 653f3a957..dcb1a8650 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 294f83049..1d93a95f5 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 64085bf0d..3abb724de 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 478/484] 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 6ae44e314..246ade7bf 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 479/484] 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 08f678b45..fd3e45bdc 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 480/484] 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 be18ebbc0..fb1100528 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 481/484] 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 78adecd3e..4b8f3ab80 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 482/484] 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 488081f46..1816d0808 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 483/484] 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 0820dcc73..7ecafda5e 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 4f4a37896e3c88831db8329e240ed127adbc2408 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Fri, 30 May 2014 22:37:13 -0500 Subject: [PATCH 484/484] 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 882a3d09b..8a22c63c6 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" && (