From ee45f54b531750231888abf55e6aab085fe8ce3a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 27 Jun 2018 12:48:34 +0400 Subject: [PATCH 001/126] Refactor AiTemporaryStorage usage --- apps/openmw/mwmechanics/actor.cpp | 7 -- apps/openmw/mwmechanics/actor.hpp | 6 -- apps/openmw/mwmechanics/actors.cpp | 4 +- apps/openmw/mwmechanics/aicombat.cpp | 70 +------------- apps/openmw/mwmechanics/aicombat.hpp | 67 ++++++++++++- apps/openmw/mwmechanics/aifollow.cpp | 16 ---- apps/openmw/mwmechanics/aifollow.hpp | 15 +++ apps/openmw/mwmechanics/aisequence.cpp | 8 +- apps/openmw/mwmechanics/aisequence.hpp | 7 +- apps/openmw/mwmechanics/aiwander.cpp | 127 +++++++------------------ apps/openmw/mwmechanics/aiwander.hpp | 90 +++++++++++++++--- 11 files changed, 201 insertions(+), 216 deletions(-) diff --git a/apps/openmw/mwmechanics/actor.cpp b/apps/openmw/mwmechanics/actor.cpp index 675bd160a..f7c6b7f1c 100644 --- a/apps/openmw/mwmechanics/actor.cpp +++ b/apps/openmw/mwmechanics/actor.cpp @@ -4,7 +4,6 @@ namespace MWMechanics { - Actor::Actor(const MWWorld::Ptr &ptr, MWRender::Animation *animation) { mCharacterController.reset(new CharacterController(ptr, animation)); @@ -19,10 +18,4 @@ namespace MWMechanics { return mCharacterController.get(); } - - AiState& Actor::getAiState() - { - return mAiState; - } - } diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index b8e114ead..119527b64 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -3,8 +3,6 @@ #include -#include "aistate.hpp" - namespace MWRender { class Animation; @@ -29,12 +27,8 @@ namespace MWMechanics CharacterController* getCharacterController(); - AiState& getAiState(); - private: std::unique_ptr mCharacterController; - - AiState mAiState; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ec256a321..a225014b4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1365,7 +1365,7 @@ namespace MWMechanics { CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first); if (isConscious(iter->first)) - stats.getAiSequence().execute(iter->first, *iter->second->getCharacterController(), iter->second->getAiState(), duration); + stats.getAiSequence().execute(iter->first, *iter->second->getCharacterController(), duration); } } @@ -1993,7 +1993,7 @@ namespace MWMechanics || ptr.getClass().getCreatureStats(ptr).isParalyzed()) continue; MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - seq.fastForward(ptr, it->second->getAiState()); + seq.fastForward(ptr); } } } diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 06248fa10..bc6d22326 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -35,74 +35,6 @@ namespace namespace MWMechanics { - - /// \brief This class holds the variables AiCombat needs which are deleted if the package becomes inactive. - struct AiCombatStorage : AiTemporaryBase - { - float mAttackCooldown; - float mTimerReact; - float mTimerCombatMove; - bool mReadyToAttack; - bool mAttack; - float mAttackRange; - bool mCombatMove; - osg::Vec3f mLastTargetPos; - const MWWorld::CellStore* mCell; - std::shared_ptr mCurrentAction; - float mActionCooldown; - float mStrength; - bool mForceNoShortcut; - ESM::Position mShortcutFailPos; - MWMechanics::Movement mMovement; - - enum FleeState - { - FleeState_None, - FleeState_Idle, - FleeState_RunBlindly, - FleeState_RunToDestination - }; - FleeState mFleeState; - bool mLOS; - float mUpdateLOSTimer; - float mFleeBlindRunTimer; - ESM::Pathgrid::Point mFleeDest; - - AiCombatStorage(): - mAttackCooldown(0.0f), - mTimerReact(AI_REACTION_TIME), - mTimerCombatMove(0.0f), - mReadyToAttack(false), - mAttack(false), - mAttackRange(0.0f), - mCombatMove(false), - mLastTargetPos(0,0,0), - mCell(NULL), - mCurrentAction(), - mActionCooldown(0.0f), - mStrength(), - mForceNoShortcut(false), - mShortcutFailPos(), - mMovement(), - mFleeState(FleeState_None), - mLOS(false), - mUpdateLOSTimer(0.0f), - mFleeBlindRunTimer(0.0f) - {} - - void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target); - void updateCombatMove(float duration); - void stopCombatMove(); - void startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController, - const ESM::Weapon* weapon, bool distantCombat); - void updateAttack(CharacterController& characterController); - void stopAttack(); - - void startFleeing(); - void stopFleeing(); - bool isFleeing(); - }; - AiCombat::AiCombat(const MWWorld::Ptr& actor) { mTargetActorId = actor.getClass().getCreatureStats(actor).getActorId(); @@ -115,7 +47,7 @@ namespace MWMechanics void AiCombat::init() { - + } /* diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 6e1f0c623..7c9891bcc 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -23,7 +23,72 @@ namespace MWMechanics { class Action; - struct AiCombatStorage; + /// \brief This class holds the variables AiCombat needs which are deleted if the package becomes inactive. + struct AiCombatStorage : AiTemporaryBase + { + float mAttackCooldown; + float mTimerReact; + float mTimerCombatMove; + bool mReadyToAttack; + bool mAttack; + float mAttackRange; + bool mCombatMove; + osg::Vec3f mLastTargetPos; + const MWWorld::CellStore* mCell; + std::shared_ptr mCurrentAction; + float mActionCooldown; + float mStrength; + bool mForceNoShortcut; + ESM::Position mShortcutFailPos; + MWMechanics::Movement mMovement; + + enum FleeState + { + FleeState_None, + FleeState_Idle, + FleeState_RunBlindly, + FleeState_RunToDestination + }; + FleeState mFleeState; + bool mLOS; + float mUpdateLOSTimer; + float mFleeBlindRunTimer; + ESM::Pathgrid::Point mFleeDest; + + AiCombatStorage(): + mAttackCooldown(0.0f), + mTimerReact(AI_REACTION_TIME), + mTimerCombatMove(0.0f), + mReadyToAttack(false), + mAttack(false), + mAttackRange(0.0f), + mCombatMove(false), + mLastTargetPos(0,0,0), + mCell(NULL), + mCurrentAction(), + mActionCooldown(0.0f), + mStrength(), + mForceNoShortcut(false), + mShortcutFailPos(), + mMovement(), + mFleeState(FleeState_None), + mLOS(false), + mUpdateLOSTimer(0.0f), + mFleeBlindRunTimer(0.0f) + {} + + void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target); + void updateCombatMove(float duration); + void stopCombatMove(); + void startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController, + const ESM::Weapon* weapon, bool distantCombat); + void updateAttack(CharacterController& characterController); + void stopAttack(); + + void startFleeing(); + void stopFleeing(); + bool isFleeing(); + }; /// \brief Causes the actor to fight another actor class AiCombat : public AiPackage diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 13de01f9a..a8f071310 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -17,22 +17,6 @@ namespace MWMechanics { - -struct AiFollowStorage : AiTemporaryBase -{ - float mTimer; - bool mMoving; - float mTargetAngleRadians; - bool mTurnActorToTarget; - - AiFollowStorage() : - mTimer(0.f), - mMoving(false), - mTargetAngleRadians(0.f), - mTurnActorToTarget(false) - {} -}; - int AiFollow::mFollowIndexCounter = 0; AiFollow::AiFollow(const std::string &actorId, float duration, float x, float y, float z) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index f0d43c9a7..96249e28c 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -19,6 +19,21 @@ namespace AiSequence namespace MWMechanics { + struct AiFollowStorage : AiTemporaryBase + { + float mTimer; + bool mMoving; + float mTargetAngleRadians; + bool mTurnActorToTarget; + + AiFollowStorage() : + mTimer(0.f), + mMoving(false), + mTargetAngleRadians(0.f), + mTurnActorToTarget(false) + {} + }; + /// \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 **/ diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 85afbc453..e3b7c63fc 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -188,7 +188,7 @@ bool isActualAiPackage(int packageTypeId) && packageTypeId != AiPackage::TypeIdInternalTravel); } -void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) +void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& characterController, float duration) { if(actor != getPlayer()) { @@ -262,7 +262,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac try { - if (package->execute (actor,characterController,state,duration)) + if (package->execute (actor, characterController, mAiState, duration)) { // Put repeating noncombat AI packages on the end of the stack so they can be used again if (isActualAiPackage(packageTypeId) && (mRepeat || package->getRepeat())) @@ -494,12 +494,12 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) mLastAiPackage = sequence.mLastAiPackage; } -void AiSequence::fastForward(const MWWorld::Ptr& actor, AiState& state) +void AiSequence::fastForward(const MWWorld::Ptr& actor) { if (!mPackages.empty()) { MWMechanics::AiPackage* package = mPackages.front(); - package->fastForward(actor, state); + package->fastForward(actor, mAiState); } } diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index d725409de..5c72bcc4c 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -3,6 +3,8 @@ #include +#include "aistate.hpp" + #include namespace MWWorld @@ -47,6 +49,7 @@ namespace MWMechanics /// The type of AI package that ran last int mLastAiPackage; + AiState mAiState; public: ///Default constructor @@ -104,10 +107,10 @@ namespace MWMechanics void stopPursuit(); /// Execute current package, switching if needed. - void execute (const MWWorld::Ptr& actor, CharacterController& characterController, MWMechanics::AiState& state, float duration); + void execute (const MWWorld::Ptr& actor, CharacterController& characterController, float duration); /// Simulate the passing of time using the currently active AI package - void fastForward(const MWWorld::Ptr &actor, AiState &state); + void fastForward(const MWWorld::Ptr &actor); /// Remove all packages. void clear(); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ee680159e..928b09cf9 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -51,67 +51,6 @@ namespace MWMechanics std::string("idle9"), }; - /// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive. - struct AiWanderStorage : AiTemporaryBase - { - // the z rotation angle to reach - // when mTurnActorGivingGreetingToFacePlayer is true - float mTargetAngleRadians; - bool mTurnActorGivingGreetingToFacePlayer; - float mReaction; // update some actions infrequently - - AiWander::GreetingState mSaidGreeting; - int mGreetingTimer; - - const MWWorld::CellStore* mCell; // for detecting cell change - - // AiWander states - AiWander::WanderState mState; - - bool mIsWanderingManually; - bool mCanWanderAlongPathGrid; - - unsigned short mIdleAnimation; - std::vector mBadIdles; // Idle animations that when called cause errors - - // do we need to calculate allowed nodes based on mDistance - bool mPopulateAvailableNodes; - - // allowed pathgrid nodes based on mDistance from the spawn point - // in local coordinates of mCell - std::vector mAllowedNodes; - - ESM::Pathgrid::Point mCurrentNode; - bool mTrimCurrentNode; - - float mDoorCheckDuration; - int mStuckCount; - - AiWanderStorage(): - mTargetAngleRadians(0), - mTurnActorGivingGreetingToFacePlayer(false), - mReaction(0), - mSaidGreeting(AiWander::Greet_None), - mGreetingTimer(0), - mCell(NULL), - mState(AiWander::Wander_ChooseAction), - mIsWanderingManually(false), - mCanWanderAlongPathGrid(true), - mIdleAnimation(0), - mBadIdles(), - mPopulateAvailableNodes(true), - mAllowedNodes(), - mTrimCurrentNode(false), - mDoorCheckDuration(0), // TODO: maybe no longer needed - mStuckCount(0) - {}; - - void setState(const AiWander::WanderState wanderState, const bool isManualWander = false) { - mState = wanderState; - mIsWanderingManually = isManualWander; - } - }; - AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): mDistance(distance), mDuration(duration), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat), mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)), mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0)) @@ -221,7 +160,7 @@ namespace MWMechanics mPathFinder.buildSyncedPath(start, dest, actor.getCell(), getPathGridGraph(actor.getCell())); if (mPathFinder.isPathConstructed()) - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); } doPerFrameActionsForState(actor, duration, storage, pos); @@ -270,7 +209,7 @@ namespace MWMechanics if(actorCanMoveByZ && mDistance > 0) { // Typically want to idle for a short time before the next wander - if (Misc::Rng::rollDice(100) >= 92 && storage.mState != Wander_Walking) { + if (Misc::Rng::rollDice(100) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) { wanderNearStart(actor, storage, mDistance); } @@ -283,7 +222,7 @@ namespace MWMechanics if (Misc::Rng::rollDice(100) >= 96) { wanderNearStart(actor, storage, mDistance); } else { - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } } else if (storage.mAllowedNodes.empty() && !storage.mIsWanderingManually) { storage.mCanWanderAlongPathGrid = false; @@ -299,13 +238,13 @@ namespace MWMechanics mDistance = 0; // Allow interrupting a walking actor to trigger a greeting - WanderState& wanderState = storage.mState; - if ((wanderState == Wander_IdleNow) || (wanderState == Wander_Walking)) + AiWanderStorage::WanderState& wanderState = storage.mState; + if ((wanderState == AiWanderStorage::Wander_IdleNow) || (wanderState == AiWanderStorage::Wander_Walking)) { playGreetingIfPlayerGetsTooClose(actor, storage); } - if ((wanderState == Wander_MoveNow) && storage.mCanWanderAlongPathGrid) + if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid) { // Construct a new path if there isn't one if(!mPathFinder.isPathConstructed()) @@ -381,7 +320,7 @@ namespace MWMechanics if (mPathFinder.isPathConstructed()) { - storage.setState(Wander_Walking, true); + storage.setState(AiWanderStorage::Wander_Walking, true); mHasDestination = true; } return; @@ -410,26 +349,26 @@ namespace MWMechanics void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) { stopWalking(actor, storage); mObstacleCheck.clear(); - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos) { switch (storage.mState) { - case Wander_IdleNow: + case AiWanderStorage::Wander_IdleNow: onIdleStatePerFrameActions(actor, duration, storage); break; - case Wander_Walking: + case AiWanderStorage::Wander_Walking: onWalkingStatePerFrameActions(actor, duration, storage, pos); break; - case Wander_ChooseAction: + case AiWanderStorage::Wander_ChooseAction: onChooseActionStatePerFrameActions(actor, storage); break; - case Wander_MoveNow: + case AiWanderStorage::Wander_MoveNow: break; // nothing to do default: @@ -451,7 +390,7 @@ namespace MWMechanics if (mDistance && // actor is not intended to be stationary proximityToDoor(actor, distance*1.6f)) { - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); storage.mTrimCurrentNode = false; // just in case return; } @@ -468,13 +407,13 @@ namespace MWMechanics } // Check if idle animation finished - GreetingState& greetingState = storage.mSaidGreeting; - if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None)) + AiWanderStorage::GreetingState& greetingState = storage.mSaidGreeting; + if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == AiWanderStorage::Greet_Done || greetingState == AiWanderStorage::Greet_None)) { if (mPathFinder.isPathConstructed()) - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); else - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); } } @@ -485,7 +424,7 @@ namespace MWMechanics if ((!mPathFinder.isPathConstructed()) || pathTo(actor, ESM::Pathgrid::Point(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE)) { stopWalking(actor, storage); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); } else { @@ -502,7 +441,7 @@ namespace MWMechanics if (!idleAnimation && mDistance) { - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); return; } if(idleAnimation) @@ -512,13 +451,13 @@ namespace MWMechanics if(!playIdle(actor, idleAnimation)) { storage.mBadIdles.push_back(idleAnimation); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); return; } } } - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos) @@ -534,7 +473,7 @@ namespace MWMechanics trimAllowedNodes(storage.mAllowedNodes, mPathFinder); mObstacleCheck.clear(); stopWalking(actor, storage); - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); } storage.mStuckCount++; // TODO: maybe no longer needed @@ -545,7 +484,7 @@ namespace MWMechanics { mObstacleCheck.clear(); stopWalking(actor, storage); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); storage.mStuckCount = 0; } } @@ -596,8 +535,8 @@ namespace MWMechanics float playerDistSqr = (playerPos - actorPos).length2(); int& greetingTimer = storage.mGreetingTimer; - GreetingState& greetingState = storage.mSaidGreeting; - if (greetingState == Greet_None) + AiWanderStorage::GreetingState& greetingState = storage.mSaidGreeting; + if (greetingState == AiWanderStorage::Greet_None) { if ((playerDistSqr <= helloDistance*helloDistance) && !player.getClass().getCreatureStats(player).isDead() && MWBase::Environment::get().getWorld()->getLOS(player, actor) @@ -606,37 +545,37 @@ namespace MWMechanics if (greetingTimer >= GREETING_SHOULD_START) { - greetingState = Greet_InProgress; + greetingState = AiWanderStorage::Greet_InProgress; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); greetingTimer = 0; } } - if (greetingState == Greet_InProgress) + if (greetingState == AiWanderStorage::Greet_InProgress) { greetingTimer++; - if (storage.mState == Wander_Walking) + if (storage.mState == AiWanderStorage::Wander_Walking) { stopWalking(actor, storage, false); mObstacleCheck.clear(); - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } turnActorToFacePlayer(actorPos, playerPos, storage); if (greetingTimer >= GREETING_SHOULD_END) { - greetingState = Greet_Done; + greetingState = AiWanderStorage::Greet_Done; greetingTimer = 0; } } - if (greetingState == MWMechanics::AiWander::Greet_Done) + if (greetingState == AiWanderStorage::Greet_Done) { float resetDist = 2 * helloDistance; if (playerDistSqr >= resetDist*resetDist) - greetingState = Greet_None; + greetingState = AiWanderStorage::Greet_None; } } @@ -676,7 +615,7 @@ namespace MWMechanics storage.mAllowedNodes.push_back(storage.mCurrentNode); storage.mCurrentNode = temp; - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); } // Choose a different node and delete this one from possible nodes because it is uncreachable: else diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index d96d93165..4a0811f50 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -21,8 +21,81 @@ namespace ESM } namespace MWMechanics -{ - struct AiWanderStorage; +{ + /// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive. + struct AiWanderStorage : AiTemporaryBase + { + // the z rotation angle to reach + // when mTurnActorGivingGreetingToFacePlayer is true + float mTargetAngleRadians; + bool mTurnActorGivingGreetingToFacePlayer; + float mReaction; // update some actions infrequently + + enum GreetingState + { + Greet_None, + Greet_InProgress, + Greet_Done + }; + GreetingState mSaidGreeting; + int mGreetingTimer; + + const MWWorld::CellStore* mCell; // for detecting cell change + + // AiWander states + enum WanderState + { + Wander_ChooseAction, + Wander_IdleNow, + Wander_MoveNow, + Wander_Walking + }; + WanderState mState; + + bool mIsWanderingManually; + bool mCanWanderAlongPathGrid; + + unsigned short mIdleAnimation; + std::vector mBadIdles; // Idle animations that when called cause errors + + // do we need to calculate allowed nodes based on mDistance + bool mPopulateAvailableNodes; + + // allowed pathgrid nodes based on mDistance from the spawn point + // in local coordinates of mCell + std::vector mAllowedNodes; + + ESM::Pathgrid::Point mCurrentNode; + bool mTrimCurrentNode; + + float mDoorCheckDuration; + int mStuckCount; + + AiWanderStorage(): + mTargetAngleRadians(0), + mTurnActorGivingGreetingToFacePlayer(false), + mReaction(0), + mSaidGreeting(Greet_None), + mGreetingTimer(0), + mCell(NULL), + mState(Wander_ChooseAction), + mIsWanderingManually(false), + mCanWanderAlongPathGrid(true), + mIdleAnimation(0), + mBadIdles(), + mPopulateAvailableNodes(true), + mAllowedNodes(), + mTrimCurrentNode(false), + mDoorCheckDuration(0), // TODO: maybe no longer needed + mStuckCount(0) + {}; + + void setState(const WanderState wanderState, const bool isManualWander = false) + { + mState = wanderState; + mIsWanderingManually = isManualWander; + } + }; /// \brief Causes the Actor to wander within a specified range class AiWander : public AiPackage @@ -52,19 +125,6 @@ namespace MWMechanics osg::Vec3f getDestination(const MWWorld::Ptr& actor) const; - enum GreetingState { - Greet_None, - Greet_InProgress, - Greet_Done - }; - - enum WanderState { - Wander_ChooseAction, - Wander_IdleNow, - Wander_MoveNow, - Wander_Walking - }; - private: // NOTE: mDistance and mDuration must be set already void init(); From ec7301161726eb6198b6adc9d105ad27fa4a1086 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 27 Jun 2018 12:52:43 +0400 Subject: [PATCH 002/126] Clean temporary storage if we assign new AI package (bug #4464) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aisequence.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8379b6bea..635512836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Bug #4458: AiWander console command handles idle chances incorrectly Bug #4459: NotCell dialogue condition doesn't support partial matches Bug #4461: "Open" spell from non-player caster isn't a crime + Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal Bug #4471: Retrieve SDL window settings instead of using magic numbers Bug #4474: No fallback when getVampireHead fails diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index e3b7c63fc..86cc2bbdc 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -360,6 +360,14 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo } mPackages.push_back (package.clone()); + + // Make sure that temporary storage is empty + if (cancelOther) + { + mAiState.moveIn(new AiCombatStorage()); + mAiState.moveIn(new AiFollowStorage()); + mAiState.moveIn(new AiWanderStorage()); + } } AiPackage* MWMechanics::AiSequence::getActivePackage() From 1fdffd6ef9604403cc21c692ca5cfb89d638fa28 Mon Sep 17 00:00:00 2001 From: Bret Curtis <> Date: Wed, 27 Jun 2018 13:57:51 +0200 Subject: [PATCH 003/126] see if we can get win10 going --- .gitlab-ci.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d815c7d77..ec3a9696c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,4 +43,21 @@ MacOS: - cd build; make -j2 package artifacts: paths: - - build/OpenMW-*.dmg \ No newline at end of file + - build/OpenMW-*.dmg + +Win10: + tags: + - win10 + - msvc2017 + stage: build + allow_failure: true + script: + - rm -fr build/* # remove anything in the build directory + - CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V + - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 + cache: + paths: + - C:\projects\openmw\deps\* + artifacts: + paths: + - */OpenMW*.exe From 51179a2c388229a5979190aeff6e26606568cd9d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:01:51 +0000 Subject: [PATCH 004/126] try a wildcard? --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ec3a9696c..e4242e3f5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,4 +60,4 @@ Win10: - C:\projects\openmw\deps\* artifacts: paths: - - */OpenMW*.exe + - "*/OpenMW*.exe" From 6d1a83e667554f49d003f89ae011e473712e9be2 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:10:09 +0000 Subject: [PATCH 005/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e4242e3f5..7aba228db 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,6 +53,7 @@ Win10: allow_failure: true script: - rm -fr build/* # remove anything in the build directory + - cd $CI_PROJECT_DIR/openmw - CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: From 0105a48a4f119db16c94c24bc982e1fd49952b7c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:15:29 +0000 Subject: [PATCH 006/126] give %% a try --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7aba228db..1dbbbab5f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,7 +53,7 @@ Win10: allow_failure: true script: - rm -fr build/* # remove anything in the build directory - - cd $CI_PROJECT_DIR/openmw + - cd %CI_PROJECT_DIR%/openmw - CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: From 218353e452c73d4f22a94732956da2c45e795f38 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:19:03 +0000 Subject: [PATCH 007/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1dbbbab5f..742d663c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,7 +53,10 @@ Win10: allow_failure: true script: - rm -fr build/* # remove anything in the build directory - - cd %CI_PROJECT_DIR%/openmw + - echo pwd + - echo $CI_PROJECT_DIR + - ls -al $CI_PROJECT_DIR + - cd $CI_PROJECT_DIR - CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: From edd22342f23507997796ba725bbc157e6ebfeb94 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:32:18 +0000 Subject: [PATCH 008/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 742d663c0..c2c6a8e49 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,12 +52,12 @@ Win10: stage: build allow_failure: true script: - - rm -fr build/* # remove anything in the build directory - - echo pwd - - echo $CI_PROJECT_DIR - - ls -al $CI_PROJECT_DIR - - cd $CI_PROJECT_DIR - - CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V + - sh rm -fr build/* # remove anything in the build directory + - sh env + - sh pwd + - sh echo $CI_PROJECT_DIR + - sh echo %CI_PROJECT_DIR% + - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: paths: From 2d5f71e5bea3c793d904dee1c7a8ff4f513e9023 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:35:02 +0000 Subject: [PATCH 009/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c2c6a8e49..39fd1681e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ Win10: stage: build allow_failure: true script: - - sh rm -fr build/* # remove anything in the build directory + # - sh rm -fr build/* # remove anything in the build directory - sh env - sh pwd - sh echo $CI_PROJECT_DIR From 6751a7991d02258c784dfd2f97c40270f4f380e0 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 12:36:12 +0000 Subject: [PATCH 010/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 39fd1681e..5fa5cafc9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,11 +52,11 @@ Win10: stage: build allow_failure: true script: - # - sh rm -fr build/* # remove anything in the build directory - - sh env - - sh pwd - - sh echo $CI_PROJECT_DIR - - sh echo %CI_PROJECT_DIR% + - rm -fr build/* # remove anything in the build directory + - env + - pwd + - echo $CI_PROJECT_DIR + - echo %CI_PROJECT_DIR% - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: From da5d7afe22f3275907a15be51f5ab6622bc3c4fa Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 13:25:23 +0000 Subject: [PATCH 011/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5fa5cafc9..acc3b880f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,14 +54,11 @@ Win10: script: - rm -fr build/* # remove anything in the build directory - env - - pwd - - echo $CI_PROJECT_DIR - - echo %CI_PROJECT_DIR% - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: paths: - - C:\projects\openmw\deps\* + - deps artifacts: paths: - "*/OpenMW*.exe" From f7e1083ba4695a7bdf6c4442709e1def9a4272de Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 13:34:37 +0000 Subject: [PATCH 012/126] get more output from boost --- CI/before_script.msvc.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 38b304bf9..5b7483b14 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -421,7 +421,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent + # "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From b6fc204dd3bc796da3268ef58763c0864a247fbb Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 14:02:30 +0000 Subject: [PATCH 013/126] be more aggressive about suppressing message boxes --- .gitlab-ci.yml | 4 ++-- CI/before_script.msvc.sh | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index acc3b880f..de5b0d3ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,6 @@ Win10: stage: build allow_failure: true script: - - rm -fr build/* # remove anything in the build directory - env - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 @@ -61,4 +60,5 @@ Win10: - deps artifacts: paths: - - "*/OpenMW*.exe" + - deps\boost_install.log + - "*\OpenMW*.exe" diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 5b7483b14..a88339fac 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -421,8 +421,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - # "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 609d6a1b291433ff6601bdd2263275b10d99e99a Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 14:05:05 +0000 Subject: [PATCH 014/126] bad syntax --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index de5b0d3ac..1e34b5ae8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -61,4 +61,3 @@ Win10: artifacts: paths: - deps\boost_install.log - - "*\OpenMW*.exe" From 59a4251a6ac9b9ae8d79284b7995b0f7096814c8 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 14:36:20 +0000 Subject: [PATCH 015/126] try to extract boost higher up in dir, then move. --- CI/before_script.msvc.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index a88339fac..308104d05 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -x MISSINGTOOLS=0 @@ -421,7 +422,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="C:\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv /c/boost $BOOST_SDK fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From bd602847b58b603a944a9be4a271fa77bdc621cd Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 15:07:53 +0000 Subject: [PATCH 016/126] fix broken QT 5.7.0 link --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 308104d05..ab2a1d39c 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -366,8 +366,8 @@ if [ -z $SKIP_DOWNLOAD ]; then QT_SUFFIX="" fi - download "Qt 5.7.2" \ - "https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ + download "Qt 5.7.0" \ + "https://download.qt.io/archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ "qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ "qt-5-install.qs" From df23e0f857269b9d6e9512e0d772374d6c11d6ef Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 16:39:45 +0000 Subject: [PATCH 017/126] Try calling it directly --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1e34b5ae8..f5ab1e4c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,7 @@ Win10: script: - env - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - - msbuild MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 + - C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: paths: - deps From 8511f2398ac029f97457415c335064c2cf5f840e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 16:53:27 +0000 Subject: [PATCH 018/126] try a set and call? --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f5ab1e4c0..f43f29b5e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,8 @@ Win10: script: - env - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - - C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 + - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" + - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 cache: paths: - deps From f17426cbcd28a67f4f3bfd75dd4fa573e984906e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 20:24:08 +0000 Subject: [PATCH 019/126] give boost 1.67 a spin with msvc 14.1 --- CI/before_script.msvc.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index ab2a1d39c..eaef17781 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -236,7 +236,7 @@ case $VS_VERSION in TOOLSET="vc140" TOOLSET_REAL="vc141" MSVC_REAL_VER="15" - MSVC_VER="14" + MSVC_VER="14.1" MSVC_YEAR="2015" MSVC_DISPLAY_YEAR="2017" ;; @@ -246,7 +246,7 @@ case $VS_VERSION in TOOLSET="vc140" TOOLSET_REAL="vc140" MSVC_REAL_VER="14" - MSVC_VER="14" + MSVC_VER="14.0" MSVC_YEAR="2015" MSVC_DISPLAY_YEAR="2015" ;; @@ -256,7 +256,7 @@ case $VS_VERSION in TOOLSET="vc120" TOOLSET_REAL="vc120" MSVC_REAL_VER="12" - MSVC_VER="12" + MSVC_VER="12.0" MSVC_YEAR="2013" MSVC_DISPLAY_YEAR="2013" ;; @@ -326,9 +326,9 @@ if [ -z $SKIP_DOWNLOAD ]; then # Boost if [ -z $APPVEYOR ]; then - download "Boost 1.61.0" \ - "https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ - "boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" + download "Boost 1.67.0" \ + "https://sourceforge.net/projects/boost/files/boost-binaries/1.67.0/boost_1_67_0-msvc-${MSVC_VER}-${BITS}.exe" \ + "boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" fi # Bullet @@ -404,7 +404,7 @@ echo # Boost if [ -z $APPVEYOR ]; then - printf "Boost 1.61.0... " + printf "Boost 1.67.0... " else if [ $MSVC_VER -eq 12 ]; then printf "Boost 1.58.0 AppVeyor... " @@ -427,7 +427,7 @@ fi fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ - -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.0" + -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" echo Done. From 83e23ee6fdc3091bae27362ffe2553bee84d8963 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 27 Jun 2018 20:45:51 +0000 Subject: [PATCH 020/126] gather up artifacts and use all processors available --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f43f29b5e..a7af340b0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,10 +55,10 @@ Win10: - env - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" - - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:2 + - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% cache: paths: - deps artifacts: paths: - - deps\boost_install.log + - MSVC2017_64 From 7cd0235feddcfe51f3b3b18e6fb7707c4b2f6d55 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 07:56:40 +0000 Subject: [PATCH 021/126] Try creating a zip and archiving it. --- .gitlab-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a7af340b0..49974c5fb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,10 +55,11 @@ Win10: - env - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" - - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% + - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% + - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ -xr"!*.pdb" cache: paths: - deps artifacts: paths: - - MSVC2017_64 + - *.zip From a8adb9374b51fa84013fc06cd414b7d4b2d34551 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 08:24:34 +0000 Subject: [PATCH 022/126] use quotes --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 49974c5fb..e30402f6b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -62,4 +62,4 @@ Win10: - deps artifacts: paths: - - *.zip + - "*.zip" From 2d70c94733c0e16283078c3c1a40a4022088afc4 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 09:05:39 +0000 Subject: [PATCH 023/126] gather up everything with 7zip --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e30402f6b..8bff1ad9c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -56,7 +56,7 @@ Win10: - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% - - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ -xr"!*.pdb" + - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ cache: paths: - deps From 45d77372a05f009355d927e0fd58983cb787dd98 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 10:41:12 +0000 Subject: [PATCH 024/126] with 260 char path fixed, this should work. --- CI/before_script.msvc.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index eaef17781..d895db5b8 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,8 +422,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="C:\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv /c/boost $BOOST_SDK + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 1061270ac09bbc6f260b4510814b79ab067aca4e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 11:05:10 +0000 Subject: [PATCH 025/126] Try using @TEMP@ instead of hard coding it. --- CI/before_script.msvc.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index d895db5b8..62f41e49c 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,7 +422,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="@TEMP@\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv @TEMP@/boost $BOOST_SDK fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 7bf502dd02946c9cc5ec10d007a14ad8f56ac03c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 11:09:27 +0000 Subject: [PATCH 026/126] Bash it out! --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 62f41e49c..b2e2144e4 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,8 +422,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="@TEMP@\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv @TEMP@/boost $BOOST_SDK + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TEMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv ${TEMP}/boost ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 1c4363eaa649c8ea7d3840b5db1aaba1a0280816 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 11:22:54 +0000 Subject: [PATCH 027/126] Using SYSTEMDRIVE because TEMP apparently means something different in bash then to windows cmd. --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index b2e2144e4..d6cb7323e 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,8 +422,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TEMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv ${TEMP}/boost ${BOOST_SDK} + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 660193ae1b6f66d3fbef9920fa82d9b4d202cb5f Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 13:59:23 +0200 Subject: [PATCH 028/126] Update before_script.msvc.sh This has working GL Win10 MSVC updates, should be cross-compatible with appveyor. --- CI/before_script.msvc.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 38b304bf9..d6cb7323e 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -x MISSINGTOOLS=0 @@ -235,7 +236,7 @@ case $VS_VERSION in TOOLSET="vc140" TOOLSET_REAL="vc141" MSVC_REAL_VER="15" - MSVC_VER="14" + MSVC_VER="14.1" MSVC_YEAR="2015" MSVC_DISPLAY_YEAR="2017" ;; @@ -245,7 +246,7 @@ case $VS_VERSION in TOOLSET="vc140" TOOLSET_REAL="vc140" MSVC_REAL_VER="14" - MSVC_VER="14" + MSVC_VER="14.0" MSVC_YEAR="2015" MSVC_DISPLAY_YEAR="2015" ;; @@ -255,7 +256,7 @@ case $VS_VERSION in TOOLSET="vc120" TOOLSET_REAL="vc120" MSVC_REAL_VER="12" - MSVC_VER="12" + MSVC_VER="12.0" MSVC_YEAR="2013" MSVC_DISPLAY_YEAR="2013" ;; @@ -325,9 +326,9 @@ if [ -z $SKIP_DOWNLOAD ]; then # Boost if [ -z $APPVEYOR ]; then - download "Boost 1.61.0" \ - "https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ - "boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" + download "Boost 1.67.0" \ + "https://sourceforge.net/projects/boost/files/boost-binaries/1.67.0/boost_1_67_0-msvc-${MSVC_VER}-${BITS}.exe" \ + "boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" fi # Bullet @@ -365,8 +366,8 @@ if [ -z $SKIP_DOWNLOAD ]; then QT_SUFFIX="" fi - download "Qt 5.7.2" \ - "https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ + download "Qt 5.7.0" \ + "https://download.qt.io/archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ "qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ "qt-5-install.qs" @@ -403,7 +404,7 @@ echo # Boost if [ -z $APPVEYOR ]; then - printf "Boost 1.61.0... " + printf "Boost 1.67.0... " else if [ $MSVC_VER -eq 12 ]; then printf "Boost 1.58.0 AppVeyor... " @@ -421,11 +422,12 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ - -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.0" + -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" echo Done. From 46575d8de7fa0e5ff5fa57efc4155bea4926dcb3 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 14:01:41 +0200 Subject: [PATCH 029/126] Update before_script.msvc.sh 1.61 -> 1.67 --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index d6cb7323e..a35a61228 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,7 +422,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} fi From 71314f0c3a9c4c365562ebee4b94b95571c2ef1a Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 12:03:52 +0000 Subject: [PATCH 030/126] Use boost 1.67 instead of 1.61 --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index d6cb7323e..a35a61228 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,7 +422,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} fi From 60ec340fa355e37b29b7a12099b14711d438b47e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 12:18:01 +0000 Subject: [PATCH 031/126] remove toolset_real, use just toolset, do proper comparison --- CI/before_script.msvc.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index a35a61228..5aea6e04c 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -233,8 +233,7 @@ fi case $VS_VERSION in 15|15.0|2017 ) GENERATOR="Visual Studio 15 2017" - TOOLSET="vc140" - TOOLSET_REAL="vc141" + TOOLSET="vc141" MSVC_REAL_VER="15" MSVC_VER="14.1" MSVC_YEAR="2015" @@ -244,7 +243,6 @@ case $VS_VERSION in 14|14.0|2015 ) GENERATOR="Visual Studio 14 2015" TOOLSET="vc140" - TOOLSET_REAL="vc140" MSVC_REAL_VER="14" MSVC_VER="14.0" MSVC_YEAR="2015" @@ -254,7 +252,6 @@ case $VS_VERSION in 12|12.0|2013 ) GENERATOR="Visual Studio 12 2013" TOOLSET="vc120" - TOOLSET_REAL="vc120" MSVC_REAL_VER="12" MSVC_VER="12.0" MSVC_YEAR="2013" @@ -406,7 +403,7 @@ echo if [ -z $APPVEYOR ]; then printf "Boost 1.67.0... " else - if [ $MSVC_VER -eq 12 ]; then + if [ $MSVC_VER -eq 12.0 ]; then printf "Boost 1.58.0 AppVeyor... " else printf "Boost 1.67.0 AppVeyor... " @@ -446,7 +443,7 @@ fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}" - add_cmake_opts -DBoost_COMPILER="-${TOOLSET_REAL}" + add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" echo Done. fi From 8be52d228e19b01ca5cc05f9aa245a781838bd4f Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 15:12:26 +0200 Subject: [PATCH 032/126] Update before_script.msvc.sh small fixes --- CI/before_script.msvc.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index a35a61228..5aea6e04c 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -233,8 +233,7 @@ fi case $VS_VERSION in 15|15.0|2017 ) GENERATOR="Visual Studio 15 2017" - TOOLSET="vc140" - TOOLSET_REAL="vc141" + TOOLSET="vc141" MSVC_REAL_VER="15" MSVC_VER="14.1" MSVC_YEAR="2015" @@ -244,7 +243,6 @@ case $VS_VERSION in 14|14.0|2015 ) GENERATOR="Visual Studio 14 2015" TOOLSET="vc140" - TOOLSET_REAL="vc140" MSVC_REAL_VER="14" MSVC_VER="14.0" MSVC_YEAR="2015" @@ -254,7 +252,6 @@ case $VS_VERSION in 12|12.0|2013 ) GENERATOR="Visual Studio 12 2013" TOOLSET="vc120" - TOOLSET_REAL="vc120" MSVC_REAL_VER="12" MSVC_VER="12.0" MSVC_YEAR="2013" @@ -406,7 +403,7 @@ echo if [ -z $APPVEYOR ]; then printf "Boost 1.67.0... " else - if [ $MSVC_VER -eq 12 ]; then + if [ $MSVC_VER -eq 12.0 ]; then printf "Boost 1.58.0 AppVeyor... " else printf "Boost 1.67.0 AppVeyor... " @@ -446,7 +443,7 @@ fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}" - add_cmake_opts -DBoost_COMPILER="-${TOOLSET_REAL}" + add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" echo Done. fi From 4ad3d66629446e2b22356f4cd32aca6b08c62bcb Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 14:18:58 +0000 Subject: [PATCH 033/126] try using just ${TMP} --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 5aea6e04c..2e96528a9 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,8 +419,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${TMP}\boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From fb6ad9faecaaa63ea4fc99f871273733bf1bb224 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 15:23:56 +0000 Subject: [PATCH 034/126] try %TMP% ? --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 2e96528a9..e33eaa59f 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,8 +419,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${TMP}\boost" ${BOOST_SDK} + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="%TMP%\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "%TMP%\boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From c4a4111b2ee8fc514e97c1454fcb7647916cae8a Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 15:33:32 +0000 Subject: [PATCH 035/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index e33eaa59f..f746cdbe1 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,7 +419,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="%TMP%\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" mv "%TMP%\boost" ${BOOST_SDK} fi From 3ceb9116dec7e9136c2574de6d2209c8724d1cb3 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 20:28:58 +0000 Subject: [PATCH 036/126] Give pwd -W a try --- CI/before_script.msvc.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index f746cdbe1..d76f29ffa 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,8 +419,9 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${TMP}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "%TMP%\boost" ${BOOST_SDK} + REAL_TEMP_PATH=`cd ${TMP} && pwd -W` + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${REAL_TEMP_PATH}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${REAL_TEMP_PATH}\boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 3379eafd33ae44688f34d33f03f5b75ccd68d81e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 28 Jun 2018 20:44:22 +0000 Subject: [PATCH 037/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index d76f29ffa..874d89947 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -421,7 +421,7 @@ fi rm -rf Boost REAL_TEMP_PATH=`cd ${TMP} && pwd -W` "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${REAL_TEMP_PATH}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${REAL_TEMP_PATH}\boost" ${BOOST_SDK} + mv "${REAL_TEMP_PATH}/boost" ${BOOST_SDK} fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From 63bbc77ee77158f62b377a21cf430284877f343f Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 07:51:45 +0000 Subject: [PATCH 038/126] try using the powershell trick from AnyOldName3 --- CI/before_script.msvc.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 874d89947..f2305c271 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -413,15 +413,19 @@ fi if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names + # We work around this by installing to root of the current working drive and then move it to our deps + BOOST_SDK="$(real_pwd)/Boost" + CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - REAL_TEMP_PATH=`cd ${TMP} && pwd -W` - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${REAL_TEMP_PATH}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${REAL_TEMP_PATH}/boost" ${BOOST_SDK} + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}\Boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${CWD_DRIVE_ROOT}\Boost" ${BOOST_SDK} + fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From bc830a9c45950ed4eef8c257c787b9ca8728dd5b Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 08:00:54 +0000 Subject: [PATCH 039/126] use boost_temp --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index f2305c271..3f31c4ddb 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -423,8 +423,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}\Boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${CWD_DRIVE_ROOT}\Boost" ${BOOST_SDK} + "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${CWD_DRIVE_ROOT}Boost_temp" ${BOOST_SDK} fi From bccd83c656763374232e9b30eea08bf5bf4e3d7b Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 08:09:41 +0000 Subject: [PATCH 040/126] Use 1.67 --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 3f31c4ddb..15903c6ba 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -423,7 +423,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" mv "${CWD_DRIVE_ROOT}Boost_temp" ${BOOST_SDK} fi From 4c0e47509287756ae2d3d72026bfc60fd35ae7d3 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 10:16:28 +0200 Subject: [PATCH 041/126] Update before_script.msvc.sh Use powershell trick with boost_temp so there is little chance of collision. --- CI/before_script.msvc.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 5aea6e04c..15903c6ba 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -413,14 +413,19 @@ fi if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names + # We work around this by installing to root of the current working drive and then move it to our deps + BOOST_SDK="$(real_pwd)/Boost" + CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${SYSTEMDRIVE}\boost" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${SYSTEMDRIVE}\boost" ${BOOST_SDK} + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${CWD_DRIVE_ROOT}Boost_temp" ${BOOST_SDK} + fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From a532aef9356e8640ea6a553d2c18482b56979630 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 11:31:37 +0200 Subject: [PATCH 042/126] Update before_script.msvc.sh updating version check and correct indentation, wrap BOOST_SDK in "" to support dirs with spaces. --- CI/before_script.msvc.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 15903c6ba..5ca1de133 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,12 +419,12 @@ fi BOOST_SDK="$(real_pwd)/Boost" CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root - if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then + if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${CWD_DRIVE_ROOT}Boost_temp" ${BOOST_SDK} + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" fi From c2ff30c4d7331ee0bf68c6e7bf389c9ef39524e7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 09:33:51 +0000 Subject: [PATCH 043/126] correcting from GH/AV feedback, testing on GL. --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 15903c6ba..17f97bc6b 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,12 +419,12 @@ fi BOOST_SDK="$(real_pwd)/Boost" CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root - if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then + if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" - mv "${CWD_DRIVE_ROOT}Boost_temp" ${BOOST_SDK} + mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" fi From 8811c7141afc9fa65a1de4f0840a80b02b6f92ba Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 15:14:23 +0200 Subject: [PATCH 044/126] Update before_script.msvc.sh taking nits into account :) --- CI/before_script.msvc.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 5ca1de133..4f471462a 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -x +# set -x # turn-on for debugging MISSINGTOOLS=0 @@ -413,17 +413,18 @@ fi if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL - # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names - # We work around this by installing to root of the current working drive and then move it to our deps + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names + # We work around this by installing to root of the current working drive and then move it to our deps BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root + CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" fi From a6d6dd59958f837aa129a5be8704e7573f9f3614 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 13:17:19 +0000 Subject: [PATCH 045/126] updating for the nits --- CI/before_script.msvc.sh | 84 +++------------------------------------- 1 file changed, 6 insertions(+), 78 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 17f97bc6b..59771ad57 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -x +# set -x # turn-on for debugging MISSINGTOOLS=0 @@ -77,7 +77,6 @@ while [ $# -gt 0 ]; do h ) cat < Set the configuration, can also be set with environment variable CONFIGURATION. @@ -413,25 +412,23 @@ fi if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL - # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names - # We work around this by installing to root of the current working drive and then move it to our deps + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names + # We work around this by installing to root of the current working drive and then move it to our deps BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT=`powershell -command '(get-location).Drive.Root'` # get the current working drive's root + CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART //SUPPRESSMSGBOXES //LOG="boost_install.log" + [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG="boost_install.log" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" - fi - add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" - echo Done. else # Appveyor unstable has all the boost we need already @@ -449,18 +446,15 @@ fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" - echo Done. fi } cd $DEPS echo - # Bullet printf "Bullet 2.86... " { cd $DEPS_INSTALL - if [ -d Bullet ]; then printf -- "Exists. (No version checking) " elif [ -z $SKIP_EXTRACT ]; then @@ -468,49 +462,38 @@ printf "Bullet 2.86... " eval 7z x -y "${DEPS}/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP mv "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}" Bullet fi - export BULLET_ROOT="$(real_pwd)/Bullet" - echo Done. } cd $DEPS echo - # FFmpeg printf "FFmpeg 3.2.4... " { cd $DEPS_INSTALL - if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf FFmpeg - eval 7z x -y "${DEPS}/ffmpeg-3.2.4-win${BITS}.zip" $STRIP eval 7z x -y "${DEPS}/ffmpeg-3.2.4-dev-win${BITS}.zip" $STRIP - mv "ffmpeg-3.2.4-win${BITS}-shared" FFmpeg cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/ rm -rf "ffmpeg-3.2.4-win${BITS}-dev" fi - export FFMPEG_HOME="$(real_pwd)/FFmpeg" add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll - if [ $BITS -eq 32 ]; then add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\"" fi - echo Done. } cd $DEPS echo - # MyGUI printf "MyGUI 3.2.2... " { cd $DEPS_INSTALL - if [ -d MyGUI ] && \ grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \ grep "MYGUI_VERSION_MINOR 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \ @@ -522,21 +505,17 @@ printf "MyGUI 3.2.2... " eval 7z x -y "${DEPS}/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP mv "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}" MyGUI fi - export MYGUI_HOME="$(real_pwd)/MyGUI" - if [ $CONFIGURATION == "Debug" ]; then SUFFIX="_d" else SUFFIX="" fi add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll" - echo Done. } cd $DEPS echo - # OpenAL printf "OpenAL-Soft 1.17.2... " { @@ -546,24 +525,18 @@ printf "OpenAL-Soft 1.17.2... " rm -rf openal-soft-1.17.2-bin eval 7z x -y OpenAL-Soft-1.17.2.zip $STRIP fi - OPENAL_SDK="$(real_pwd)/openal-soft-1.17.2-bin" - add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \ -DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib" - add_runtime_dlls "$(pwd)/openal-soft-1.17.2-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll" - echo Done. } cd $DEPS echo - # OSG printf "OSG 3.4.1-scrawl... " { cd $DEPS_INSTALL - if [ -d OSG ] && \ grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \ grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \ @@ -575,28 +548,21 @@ printf "OSG 3.4.1-scrawl... " eval 7z x -y "${DEPS}/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP mv "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}" OSG fi - OSG_SDK="$(real_pwd)/OSG" - add_cmake_opts -DOSG_DIR="$OSG_SDK" - if [ $CONFIGURATION == "Debug" ]; then SUFFIX="d" else SUFFIX="" fi - add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng*}${SUFFIX}.dll \ "$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer}${SUFFIX}.dll - add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_"{bmp,dds,jpeg,osg,png,tga}${SUFFIX}.dll add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer}${SUFFIX}.dll - echo Done. } cd $DEPS echo - # Qt if [ -z $APPVEYOR ]; then printf "Qt 5.7.0... " @@ -609,71 +575,53 @@ fi else SUFFIX="" fi - if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL QT_SDK="$(real_pwd)/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}" - if [ -d Qt ] && head -n2 Qt/InstallationLog.txt | grep "5.7.0" > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Qt cp "${DEPS}/qt-5-install.qs" qt-install.qs - - sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" qt-install.qs sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs - printf -- "(Installation might take a while) " "${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent - mv qt-install.qs Qt/ - echo Done. printf " Cleaning up extraneous data... " rm -r "$(real_pwd)/Qt/"{dist,Docs,Examples,Tools,vcredist,components.xml,MaintenanceTool.dat,MaintenanceTool.exe,MaintenanceTool.ini,network.xml,qt-install.qs} fi - cd $QT_SDK - add_cmake_opts -DDESIRED_QT_VERSION=5 \ -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DCMAKE_PREFIX_PATH="$QT_SDK" - if [ $CONFIGURATION == "Debug" ]; then SUFFIX="d" else SUFFIX="" fi - add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll" - echo Done. else QT_SDK="C:/Qt/5.10/msvc${MSVC_DISPLAY_YEAR}${SUFFIX}" - add_cmake_opts -DDESIRED_QT_VERSION=5 \ -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DCMAKE_PREFIX_PATH="$QT_SDK" - if [ $CONFIGURATION == "Debug" ]; then SUFFIX="d" else SUFFIX="" fi - DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") - add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll" - echo Done. fi } cd $DEPS echo - # SDL2 printf "SDL 2.0.7... " { @@ -683,26 +631,18 @@ printf "SDL 2.0.7... " rm -rf SDL2-2.0.7 eval 7z x -y SDL2-2.0.7.zip $STRIP fi - export SDL2DIR="$(real_pwd)/SDL2-2.0.7" - add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll" - echo Done. } echo - - cd $DEPS_INSTALL/.. - echo echo "Setting up OpenMW build..." - add_cmake_opts -DBUILD_BSATOOL=no \ -DBUILD_ESMTOOL=no \ -DBUILD_MYGUI_PLUGIN=no \ -DOPENMW_MP_BUILD=on - if [ ! -z $CI ]; then case $STEP in components ) @@ -714,7 +654,6 @@ if [ ! -z $CI ]; then -DBUILD_OPENMW=no \ -DBUILD_WIZARD=no ;; - openmw ) echo " Building subproject: OpenMW." add_cmake_opts -DBUILD_ESSIMPORTER=no \ @@ -723,7 +662,6 @@ if [ ! -z $CI ]; then -DBUILD_OPENCS=no \ -DBUILD_WIZARD=no ;; - opencs ) echo " Building subproject: OpenCS." add_cmake_opts -DBUILD_ESSIMPORTER=no \ @@ -732,7 +670,6 @@ if [ ! -z $CI ]; then -DBUILD_OPENMW=no \ -DBUILD_WIZARD=no ;; - misc ) echo " Building subprojects: Misc." add_cmake_opts -DBUILD_OPENCS=no \ @@ -740,7 +677,6 @@ if [ ! -z $CI ]; then ;; esac fi - # NOTE: Disable this when/if we want to run test cases #if [ -z $CI ]; then echo "- Copying Runtime DLLs..." @@ -749,16 +685,13 @@ fi TARGET="$(basename "$DLL")" if [[ "$DLL" == *":"* ]]; then IFS=':'; SPLIT=( ${DLL} ); unset IFS - DLL=${SPLIT[0]} TARGET=${SPLIT[1]} fi - echo " ${TARGET}." cp "$DLL" "$BUILD_CONFIG/$TARGET" done echo - echo "- OSG Plugin DLLs..." mkdir -p $BUILD_CONFIG/osgPlugins-3.4.1 for DLL in $OSG_PLUGINS; do @@ -766,7 +699,6 @@ fi cp "$DLL" $BUILD_CONFIG/osgPlugins-3.4.1 done echo - echo "- Qt Platform DLLs..." mkdir -p ${BUILD_CONFIG}/platforms for DLL in $QT_PLATFORMS; do @@ -775,16 +707,13 @@ fi done echo #fi - if [ -z $VERBOSE ]; then printf -- "- Configuring... " else echo "- cmake .. $CMAKE_OPTS" fi - run_cmd cmake .. $CMAKE_OPTS RET=$? - if [ -z $VERBOSE ]; then if [ $RET -eq 0 ]; then echo Done. @@ -792,5 +721,4 @@ if [ -z $VERBOSE ]; then echo Failed. fi fi - exit $RET From dc48a46e50380d1f4762c792075b49283618690b Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 13:22:07 +0000 Subject: [PATCH 046/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 59771ad57..5f2b8a520 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,8 +422,8 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG="boost_install.log" - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} + [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ From ca0f6fff4a12a4115cf43b662a879cc205a8b29d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 13:25:36 +0000 Subject: [PATCH 047/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 5f2b8a520..4a7162fdf 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -422,7 +422,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" + [ -n "$CI" ] && CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" fi From c474709127125e8eeed7f7aaec6f1590f721c465 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 15:26:11 +0200 Subject: [PATCH 048/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 4f471462a..f6736c2ee 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -423,7 +423,7 @@ fi printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost - [ -n "$CI" ] CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG="boost_install.log" + [ -n "$CI" ] && CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" From 06216aa1240598ec063d384f2e31936eb3c6bfbc Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 13:36:00 +0000 Subject: [PATCH 049/126] Update .gitlab-ci.yml --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8bff1ad9c..6aa0773eb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ Win10: stage: build allow_failure: true script: - - env + # - env # turn on for debugging - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% From d3dfe17441cba6db43b0bdc6eee3b05c5ba3a05c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 15:13:06 +0000 Subject: [PATCH 050/126] try limiting scope --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6aa0773eb..25d9a876d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,6 +34,8 @@ MacOS: tags: - macos - xcode + except: + - branches stage: build allow_failure: true script: @@ -45,10 +47,12 @@ MacOS: paths: - build/OpenMW-*.dmg -Win10: +Windows: tags: - win10 - msvc2017 + only: + - branches stage: build allow_failure: true script: From 9b6ea0e89f15c9b64123b83ba8ec8b8d400f207d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 15:15:29 +0000 Subject: [PATCH 051/126] # because our CI VMs are not public, MRs can't use them and timeout --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 25d9a876d..565feff14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,7 +35,7 @@ MacOS: - macos - xcode except: - - branches + - branches # because our CI VMs are not public, MRs can't use them and timeout stage: build allow_failure: true script: @@ -51,8 +51,8 @@ Windows: tags: - win10 - msvc2017 - only: - - branches + except: + - branches # because our CI VMs are not public, MRs can't use them and timeout stage: build allow_failure: true script: From 2bf0d598cfb138dc5d7c234d95ce4a19b2c64901 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 20:01:35 +0200 Subject: [PATCH 052/126] Update before_script.msvc.sh Wrap in quites --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index f6736c2ee..ce13846c8 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -417,7 +417,7 @@ fi # We work around this by installing to root of the current working drive and then move it to our deps BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') # get the current working drive's root + CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " From 78a3f95ee4133f2f7f1d48f5aca26c66bbe221ba Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 18:03:25 +0000 Subject: [PATCH 053/126] Update before_script.msvc.sh --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 4a7162fdf..3f6c4d307 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -416,7 +416,7 @@ fi # We work around this by installing to root of the current working drive and then move it to our deps BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') # get the current working drive's root + CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" # get the current working drive's root if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " From 209359bbc355510ee2f096c510f340eb008882f9 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 19:07:39 +0000 Subject: [PATCH 054/126] Try this on for size... --- .gitlab-ci.yml | 4 ++-- CI/before_script.msvc.sh | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 565feff14..1898c6c3c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,8 +51,8 @@ Windows: tags: - win10 - msvc2017 - except: - - branches # because our CI VMs are not public, MRs can't use them and timeout +# except: +# - branches # because our CI VMs are not public, MRs can't use them and timeout stage: build allow_failure: true script: diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 3f6c4d307..be2a58aa6 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -412,11 +412,13 @@ fi if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL + BOOST_SDK="$(real_pwd)/Boost" + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps - - BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" # get the current working drive's root + # get the current working drive's root, we'll install to that temporarily + CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") + if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " From 4177fd04ebb49afc8c041b8eb6ac51f68e2a4cd7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 21:08:42 +0200 Subject: [PATCH 055/126] Update before_script.msvc.sh Does it blend? --- CI/before_script.msvc.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index ce13846c8..7c8f3ef68 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -412,12 +412,13 @@ fi { if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL - + + BOOST_SDK="$(real_pwd)/Boost" + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps - - BOOST_SDK="$(real_pwd)/Boost" - CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" # get the current working drive's root + # get the current working drive's root, we'll install to that temporarily + CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " From b8b07b52f0a8593a818e94b110ffefd907d97258 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 29 Jun 2018 22:42:12 +0000 Subject: [PATCH 056/126] try this... --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index be2a58aa6..b85196079 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -417,7 +417,7 @@ fi # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") + CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root' | sed "s,\\\\,/,g") if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then From 4d60fe5a76c8bd238e7ecfe4848445fa8b99eb17 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 30 Jun 2018 06:10:26 +0000 Subject: [PATCH 057/126] reverting back --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index b85196079..78ec4fa94 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -417,7 +417,7 @@ fi # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root' | sed "s,\\\\,/,g") + CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then From af75c1e909e136fd32776c6070241f070c9df5e2 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 30 Jun 2018 08:40:21 +0200 Subject: [PATCH 058/126] Update before_script.msvc.sh reverting back to what works --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 7c8f3ef68..22f4cc2fe 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -418,7 +418,7 @@ fi # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") + CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " From d4c9586bd0cc926ac3bc63e38560b43ddfbbd68d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 3 Jul 2018 12:53:30 +0000 Subject: [PATCH 059/126] try just converting the \ to a / --- CI/before_script.msvc.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 78ec4fa94..74d2df5a2 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -417,9 +417,8 @@ fi # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT=$(powershell -command '(get-location).Drive.Root') + CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g") - if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then From 4f07ca28a64c91400aa7c9cd4f44de34a91b8dde Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 3 Jul 2018 13:00:19 +0000 Subject: [PATCH 060/126] Try passing the _real_ windows dir to innoinstaller, then using the linux-like directory for mv. --- CI/before_script.msvc.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 74d2df5a2..792053ad4 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -417,15 +417,16 @@ fi # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT=$(echo "$(powershell -command '(get-location).Drive.Root')" | sed "s,\\\\,/,g") + CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp" + CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost [ -n "$CI" ] && CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} - mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} + mv "${CWD_DRIVE_ROOT_BASH}" "${BOOST_SDK}" fi add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}" From 11030e56c4aac0b6e6b65e28b3565be60fd2dda4 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 3 Jul 2018 13:41:06 +0000 Subject: [PATCH 061/126] detect existing dir --- CI/before_script.msvc.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 792053ad4..3ffca88de 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,8 +419,12 @@ fi # get the current working drive's root, we'll install to that temporarily CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp" CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") - - if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then + if [ -d CWD_DRIVE_ROOT_BASH ] then + printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. " + exit 1 + fi + + if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost From 70e9d5c0a099529bc93137339b02d6b148408281 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 3 Jul 2018 13:53:13 +0000 Subject: [PATCH 062/126] ; it? --- CI/before_script.msvc.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 3ffca88de..56a9d92d9 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -419,9 +419,9 @@ fi # get the current working drive's root, we'll install to that temporarily CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp" CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") - if [ -d CWD_DRIVE_ROOT_BASH ] then - printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. " - exit 1 + if [ -d CWD_DRIVE_ROOT_BASH ]; then + printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. "; + exit 1; fi if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then From 57e25735939d310933e4df94ea6bce2168ff2990 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 3 Jul 2018 15:59:51 +0200 Subject: [PATCH 063/126] Update before_script.msvc.sh check if temp directory exists, error out and warn user about it. --- CI/before_script.msvc.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 22f4cc2fe..eba278316 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -412,28 +412,30 @@ fi { if [ -z $APPVEYOR ]; then cd $DEPS_INSTALL - + BOOST_SDK="$(real_pwd)/Boost" - + # Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names # We work around this by installing to root of the current working drive and then move it to our deps # get the current working drive's root, we'll install to that temporarily - CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')" + CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp" + CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") + if [ -d CWD_DRIVE_ROOT_BASH ]; then + printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. "; + exit 1; + fi - if [ -d Boost ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then + if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf Boost [ -n "$CI" ] && CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'" - "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}Boost_temp" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} - mv "${CWD_DRIVE_ROOT}Boost_temp" "${BOOST_SDK}" - + "${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS} + mv "${CWD_DRIVE_ROOT_BASH}" "${BOOST_SDK}" fi - add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" - echo Done. else # Appveyor unstable has all the boost we need already From d4d46fc60256177968c96e9653ced2f83652338e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 4 Jul 2018 16:51:57 +0000 Subject: [PATCH 064/126] Build everything but branches until we can allow VM/CIs to run on forked projects. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1898c6c3c..565feff14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,8 +51,8 @@ Windows: tags: - win10 - msvc2017 -# except: -# - branches # because our CI VMs are not public, MRs can't use them and timeout + except: + - branches # because our CI VMs are not public, MRs can't use them and timeout stage: build allow_failure: true script: From 414f626309449491739b2ec343f854f60a433694 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 21:03:54 +0200 Subject: [PATCH 065/126] Implemented search case sensitivity --- apps/opencs/model/tools/search.cpp | 18 ++++++------ apps/opencs/model/tools/search.hpp | 7 +++-- apps/opencs/view/tools/searchbox.cpp | 43 ++++++++++++++-------------- apps/opencs/view/tools/searchbox.hpp | 2 ++ 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/apps/opencs/model/tools/search.cpp b/apps/opencs/model/tools/search.cpp index 0c068ba11..7cf89f3b5 100644 --- a/apps/opencs/model/tools/search.cpp +++ b/apps/opencs/model/tools/search.cpp @@ -22,7 +22,8 @@ void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model, int pos = 0; - while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1) + Qt::CaseSensitivity caseSensitivity = mCase ? Qt::CaseSensitive : Qt::CaseInsensitive; + while ((pos = text.indexOf (search, pos, caseSensitivity))!=-1) { std::ostringstream hint; hint @@ -120,25 +121,26 @@ QString CSMTools::Search::flatten (const QString& text) const return flat; } -CSMTools::Search::Search() : mType (Type_None), mValue (0), mIdColumn (0), mTypeColumn (0), +CSMTools::Search::Search() : mType (Type_None), mValue (0), mCase (false), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) {} -CSMTools::Search::Search (Type type, const std::string& value) -: mType (type), mText (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) +CSMTools::Search::Search (Type type, bool caseSensitive, const std::string& value) +: mType (type), mText (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) { if (type!=Type_Text && type!=Type_Id) throw std::logic_error ("Invalid search parameter (string)"); } -CSMTools::Search::Search (Type type, const QRegExp& value) -: mType (type), mRegExp (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) +CSMTools::Search::Search (Type type, bool caseSensitive, const QRegExp& value) +: mType (type), mRegExp (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) { + mRegExp.setCaseSensitivity(mCase ? Qt::CaseSensitive : Qt::CaseInsensitive); if (type!=Type_TextRegEx && type!=Type_IdRegEx) throw std::logic_error ("Invalid search parameter (RegExp)"); } -CSMTools::Search::Search (Type type, int value) -: mType (type), mValue (value), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) +CSMTools::Search::Search (Type type, bool caseSensitive, int value) +: mType (type), mValue (value), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) { if (type!=Type_RecordState) throw std::logic_error ("invalid search parameter (int)"); diff --git a/apps/opencs/model/tools/search.hpp b/apps/opencs/model/tools/search.hpp index 69b98bbdb..35cfa6402 100644 --- a/apps/opencs/model/tools/search.hpp +++ b/apps/opencs/model/tools/search.hpp @@ -43,6 +43,7 @@ namespace CSMTools std::string mText; QRegExp mRegExp; int mValue; + bool mCase; std::set mColumns; int mIdColumn; int mTypeColumn; @@ -67,11 +68,11 @@ namespace CSMTools Search(); - Search (Type type, const std::string& value); + Search (Type type, bool caseSensitive, const std::string& value); - Search (Type type, const QRegExp& value); + Search (Type type, bool caseSensitive, const QRegExp& value); - Search (Type type, int value); + Search (Type type, bool caseSensitive, int value); // Configure search for the specified model. void configure (const CSMWorld::IdTableBase *model); diff --git a/apps/opencs/view/tools/searchbox.cpp b/apps/opencs/view/tools/searchbox.cpp index d98044760..0c547c880 100644 --- a/apps/opencs/view/tools/searchbox.cpp +++ b/apps/opencs/view/tools/searchbox.cpp @@ -35,7 +35,7 @@ void CSVTools::SearchBox::updateSearchButton() } CSVTools::SearchBox::SearchBox (QWidget *parent) -: QWidget (parent), mSearch ("Search"), mSearchEnabled (false), mReplace ("Replace All") +: QWidget (parent), mSearch (tr("Search")), mSearchEnabled (false), mReplace (tr("Replace All")) { mLayout = new QGridLayout (this); @@ -48,29 +48,27 @@ CSVTools::SearchBox::SearchBox (QWidget *parent) ++iter) mRecordState.addItem (QString::fromUtf8 (iter->c_str())); - mMode.addItem ("Text"); - mMode.addItem ("Text (RegEx)"); - mMode.addItem ("ID"); - mMode.addItem ("ID (RegEx)"); - mMode.addItem ("Record State"); - + mMode.addItem (tr("Text")); + mMode.addItem (tr("Text (RegEx)")); + mMode.addItem (tr("ID")); + mMode.addItem (tr("ID (RegEx)")); + mMode.addItem (tr("Record State")); + connect (&mMode, SIGNAL (activated (int)), this, SLOT (modeSelected (int))); mLayout->addWidget (&mMode, 0, 0); - mLayout->addWidget (&mSearch, 0, 3); - + connect (&mText, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); + connect (&mText, SIGNAL (returnPressed()), this, SLOT (startSearch())); mInput.insertWidget (0, &mText); - mInput.insertWidget (1, &mRecordState); - mLayout->addWidget (&mInput, 0, 1); - - connect (&mMode, SIGNAL (activated (int)), this, SLOT (modeSelected (int))); + mInput.insertWidget (1, &mRecordState); + mLayout->addWidget (&mInput, 0, 1); - connect (&mText, SIGNAL (textChanged (const QString&)), - this, SLOT (textChanged (const QString&))); + mCaseSensitive.setText (tr ("Case")); + connect (&mCaseSensitive, SIGNAL (toggled (bool)), this, SLOT (caseSensitiveChanged (bool))); + mLayout->addWidget (&mCaseSensitive, 0, 2); connect (&mSearch, SIGNAL (clicked (bool)), this, SLOT (startSearch (bool))); - - connect (&mText, SIGNAL (returnPressed()), this, SLOT (startSearch())); + mLayout->addWidget (&mSearch, 0, 3); // replace panel mReplaceInput.insertWidget (0, &mReplaceText); @@ -102,23 +100,24 @@ void CSVTools::SearchBox::setSearchMode (bool enabled) CSMTools::Search CSVTools::SearchBox::getSearch() const { - CSMTools::Search::Type type = static_cast (mMode.currentIndex()); - + CSMTools::Search::Type type = static_cast (mMode.currentIndex()); + bool caseSensitive = mCaseSensitive.isChecked(); + switch (type) { case CSMTools::Search::Type_Text: case CSMTools::Search::Type_Id: - return CSMTools::Search (type, std::string (mText.text().toUtf8().data())); + return CSMTools::Search (type, caseSensitive, std::string (mText.text().toUtf8().data())); case CSMTools::Search::Type_TextRegEx: case CSMTools::Search::Type_IdRegEx: - return CSMTools::Search (type, QRegExp (mText.text().toUtf8().data(), Qt::CaseInsensitive)); + return CSMTools::Search (type, caseSensitive, QRegExp (mText.text().toUtf8().data(), Qt::CaseInsensitive)); case CSMTools::Search::Type_RecordState: - return CSMTools::Search (type, mRecordState.currentIndex()); + return CSMTools::Search (type, caseSensitive, mRecordState.currentIndex()); case CSMTools::Search::Type_None: diff --git a/apps/opencs/view/tools/searchbox.hpp b/apps/opencs/view/tools/searchbox.hpp index fe56966d1..eff5296b4 100644 --- a/apps/opencs/view/tools/searchbox.hpp +++ b/apps/opencs/view/tools/searchbox.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ namespace CSVTools QStackedWidget mInput; QLineEdit mText; QComboBox mRecordState; + QCheckBox mCaseSensitive; QPushButton mSearch; QGridLayout *mLayout; QComboBox mMode; From baf21362e165ce642c47d2a312336e28a16e32f3 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 21:47:16 +0200 Subject: [PATCH 066/126] Fixed undo / redo actions losing their shortcuts --- apps/opencs/view/doc/view.cpp | 22 +++++++++++++++++++++- apps/opencs/view/doc/view.hpp | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 10de46e06..f4d9b8ede 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -101,15 +102,34 @@ void CSVDoc::View::setupFileMenu() file->addAction(exit); } +static void updateUndoRedoAction(QAction *action, const std::string &settingsKey) +{ + QKeySequence seq; + CSMPrefs::State::get().getShortcutManager().getSequence(settingsKey, seq); + action->setShortcut(seq); +} + +void CSVDoc::View::undoActionChanged() +{ + updateUndoRedoAction(mUndo, "document-edit-undo"); +} + +void CSVDoc::View::redoActionChanged() +{ + updateUndoRedoAction(mRedo, "document-edit-redo"); +} + void CSVDoc::View::setupEditMenu() { QMenu *edit = menuBar()->addMenu (tr ("Edit")); mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo")); setupShortcut("document-edit-undo", mUndo); + connect(mUndo, SIGNAL (changed ()), this, SLOT (undoActionChanged ())); edit->addAction (mUndo); - mRedo= mDocument->getUndoStack().createRedoAction (this, tr("Redo")); + mRedo = mDocument->getUndoStack().createRedoAction (this, tr("Redo")); + connect(mRedo, SIGNAL (changed ()), this, SLOT (redoActionChanged ())); setupShortcut("document-edit-redo", mRedo); edit->addAction (mRedo); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 46aa87891..5418b7720 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -152,6 +152,10 @@ namespace CSVDoc void settingChanged (const CSMPrefs::Setting *setting); + void undoActionChanged(); + + void redoActionChanged(); + void newView(); void save(); From 2c39dba83b045e0ba0096bb86e50075362d648d9 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 22:01:45 +0200 Subject: [PATCH 067/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55442586b..14fbd1b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory + Bug #2606: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command From 5d381602390458bc1242d2a2412a4e6143bbf8ee Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 22:03:42 +0200 Subject: [PATCH 068/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55442586b..3cb7c8073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory + Bug #4110: Fixed undo / redo menu text losing the assigned shortcuts Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command From 1c1b5986e98debb16e2bc0dffc1f14c629af678c Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 22:05:07 +0200 Subject: [PATCH 069/126] Updated change log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14fbd1b9c..733955aa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,7 @@ Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory - Bug #2606: Implemented (optional) case sensitive global search + Feature #2606: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command From 96cf2cbd05b87ca2163381f8ee9cbed15654ee27 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 22:37:10 +0200 Subject: [PATCH 070/126] Notify views of changes of all cells in a row to properly update the row after revert --- apps/opencs/model/world/commands.cpp | 9 +++++++++ apps/opencs/model/world/idtable.cpp | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 79900c6c4..a572ca632 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -319,6 +319,15 @@ void CSMWorld::RevertCommand::redo() } else { + // notify view that data has changed, previously only the modified column was + // updated in the view unless the user had selected another item or forced a + // repaint with other means + int count = mModel.columnCount (index.parent ()); + if (count > 0) + { + emit mModel.dataChanged(mModel.index (index.row(), 0, index.parent ()), + mModel.index (index.row(), count - 1, index.parent ())); + } mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 3e503a80c..7492b6b17 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -86,9 +86,9 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value mIdCollection->setData (index.row(), index.column(), value); emit dataChanged(index, index); - // Modifying a value can also change the Modified status of a record. + // Modifying a value can also change the Modified status of a record unless . int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); - if (stateColumn != -1) + if (stateColumn != -1 && index.column() != stateColumn) { QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); From bf49a3e7603464611a80842d133ad55a006bb4db Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 23:21:55 +0200 Subject: [PATCH 071/126] Use setData() instead of emtitting dataChanged() which does not work on CI. Also Fixes the remaining issue with subviews not updating due to only the modified flag emitting a change, which prevented the widget mapper from working for updates. --- apps/opencs/model/world/commands.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index a572ca632..c67de6350 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -323,11 +323,16 @@ void CSMWorld::RevertCommand::redo() // updated in the view unless the user had selected another item or forced a // repaint with other means int count = mModel.columnCount (index.parent ()); - if (count > 0) + for (int i=0; i (RecordBase::State_BaseOnly)); } } From 3cbbbeceb4eae004e3e53e46b188ad55c15b9a9e Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 23:25:24 +0200 Subject: [PATCH 072/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f839279f3..4f098139e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory + Bug #3249: Fixed revert function not updating views properly Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window Feature #4222: 360° screenshots From 9bfa01c57941b3d5c0d2eea8927fd75f828d679f Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 00:37:19 +0200 Subject: [PATCH 073/126] Changed the way the revert command works: it now clones the changed record and uses the new RecordBase::revert() method to restore the previous value Added Flag_Dialogue_Refresh to var type and var value columns so that sub views update properly --- apps/opencs/model/world/columnimp.hpp | 4 ++-- apps/opencs/model/world/commands.cpp | 20 +++++--------------- apps/opencs/model/world/commands.hpp | 1 + apps/opencs/model/world/record.hpp | 12 +++++++++++- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 4ad447b0a..cd2a4c79e 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -136,7 +136,7 @@ namespace CSMWorld struct VarTypeColumn : public Column { VarTypeColumn (ColumnBase::Display display) - : Column (Columns::ColumnId_ValueType, display) + : Column (Columns::ColumnId_ValueType, display, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} virtual QVariant get (const Record& record) const @@ -161,7 +161,7 @@ namespace CSMWorld template struct VarValueColumn : public Column { - VarValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Var) {} + VarValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Var, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} virtual QVariant get (const Record& record) const { diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index c67de6350..ff4bab989 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -294,16 +294,19 @@ void CSMWorld::CreateCommand::undo() } CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand* parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0), mNew (0) { setText (("Revert record " + id).c_str()); + mNew = model.getRecord(id).clone(); + mNew->revert(); mOld = model.getRecord (id).clone(); } CSMWorld::RevertCommand::~RevertCommand() { delete mOld; + delete mNew; } void CSMWorld::RevertCommand::redo() @@ -319,20 +322,7 @@ void CSMWorld::RevertCommand::redo() } else { - // notify view that data has changed, previously only the modified column was - // updated in the view unless the user had selected another item or forced a - // repaint with other means - int count = mModel.columnCount (index.parent ()); - for (int i=0; i (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 58a1b1d1c..46fa6d8a0 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -201,6 +201,7 @@ namespace CSMWorld IdTable& mModel; std::string mId; RecordBase *mOld; + RecordBase *mNew; // not implemented RevertCommand (const RevertCommand&); diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 0313f2e41..db5822c97 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -24,6 +24,8 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const = 0; + virtual void revert() = 0; + virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. @@ -49,6 +51,8 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const; + void revert() override; + virtual void assign (const RecordBase& record); const ESXRecordT& get() const; @@ -96,6 +100,12 @@ namespace CSMWorld return new Record (*this); } + template + void Record::revert() + { + mModified = mBase; + } + template void Record::assign (const RecordBase& record) { @@ -156,4 +166,4 @@ namespace CSMWorld } } -#endif \ No newline at end of file +#endif From faf3e9ba5a0f75986135a929b8f0435f4231854b Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 5 Jul 2018 01:37:11 +0300 Subject: [PATCH 074/126] Make spellcasting stance transition more smooth (fixes #4358) If a movement animation was identical to the previous one that was played, restart it from the point the previous animation ended --- apps/openmw/mwmechanics/character.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c049d7933..6c1332154 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -459,9 +459,11 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character } } - /* If we're playing the same animation, restart from the loop start instead of the - * beginning. */ - int mode = ((movementAnimName == mCurrentMovement) ? 2 : 1); + // If we're playing the same animation, start it from the point it ended + bool sameAnim = (movementAnimName == mCurrentMovement); + float startPoint = 0.f; + if (sameAnim) + mAnimation->getInfo(mCurrentMovement, &startPoint); mMovementAnimationControlled = true; @@ -510,7 +512,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character } mAnimation->play(mCurrentMovement, Priority_Movement, movemask, false, - 1.f, ((mode!=2)?"start":"loop start"), "stop", 0.0f, ~0ul, true); + 1.f, (!sameAnim ? "start" : "loop start"), "stop", startPoint, ~0ul, true); } } } From 5bc073603e8c7887e015a0ef41b4cefd6e688aaf Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 5 Jul 2018 01:59:14 +0300 Subject: [PATCH 075/126] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f839279f3..da7dda03a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Bug #4293: Faction members are not aware of faction ownerships in barter Bug #4307: World cleanup should remove dead bodies only if death animation is finished Bug #4327: Missing animations during spell/weapon stance switching + Bug #4358: Running animation is interrupted when magic mode is toggled Bug #4368: Settings window ok button doesn't have key focus by default Bug #4393: NPCs walk back to where they were after using ResetActors Bug #4416: Handle exception if we try to play non-music file From d03f9125e348143ccbc91e79788044b0f9812b69 Mon Sep 17 00:00:00 2001 From: David Walley Date: Thu, 5 Jul 2018 08:45:09 +0000 Subject: [PATCH 076/126] Update documentationHowTo.rst - extend to integrate GitLab into PyCharm A subsequent MR will suggest moving most of this to a separate document for intermediate-level contributors, and replacing it with much simpler instructions for beginners - basically edit directly on GitLab as suggested by Psi29a on the forum here - https://forum.openmw.org/viewtopic.php?f=43&p=56458#p56457 --- docs/source/reference/documentationHowTo.rst | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/source/reference/documentationHowTo.rst b/docs/source/reference/documentationHowTo.rst index 2d8b4fae2..f2f809815 100644 --- a/docs/source/reference/documentationHowTo.rst +++ b/docs/source/reference/documentationHowTo.rst @@ -103,6 +103,33 @@ You will probably find it helpful to be able to preview any documentation you've Now in order to generate the documentation on your computer to preview them, just click the green play button in the top right, next to the drop down menu with the name you chose above selected. Sphinx will run and you can view the resulting documentation wherever you chose Output to be, above. The window that Sphinx runs in will also show any errors that occur during the build in red, which should help you find typos and missing/incorrect syntax. +GitLab integration in PyCharm +============================= + +As most of the hosting of OpenMW is moving to Gitlab, we should encourage the use of GitLab, though GitHub will continue to be supported. + +Add a couple of plugins to Pycharm - see general instructions at https://www.jetbrains.com/help/pycharm/installing-updating-and-uninstalling-repository-plugins.html + +For Linux/Windows - (Macos is a little different) + +1. File/Settings/Plugins +2. Browse Repositories +3. Filter with “GitLab” +4. Install “GitLab Integration Plugin”, +5. Follow the accompanying instructions to register your GitLab account (after restarting PyCharm) - File/Settings/Other Settings/Gitlab Integration +6. Install “GitLab Projects” + +Within your account on GitLab + +1. Fork OpenMW if you haven’t already done so +2. Select Settings from the dropdown box in your Avatar (top right) +3. Select Access Tokens from the list on the left +4. Enter a name for application that will use it – say “PyCharm” +5. Set an expiry date +6. Check the “api” box +7. Create the token, and use it to complete the setup of the "GitLab Integration Plugin" above. + + Sample PR ========= From 9ebcd656347f5af049b00ba882d3fb7a475e3819 Mon Sep 17 00:00:00 2001 From: David Walley Date: Thu, 5 Jul 2018 10:58:52 +0000 Subject: [PATCH 077/126] Update docs/source/reference/documentationHowTo.rst --- docs/source/reference/documentationHowTo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/reference/documentationHowTo.rst b/docs/source/reference/documentationHowTo.rst index f2f809815..442e52946 100644 --- a/docs/source/reference/documentationHowTo.rst +++ b/docs/source/reference/documentationHowTo.rst @@ -106,7 +106,7 @@ Now in order to generate the documentation on your computer to preview them, jus GitLab integration in PyCharm ============================= -As most of the hosting of OpenMW is moving to Gitlab, we should encourage the use of GitLab, though GitHub will continue to be supported. +As most of the hosting of OpenMW has moved to Gitlab, we should encourage the use of GitLab, though GitHub will continue to be supported. Add a couple of plugins to Pycharm - see general instructions at https://www.jetbrains.com/help/pycharm/installing-updating-and-uninstalling-repository-plugins.html From 61109d70b17826edcef0da3f898c28c9a189dc71 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 17:21:32 +0200 Subject: [PATCH 078/126] Removed invalid / unused signal / slot connection --- apps/opencs/view/tools/searchbox.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/tools/searchbox.cpp b/apps/opencs/view/tools/searchbox.cpp index 0c547c880..87a8be574 100644 --- a/apps/opencs/view/tools/searchbox.cpp +++ b/apps/opencs/view/tools/searchbox.cpp @@ -64,7 +64,6 @@ CSVTools::SearchBox::SearchBox (QWidget *parent) mLayout->addWidget (&mInput, 0, 1); mCaseSensitive.setText (tr ("Case")); - connect (&mCaseSensitive, SIGNAL (toggled (bool)), this, SLOT (caseSensitiveChanged (bool))); mLayout->addWidget (&mCaseSensitive, 0, 2); connect (&mSearch, SIGNAL (clicked (bool)), this, SLOT (startSearch (bool))); From f9b565a46e6e146391b295455cb5d7f6d25c4737 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 17:29:58 +0200 Subject: [PATCH 079/126] Removed QDebug include, moved updateUndoRedoAction to an anonymous namespace --- apps/opencs/view/doc/view.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index f4d9b8ede..9e87e9a3a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -102,11 +101,16 @@ void CSVDoc::View::setupFileMenu() file->addAction(exit); } -static void updateUndoRedoAction(QAction *action, const std::string &settingsKey) +namespace { - QKeySequence seq; - CSMPrefs::State::get().getShortcutManager().getSequence(settingsKey, seq); - action->setShortcut(seq); + + void updateUndoRedoAction(QAction *action, const std::string &settingsKey) + { + QKeySequence seq; + CSMPrefs::State::get().getShortcutManager().getSequence(settingsKey, seq); + action->setShortcut(seq); + } + } void CSVDoc::View::undoActionChanged() From e1877338113e4d1300e63984845f6a9280fe17fc Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 18:03:55 +0200 Subject: [PATCH 080/126] Notify views of changes in all columns when updating the ColumnId_Modification column --- apps/opencs/model/world/commands.cpp | 6 +----- apps/opencs/model/world/commands.hpp | 1 - apps/opencs/model/world/idtable.cpp | 26 ++++++++++++++++++++++---- apps/opencs/model/world/record.hpp | 10 ---------- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index ff4bab989..79900c6c4 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -294,19 +294,16 @@ void CSMWorld::CreateCommand::undo() } CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand* parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0), mNew (0) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) { setText (("Revert record " + id).c_str()); - mNew = model.getRecord(id).clone(); - mNew->revert(); mOld = model.getRecord (id).clone(); } CSMWorld::RevertCommand::~RevertCommand() { delete mOld; - delete mNew; } void CSMWorld::RevertCommand::redo() @@ -322,7 +319,6 @@ void CSMWorld::RevertCommand::redo() } else { - mModel.setRecord (mId, *mNew); mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 46fa6d8a0..58a1b1d1c 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -201,7 +201,6 @@ namespace CSMWorld IdTable& mModel; std::string mId; RecordBase *mOld; - RecordBase *mNew; // not implemented RevertCommand (const RevertCommand&); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 7492b6b17..75355116f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -86,12 +86,30 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value mIdCollection->setData (index.row(), index.column(), value); emit dataChanged(index, index); - // Modifying a value can also change the Modified status of a record unless . int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); - if (stateColumn != -1 && index.column() != stateColumn) + if (stateColumn != -1) { - QModelIndex stateIndex = this->index(index.row(), stateColumn); - emit dataChanged(stateIndex, stateIndex); + if (index.column() == stateColumn) + { + // modifying the state column can modify other values. we need to tell + // views that the whole row has changed. + + int count = columnCount(index.parent()); + for (int i=0; iindex(index.row(), i); + emit dataChanged(columnIndex, columnIndex); + } + } + + } else + { + // Modifying a value can also change the Modified status of a record unless . + QModelIndex stateIndex = this->index(index.row(), stateColumn); + emit dataChanged(stateIndex, stateIndex); + } } return true; diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index db5822c97..3362f9f96 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -24,8 +24,6 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const = 0; - virtual void revert() = 0; - virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. @@ -51,8 +49,6 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const; - void revert() override; - virtual void assign (const RecordBase& record); const ESXRecordT& get() const; @@ -100,12 +96,6 @@ namespace CSMWorld return new Record (*this); } - template - void Record::revert() - { - mModified = mBase; - } - template void Record::assign (const RecordBase& record) { From b8e53b5b81872f7fce006f3456e62b2c0b5b467d Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 18:10:43 +0200 Subject: [PATCH 081/126] Fixed comment --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 75355116f..0a2052fd8 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -106,7 +106,7 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value } else { - // Modifying a value can also change the Modified status of a record unless . + // Modifying a value can also change the Modified status of a record. QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); } From 9abfabb065f244fb190eb754ce1d860836062445 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 5 Jul 2018 22:49:40 +0300 Subject: [PATCH 082/126] Ensure forward-compatibility of death animations in old saves (fixes #4274) --- apps/openmw/mwmechanics/character.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 6c1332154..e6a8e8152 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -662,16 +662,19 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I void CharacterController::playDeath(float startpoint, CharacterState death) { + // Make sure the character was swimming upon death for forward-compatibility + const bool wasSwimming = MWBase::Environment::get().getWorld()->isSwimming(mPtr); + switch (death) { case CharState_SwimDeath: mCurrentDeath = "swimdeath"; break; case CharState_SwimDeathKnockDown: - mCurrentDeath = "swimdeathknockdown"; + mCurrentDeath = (wasSwimming ? "swimdeathknockdown" : "deathknockdown"); break; case CharState_SwimDeathKnockOut: - mCurrentDeath = "swimdeathknockout"; + mCurrentDeath = (wasSwimming ? "swimdeathknockout" : "deathknockout"); break; case CharState_DeathKnockDown: mCurrentDeath = "deathknockdown"; From 33c462c3c254a90f214106f7e7a9dc37c9ee7673 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 5 Jul 2018 22:56:09 +0300 Subject: [PATCH 083/126] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da7dda03a..6b5f1a39d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Bug #4215: OpenMW shows book text after last EOL tag Bug #4221: Characters get stuck in V-shaped terrain Bug #4251: Stationary NPCs do not return to their position after combat + Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+ Bug #4286: Scripted animations can be interrupted Bug #4291: Non-persistent actors that started the game as dead do not play death animations Bug #4293: Faction members are not aware of faction ownerships in barter From 03c75794c1ca41537b986ff789b3d6e4bfff1fb0 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 22:55:19 +0200 Subject: [PATCH 084/126] Moved crashcatcher to a component and also use it in CS Reworked debugger detection (failed on gdb 7.11), it now uses /proc to detect the debugger --- apps/opencs/editor.cpp | 11 ++++- apps/opencs/editor.hpp | 2 +- apps/opencs/main.cpp | 4 +- apps/openmw/CMakeLists.txt | 4 +- apps/openmw/main.cpp | 26 +----------- cmake/OpenMWMacros.cmake | 2 +- components/CMakeLists.txt | 6 +++ .../crashcatcher}/crashcatcher.cpp | 40 +++++++++++++------ components/crashcatcher/crashcatcher.hpp | 18 +++++++++ 9 files changed, 68 insertions(+), 45 deletions(-) rename {apps/openmw => components/crashcatcher}/crashcatcher.cpp (93%) create mode 100644 components/crashcatcher/crashcatcher.hpp diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 35ce51337..2be3dc24c 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,9 @@ #include #include + +#include + #include #include @@ -18,12 +21,16 @@ using namespace Fallback; -CS::Editor::Editor () +CS::Editor::Editor (int argc, char **argv) : mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mPid(""), mLock(), mMerge (mDocumentManager), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) -{ +{ + // install the crash handler as soon as possible. note that the log path + // does not depend on config being read. + cc_install(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string()); + std::pair > config = readConfig(); setupDataFiles (config.first); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index b60f5c6a8..21199e2ca 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -66,7 +66,7 @@ namespace CS public: - Editor (); + Editor (int argc, char **argv); ~Editor (); bool makeIPCServer(); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index fc5e8fc7a..d599f1f96 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) #endif try - { + { // To allow background thread drawing in OSG QApplication::setAttribute(Qt::AA_X11InitThreads, true); @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) application.setWindowIcon (QIcon (":./openmw-cs.png")); - CS::Editor editor; + CS::Editor editor(argc, argv); if(!editor.makeIPCServer()) { diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e64998077..e8a958d45 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -11,12 +11,10 @@ if (ANDROID) set(GAME ${GAME} android_main.c) endif() -if(NOT WIN32 AND NOT ANDROID) - set(GAME ${GAME} crashcatcher.cpp) -endif() set(GAME_HEADER engine.hpp ) + source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 109610b1e..db095c73d 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -24,18 +25,6 @@ #include #endif -#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) - #define USE_CRASH_CATCHER 1 -#else - #define USE_CRASH_CATCHER 0 -#endif - -#if USE_CRASH_CATCHER -#include -extern int cc_install_handlers(int argc, char **argv, int num_signals, int *sigs, const char *logfile, int (*user_info)(char*, char*)); -extern int is_debugger_attached(void); -#endif - /** * Workaround for problems with whitespaces in paths in older versions of Boost library */ @@ -339,18 +328,7 @@ int main(int argc, char**argv) std::cerr.rdbuf (&cerrsb); #endif - -#if USE_CRASH_CATCHER - // Unix crash catcher - if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached()) - { - int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; - cc_install_handlers(argc, argv, 5, s, (cfgMgr.getLogPath() / "crash.log").string().c_str(), NULL); - std::cout << "Installing crash catcher" << std::endl; - } - else - std::cout << "Running in a debugger, not installing crash catcher" << std::endl; -#endif + cc_install(argc, argv, (cfgMgr.getLogPath() / "crash.log").string()); #ifdef __APPLE__ boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 2fa86094f..f385437b4 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -204,4 +204,4 @@ macro (copy_all_resource_files source_dir destination_dir_base destination_dir_r get_filename_component(filename ${f} NAME) copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${filename}") endforeach (f) -endmacro (copy_all_resource_files) \ No newline at end of file +endmacro (copy_all_resource_files) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 3efd236cb..b6f390b06 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -145,6 +145,12 @@ add_component_dir (fallback fallback validate ) +if(NOT WIN32 AND NOT ANDROID) + add_component_dir (crashcatcher + crashcatcher + ) +endif() + set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) diff --git a/apps/openmw/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp similarity index 93% rename from apps/openmw/crashcatcher.cpp rename to components/crashcatcher/crashcatcher.cpp index 0078ef169..6aeed114c 100644 --- a/apps/openmw/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -14,7 +14,11 @@ #include #include -#include +#include + +#include + +namespace bfs = boost::filesystem; #include @@ -454,19 +458,31 @@ int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, co return retval; } - -// gdb apparently opens FD(s) 3,4,5 (whereas a typical prog uses only stdin=0, stdout=1,stderr=2) -bool -is_debugger_attached(void) +static bool is_debugger_present() { - bool rc = false; - FILE *fd = fopen("/tmp", "r"); - - if (fileno(fd) > 5) + bfs::ifstream file((bfs::path("/proc/self/status"))); + while (!file.eof()) { - rc = true; + std::string word; + file >> word; + if (word == "TracerPid:") + { + file >> word; + return word != "0"; + } } + return false; +} - fclose(fd); - return rc; +void cc_install(int argc, char **argv, const std::string &crashLogPath) +{ + if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_present()) + { + int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; + if (cc_install_handlers(argc, argv, 5, s, crashLogPath.c_str(), NULL) == -1) + { + std::cerr << "Installing crash handler failed" << std::endl; + } else + std::cout << "Crash handler installed" << std::endl; + } } diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp new file mode 100644 index 000000000..3d5d61a9f --- /dev/null +++ b/components/crashcatcher/crashcatcher.hpp @@ -0,0 +1,18 @@ +#ifndef CRASHCATCHER_H +#define CRASHCATCHER_H + +#include + +#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) + #define USE_CRASH_CATCHER 1 +#else + #define USE_CRASH_CATCHER 0 +#endif + +#if USE_CRASH_CATCHER +extern void cc_install(int argc, char **argv, const std::string &crashLogPath); +#else +inline void cc_install(int, char **) { return 0; } +#endif + +#endif From 6a78379757515161616c68a2be02533337824ff8 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 22:59:29 +0200 Subject: [PATCH 085/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da7dda03a..20e8ff961 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier + Feature #4012: Editor: write a log file if OpenCS crashes 0.44.0 ------ From 6a2b8f7e85174dfa51361dbe09651d70afa5be7f Mon Sep 17 00:00:00 2001 From: Alex S Date: Fri, 6 Jul 2018 08:14:26 +0000 Subject: [PATCH 086/126] Fixed changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20e8ff961..fb4ba0247 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,7 @@ Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier - Feature #4012: Editor: write a log file if OpenCS crashes + Feature #4012: Editor: Write a log file if OpenCS crashes 0.44.0 ------ From bded697f07ffc1fa0dc7eb6c1700e413483b0f20 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Fri, 6 Jul 2018 19:38:36 +0300 Subject: [PATCH 087/126] Make Goodbye block using hyperlinks --- apps/openmw/mwgui/dialogue.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 450799f29..f4fe54917 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -629,6 +629,9 @@ namespace MWGui void DialogueWindow::onTopicActivated(const std::string &topicId) { + if (mGoodbye) + return; + MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId, mCallback.get()); updateTopics(); } From b5abe6a230e5e275d5f424080de120eaaf1ed711 Mon Sep 17 00:00:00 2001 From: David Walley Date: Fri, 6 Jul 2018 19:06:32 +0000 Subject: [PATCH 088/126] Update documentationHowTo.rst Add a section, under the provisional name "Baby Steps" to describe a minimal process for editing/contributing. Basically just create an account on GitLab, fork openmw there, then edit the relevant document to create Merge Request --- docs/source/reference/documentationHowTo.rst | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/source/reference/documentationHowTo.rst b/docs/source/reference/documentationHowTo.rst index 442e52946..b27c122cb 100644 --- a/docs/source/reference/documentationHowTo.rst +++ b/docs/source/reference/documentationHowTo.rst @@ -12,6 +12,32 @@ The premise of this guide is that you would like to help out the OpenMW project *However*, as much as I will try to guide you through all the tedious setup and day-to-day stuff, you will eventually have to learn to write using ReST (reStructuredText) formatting. Since you're probably like me when I started helping and don't know wtf ReST is, never fear. It's an incredibly simple language that is easy to read in plain text form that can then be converted automatically into different types of documents like PDFs and html for webpages. +Baby Steps +========== + +Create an account on GitLab (https://gitlab.com), and sign in. +(Github probably works too, though some details will differ. More details later – maybe.) + +Go to the OpenMW project on GitLab (https://gitlab.com/OpenMW/openmw) +Navigate to whatever documentation you want to tackle. +Choose Repository and Files in the menu on the left, then docs and source in the tree in the centre. + +Don’t overlook the tutorial-style-guide.txt there for some tips to get you started. + +Open whichever file you want to tackle – probably within the manuals or reference directories. +There’s also a dropdown box to the right of edit, at the top of the left menu, which offers options such as new file or directory, or upload file, with “+” to close that dropdown box. + +Click on "Edit" towards top right which will reveal the underlying version, rather than the version displayed to normal reaaders. Use "Write" and "Preview" to switch between the two views. + +When you have made the appropriate changes, and checked them in Preview mode, click the Green "Commit changes" button at the bottom. +This should add a branch, with a default name such as patch-1, to your own repository, and add a Merge Request to the main OpenMW Project. + +[More details on the commit and review process] + +Changes between submission and acceptance of the Merge Request - just make them in your branch, then press the Commit button there. + +Going Deeper +============ So here's what you're gonna be learning how to set up: 1. `GitHub`_ From 380384ff3954d05d3344bcccbcff0e1e7aacc7f8 Mon Sep 17 00:00:00 2001 From: Ryan Tucker Date: Sat, 30 Jun 2018 13:29:27 -0700 Subject: [PATCH 089/126] Migrated textures section of wiki. --- docs/requirements.txt | 2 +- docs/source/conf.py | 5 +- docs/source/index.rst | 10 +- .../manuals/installation/common-problems.rst | 50 +++++ docs/source/manuals/installation/index.rst | 3 +- .../installation/install-game-files.rst | 127 ++++++++++++- docs/source/reference/index.rst | 9 +- docs/source/reference/modding/index.rst | 26 +-- .../convert-bump-mapped-mods.rst} | 0 .../modding/texture-modding/index.rst | 16 ++ .../texture-modding/native-mesh-format.rst | 114 ++++++++++++ .../texture-modding/texture-basics.rst | 171 ++++++++++++++++++ 12 files changed, 504 insertions(+), 29 deletions(-) create mode 100644 docs/source/manuals/installation/common-problems.rst rename docs/source/reference/modding/{convert_bump_mapped_mods.rst => texture-modding/convert-bump-mapped-mods.rst} (100%) create mode 100644 docs/source/reference/modding/texture-modding/index.rst create mode 100644 docs/source/reference/modding/texture-modding/native-mesh-format.rst create mode 100644 docs/source/reference/modding/texture-modding/texture-basics.rst diff --git a/docs/requirements.txt b/docs/requirements.txt index 72c2aaa12..288d462d0 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ parse_cmake -sphinx +sphinx>=1.7.0 diff --git a/docs/source/conf.py b/docs/source/conf.py index 0ba8567c0..8905044dd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ sys.path.insert(0, project_root) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +needs_sphinx = '1.7' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -34,8 +34,11 @@ extensions = [ 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', + 'sphinx.ext.autosectionlabel', ] +#autosectionlabel_prefix_document = True + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/docs/source/index.rst b/docs/source/index.rst index 3781733cb..de3773ddb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,11 +1,9 @@ Welcome to OpenMW's Documentation! ================================== -Sections --------- - .. toctree:: - :maxdepth: 3 + :caption: Table of Contents + :maxdepth: 3 - manuals/index - reference/index + manuals/index + reference/index diff --git a/docs/source/manuals/installation/common-problems.rst b/docs/source/manuals/installation/common-problems.rst new file mode 100644 index 000000000..543b8ec9b --- /dev/null +++ b/docs/source/manuals/installation/common-problems.rst @@ -0,0 +1,50 @@ +############### +Common Problems +############### + +ERROR: Unknown fallback name: FontColor_color_header +#################################################### + +:Symptoms: + OpenMW crashes at startup with + ``ERROR: Unknown fallback name: FontColor_color_header`` + message at the end of ``openmw.log``, located `here `_. + +:Cause: + The OpenMW `configuration file `_ ``openmw.cfg`` + is severely lacking and missing fallback values + because "Settings Importer" was not run correctly. + +:Fix: + Re-run "Settings Importer" from the OpenMW launcher. + +Installing game files via Steam on macOS: DISK WRITE ERROR +########################################################## + +:Symptoms: + Steam stages the download for Morrowind, but does not proceed. + The download will read "Paused: DISK WRITE ERROR". + +:Cause: + The OpenMW `configuration file `_ ``openmw.cfg`` + is severely lacking and missing fallback values + because "Settings Importer" was not run correctly. + +:Fix: + Open appmanifest_22320.acf in your favorite text editor. + Locate or create an entry under the "StateFlags" entry titled "installdir" + and give it the value "Morrowind". + Your file should now look something like this:: + + "AppState" + { + "appid" "22320" + "Universe" "1" + "name" "The Elder Scrolls III: Morrowind" + "StateFlags" "4" + "installdir" "Morrowind" + + [other entries] + } + + Restart the Steam client. The download should now proceed. \ No newline at end of file diff --git a/docs/source/manuals/installation/index.rst b/docs/source/manuals/installation/index.rst index f22e77449..6e6f5034e 100644 --- a/docs/source/manuals/installation/index.rst +++ b/docs/source/manuals/installation/index.rst @@ -1,3 +1,4 @@ +################## Installation Guide ################## @@ -8,4 +9,4 @@ In order to use OpenMW, you must install both the engine and the game files for install-openmw install-game-files - + common-problems \ No newline at end of file diff --git a/docs/source/manuals/installation/install-game-files.rst b/docs/source/manuals/installation/install-game-files.rst index 11c746f44..ac3688e88 100644 --- a/docs/source/manuals/installation/install-game-files.rst +++ b/docs/source/manuals/installation/install-game-files.rst @@ -1,5 +1,126 @@ -================== +################## Install Game Files -================== +################## + +OpenMW is a complete game engine that can either run `Morrowind`_ +or original projects created with OpenMW-CS, such as `Example Suite`_. + +Morrowind +######### + +Running the Morrowind Installation Wizard +========================================= + +#. Launch the OpenMW Launcher +#. Launch the Installation Wizard + + .. note:: + If you are prompted with an error message stating + "Could not find the Data Files location," + click the "Run Installation Wizard" button. + .. note:: + If you arrive at the main screen, click the "Settings" tab, + and then click the "Run Installation Wizard" button. + +#. Follow further instructions below + to install Morrowind from either a retail CD or an existing installation. + + - **Morrowind (from retail CD)** + + #. Make sure that the retail CD is in your computer's CD/DVD drive + and the Installation Wizard is running. + #. On the "Select Installation Method" screen of the Installation Wizard, + choose "Install Morrowind to a New Location" and click the "Next" button. + #. Choose a location to install Morrowind to your hard drive + (or accept the suggested location) and click the "Next" button. + #. Select your preferred language for the installation + and click the "Next" button + #. Select which official expansions (Tribunal or Bloodmoon) should be installed. + For best results, it is recommended to have both expansions installed. + #. Click the "Install" button. + + - **Morrowind (from existing installation)** + + #. On the "Select Installation Method" screen of the Installation Wizard, + choose "Select an existing Morrowind installation" and click the "Next" button + #. Select an installation. If nothing is detected, click browse. + #. Navigate to the directory containing the file ``Morrowind.esm`` and select that file. + +#. You will be asked if you wish to import settings from ``Morrowind.ini``. + Select "Import", otherwise OpenMW will not work. + (You do not need to check the box "Include selected masters and plugins"). +#. The OpenMW launcher window should now open. + Switch to the "Data Files" tab and check the box to the left of ``Morrowind.esm``. +#. You are now ready to play! + +Installing Morrowind +==================== + +----------------- +Retail CD and GOG +----------------- + +Windows users can run the installer if they haven't already. +By default, both Bethesda's official installer on the retail CD +and the GOG installer install to ``C:\Program Files\Bethesda Softworks\Morrowind``. +You will find ``Morrowind.esm`` there. + +Users of other platforms running Wine, will find it at +``~/.wine/drive_c/Program Files/Bethesda Softworks/Morrowind`` + +----- +Steam +----- + +Windows +------- + +Windows users can download Morrowind through Steam. +Afterwards, you can point OpenMW to the Steam install location at +``C:\Program Files\Steam\SteamApps\common\Morrowind\Data Files\`` +and find ``Morrowind.esm`` there. + +macOS +----- + +If you are running macOS, you can also download Morrowind through Steam: + +#. Navigate to ``/Users/YOUR_USERNAME_HERE/Library/Application Support/Steam/steamapps/`` +#. Create a file called ``appmanifest_22320.acf`` + (the number is based on its `Steam App ID `_). + If using TextEdit, + make sure that your document is in plain text mode by going to the menu bar + and choosing "Format" -> "Make Plain Text". + Also, ensure that it's not named with the extension ``.acf.txt``. + Add the following into that file:: + + "AppState" + { + "AppID" "22320" + "Universe" "1" + "StateFlags" "1026" + "installdir" "The Elder Scrolls III - Morrowind" + } + +#. Launch the Steam client and let it download. You can then find ``Morrowind.esm`` at + ``~/Library/Application Support/Steam/steamapps/common/The Elder Scrolls III - Morrowind/Data Files/`` + +Wine +---- + +Users of other platforms running Wine can run Steam within it +and find ``Morrowind.esm`` at +``~/.wine/drive_c/Program Files/Steam/SteamApps/common/Morrowind/Data Files/``. + +Example Suite +############# + +Example Suite is a demo showing the capabilities of the OpenMW engine. +At this time, it requires Morrowind to be installed to run, +but does not use any assets from it. +In the future, it will be possible to run without installing Morrowind first. + +#. `Install Morrowind `_ +#. `Download the latest version `_ +#. Follow the platform-specific instructions in the zip file's ``Installation.md`` file. -Coming Soon... \ No newline at end of file diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst index 3f2e2f560..cd947745e 100644 --- a/docs/source/reference/index.rst +++ b/docs/source/reference/index.rst @@ -1,8 +1,9 @@ +################## Reference Material -================== +################## .. toctree:: - :maxdepth: 2 + :maxdepth: 2 - modding/index - documentationHowTo \ No newline at end of file + modding/index + documentationHowTo \ No newline at end of file diff --git a/docs/source/reference/modding/index.rst b/docs/source/reference/modding/index.rst index d2dd90850..30793504e 100644 --- a/docs/source/reference/modding/index.rst +++ b/docs/source/reference/modding/index.rst @@ -8,19 +8,19 @@ about creating new content for OpenMW, please refer to :doc:`/manuals/openmw-cs/index`. .. warning:: - OpenMW is still software in development. This manual does not cover any - of its shortcomings. It is written as if everything was working as - intended. Please report any software problems as bugs in the software, - not errors in the manual. + OpenMW is still software in development. This manual does not cover any + of its shortcomings. It is written as if everything was working as + intended. Please report any software problems as bugs in the software, + not errors in the manual. .. toctree:: - :caption: Table of Contents - :maxdepth: 2 + :caption: Table of Contents + :maxdepth: 2 - foreword - differences - mod-install - settings/index - font - convert_bump_mapped_mods - paths + foreword + differences + mod-install + settings/index + texture-modding/index + font + paths diff --git a/docs/source/reference/modding/convert_bump_mapped_mods.rst b/docs/source/reference/modding/texture-modding/convert-bump-mapped-mods.rst similarity index 100% rename from docs/source/reference/modding/convert_bump_mapped_mods.rst rename to docs/source/reference/modding/texture-modding/convert-bump-mapped-mods.rst diff --git a/docs/source/reference/modding/texture-modding/index.rst b/docs/source/reference/modding/texture-modding/index.rst new file mode 100644 index 000000000..3e0b359ee --- /dev/null +++ b/docs/source/reference/modding/texture-modding/index.rst @@ -0,0 +1,16 @@ +###################### +OpenMW Texture Modding +###################### + +Although texture modding requires external tools not supported by the OpenMW team, +adding and modifying textures is an important part of content creation. +Therefore, we've included the following in hopes of helping modders transition +to texture modding in OpenMW. + +.. toctree:: + :caption: Table of Contents + :maxdepth: 2 + + texture-basics + convert-bump-mapped-mods + native-mesh-format diff --git a/docs/source/reference/modding/texture-modding/native-mesh-format.rst b/docs/source/reference/modding/texture-modding/native-mesh-format.rst new file mode 100644 index 000000000..c2ddd26ba --- /dev/null +++ b/docs/source/reference/modding/texture-modding/native-mesh-format.rst @@ -0,0 +1,114 @@ +################## +Native Mesh Format +################## + +This article explains how to export a model from Blender to OpenMW using the OSG model format. +Starting with OpenMW version 0.38 we can utilize the OSG native model format. +The OSG model format doesn't yet support all the features that NIF's support, +but works for basic models. For more details on the format, refer to +`this forum post `_. + +Previously, NIF files were the only way to get models into the game. +Unfortunately, the NIF format is proprietary, bloated, +and the available exporters are not in great shape. +For example, the Blender NIF exporter currently only works with the very old Blender 2.49. + +Prerequisites +############# + +- OpenMW 0.38 or later +- Blender 2.60 or later +- OSG exporter add-on for Blender +- A Blender model you would like to export + +Installing the exporter +####################### + +#. Download the + `OSG export script + `_ +#. Open Blender and go to File -> User Preferences +#. Select Add-ons -> Install from File, then select the downloaded `.zip` +#. Enter "osg" into the search bar, then tick the checkbox next to the add-on to enable it +#. Now click Save user setting so the exporter stays enabled when you re-start Blender + +You can now export your models using the OSG model (osgt) entry in the File -> Export menu. + +Model's location +################ + +The model needs to be at 0,0,0 coordinates in Blender, +as this is where its origin will always be when exported. +If the model is offset from 0,0,0 in Blender, +it will be offset from its origin in the exported file as well. + +Model's rotation +################ + +- Blender's Z axis is up axis in OpenMW +- Blender's Y axis is front axis in OpenMW +- Blender's X axis is left-right axis in OpenMW +- Visual rotation is taken into account when exporting + +Model's scale +############# + +Blender:OpenMW model scale is 70:1, +which means 70 Blender units (BU) translate into 1m in OpenMW. +Using this scale, any models you make will fit with the existing ones. +The scale does not need to be applied, +the exporter will always use the visual scale of the model. +However, 70 is an odd number to work with so here's an alternative workflow: + +- In Blender, use a scale of 1BU = 1m which is a nice scale and ratio to work with. + Have all models use this scale. +- Before exporting a model, scale it up by a factor of 70. +- After exporting, undo the model's scale change and continue working as normal + (in the future a preferable way would be to apply the scale through the exporter) + +Putting the model in-game +######################### + +Place the exported model in the Meshes sub-folder of a data folder recognized by the game, +e.g. the Morrowind Data Files folder, or the local data folder. +Place all required textures in the Textures sub-folder. +Now start OpenMW-CS, create a new addon file +and you should see your mesh in the Assets -> Meshes table. +Go ahead and make some object use your mesh. +You can now preview by right clicking on the object -> Preview to see what the mesh will look like. + +Converting the model to binary +############################## + +When the model behaves to our liking, +we can think about converting it from the "osgt" text format to the "osgb" binary format +so that it's smaller in size - and thus faster to load. + +To do this, simply invoke the osgconv tool. +This tool should be included with your distribution of OpensceneGraph. + +`osgconv -O WriteImageHint=UseExternal model.osgt model.osgb` + +Of course, you can convert the binary model back to text format as well: + +`osgconv -O WriteImageHint=UseExternal model.osgb model.osgt` + +Note the use of `-O WriteHint=UseExternal` option. +Enabling this option is desirable because it keeps the textures as external file references, +rather than embedding the textures within the model file. +Embedded textures have disadvantages such as being hard to inspect, +and impossible to share between model files. + +Using shaders/normal maps +######################### + +See :ref:`OSG Native Files` + +Conclusion +########## + +These are the basics of getting a textured, static model from Blender into the game. +In the future, we will want a way to add texture animations, +skeletal animations, separate collision shapes, +and some other features that are currently only available via NIF files. +We will likely add these features to the native OSG format after OpenMW 1.0. \ No newline at end of file diff --git a/docs/source/reference/modding/texture-modding/texture-basics.rst b/docs/source/reference/modding/texture-modding/texture-basics.rst new file mode 100644 index 000000000..09bd9a7ec --- /dev/null +++ b/docs/source/reference/modding/texture-modding/texture-basics.rst @@ -0,0 +1,171 @@ +autosectionlabel_prefix_document = True + +###################### +Texture Modding Basics +###################### + +OpenMW supports new texture mapping techniques +that were not available in the vanilla Morrowind engine. + +`Normal mapping`_ is a technique used to fake lighting of bumps, +cracks and other small details. + +`Specular mapping`_ is used to vary the shininess/specularity along the surface of an object. + +The prerequisite to using these techniques are +`shaders `_. +OpenMW automatically uses shaders for objects with these mapping techniques. + +Normal Mapping +############## + +To plug in a normal map, you can edit the NIF mesh file(s) using NifSkope +and assign the normal map texture to the BumpTexture slot in the NiTexturingProperty. + +.. note:: + While the original Morrowind engine does support the BumpTexture slot, + it uses a strange form of normal mapping that applies to an environment map. + OpenMW uses standard normal mapping, which can achieve much better results. + Unfortunately, this difference can result in incompatibilities. + Some mods + (e.g. `Redoran Bump Mapped `_) + look much darker compared to the vanilla engine and will have to be recalibrated. + +Specular Mapping +################ + +The RGB channels of the specular map are used as the specular color. +The alpha channel specifies shininess in range [0, 255]. +If a specular map is used, it will override the shininess and specular color +set in the NiMaterialProperty / osg::Material. + +NIF files do not support specular maps. +In order to use them anyway, see the next section. + +Automatic Use +############# + +In addition to editing mesh files, +there is another way of plugging in these texture maps. +Simply create the textures with appropriate naming convention +(e.g. when the base texture is called foo.dds, +the normal map would have to be called foo_n.dds). +To enable this automatic use based on filename pattern, +you will have to add the following to your +`settings.cfg `_ file:: + + [Shaders] + auto use object normal maps = true + + auto use object specular maps = true + + normal map pattern = _n + normal height map pattern = _nh + + specular map pattern = _spec + +Additionally, a normal map with the `_nh` pattern enables +the use of the normal map's alpha channel as height information. +This can be used by a `parallax mapping `_ +shader to offset the texture depending on the viewing angle and height, +creating a fake 3D effect. + +The above settings are not enabled by default to prevent incompatibilities +with mods that may be inadvertently using these naming schemes. + +On the topic of shader settings, +you may be interested in these three settings as well: :ref:`force shaders`, +:ref:`force per pixel lighting`, and :ref:`clamp lighting`. +In particular, `clamp lighting = false` makes normal maps look much better! + +Terrain +####### + +The terrain shader also supports normal, normal-height and specular maps, +with one difference compared to objects: +the specular value must be packed into the layer texture's alpha channel. + +For example, if you wanted to add specular mapping to a terrain layer called rock.dds, +you would copy this texture to a new file called rock_diffusespec.dds, +and then edit its alpha channel to set the specular intensity. + +The relevant settings are:: + + [Shaders] + auto use terrain normal maps = true + + auto use terrain specular maps = true + + terrain specular map pattern = _diffusespec + + # Also used for terrain normal maps + normal map pattern = _n + normal height map pattern = _nh + +OSG native files +################ + +OpenMW supports all the above shader features for meshes in the Native Mesh Format. +To have the shader generator recognize specific textures, +the `osg::Texture2D` must be named appropriately. + +Available texture types are the following (most of which also have NIF equivalents): + +:diffuseMap: base texture +:normalMap: normal map, as described earlier +:normalHeightMap: same as normal map, but including height information in alpha channel to be used for parallax effects +:emissiveMap: controls the material's emission, useful for objects that glow in the dark +:darkMap: multiplied onto the base texture +:detailMap: multiplied by 2 and then multiplied onto the base texture +:envMap: spherical environment map +:specularMap: specular map, as described earlier + +The first texture unit automatically acts as diffuseMap if no recognized type is specified. + +Example: `.osgt` file excerpt of a normal mapped mesh:: + + TextureModeList 2 { + Data 1 { + GL_TEXTURE_2D ON + } + Data 1 { + GL_TEXTURE_2D ON + } + } + TextureAttributeList 2 { + Data 1 { + osg::Texture2D { + UniqueID 37 + Name "diffuseMap" + WRAP_S REPEAT + WRAP_T REPEAT + WRAP_R REPEAT + MIN_FILTER LINEAR_MIPMAP_LINEAR + MAG_FILTER LINEAR + Image TRUE { + UniqueID 60 + FileName "textures/BuddhaStatue_Dif.jpg" + WriteHint 2 2 + } + } + Value OFF + } + Data 1 { + osg::Texture2D { + UniqueID 38 + Name "normalMap" + WRAP_S REPEAT + WRAP_T REPEAT + WRAP_R REPEAT + MIN_FILTER LINEAR_MIPMAP_LINEAR + MAG_FILTER LINEAR + Image TRUE { + UniqueID 61 + FileName "textures/BuddhaStatue_Nor.jpg" + WriteHint 2 2 + } + } + Value OFF + } + } + From 14d3b213a1a57af2baa31bfa3205f03c389186f5 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Sun, 8 Jul 2018 23:08:57 +0300 Subject: [PATCH 090/126] Fix double call of addContainerScripts on player in moveObject (fixes #4490) --- apps/openmw/mwworld/worldimp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 9de4da1ee..3ea364b77 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1166,7 +1166,10 @@ namespace MWWorld if (isPlayer) { if (!newCell->isExterior()) + { changeToInteriorCell(Misc::StringUtils::lowerCase(newCell->getCell()->mName), pos, false); + removeContainerScripts(getPlayerPtr()); + } else { if (mWorldScene->isCellActive(*newCell)) @@ -1187,9 +1190,8 @@ namespace MWWorld mWorldScene->addObjectToScene(newPtr); std::string script = newPtr.getClass().getScript(newPtr); - if (!script.empty()) { + if (!script.empty()) mLocalScripts.add(script, newPtr); - } addContainerScripts(newPtr, newCell); } else if (!newCellActive && currCellActive) From efcad5e7513afe7734000174557abb051f44c434 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Mon, 9 Jul 2018 08:58:01 +0000 Subject: [PATCH 091/126] Updates to the texture modding page There were some errors in the texture modding page about normal maps, so I did a quick change. Please do review if I made some errors, spelling or factual. --- .../reference/modding/texture-modding/texture-basics.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/source/reference/modding/texture-modding/texture-basics.rst b/docs/source/reference/modding/texture-modding/texture-basics.rst index 09bd9a7ec..82f1ada1c 100644 --- a/docs/source/reference/modding/texture-modding/texture-basics.rst +++ b/docs/source/reference/modding/texture-modding/texture-basics.rst @@ -19,13 +19,11 @@ OpenMW automatically uses shaders for objects with these mapping techniques. Normal Mapping ############## -To plug in a normal map, you can edit the NIF mesh file(s) using NifSkope -and assign the normal map texture to the BumpTexture slot in the NiTexturingProperty. +To plug in a normal map, you name the normal map as the diffuse texture but with a specified suffix after. OpenMW will then recognise the file and load it as a normal map, provided you have set up your settings file correctly. See the section `Automatic use`_ further down below for detailed information. .. note:: - While the original Morrowind engine does support the BumpTexture slot, - it uses a strange form of normal mapping that applies to an environment map. - OpenMW uses standard normal mapping, which can achieve much better results. + While the original Morrowind engine does support the loading of a BumpTexture slot in the NIF, it will not display it as a normal map. Morrowind Code Patch (MCP) added a way to hack normal maps into the engine by first enabling the engine to load the BumpTexture slot as an environment map and then turn down the brightness of the environment map. This will imitate how a real normal map shader would display a normal map, but it will not look exactly the same. + OpenMW uses standard normal mapping, which achieve much better results. Unfortunately, this difference can result in incompatibilities. Some mods (e.g. `Redoran Bump Mapped `_) From d09c327b203adf983f3cd48e586b956ef5c7f9d9 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Sun, 8 Jul 2018 23:13:24 +0300 Subject: [PATCH 092/126] Update changelog --- CHANGELOG.md | 6 ++++-- apps/openmw/mwworld/worldimp.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6bbcb96f..8017a253f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Bug #3997: Almalexia doesn't pace Bug #4036: Weird behaviour of AI packages if package target has non-unique ID Bug #4047: OpenMW not reporting its version number in MacOS; OpenMW-CS not doing it fully + Bug #4110: Fixed undo / redo menu text losing the assigned shortcuts Bug #4125: OpenMW logo cropped on bugtracker Bug #4215: OpenMW shows book text after last EOL tag Bug #4221: Characters get stuck in V-shaped terrain @@ -55,8 +56,9 @@ Bug #4474: No fallback when getVampireHead fails Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long - Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory - Bug #4110: Fixed undo / redo menu text losing the assigned shortcuts + Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory + Bug #4489: Goodbye doesn't block dialogue hyperlinks + Bug #4490: PositionCell on player gives "Error: tried to add local script twice" Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3ea364b77..5d554176a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1191,7 +1191,9 @@ namespace MWWorld std::string script = newPtr.getClass().getScript(newPtr); if (!script.empty()) + { mLocalScripts.add(script, newPtr); + } addContainerScripts(newPtr, newCell); } else if (!newCellActive && currCellActive) From ba15d0a8480470522156104d3f60d21b3fde2578 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Mon, 9 Jul 2018 10:19:32 +0000 Subject: [PATCH 093/126] Fixed spelling error --- .../source/reference/modding/texture-modding/texture-basics.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/reference/modding/texture-modding/texture-basics.rst b/docs/source/reference/modding/texture-modding/texture-basics.rst index 82f1ada1c..d9137c89d 100644 --- a/docs/source/reference/modding/texture-modding/texture-basics.rst +++ b/docs/source/reference/modding/texture-modding/texture-basics.rst @@ -23,7 +23,7 @@ To plug in a normal map, you name the normal map as the diffuse texture but with .. note:: While the original Morrowind engine does support the loading of a BumpTexture slot in the NIF, it will not display it as a normal map. Morrowind Code Patch (MCP) added a way to hack normal maps into the engine by first enabling the engine to load the BumpTexture slot as an environment map and then turn down the brightness of the environment map. This will imitate how a real normal map shader would display a normal map, but it will not look exactly the same. - OpenMW uses standard normal mapping, which achieve much better results. + OpenMW uses standard normal mapping, which achieves much better results. Unfortunately, this difference can result in incompatibilities. Some mods (e.g. `Redoran Bump Mapped `_) From 78a579991134f9c8f955484a87c0dea615012a4e Mon Sep 17 00:00:00 2001 From: Alexander Stillich Date: Mon, 9 Jul 2018 16:05:06 +0200 Subject: [PATCH 094/126] Issue a single dataChanged() when the modified column changes --- apps/opencs/model/world/idtable.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 0a2052fd8..cb48fc85f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -84,7 +84,6 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged(index, index); int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); if (stateColumn != -1) @@ -94,23 +93,19 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value // modifying the state column can modify other values. we need to tell // views that the whole row has changed. - int count = columnCount(index.parent()); - for (int i=0; iindex(index.row(), i); - emit dataChanged(columnIndex, columnIndex); - } - } + emit dataChanged(this->index(index.row(), 0), + this->index(index.row(), columnCount(index.parent()))); } else { + emit dataChanged(index, index); + // Modifying a value can also change the Modified status of a record. QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); } - } + } else + emit dataChanged(index, index); return true; } From 4780f1b2bdbe0559532bce98699c7c474c2b0d48 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 22:37:10 +0200 Subject: [PATCH 095/126] Notify views of changes of all cells in a row to properly update the row after revert --- apps/opencs/model/world/commands.cpp | 9 +++++++++ apps/opencs/model/world/idtable.cpp | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 79900c6c4..a572ca632 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -319,6 +319,15 @@ void CSMWorld::RevertCommand::redo() } else { + // notify view that data has changed, previously only the modified column was + // updated in the view unless the user had selected another item or forced a + // repaint with other means + int count = mModel.columnCount (index.parent ()); + if (count > 0) + { + emit mModel.dataChanged(mModel.index (index.row(), 0, index.parent ()), + mModel.index (index.row(), count - 1, index.parent ())); + } mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 3e503a80c..7492b6b17 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -86,9 +86,9 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value mIdCollection->setData (index.row(), index.column(), value); emit dataChanged(index, index); - // Modifying a value can also change the Modified status of a record. + // Modifying a value can also change the Modified status of a record unless . int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); - if (stateColumn != -1) + if (stateColumn != -1 && index.column() != stateColumn) { QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); From 143eadb58e2d4790a223385e9d0f6b1111c40b3e Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 23:21:55 +0200 Subject: [PATCH 096/126] Use setData() instead of emtitting dataChanged() which does not work on CI. Also Fixes the remaining issue with subviews not updating due to only the modified flag emitting a change, which prevented the widget mapper from working for updates. --- apps/opencs/model/world/commands.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index a572ca632..c67de6350 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -323,11 +323,16 @@ void CSMWorld::RevertCommand::redo() // updated in the view unless the user had selected another item or forced a // repaint with other means int count = mModel.columnCount (index.parent ()); - if (count > 0) + for (int i=0; i (RecordBase::State_BaseOnly)); } } From 4222b44dbbb71c66d24ea591723b2897378d1cb4 Mon Sep 17 00:00:00 2001 From: Doc West Date: Wed, 4 Jul 2018 23:25:24 +0200 Subject: [PATCH 097/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8017a253f..e51384a58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory Bug #4489: Goodbye doesn't block dialogue hyperlinks Bug #4490: PositionCell on player gives "Error: tried to add local script twice" + Bug #3249: Fixed revert function not updating views properly Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window From 4a6457c3464dc0b39090a3fc6ee4c1cdb74150b1 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 00:37:19 +0200 Subject: [PATCH 098/126] Changed the way the revert command works: it now clones the changed record and uses the new RecordBase::revert() method to restore the previous value Added Flag_Dialogue_Refresh to var type and var value columns so that sub views update properly --- apps/opencs/model/world/columnimp.hpp | 4 ++-- apps/opencs/model/world/commands.cpp | 20 +++++--------------- apps/opencs/model/world/commands.hpp | 1 + apps/opencs/model/world/record.hpp | 12 +++++++++++- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 4ad447b0a..cd2a4c79e 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -136,7 +136,7 @@ namespace CSMWorld struct VarTypeColumn : public Column { VarTypeColumn (ColumnBase::Display display) - : Column (Columns::ColumnId_ValueType, display) + : Column (Columns::ColumnId_ValueType, display, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} virtual QVariant get (const Record& record) const @@ -161,7 +161,7 @@ namespace CSMWorld template struct VarValueColumn : public Column { - VarValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Var) {} + VarValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Var, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} virtual QVariant get (const Record& record) const { diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index c67de6350..ff4bab989 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -294,16 +294,19 @@ void CSMWorld::CreateCommand::undo() } CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand* parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0), mNew (0) { setText (("Revert record " + id).c_str()); + mNew = model.getRecord(id).clone(); + mNew->revert(); mOld = model.getRecord (id).clone(); } CSMWorld::RevertCommand::~RevertCommand() { delete mOld; + delete mNew; } void CSMWorld::RevertCommand::redo() @@ -319,20 +322,7 @@ void CSMWorld::RevertCommand::redo() } else { - // notify view that data has changed, previously only the modified column was - // updated in the view unless the user had selected another item or forced a - // repaint with other means - int count = mModel.columnCount (index.parent ()); - for (int i=0; i (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 58a1b1d1c..46fa6d8a0 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -201,6 +201,7 @@ namespace CSMWorld IdTable& mModel; std::string mId; RecordBase *mOld; + RecordBase *mNew; // not implemented RevertCommand (const RevertCommand&); diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 0313f2e41..db5822c97 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -24,6 +24,8 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const = 0; + virtual void revert() = 0; + virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. @@ -49,6 +51,8 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const; + void revert() override; + virtual void assign (const RecordBase& record); const ESXRecordT& get() const; @@ -96,6 +100,12 @@ namespace CSMWorld return new Record (*this); } + template + void Record::revert() + { + mModified = mBase; + } + template void Record::assign (const RecordBase& record) { @@ -156,4 +166,4 @@ namespace CSMWorld } } -#endif \ No newline at end of file +#endif From 01b8ce5f7036f6b91c30d368255cb8b8c1d209ce Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 18:03:55 +0200 Subject: [PATCH 099/126] Notify views of changes in all columns when updating the ColumnId_Modification column --- apps/opencs/model/world/commands.cpp | 6 +----- apps/opencs/model/world/commands.hpp | 1 - apps/opencs/model/world/idtable.cpp | 26 ++++++++++++++++++++++---- apps/opencs/model/world/record.hpp | 10 ---------- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index ff4bab989..79900c6c4 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -294,19 +294,16 @@ void CSMWorld::CreateCommand::undo() } CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand* parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0), mNew (0) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) { setText (("Revert record " + id).c_str()); - mNew = model.getRecord(id).clone(); - mNew->revert(); mOld = model.getRecord (id).clone(); } CSMWorld::RevertCommand::~RevertCommand() { delete mOld; - delete mNew; } void CSMWorld::RevertCommand::redo() @@ -322,7 +319,6 @@ void CSMWorld::RevertCommand::redo() } else { - mModel.setRecord (mId, *mNew); mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); } } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 46fa6d8a0..58a1b1d1c 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -201,7 +201,6 @@ namespace CSMWorld IdTable& mModel; std::string mId; RecordBase *mOld; - RecordBase *mNew; // not implemented RevertCommand (const RevertCommand&); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 7492b6b17..75355116f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -86,12 +86,30 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value mIdCollection->setData (index.row(), index.column(), value); emit dataChanged(index, index); - // Modifying a value can also change the Modified status of a record unless . int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); - if (stateColumn != -1 && index.column() != stateColumn) + if (stateColumn != -1) { - QModelIndex stateIndex = this->index(index.row(), stateColumn); - emit dataChanged(stateIndex, stateIndex); + if (index.column() == stateColumn) + { + // modifying the state column can modify other values. we need to tell + // views that the whole row has changed. + + int count = columnCount(index.parent()); + for (int i=0; iindex(index.row(), i); + emit dataChanged(columnIndex, columnIndex); + } + } + + } else + { + // Modifying a value can also change the Modified status of a record unless . + QModelIndex stateIndex = this->index(index.row(), stateColumn); + emit dataChanged(stateIndex, stateIndex); + } } return true; diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index db5822c97..3362f9f96 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -24,8 +24,6 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const = 0; - virtual void revert() = 0; - virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. @@ -51,8 +49,6 @@ namespace CSMWorld virtual RecordBase *modifiedCopy() const; - void revert() override; - virtual void assign (const RecordBase& record); const ESXRecordT& get() const; @@ -100,12 +96,6 @@ namespace CSMWorld return new Record (*this); } - template - void Record::revert() - { - mModified = mBase; - } - template void Record::assign (const RecordBase& record) { From d26b5a13efe317b3c67dc3384e0ddeaafd4eaf30 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 18:10:43 +0200 Subject: [PATCH 100/126] Fixed comment --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 75355116f..0a2052fd8 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -106,7 +106,7 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value } else { - // Modifying a value can also change the Modified status of a record unless . + // Modifying a value can also change the Modified status of a record. QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); } From 1177e5ac799353b576c67132d242d86e6cf36fdf Mon Sep 17 00:00:00 2001 From: Alexander Stillich Date: Mon, 9 Jul 2018 16:05:06 +0200 Subject: [PATCH 101/126] Issue a single dataChanged() when the modified column changes --- apps/opencs/model/world/idtable.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 0a2052fd8..cb48fc85f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -84,7 +84,6 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged(index, index); int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); if (stateColumn != -1) @@ -94,23 +93,19 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value // modifying the state column can modify other values. we need to tell // views that the whole row has changed. - int count = columnCount(index.parent()); - for (int i=0; iindex(index.row(), i); - emit dataChanged(columnIndex, columnIndex); - } - } + emit dataChanged(this->index(index.row(), 0), + this->index(index.row(), columnCount(index.parent()))); } else { + emit dataChanged(index, index); + // Modifying a value can also change the Modified status of a record. QModelIndex stateIndex = this->index(index.row(), stateColumn); emit dataChanged(stateIndex, stateIndex); } - } + } else + emit dataChanged(index, index); return true; } From 467989cdd506bc9718f25d406ebdd3cc82092f77 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 22:55:19 +0200 Subject: [PATCH 102/126] Moved crashcatcher to a component and also use it in CS Reworked debugger detection (failed on gdb 7.11), it now uses /proc to detect the debugger --- apps/opencs/editor.cpp | 11 ++++- apps/opencs/editor.hpp | 2 +- apps/opencs/main.cpp | 4 +- apps/openmw/CMakeLists.txt | 4 +- apps/openmw/main.cpp | 26 +----------- cmake/OpenMWMacros.cmake | 2 +- components/CMakeLists.txt | 6 +++ .../crashcatcher}/crashcatcher.cpp | 40 +++++++++++++------ components/crashcatcher/crashcatcher.hpp | 18 +++++++++ 9 files changed, 68 insertions(+), 45 deletions(-) rename {apps/openmw => components/crashcatcher}/crashcatcher.cpp (93%) create mode 100644 components/crashcatcher/crashcatcher.hpp diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 35ce51337..2be3dc24c 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,9 @@ #include #include + +#include + #include #include @@ -18,12 +21,16 @@ using namespace Fallback; -CS::Editor::Editor () +CS::Editor::Editor (int argc, char **argv) : mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mPid(""), mLock(), mMerge (mDocumentManager), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) -{ +{ + // install the crash handler as soon as possible. note that the log path + // does not depend on config being read. + cc_install(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string()); + std::pair > config = readConfig(); setupDataFiles (config.first); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index b60f5c6a8..21199e2ca 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -66,7 +66,7 @@ namespace CS public: - Editor (); + Editor (int argc, char **argv); ~Editor (); bool makeIPCServer(); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index fc5e8fc7a..d599f1f96 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) #endif try - { + { // To allow background thread drawing in OSG QApplication::setAttribute(Qt::AA_X11InitThreads, true); @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) application.setWindowIcon (QIcon (":./openmw-cs.png")); - CS::Editor editor; + CS::Editor editor(argc, argv); if(!editor.makeIPCServer()) { diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e64998077..e8a958d45 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -11,12 +11,10 @@ if (ANDROID) set(GAME ${GAME} android_main.c) endif() -if(NOT WIN32 AND NOT ANDROID) - set(GAME ${GAME} crashcatcher.cpp) -endif() set(GAME_HEADER engine.hpp ) + source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 109610b1e..db095c73d 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -24,18 +25,6 @@ #include #endif -#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) - #define USE_CRASH_CATCHER 1 -#else - #define USE_CRASH_CATCHER 0 -#endif - -#if USE_CRASH_CATCHER -#include -extern int cc_install_handlers(int argc, char **argv, int num_signals, int *sigs, const char *logfile, int (*user_info)(char*, char*)); -extern int is_debugger_attached(void); -#endif - /** * Workaround for problems with whitespaces in paths in older versions of Boost library */ @@ -339,18 +328,7 @@ int main(int argc, char**argv) std::cerr.rdbuf (&cerrsb); #endif - -#if USE_CRASH_CATCHER - // Unix crash catcher - if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached()) - { - int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; - cc_install_handlers(argc, argv, 5, s, (cfgMgr.getLogPath() / "crash.log").string().c_str(), NULL); - std::cout << "Installing crash catcher" << std::endl; - } - else - std::cout << "Running in a debugger, not installing crash catcher" << std::endl; -#endif + cc_install(argc, argv, (cfgMgr.getLogPath() / "crash.log").string()); #ifdef __APPLE__ boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 2fa86094f..f385437b4 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -204,4 +204,4 @@ macro (copy_all_resource_files source_dir destination_dir_base destination_dir_r get_filename_component(filename ${f} NAME) copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${filename}") endforeach (f) -endmacro (copy_all_resource_files) \ No newline at end of file +endmacro (copy_all_resource_files) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 3efd236cb..b6f390b06 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -145,6 +145,12 @@ add_component_dir (fallback fallback validate ) +if(NOT WIN32 AND NOT ANDROID) + add_component_dir (crashcatcher + crashcatcher + ) +endif() + set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) diff --git a/apps/openmw/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp similarity index 93% rename from apps/openmw/crashcatcher.cpp rename to components/crashcatcher/crashcatcher.cpp index 0078ef169..6aeed114c 100644 --- a/apps/openmw/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -14,7 +14,11 @@ #include #include -#include +#include + +#include + +namespace bfs = boost::filesystem; #include @@ -454,19 +458,31 @@ int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, co return retval; } - -// gdb apparently opens FD(s) 3,4,5 (whereas a typical prog uses only stdin=0, stdout=1,stderr=2) -bool -is_debugger_attached(void) +static bool is_debugger_present() { - bool rc = false; - FILE *fd = fopen("/tmp", "r"); - - if (fileno(fd) > 5) + bfs::ifstream file((bfs::path("/proc/self/status"))); + while (!file.eof()) { - rc = true; + std::string word; + file >> word; + if (word == "TracerPid:") + { + file >> word; + return word != "0"; + } } + return false; +} - fclose(fd); - return rc; +void cc_install(int argc, char **argv, const std::string &crashLogPath) +{ + if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_present()) + { + int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; + if (cc_install_handlers(argc, argv, 5, s, crashLogPath.c_str(), NULL) == -1) + { + std::cerr << "Installing crash handler failed" << std::endl; + } else + std::cout << "Crash handler installed" << std::endl; + } } diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp new file mode 100644 index 000000000..3d5d61a9f --- /dev/null +++ b/components/crashcatcher/crashcatcher.hpp @@ -0,0 +1,18 @@ +#ifndef CRASHCATCHER_H +#define CRASHCATCHER_H + +#include + +#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) + #define USE_CRASH_CATCHER 1 +#else + #define USE_CRASH_CATCHER 0 +#endif + +#if USE_CRASH_CATCHER +extern void cc_install(int argc, char **argv, const std::string &crashLogPath); +#else +inline void cc_install(int, char **) { return 0; } +#endif + +#endif From a6f962156ce4365deb69514b970d938d07a2a9f3 Mon Sep 17 00:00:00 2001 From: Doc West Date: Thu, 5 Jul 2018 22:59:29 +0200 Subject: [PATCH 103/126] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8017a253f..b33f90675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier + Feature #4012: Editor: write a log file if OpenCS crashes 0.44.0 ------ From d4d207717471f48b25cfad8713eb6791c666bbba Mon Sep 17 00:00:00 2001 From: Alex S Date: Fri, 6 Jul 2018 08:14:26 +0000 Subject: [PATCH 104/126] Fixed changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b33f90675..37bb8d7b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,7 +69,7 @@ Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier - Feature #4012: Editor: write a log file if OpenCS crashes + Feature #4012: Editor: Write a log file if OpenCS crashes 0.44.0 ------ From 725cc94210a7e8c5c0b52daaa4f66f12416cb5a4 Mon Sep 17 00:00:00 2001 From: Alexander Stillich Date: Mon, 9 Jul 2018 16:20:49 +0200 Subject: [PATCH 105/126] Renamed cc_install to something less cryptic (crashCatcherInstall) --- apps/opencs/editor.cpp | 2 +- apps/openmw/main.cpp | 2 +- components/crashcatcher/crashcatcher.cpp | 6 +++--- components/crashcatcher/crashcatcher.hpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 2be3dc24c..6ca10e0f6 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -29,7 +29,7 @@ CS::Editor::Editor (int argc, char **argv) { // install the crash handler as soon as possible. note that the log path // does not depend on config being read. - cc_install(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string()); + crashCatcherInstall(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string()); std::pair > config = readConfig(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index db095c73d..d13a73127 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -328,7 +328,7 @@ int main(int argc, char**argv) std::cerr.rdbuf (&cerrsb); #endif - cc_install(argc, argv, (cfgMgr.getLogPath() / "crash.log").string()); + crashCatcherInstall(argc, argv, (cfgMgr.getLogPath() / "crash.log").string()); #ifdef __APPLE__ boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); diff --git a/components/crashcatcher/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp index 6aeed114c..af42eb695 100644 --- a/components/crashcatcher/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -406,7 +406,7 @@ static void crash_handler(const char *logfile) exit(0); } -int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) +int crashCatcherInstallHandlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) { struct sigaction sa; stack_t altss; @@ -474,12 +474,12 @@ static bool is_debugger_present() return false; } -void cc_install(int argc, char **argv, const std::string &crashLogPath) +void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath) { if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_present()) { int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; - if (cc_install_handlers(argc, argv, 5, s, crashLogPath.c_str(), NULL) == -1) + if (crashCatcherInstallHandlers(argc, argv, 5, s, crashLogPath.c_str(), NULL) == -1) { std::cerr << "Installing crash handler failed" << std::endl; } else diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp index 3d5d61a9f..e2390df9c 100644 --- a/components/crashcatcher/crashcatcher.hpp +++ b/components/crashcatcher/crashcatcher.hpp @@ -10,9 +10,9 @@ #endif #if USE_CRASH_CATCHER -extern void cc_install(int argc, char **argv, const std::string &crashLogPath); +extern void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath); #else -inline void cc_install(int, char **) { return 0; } +inline void crashCatcherInstall(int, char **, const std::string &crashLogPath) { return 0; } #endif #endif From 48296a7452094a7da4aedc6a00ee55a2290bdbbe Mon Sep 17 00:00:00 2001 From: terrabyte25 Date: Mon, 9 Jul 2018 23:13:52 +0400 Subject: [PATCH 106/126] Update trainingwindow.cpp --- apps/openmw/mwgui/trainingwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 04b051e16..ad925bbff 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -80,7 +80,7 @@ namespace MWGui for (int i=0; i Date: Mon, 9 Jul 2018 21:51:38 +0400 Subject: [PATCH 107/126] Make void function to do not return value --- components/crashcatcher/crashcatcher.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp index e2390df9c..fd8f0d154 100644 --- a/components/crashcatcher/crashcatcher.hpp +++ b/components/crashcatcher/crashcatcher.hpp @@ -12,7 +12,9 @@ #if USE_CRASH_CATCHER extern void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath); #else -inline void crashCatcherInstall(int, char **, const std::string &crashLogPath) { return 0; } +inline void crashCatcherInstall(int, char **, const std::string &crashLogPath) +{ +} #endif #endif From 27a5da59baa005f8b645b97fbc138b4ea015aa1d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 10 Jul 2018 10:05:13 +0400 Subject: [PATCH 108/126] Fix MSVC warnings C4456 --- apps/mwiniimporter/importer.cpp | 3 +-- apps/opencs/view/render/object.cpp | 4 ++-- apps/opencs/view/render/worldspacewidget.cpp | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 6f5c2e2cd..4fbe97720 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -874,7 +874,6 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co { std::vector> contentFiles; std::string baseGameFile("Game Files:GameFile"); - std::string gameFile(""); std::time_t defaultTime = 0; ToUTF8::Utf8Encoder encoder(mEncoding); @@ -890,7 +889,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co multistrmap::const_iterator it = ini.begin(); for (int i=0; it != ini.end(); i++) { - gameFile = baseGameFile; + std::string gameFile = baseGameFile; gameFile.append(std::to_string(i)); it = ini.find(gameFile); diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index dae6467c5..204bf4c2f 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -372,10 +372,10 @@ osg::ref_ptr CSVRender::Object::makeRotateMarker (int axis) indices[j] -= VertexCount; } - size_t offset = i * IndicesPerSegment; + size_t elementOffset = i * IndicesPerSegment; for (size_t j = 0; j < IndicesPerSegment; ++j) { - primitives->setElement(offset++, indices[IndexPattern[j]]); + primitives->setElement(elementOffset++, indices[IndexPattern[j]]); } } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 084fb87e6..5b825fab1 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -651,7 +651,6 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) if (mDragMode == InteractionType_PrimaryEdit) { - EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); editMode.drag (event->pos(), mDragX, mDragY, mDragFactor); // note: terraintexturemode only uses pos } } From c921d1c7e91bd37048f33b491fadcaede007cf2c Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 10 Jul 2018 13:32:52 +0400 Subject: [PATCH 109/126] Refactor NifStream class (eliminate LNK4221 MSVC warning) --- components/nif/nifstream.cpp | 24 +++++++-- components/nif/nifstream.hpp | 99 ++++++++++++++++++++---------------- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 08a7466fa..3811d05ee 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -4,10 +4,24 @@ namespace Nif { + osg::Quat NIFStream::getQuaternion() + { + float f[4]; + readLittleEndianBufferOfType<4, float,uint32_t>(inp, (float*)&f); + osg::Quat quat; + quat.w() = f[0]; + quat.x() = f[1]; + quat.y() = f[2]; + quat.z() = f[3]; + return quat; + } -//Private functions - - -//Public functions - + Transformation NIFStream::getTrafo() + { + Transformation t; + t.pos = getVector3(); + t.rotation = getMatrix3(); + t.scale = getFloat(); + return t; + } } diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index d00069be7..0fdf4b440 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -80,8 +80,8 @@ template type inline readLittleEndianType(File return val; } -class NIFStream { - +class NIFStream +{ /// Input stream Files::IStreamPtr inp; @@ -93,71 +93,71 @@ public: void skip(size_t size) { inp->ignore(size); } - char getChar() + char getChar() { - return readLittleEndianType(inp); + return readLittleEndianType(inp); } - short getShort() - { + + short getShort() + { return readLittleEndianType(inp); } - unsigned short getUShort() - { + + unsigned short getUShort() + { return readLittleEndianType(inp); } - int getInt() + + int getInt() { return readLittleEndianType(inp); } - unsigned int getUInt() - { + + unsigned int getUInt() + { return readLittleEndianType(inp); } - float getFloat() - { + + float getFloat() + { return readLittleEndianType(inp); } - osg::Vec2f getVector2() { + osg::Vec2f getVector2() + { osg::Vec2f vec; readLittleEndianBufferOfType<2,float,uint32_t>(inp, (float*)&vec._v[0]); return vec; } - osg::Vec3f getVector3() { + + osg::Vec3f getVector3() + { osg::Vec3f vec; readLittleEndianBufferOfType<3, float,uint32_t>(inp, (float*)&vec._v[0]); return vec; } - osg::Vec4f getVector4() { + + osg::Vec4f getVector4() + { osg::Vec4f vec; readLittleEndianBufferOfType<4, float,uint32_t>(inp, (float*)&vec._v[0]); return vec; } - Matrix3 getMatrix3() { + + Matrix3 getMatrix3() + { Matrix3 mat; readLittleEndianBufferOfType<9, float,uint32_t>(inp, (float*)&mat.mValues); return mat; } - osg::Quat getQuaternion() { - float f[4]; - readLittleEndianBufferOfType<4, float,uint32_t>(inp, (float*)&f); - osg::Quat quat; - quat.w() = f[0]; - quat.x() = f[1]; - quat.y() = f[2]; - quat.z() = f[3]; - return quat; - } - Transformation getTrafo() { - Transformation t; - t.pos = getVector3(); - t.rotation = getMatrix3(); - t.scale = getFloat(); - return t; - } + + osg::Quat getQuaternion(); + + Transformation getTrafo(); ///Read in a string of the given length - std::string getString(size_t length) { + std::string getString(size_t length) + { std::vector str(length + 1, 0); inp->read(&str[0], length); @@ -165,41 +165,54 @@ public: return &str[0]; } ///Read in a string of the length specified in the file - std::string getString() { + std::string getString() + { size_t size = readLittleEndianType(inp); return getString(size); } ///This is special since the version string doesn't start with a number, and ends with "\n" - std::string getVersionString() { + std::string getVersionString() + { std::string result; std::getline(*inp, result); return result; } - void getUShorts(std::vector &vec, size_t size) { + void getUShorts(std::vector &vec, size_t size) + { vec.resize(size); readLittleEndianDynamicBufferOfType(inp, &vec.front(), size); } - void getFloats(std::vector &vec, size_t size) { + + void getFloats(std::vector &vec, size_t size) + { vec.resize(size); readLittleEndianDynamicBufferOfType(inp, &vec.front(), size); } - void getVector2s(std::vector &vec, size_t size) { + + void getVector2s(std::vector &vec, size_t size) + { vec.resize(size); /* The packed storage of each Vec2f is 2 floats exactly */ readLittleEndianDynamicBufferOfType(inp,(float*) &vec.front(), size*2); } - void getVector3s(std::vector &vec, size_t size) { + + void getVector3s(std::vector &vec, size_t size) + { vec.resize(size); /* The packed storage of each Vec3f is 3 floats exactly */ readLittleEndianDynamicBufferOfType(inp, (float*) &vec.front(), size*3); } - void getVector4s(std::vector &vec, size_t size) { + + void getVector4s(std::vector &vec, size_t size) + { vec.resize(size); /* The packed storage of each Vec4f is 4 floats exactly */ readLittleEndianDynamicBufferOfType(inp, (float*) &vec.front(), size*4); } - void getQuaternions(std::vector &quat, size_t size) { + + void getQuaternions(std::vector &quat, size_t size) + { quat.resize(size); for (size_t i = 0;i < quat.size();i++) quat[i] = getQuaternion(); From 7fd66c77e6da50b94a0b8fcb6d52e849c536254e Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Mon, 9 Jul 2018 23:04:45 +0300 Subject: [PATCH 110/126] Update CMake lists for Windows Don't use the debug console on Release-mode builds Disable spammy 4297 and 5032 warnings that are not specific to OpenMW --- CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15ca3efb3..f42014951 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,10 +610,10 @@ if (WIN32) endif() if (BUILD_OPENMW) - # Release builds use the debug console - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE") - set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") - set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE") + # Release builds don't use the debug console + set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") + set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_WINDOWS") + set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") endif() # Play a bit with the warning levels @@ -642,9 +642,11 @@ if (WIN32) # caused by boost 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) + 5032 # detected #pragma warning(push) with no corresponding #pragma warning(pop) # caused by MyGUI 4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception' + 4297 # function assumed not to throw an exception but does # OpenMW specific warnings 4099 # Type mismatch, declared class or struct is defined with other type From 21403f892026e26f87b739f6cc67bae03d759f38 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Mon, 9 Jul 2018 23:08:29 +0300 Subject: [PATCH 111/126] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f7e4e095..140d6daf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier Feature #4012: Editor: Write a log file if OpenCS crashes + Task #2490: Don't open command prompt window on Release-mode builds automatically 0.44.0 ------ From d000f2756e7421437ef50cce171abc5717a98875 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Tue, 10 Jul 2018 13:02:03 +0300 Subject: [PATCH 112/126] Update disabled warnings --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f42014951..678f3e16b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -624,7 +624,8 @@ if (WIN32) # Warnings that aren't enabled normally and don't need to be enabled # They're unneeded and sometimes completely retarded warnings that /Wall enables # Not going to bother commenting them as they tend to warn on every standard library file - 4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625 4626 4628 4640 4668 4710 4711 4820 4826 4917 4946 + 4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625 + 4626 4628 4640 4668 4710 4711 4768 4820 4826 4917 4946 5032 5039 5045 # Warnings that are thrown on standard libraries and not OpenMW 4347 # Non-template function with same name and parameter count as template function @@ -642,7 +643,6 @@ if (WIN32) # caused by boost 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) - 5032 # detected #pragma warning(push) with no corresponding #pragma warning(pop) # caused by MyGUI 4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception' From 75dcbea36545fd564fd98561988cb423342d44a4 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 22 Jun 2018 13:09:02 +0400 Subject: [PATCH 113/126] Apply weapon reload animations only for upper body --- apps/openmw/mwmechanics/character.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index e6a8e8152..ef158a258 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1627,16 +1627,18 @@ bool CharacterController::updateWeaponState() break; } + // Note: apply reload animations only for upper body since blending with movement animations can give weird result. + // Especially noticable with crossbow reload animation. if(!start.empty()) { mAnimation->disable(mCurrentWeapon); if (mUpperBodyState == UpperCharState_FollowStartToFollowStop) mAnimation->play(mCurrentWeapon, priorityWeapon, - MWRender::Animation::BlendMask_All, true, + MWRender::Animation::BlendMask_UpperBody, true, weapSpeed, start, stop, 0.0f, 0); else mAnimation->play(mCurrentWeapon, priorityWeapon, - MWRender::Animation::BlendMask_All, false, + MWRender::Animation::BlendMask_UpperBody, false, weapSpeed, start, stop, 0.0f, 0); } } From 1c35e20fcc4d140e1fdabdc84d47e16263926d81 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 22 Jun 2018 18:40:49 +0400 Subject: [PATCH 114/126] Use 1h animations as fallback for crossbows --- CHANGELOG.md | 3 ++- apps/openmw/mwmechanics/character.cpp | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 140d6daf3..26f51d057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Bug #2852: No murder bounty when a player follower commits murder Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y + Bug #3249: Fixed revert function not updating views properly Bug #3374: Touch spells not hitting kwama foragers Bug #3486: [Mod] NPC Commands does not work Bug #3591: Angled hit distance too low @@ -59,7 +60,7 @@ Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory Bug #4489: Goodbye doesn't block dialogue hyperlinks Bug #4490: PositionCell on player gives "Error: tried to add local script twice" - Bug #3249: Fixed revert function not updating views properly + Bug #4495: Crossbow animations blending is buggy Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ef158a258..c6114dd8c 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -370,6 +370,10 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState { jumpmask = MWRender::Animation::BlendMask_LowerBody; jumpAnimName = "jump"; + + // For crossbow animations use 1h ones as fallback + if (mWeaponType == WeapType_Crossbow) + jumpAnimName += "1h"; } } } @@ -423,6 +427,10 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character { movemask = MWRender::Animation::BlendMask_LowerBody; movementAnimName = movestate->groupname; + + // For crossbow animations use 1h ones as fallback + if (mWeaponType == WeapType_Crossbow) + movementAnimName += "1h"; } } From 76fa8a163d8fda9f297d59f9b342b07ee8363514 Mon Sep 17 00:00:00 2001 From: terrabyte25 Date: Tue, 10 Jul 2018 17:09:14 +0400 Subject: [PATCH 115/126] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f7e4e095..4d6ec252f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory Bug #4489: Goodbye doesn't block dialogue hyperlinks Bug #4490: PositionCell on player gives "Error: tried to add local script twice" + Bug #4491: Training cap based off Base Skill instead of Modified Skill Bug #3249: Fixed revert function not updating views properly Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results From 5cb9dc9d12d892431a3b0db472de549ee1ae3c36 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 10 Jul 2018 22:19:56 +0300 Subject: [PATCH 116/126] Use SpellTurnLeft/TurnRight animation groups --- apps/openmw/mwmechanics/character.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c6114dd8c..c36129c4e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -422,7 +422,10 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character movementAnimName = movestate->groupname; if(weap != sWeaponTypeListEnd && movementAnimName.find("swim") == std::string::npos) { - movementAnimName += weap->shortgroup; + if (mWeaponType == WeapType_Spell && (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)) // Spellcasting stance turning is a special case + movementAnimName = weap->shortgroup + movementAnimName; + else + movementAnimName += weap->shortgroup; if(!mAnimation->hasAnimation(movementAnimName)) { movemask = MWRender::Animation::BlendMask_LowerBody; From 3186edc63084f17a566fa52628190731b5418052 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Tue, 10 Jul 2018 22:22:20 +0300 Subject: [PATCH 117/126] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44c7398ba..470dd921b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,7 +61,8 @@ Bug #4489: Goodbye doesn't block dialogue hyperlinks Bug #4490: PositionCell on player gives "Error: tried to add local script twice" Bug #4491: Training cap based off Base Skill instead of Modified Skill - Bug #4495: Crossbow animations blending is buggy + Bug #4495: Crossbow animations blending is buggy + Bug #4496: SpellTurnLeft and SpellTurnRight animation groups are unused Bug #3249: Fixed revert function not updating views properly Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results From c77c50e92b3c9e7570e1f5b647a34f076636fdec Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 9 Jul 2018 19:31:40 +0400 Subject: [PATCH 118/126] Make Equip console command to bypass most of restrictions (bug #4460) --- CHANGELOG.md | 1 + apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwclass/apparatus.cpp | 5 ++- apps/openmw/mwclass/apparatus.hpp | 3 +- apps/openmw/mwclass/armor.cpp | 4 +-- apps/openmw/mwclass/armor.hpp | 3 +- apps/openmw/mwclass/book.cpp | 2 +- apps/openmw/mwclass/book.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 4 +-- apps/openmw/mwclass/clothing.hpp | 3 +- apps/openmw/mwclass/ingredient.cpp | 2 +- apps/openmw/mwclass/ingredient.hpp | 3 +- apps/openmw/mwclass/light.cpp | 4 +-- apps/openmw/mwclass/light.hpp | 3 +- apps/openmw/mwclass/lockpick.cpp | 4 +-- apps/openmw/mwclass/lockpick.hpp | 3 +- apps/openmw/mwclass/misc.cpp | 2 +- apps/openmw/mwclass/misc.hpp | 3 +- apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwclass/potion.hpp | 2 +- apps/openmw/mwclass/probe.cpp | 4 +-- apps/openmw/mwclass/probe.hpp | 3 +- apps/openmw/mwclass/repair.cpp | 4 +-- apps/openmw/mwclass/repair.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 4 +-- apps/openmw/mwclass/weapon.hpp | 3 +- apps/openmw/mwgui/inventorywindow.cpp | 26 ++++++++++----- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 4 +-- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 8 ++--- apps/openmw/mwworld/actionalchemy.cpp | 9 +++++- apps/openmw/mwworld/actionalchemy.hpp | 6 +++- apps/openmw/mwworld/actionequip.cpp | 33 ++++++++++++++------ apps/openmw/mwworld/actionequip.hpp | 11 ++++--- apps/openmw/mwworld/actionrepair.cpp | 8 +++-- apps/openmw/mwworld/actionrepair.hpp | 7 +++-- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 39 files changed, 114 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8017a253f..16c49c6a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ Bug #4457: Item without CanCarry flag prevents shield autoequipping in dark areas Bug #4458: AiWander console command handles idle chances incorrectly Bug #4459: NotCell dialogue condition doesn't support partial matches + Bug #4460: Script function "Equip" doesn't bypass beast restrictions Bug #4461: "Open" spell from non-player caster isn't a crime Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index d454067c8..39eed5537 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -146,7 +146,7 @@ namespace MWBase virtual MWGui::TradeWindow* getTradeWindow() = 0; /// Make the player use an item, while updating GUI state accordingly - virtual void useItem(const MWWorld::Ptr& item) = 0; + virtual void useItem(const MWWorld::Ptr& item, bool force=false) = 0; virtual void updateSpellWindow() = 0; diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index a271dc5e9..e151e39c5 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -124,10 +124,9 @@ namespace MWClass return info; } - - std::shared_ptr Apparatus::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Apparatus::use (const MWWorld::Ptr& ptr, bool force) const { - return std::shared_ptr(new MWWorld::ActionAlchemy()); + return std::shared_ptr(new MWWorld::ActionAlchemy(force)); } MWWorld::Ptr Apparatus::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 539c1068b..e9b645763 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -50,8 +50,7 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; ///< Return name of inventory icon. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 460cd517a..0d267046f 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -354,9 +354,9 @@ namespace MWClass return std::make_pair(1,""); } - std::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Armor::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 628ac1b88..6b098fa9a 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -73,8 +73,7 @@ namespace MWClass ///< 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 /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 3d6455dc6..4b5ca2ee7 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -162,7 +162,7 @@ namespace MWClass return record->mId; } - std::shared_ptr Book::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Book::use (const MWWorld::Ptr& ptr, bool force) const { return std::shared_ptr(new MWWorld::ActionRead(ptr)); } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 82ca08a4d..4cb51ff58 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -53,7 +53,7 @@ namespace MWClass virtual std::string applyEnchantment(const MWWorld::ConstPtr &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::shared_ptr use (const MWWorld::Ptr& ptr) const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index b37d1e90b..027882304 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -243,9 +243,9 @@ namespace MWClass return std::make_pair (1, ""); } - std::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Clothing::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 202b6596e..81b5c2ef4 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -65,8 +65,7 @@ namespace MWClass ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 09d149331..df7c61ebf 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -75,7 +75,7 @@ namespace MWClass } - std::shared_ptr Ingredient::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Ingredient::use (const MWWorld::Ptr& ptr, bool force) const { std::shared_ptr action (new MWWorld::ActionEat (ptr)); diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 1136eb50f..668fea29a 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -36,8 +36,7 @@ namespace MWClass virtual int getValue (const MWWorld::ConstPtr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu static void registerSelf(); diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index aeeb89a72..27a9f3f2b 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -186,9 +186,9 @@ namespace MWClass return Class::showsInInventory(ptr); } - std::shared_ptr Light::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Light::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 59085d97e..013b9eee3 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -55,8 +55,7 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; ///< Return name of inventory icon. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 15499c1a8..5673465a0 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -140,9 +140,9 @@ namespace MWClass return info; } - std::shared_ptr Lockpick::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Lockpick::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 1bcf7fb85..c8df860f6 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -53,8 +53,7 @@ namespace MWClass virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 62b15bc86..40ec2b34b 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -226,7 +226,7 @@ namespace MWClass return newPtr; } - std::shared_ptr Miscellaneous::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Miscellaneous::use (const MWWorld::Ptr& ptr, bool force) const { if (ptr.getCellRef().getSoul().empty() || !MWBase::Environment::get().getWorld()->getStore().get().search(ptr.getCellRef().getSoul())) return std::shared_ptr(new MWWorld::NullAction()); diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 37e77860b..77e7d105b 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -49,8 +49,7 @@ namespace MWClass virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual float getWeight (const MWWorld::ConstPtr& ptr) const; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index ffdccf438..39b1cc6c2 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -139,7 +139,7 @@ namespace MWClass return info; } - std::shared_ptr Potion::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Potion::use (const MWWorld::Ptr& ptr, bool force) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index ad9a329c0..90dbe5281 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -36,7 +36,7 @@ namespace MWClass virtual int getValue (const MWWorld::ConstPtr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu static void registerSelf(); diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 030ee3f8b..734b6b1fd 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -140,9 +140,9 @@ namespace MWClass return info; } - std::shared_ptr Probe::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Probe::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 9ac3ab0c9..86f6f677a 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -53,8 +53,7 @@ namespace MWClass virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 566d16106..7cd7ef10d 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -149,9 +149,9 @@ namespace MWClass return MWWorld::Ptr(cell.insert(ref), &cell); } - std::shared_ptr Repair::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Repair::use (const MWWorld::Ptr& ptr, bool force) const { - return std::shared_ptr(new MWWorld::ActionRepair(ptr)); + return std::shared_ptr(new MWWorld::ActionRepair(ptr, force)); } bool Repair::canSell (const MWWorld::ConstPtr& item, int npcServices) const diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 34ba4035b..f60dbad90 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -49,7 +49,7 @@ namespace MWClass virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu (default implementation: return a /// null action). diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index e59567aac..bb1ca09a3 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -401,9 +401,9 @@ namespace MWClass return std::make_pair(1, ""); } - std::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const + std::shared_ptr Weapon::use (const MWWorld::Ptr& ptr, bool force) const { - std::shared_ptr action(new MWWorld::ActionEquip(ptr)); + std::shared_ptr action(new MWWorld::ActionEquip(ptr, force)); action->setSound(getUpSoundId(ptr)); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index c14847363..423ba0dd2 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -72,8 +72,7 @@ namespace MWClass ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr) - const; + virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4acf61d93..e909ecbba 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -25,7 +25,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" -#include "../mwworld/action.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwscript/interpretercontext.hpp" #include "../mwmechanics/actorutil.hpp" @@ -474,7 +474,7 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory); } - void InventoryWindow::useItem(const MWWorld::Ptr &ptr) + void InventoryWindow::useItem(const MWWorld::Ptr &ptr, bool force) { const std::string& script = ptr.getClass().getScript(ptr); @@ -483,13 +483,24 @@ namespace MWGui // early-out for items that need to be equipped, but can't be equipped: we don't want to set OnPcEquip in that case if (!ptr.getClass().getEquipmentSlots(ptr).first.empty()) { - std::pair canEquip = ptr.getClass().canBeEquipped(ptr, player); - if (canEquip.first == 0) + if (ptr.getClass().hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0) { - MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second); + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}"); updateItemView(); return; } + + if (!force) + { + std::pair canEquip = ptr.getClass().canBeEquipped(ptr, player); + + if (canEquip.first == 0) + { + MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second); + updateItemView(); + return; + } + } } // If the item has a script, set its OnPcEquip to 1 @@ -512,9 +523,8 @@ namespace MWGui { if (script.empty() || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 0) { - std::shared_ptr action = ptr.getClass().use(ptr); - - action->execute (player); + std::shared_ptr action = ptr.getClass().use(ptr, force); + action->execute(player); } else mSkippedToEquip = ptr; diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 5576b52ed..124fe7b0e 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -58,7 +58,7 @@ namespace MWGui void clear(); - void useItem(const MWWorld::Ptr& ptr); + void useItem(const MWWorld::Ptr& ptr, bool force=false); void setGuiMode(GuiMode mode); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 927bee88b..df2d5ed6d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1328,10 +1328,10 @@ namespace MWGui MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } - void WindowManager::useItem(const MWWorld::Ptr &item) + void WindowManager::useItem(const MWWorld::Ptr &item, bool bypassBeastRestrictions) { if (mInventoryWindow) - mInventoryWindow->useItem(item); + mInventoryWindow->useItem(item, bypassBeastRestrictions); } bool WindowManager::isAllowed (GuiWindow wnd) const diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 1d250f6d4..657548397 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -185,7 +185,7 @@ namespace MWGui virtual MWGui::TradeWindow* getTradeWindow(); /// Make the player use an item, while updating GUI state accordingly - virtual void useItem(const MWWorld::Ptr& item); + virtual void useItem(const MWWorld::Ptr& item, bool bypassBeastRestrictions=false); virtual void updateSpellWindow(); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 8457b33cb..0feadaa59 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -20,6 +20,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/inventorystore.hpp" @@ -193,12 +194,11 @@ namespace MWScript "to fulfil requirements of Equip instruction" << std::endl; } - if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) - MWBase::Environment::get().getWindowManager()->useItem(*it); + if (ptr == MWMechanics::getPlayer()) + MWBase::Environment::get().getWindowManager()->useItem(*it, true); else { - std::shared_ptr action = it->getClass().use(*it); - // No equip sound for actors other than the player + std::shared_ptr action = it->getClass().use(*it, true); action->execute(ptr, true); } } diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index 53ed1ad84..37d811eb6 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -9,12 +9,19 @@ namespace MWWorld { + ActionAlchemy::ActionAlchemy(bool force) + : Action (false) + , mForce(force) + { + } + void ActionAlchemy::executeImp (const Ptr& actor) { if (actor != MWMechanics::getPlayer()) return; - if(MWMechanics::isPlayerInCombat()) { //Ensure we're not in combat + if(!mForce && MWMechanics::isPlayerInCombat()) + { //Ensure we're not in combat MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage3}"); return; } diff --git a/apps/openmw/mwworld/actionalchemy.hpp b/apps/openmw/mwworld/actionalchemy.hpp index e6d1a7976..0f79d5c2d 100644 --- a/apps/openmw/mwworld/actionalchemy.hpp +++ b/apps/openmw/mwworld/actionalchemy.hpp @@ -7,7 +7,11 @@ namespace MWWorld { class ActionAlchemy : public Action { - virtual void executeImp (const Ptr& actor); + bool mForce; + virtual void executeImp (const Ptr& actor); + + public: + ActionAlchemy(bool force=false); }; } diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index a6d6eef2b..da794bcd2 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -14,7 +14,9 @@ namespace MWWorld { - ActionEquip::ActionEquip (const MWWorld::Ptr& object) : Action (false, object) + ActionEquip::ActionEquip (const MWWorld::Ptr& object, bool force) + : Action (false, object) + , mForce(force) { } @@ -23,18 +25,29 @@ namespace MWWorld MWWorld::Ptr object = getTarget(); MWWorld::InventoryStore& invStore = actor.getClass().getInventoryStore(actor); - std::pair result = object.getClass().canBeEquipped (object, actor); + if (object.getClass().hasItemHealth(object) && object.getCellRef().getCharge() == 0) + { + if (actor == MWMechanics::getPlayer()) + MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}"); - // display error message if the player tried to equip something - if (!result.second.empty() && actor == MWMechanics::getPlayer()) - MWBase::Environment::get().getWindowManager()->messageBox(result.second); + return; + } - switch(result.first) + if (!mForce) { - case 0: - return; - default: - break; + std::pair result = object.getClass().canBeEquipped (object, actor); + + // display error message if the player tried to equip something + if (!result.second.empty() && actor == MWMechanics::getPlayer()) + MWBase::Environment::get().getWindowManager()->messageBox(result.second); + + switch(result.first) + { + case 0: + return; + default: + break; + } } // slots that this item can be equipped in diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp index 3b56c7402..1b5e52dd8 100644 --- a/apps/openmw/mwworld/actionequip.hpp +++ b/apps/openmw/mwworld/actionequip.hpp @@ -2,17 +2,18 @@ #define GAME_MWWORLD_ACTIONEQUIP_H #include "action.hpp" -#include "ptr.hpp" namespace MWWorld { class ActionEquip : public Action { - virtual void executeImp (const Ptr& actor); + bool mForce; - public: - /// @param item to equip - ActionEquip (const Ptr& object); + virtual void executeImp (const Ptr& actor); + + public: + /// @param item to equip + ActionEquip (const Ptr& object, bool force=false); }; } diff --git a/apps/openmw/mwworld/actionrepair.cpp b/apps/openmw/mwworld/actionrepair.cpp index 191cf2063..4fb7f7ada 100644 --- a/apps/openmw/mwworld/actionrepair.cpp +++ b/apps/openmw/mwworld/actionrepair.cpp @@ -8,8 +8,9 @@ namespace MWWorld { - ActionRepair::ActionRepair(const Ptr &item) - : Action(false, item) + ActionRepair::ActionRepair(const Ptr& item, bool force) + : Action (false, item) + , mForce(force) { } @@ -18,7 +19,8 @@ namespace MWWorld if (actor != MWMechanics::getPlayer()) return; - if(MWMechanics::isPlayerInCombat()) { + if(!mForce && MWMechanics::isPlayerInCombat()) + { MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage2}"); return; } diff --git a/apps/openmw/mwworld/actionrepair.hpp b/apps/openmw/mwworld/actionrepair.hpp index 1d3ef2bc1..fc64522d8 100644 --- a/apps/openmw/mwworld/actionrepair.hpp +++ b/apps/openmw/mwworld/actionrepair.hpp @@ -7,10 +7,13 @@ namespace MWWorld { class ActionRepair : public Action { - virtual void executeImp (const Ptr& actor); + bool mForce; + + virtual void executeImp (const Ptr& actor); public: - ActionRepair(const MWWorld::Ptr& item); + /// @param item repair hammer + ActionRepair(const Ptr& item, bool force=false); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 5425c2bd3..68d5998ac 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -113,7 +113,7 @@ namespace MWWorld return std::shared_ptr (new NullAction); } - std::shared_ptr Class::use (const Ptr& ptr) const + std::shared_ptr Class::use (const Ptr& ptr, bool force) const { return std::shared_ptr (new NullAction); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 097ec0faa..132b7e9e8 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -141,7 +141,7 @@ namespace MWWorld virtual std::shared_ptr activate (const Ptr& ptr, const Ptr& actor) const; ///< Generate action for activation (default implementation: return a null action). - virtual std::shared_ptr use (const Ptr& ptr) + virtual std::shared_ptr use (const Ptr& ptr, bool force=false) const; ///< Generate action for using via inventory menu (default implementation: return a /// null action). From 2599aba19625074c7c03fb8a13f660d56803e7bd Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 8 Jul 2018 20:36:04 +0300 Subject: [PATCH 119/126] Fix check whether file name starts with x or X If path doens't contains / or \, then slashpos will be 0. Therefore slashpos + 1 = 1 doesn't point to first symbol. xmesh.nif ^ slashpos + 1 --- components/nifbullet/bulletnifloader.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 8f827e4e2..a7afabf8f 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -88,18 +88,13 @@ osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr& else { bool autogenerated = hasAutoGeneratedCollision(node); - bool isAnimated = false; // files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see Animation::addAnimSource). // assume all nodes in the file will be animated std::string filename = nif->getFilename(); - size_t slashpos = filename.find_last_of("/\\"); - if (slashpos == std::string::npos) - slashpos = 0; - if (slashpos+1 < filename.size() && (filename[slashpos+1] == 'x' || filename[slashpos+1] == 'X')) - { - isAnimated = true; - } + const std::size_t slashpos = filename.find_last_of("/\\"); + const std::size_t letterPos = slashpos == std::string::npos ? 0 : slashpos + 1; + const bool isAnimated = letterPos < filename.size() && (filename[letterPos] == 'x' || filename[letterPos] == 'X'); handleNode(node, 0, autogenerated, isAnimated, autogenerated); From 3f21c49479e1927f8ceea2345bc91717e1e9fb8f Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 8 Jul 2018 20:52:16 +0300 Subject: [PATCH 120/126] Put check for nif file name into separate function --- components/nifbullet/bulletnifloader.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index a7afabf8f..be5a7d9d6 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -34,6 +34,13 @@ btVector3 getbtVector(const osg::Vec3f &v) return btVector3(v.x(), v.y(), v.z()); } +bool pathFileNameStartsWithX(const std::string& path) +{ + const std::size_t slashpos = path.find_last_of("/\\"); + const std::size_t letterPos = slashpos == std::string::npos ? 0 : slashpos + 1; + return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X'); +} + } namespace NifBullet @@ -91,10 +98,7 @@ osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr& // files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see Animation::addAnimSource). // assume all nodes in the file will be animated - std::string filename = nif->getFilename(); - const std::size_t slashpos = filename.find_last_of("/\\"); - const std::size_t letterPos = slashpos == std::string::npos ? 0 : slashpos + 1; - const bool isAnimated = letterPos < filename.size() && (filename[letterPos] == 'x' || filename[letterPos] == 'X'); + const bool isAnimated = pathFileNameStartsWithX(nif->getFilename()); handleNode(node, 0, autogenerated, isAnimated, autogenerated); From 686830a6e32b3cc8615df3eb665d15c5469e6ffd Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 10 Jul 2018 23:52:51 +0300 Subject: [PATCH 121/126] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44c7398ba..9223b891d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,7 +61,8 @@ Bug #4489: Goodbye doesn't block dialogue hyperlinks Bug #4490: PositionCell on player gives "Error: tried to add local script twice" Bug #4491: Training cap based off Base Skill instead of Modified Skill - Bug #4495: Crossbow animations blending is buggy + Bug #4495: Crossbow animations blending is buggy + Bug #4497: File names starting with x or X are not classified as animation Bug #3249: Fixed revert function not updating views properly Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results From 232be000a22fbc0060963946d4bbfcbcf69ede72 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 11 Jul 2018 10:09:31 +0200 Subject: [PATCH 122/126] Updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index f1e6e58ee..d2fd05180 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -143,6 +143,7 @@ Programmers Rohit Nirmal Roman Melnik (Kromgart) Roman Proskuryakov (kpp) + Roman Siromakha (elsid) Sandy Carter (bwrsandman) Scott Howard scrawl From 2d919ba21582ce2d6271fecc9d5dd3787c4abf12 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 11 Jul 2018 10:10:38 +0200 Subject: [PATCH 123/126] changelog cleanup --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb71b8ee..ea4a02085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,6 @@ Bug #4495: Crossbow animations blending is buggy Bug #4496: SpellTurnLeft and SpellTurnRight animation groups are unused Bug #4497: File names starting with x or X are not classified as animation - Bug #3249: Fixed revert function not updating views properly Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window From 70b6d4983dba2389182bc5c7c0d63fb205885c31 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 28 Jun 2018 18:05:00 +0400 Subject: [PATCH 124/126] Use the DejaVuLGCSansMono.ttf in profilier output --- apps/openmw/engine.cpp | 47 +++++++++++++++++++---------------- components/resource/stats.cpp | 14 +++++++++-- components/resource/stats.hpp | 7 +++++- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8c3c9494c..cce201718 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -646,28 +646,19 @@ void OMW::Engine::go() std::cout << "OSG version: " << osgGetVersion() << std::endl; - mViewer = new osgViewer::Viewer; - mViewer->setReleaseContextAtEndOfFrameHint(false); - - osg::ref_ptr statshandler = new osgViewer::StatsHandler; - statshandler->setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3); - - statshandler->addUserStatsLine("Script", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "script_time_taken", 1000.0, true, false, "script_time_begin", "script_time_end", 10000); - statshandler->addUserStatsLine("Mechanics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "mechanics_time_taken", 1000.0, true, false, "mechanics_time_begin", "mechanics_time_end", 10000); - statshandler->addUserStatsLine("Physics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "physics_time_taken", 1000.0, true, false, "physics_time_begin", "physics_time_end", 10000); - - mViewer->addEventHandler(statshandler); - - mViewer->addEventHandler(new Resource::StatsHandler); - + // Load settings Settings::Manager settings; std::string settingspath; - settingspath = loadSettings (settings); + // Create encoder + ToUTF8::Utf8Encoder encoder (mEncoding); + mEncoder = &encoder; + + // Setup viewer + mViewer = new osgViewer::Viewer; + mViewer->setReleaseContextAtEndOfFrameHint(false); + mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(), Settings::Manager::getString("screenshot format", "General")); @@ -677,12 +668,24 @@ void OMW::Engine::go() mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video")); - // Create encoder - ToUTF8::Utf8Encoder encoder (mEncoding); - mEncoder = &encoder; - prepareEngine (settings); + // Setup profiler + osg::ref_ptr statshandler = new Resource::Profiler; + + statshandler->addUserStatsLine("Script", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), + "script_time_taken", 1000.0, true, false, "script_time_begin", "script_time_end", 10000); + statshandler->addUserStatsLine("Mechanics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), + "mechanics_time_taken", 1000.0, true, false, "mechanics_time_begin", "mechanics_time_end", 10000); + statshandler->addUserStatsLine("Physics", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), + "physics_time_taken", 1000.0, true, false, "physics_time_begin", "physics_time_end", 10000); + + mViewer->addEventHandler(statshandler); + + osg::ref_ptr resourceshandler = new Resource::StatsHandler; + mViewer->addEventHandler(resourceshandler); + + // Start the game if (!mSaveGameFile.empty()) { mEnvironment.getStateManager()->loadGame(mSaveGameFile); diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index bf34d5534..0a70d75ab 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -10,6 +10,8 @@ #include #include +#include + namespace Resource { @@ -19,7 +21,7 @@ StatsHandler::StatsHandler(): _statsType(false), _statsWidth(1280.0f), _statsHeight(1024.0f), - _font("fonts/arial.ttf"), + _font(""), _characterSize(20.0f) { _camera = new osg::Camera; @@ -28,6 +30,15 @@ StatsHandler::StatsHandler(): _camera->setProjectionResizePolicy(osg::Camera::FIXED); _resourceStatsChildNum = 0; + + _font = osgMyGUI::DataManager::getInstance().getDataPath("DejaVuLGCSansMono.ttf"); +} + +Profiler::Profiler() +{ + _font = osgMyGUI::DataManager::getInstance().getDataPath("DejaVuLGCSansMono.ttf"); + + setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3); } bool StatsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) @@ -77,7 +88,6 @@ void StatsHandler::setWindowSize(int width, int height) { _camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,_statsHeight-height*_statsWidth/width,_statsHeight)); } - } void StatsHandler::toggle(osgViewer::ViewerBase *viewer) diff --git a/components/resource/stats.hpp b/components/resource/stats.hpp index 55b016602..8f04ee10d 100644 --- a/components/resource/stats.hpp +++ b/components/resource/stats.hpp @@ -1,7 +1,7 @@ #ifndef OPENMW_COMPONENTS_RESOURCE_STATS_H #define OPENMW_COMPONENTS_RESOURCE_STATS_H -#include +#include namespace osgViewer { @@ -15,6 +15,11 @@ namespace osg namespace Resource { + class Profiler : public osgViewer::StatsHandler + { + public: + Profiler(); + }; class StatsHandler : public osgGA::GUIEventHandler { From 3d1daaebab4d7100afbcca8c8d22c0571356129a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 28 Jun 2018 16:58:51 +0400 Subject: [PATCH 125/126] Rework manual spellcasting (e.g. via scripts) --- apps/openmw/CMakeLists.txt | 4 +- apps/openmw/mwbase/mechanicsmanager.hpp | 3 + apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 16 ++++ apps/openmw/mwmechanics/actors.hpp | 3 + apps/openmw/mwmechanics/aicast.cpp | 84 +++++++++++++++++ apps/openmw/mwmechanics/aicast.hpp | 37 ++++++++ apps/openmw/mwmechanics/aipackage.hpp | 3 +- apps/openmw/mwmechanics/aisequence.cpp | 20 +++-- apps/openmw/mwmechanics/character.cpp | 34 +++++-- apps/openmw/mwmechanics/character.hpp | 3 + .../mwmechanics/mechanicsmanagerimp.cpp | 11 +++ .../mwmechanics/mechanicsmanagerimp.hpp | 4 + apps/openmw/mwmechanics/spellcasting.cpp | 15 +++- apps/openmw/mwmechanics/spellcasting.hpp | 5 +- apps/openmw/mwscript/miscextensions.cpp | 23 ++++- apps/openmw/mwworld/worldimp.cpp | 90 +++++++++++-------- apps/openmw/mwworld/worldimp.hpp | 2 +- 18 files changed, 298 insertions(+), 61 deletions(-) create mode 100644 apps/openmw/mwmechanics/aicast.cpp create mode 100644 apps/openmw/mwmechanics/aicast.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e8a958d45..0092712db 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -81,9 +81,9 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat creaturestats magiceffects movement actorutil drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe - aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting + aicast aiescort aiface aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning - character actors objects aistate coordinateconverter trading aiface weaponpriority spellpriority + character actors objects aistate coordinateconverter trading weaponpriority spellpriority ) add_openmw_dir (mwstate diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index f15a86918..995c8d736 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -225,9 +225,12 @@ namespace MWBase /// Resurrects the player if necessary virtual void keepPlayerAlive() = 0; + virtual bool isCastingSpell (const MWWorld::Ptr& ptr) const = 0; virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0; virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0; + virtual void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) = 0; + /// Check if the target actor was detected by an observer /// If the observer is a non-NPC, check all actors in AI processing distance as observers virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index e07c1ffd9..97993e984 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -487,7 +487,7 @@ namespace MWBase */ virtual bool startSpellCast (const MWWorld::Ptr& actor) = 0; - virtual void castSpell (const MWWorld::Ptr& actor) = 0; + virtual void castSpell (const MWWorld::Ptr& actor, bool manualSpell=false) = 0; virtual void launchMagicBolt (const std::string& spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection) = 0; virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a225014b4..36ba77cfb 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1157,6 +1157,13 @@ namespace MWMechanics } } + void Actors::castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) + { + PtrActorMap::iterator iter = mActors.find(ptr); + if(iter != mActors.end()) + iter->second->getCharacterController()->castSpell(spellId, manualSpell); + } + bool Actors::isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) { if (!actor.getClass().isActor()) @@ -1968,6 +1975,15 @@ namespace MWMechanics return it->second->getCharacterController()->isReadyToBlock(); } + bool Actors::isCastingSpell(const MWWorld::Ptr &ptr) const + { + PtrActorMap::const_iterator it = mActors.find(ptr); + if (it == mActors.end()) + return false; + + return it->second->getCharacterController()->isCastingSpell(); + } + bool Actors::isAttackingOrSpell(const MWWorld::Ptr& ptr) const { PtrActorMap::const_iterator it = mActors.find(ptr); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 0de1f4d6c..492ff1e2e 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -77,6 +77,8 @@ namespace MWMechanics /// /// \note Ignored, if \a ptr is not a registered actor. + void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false); + void updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr& ptr); ///< Updates an actor with a new Ptr @@ -161,6 +163,7 @@ namespace MWMechanics void clear(); // Clear death counter + bool isCastingSpell(const MWWorld::Ptr& ptr) const; bool isReadyToBlock(const MWWorld::Ptr& ptr) const; bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwmechanics/aicast.cpp b/apps/openmw/mwmechanics/aicast.cpp new file mode 100644 index 000000000..48cb17f6d --- /dev/null +++ b/apps/openmw/mwmechanics/aicast.cpp @@ -0,0 +1,84 @@ +#include "aicast.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" + +#include "../mwworld/class.hpp" + +#include "aicombataction.hpp" +#include "creaturestats.hpp" +#include "spellcasting.hpp" +#include "steering.hpp" + +MWMechanics::AiCast::AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell) + : mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(0) +{ + ActionSpell action = ActionSpell(spellId); + bool isRanged; + mDistance = action.getCombatRange(isRanged); +} + +MWMechanics::AiPackage *MWMechanics::AiCast::clone() const +{ + return new AiCast(*this); +} + +bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::CharacterController& characterController, MWMechanics::AiState& state, float duration) +{ + MWWorld::Ptr target; + if (actor.getCellRef().getRefId() == mTargetId) + { + // If the target has the same ID as caster, consider that actor casts spell with Self range. + target = actor; + } + else + { + target = getTarget(); + if (!target) + return true; + + if (!mManual && !pathTo(actor, target.getRefData().getPosition().pos, duration, mDistance)) + { + return false; + } + + osg::Vec3f dir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3(); + bool turned = smoothTurn(actor, getZAngleToDir(dir), 2, osg::DegreesToRadians(3.f)); + turned &= smoothTurn(actor, getXAngleToDir(dir), 0, osg::DegreesToRadians(3.f)); + + if (!turned) + return false; + } + + // Check if the actor is already casting another spell + bool isCasting = MWBase::Environment::get().getMechanicsManager()->isCastingSpell(actor); + if (isCasting && !mCasting) + return false; + + if (!mCasting) + { + MWBase::Environment::get().getMechanicsManager()->castSpell(actor, mSpellId, mManual); + mCasting = true; + return false; + } + + // Finish package, if actor finished spellcasting + return !isCasting; +} + +MWWorld::Ptr MWMechanics::AiCast::getTarget() const +{ + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mTargetId, false); + + return target; +} + +int MWMechanics::AiCast::getTypeId() const +{ + return AiPackage::TypeIdCast; +} + +unsigned int MWMechanics::AiCast::getPriority() const +{ + return 3; +} diff --git a/apps/openmw/mwmechanics/aicast.hpp b/apps/openmw/mwmechanics/aicast.hpp new file mode 100644 index 000000000..70a8a6bbd --- /dev/null +++ b/apps/openmw/mwmechanics/aicast.hpp @@ -0,0 +1,37 @@ +#ifndef GAME_MWMECHANICS_AICAST_H +#define GAME_MWMECHANICS_AICAST_H + +#include "../mwbase/world.hpp" + +#include "aipackage.hpp" + +namespace MWMechanics +{ + /// AiPackage which makes an actor to cast given spell. + class AiCast : public AiPackage { + public: + AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell=false); + + virtual AiPackage *clone() const; + + virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration); + + virtual int getTypeId() const; + + virtual MWWorld::Ptr getTarget() const; + + virtual unsigned int getPriority() const; + + virtual bool canCancel() const { return false; } + virtual bool shouldCancelPreviousAi() const { return false; } + + private: + std::string mTargetId; + std::string mSpellId; + bool mCasting; + bool mManual; + float mDistance; + }; +} + +#endif diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 2b685accc..f1941ff1d 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -49,7 +49,8 @@ namespace MWMechanics TypeIdAvoidDoor = 7, TypeIdFace = 8, TypeIdBreathe = 9, - TypeIdInternalTravel = 10 + TypeIdInternalTravel = 10, + TypeIdCast = 11 }; ///Default constructor diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 86cc2bbdc..085174820 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -180,12 +180,8 @@ bool AiSequence::isPackageDone() const bool isActualAiPackage(int packageTypeId) { - return (packageTypeId != AiPackage::TypeIdCombat - && packageTypeId != AiPackage::TypeIdPursue - && packageTypeId != AiPackage::TypeIdAvoidDoor - && packageTypeId != AiPackage::TypeIdFace - && packageTypeId != AiPackage::TypeIdBreathe - && packageTypeId != AiPackage::TypeIdInternalTravel); + return (packageTypeId >= AiPackage::TypeIdWander && + packageTypeId <= AiPackage::TypeIdActivate); } void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& characterController, float duration) @@ -308,7 +304,7 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo if (isActualAiPackage(package.getTypeId())) stopCombat(); - // We should return a wandering actor back after combat or pursuit. + // We should return a wandering actor back after combat, casting or pursuit. // The same thing for actors without AI packages. // Also there is no point to stack return packages. int currentTypeId = getTypeId(); @@ -316,7 +312,8 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo if (currentTypeId <= MWMechanics::AiPackage::TypeIdWander && !hasPackage(MWMechanics::AiPackage::TypeIdInternalTravel) && (newTypeId <= MWMechanics::AiPackage::TypeIdCombat - || newTypeId == MWMechanics::AiPackage::TypeIdPursue)) + || newTypeId == MWMechanics::AiPackage::TypeIdPursue + || newTypeId == MWMechanics::AiPackage::TypeIdCast)) { osg::Vec3f dest; if (currentTypeId == MWMechanics::AiPackage::TypeIdWander) @@ -352,6 +349,13 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo // insert new package in correct place depending on priority for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { + // We should keep current AiCast package, if we try to add a new one. + if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdCast && + package.getTypeId() == MWMechanics::AiPackage::TypeIdCast) + { + continue; + } + if((*it)->getPriority() <= package.getPriority()) { mPackages.insert(it,package.clone()); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c36129c4e..aaa6c7aeb 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -39,6 +39,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/player.hpp" +#include "aicombataction.hpp" #include "movement.hpp" #include "npcstats.hpp" #include "creaturestats.hpp" @@ -794,6 +795,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim , mSecondsOfRunning(0) , mTurnAnimationThreshold(0) , mAttackingOrSpell(false) + , mCastingManualSpell(false) , mTimeUntilWake(0.f) { if(!mAnimation) @@ -1007,7 +1009,8 @@ void CharacterController::handleTextKey(const std::string &groupname, const std: // the same animation for all range types, so there are 3 "release" keys on the same time, one for each range type. && evt.compare(off, len, mAttackType + " release") == 0) { - MWBase::Environment::get().getWorld()->castSpell(mPtr); + MWBase::Environment::get().getWorld()->castSpell(mPtr, mCastingManualSpell); + mCastingManualSpell = false; } else if (groupname == "shield" && evt.compare(off, len, "block hit") == 0) @@ -1088,13 +1091,18 @@ bool CharacterController::updateCreatureState() if (weapType == WeapType_Spell) { const std::string spellid = stats.getSpells().getSelectedSpell(); - if (!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr)) + bool canCast = mCastingManualSpell || MWBase::Environment::get().getWorld()->startSpellCast(mPtr); + + if (!spellid.empty() && canCast) { - MWMechanics::CastSpell cast(mPtr, NULL); + MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell); cast.playSpellCastingEffects(spellid); if (!mAnimation->hasAnimation("spellcast")) - MWBase::Environment::get().getWorld()->castSpell(mPtr); // No "release" text key to use, so cast immediately + { + MWBase::Environment::get().getWorld()->castSpell(mPtr, mCastingManualSpell); // No "release" text key to use, so cast immediately + mCastingManualSpell = false; + } else { const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellid); @@ -1367,10 +1375,11 @@ bool CharacterController::updateWeaponState() stats.getSpells().setSelectedSpell(selectedSpell); } std::string spellid = stats.getSpells().getSelectedSpell(); + bool canCast = mCastingManualSpell || MWBase::Environment::get().getWorld()->startSpellCast(mPtr); - if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr)) + if(!spellid.empty() && canCast) { - MWMechanics::CastSpell cast(mPtr, NULL); + MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell); cast.playSpellCastingEffects(spellid); const ESM::Spell *spell = store.get().find(spellid); @@ -2377,6 +2386,11 @@ bool CharacterController::isAttackPrepairing() const mUpperBodyState == UpperCharState_MinAttackToMaxAttack; } +bool CharacterController::isCastingSpell() const +{ + return mCastingManualSpell || mUpperBodyState == UpperCharState_CastingSpell; +} + bool CharacterController::isReadyToBlock() const { return updateCarriedLeftVisible(mWeaponType); @@ -2440,6 +2454,14 @@ void CharacterController::setAttackingOrSpell(bool attackingOrSpell) mAttackingOrSpell = attackingOrSpell; } +void CharacterController::castSpell(const std::string spellId, bool manualSpell) +{ + mAttackingOrSpell = true; + mCastingManualSpell = manualSpell; + ActionSpell action = ActionSpell(spellId); + action.prepare(mPtr); +} + void CharacterController::setAIAttackType(const std::string& attackType) { mAttackType = attackType; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 381cf71a5..84630a479 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -204,6 +204,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener std::string mAttackType; // slash, chop or thrust bool mAttackingOrSpell; + bool mCastingManualSpell; float mTimeUntilWake; @@ -276,6 +277,7 @@ public: void forceStateUpdate(); bool isAttackPrepairing() const; + bool isCastingSpell() const; bool isReadyToBlock() const; bool isKnockedDown() const; bool isKnockedOut() const; @@ -286,6 +288,7 @@ public: bool isAttackingOrSpell() const; void setAttackingOrSpell(bool attackingOrSpell); + void castSpell(const std::string spellId, bool manualSpell=false); void setAIAttackType(const std::string& attackType); static void setAttackTypeRandomly(std::string& attackType); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index c2f7a664c..7814b4a91 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -253,6 +253,12 @@ namespace MWMechanics mObjects.addObject(ptr); } + void MechanicsManager::castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) + { + if(ptr.getClass().isActor()) + mActors.castSpell(ptr, spellId, manualSpell); + } + void MechanicsManager::remove(const MWWorld::Ptr& ptr) { if(ptr == mWatched) @@ -1758,6 +1764,11 @@ namespace MWMechanics stats.resurrect(); } + bool MechanicsManager::isCastingSpell(const MWWorld::Ptr &ptr) const + { + return mActors.isCastingSpell(ptr); + } + bool MechanicsManager::isReadyToBlock(const MWWorld::Ptr &ptr) const { return mActors.isReadyToBlock(ptr); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 07dfd81ff..676a75caf 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -190,10 +190,14 @@ namespace MWMechanics virtual void keepPlayerAlive(); + virtual bool isCastingSpell (const MWWorld::Ptr& ptr) const; + virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const; /// Is \a ptr casting spell or using weapon now? virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const; + virtual void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false); + /// Check if the target actor was detected by an observer /// If the observer is a non-NPC, check all actors in AI processing distance as observers virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index f1997e8d7..4557a52df 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -315,13 +315,14 @@ namespace MWMechanics return true; } - CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target, const bool fromProjectile) + CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target, const bool fromProjectile, const bool isScripted) : mCaster(caster) , mTarget(target) , mStack(false) , mHitPosition(0,0,0) , mAlwaysSucceed(false) , mFromProjectile(fromProjectile) + , mIsScripted(isScripted) { } @@ -863,7 +864,7 @@ namespace MWMechanics bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); - if (mCaster.getClass().isActor() && !mAlwaysSucceed) + if (mCaster.getClass().isActor() && !mAlwaysSucceed && !mIsScripted) { school = getSpellSchool(spell, mCaster); @@ -910,7 +911,7 @@ namespace MWMechanics stats.getSpells().usePower(spell); } - if (mCaster == getPlayer() && spellIncreasesSkill(spell)) + if (mCaster == getPlayer() && spellIncreasesSkill()) mCaster.getClass().skillUsageSucceeded(mCaster, spellSchoolToSkill(school), 0); @@ -1034,6 +1035,14 @@ namespace MWMechanics } } + bool CastSpell::spellIncreasesSkill() + { + if (mIsScripted) + return false; + + return MWMechanics::spellIncreasesSkill(mId); + } + int getEffectiveEnchantmentCastCost(float castCost, const MWWorld::Ptr &actor) { /* diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 07c5b8477..5e69b4696 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -88,9 +88,10 @@ namespace MWMechanics osg::Vec3f mHitPosition; // Used for spawning area orb bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false) bool mFromProjectile; // True if spell is cast by enchantment of some projectile (arrow, bolt or thrown weapon) + bool mIsScripted; // True if spell is casted from script and ignores some checks (mana level, success chance, etc.) public: - CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target, const bool fromProjectile=false); + CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target, const bool fromProjectile=false, const bool isScripted=false); bool cast (const ESM::Spell* spell); @@ -108,6 +109,8 @@ namespace MWMechanics void playSpellCastingEffects(const std::string &spellid); + bool spellIncreasesSkill(); + /// Launch a bolt with the given effects. void launchMagicBolt (); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 3fa66af10..30d0c6fee 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -25,6 +25,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwmechanics/aicast.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/spellcasting.hpp" @@ -1056,15 +1057,31 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - std::string spell = runtime.getStringLiteral (runtime[0].mInteger); + std::string spellId = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); std::string targetId = ::Misc::StringUtils::lowerCase(runtime.getStringLiteral (runtime[0].mInteger)); runtime.pop(); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find (spellId); + if (spell && spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power) + { + runtime.getContext().report("spellcasting failed: you can cast only spells and powers."); + return; + } + + // Obviously we can not use casting animation for player here + if (ptr.getClass().isActor() && ptr != MWMechanics::getPlayer()) + { + MWMechanics::AiCast castPackage(targetId, spellId, true); + ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(castPackage, ptr); + + return; + } + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false); - MWMechanics::CastSpell cast(ptr, target); + MWMechanics::CastSpell cast(ptr, target, false, true); cast.mHitPosition = target.getRefData().getPosition().asVec3(); cast.mAlwaysSucceed = true; cast.cast(spell); @@ -1082,7 +1099,7 @@ namespace MWScript std::string spell = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWMechanics::CastSpell cast(ptr, ptr); + MWMechanics::CastSpell cast(ptr, ptr, false, true); cast.mHitPosition = ptr.getRefData().getPosition().asVec3(); cast.mAlwaysSucceed = true; cast.cast(spell); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5d554176a..6bf964d9b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2771,13 +2771,13 @@ namespace MWWorld return !fail; } - void World::castSpell(const Ptr &actor) + void World::castSpell(const Ptr &actor, bool manualSpell) { MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); // For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit result. std::vector targetActors; - if (!actor.isEmpty() && actor != MWMechanics::getPlayer()) + if (!actor.isEmpty() && actor != MWMechanics::getPlayer() && !manualSpell) actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors); const float fCombatDistance = getStore().get().find("fCombatDistance")->getFloat(); @@ -2795,51 +2795,71 @@ namespace MWWorld if (target.isEmpty()) { - // For actor targets, we want to use hit contact with bounding boxes. - // This is to give a slight tolerance for errors, especially with creatures like the Skeleton that would be very hard to aim at otherwise. - // For object targets, we want the detailed shapes (rendering raycast). - // If we used the bounding boxes for static objects, then we would not be able to target e.g. objects lying on a shelf. - std::pair result1 = getHitContact(actor, fCombatDistance, targetActors); + // For scripted spells we should not use hit contact + if (manualSpell) + { + // Actors that are targeted by this actor's Follow or Escort packages also side with them + if (actor != MWMechanics::getPlayer()) + { + const MWMechanics::CreatureStats &stats = actor.getClass().getCreatureStats(actor); + for (std::list::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) + { + if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdCast) + { + target = (*it)->getTarget(); + break; + } + } + } + } + else + { + // For actor targets, we want to use hit contact with bounding boxes. + // This is to give a slight tolerance for errors, especially with creatures like the Skeleton that would be very hard to aim at otherwise. + // For object targets, we want the detailed shapes (rendering raycast). + // If we used the bounding boxes for static objects, then we would not be able to target e.g. objects lying on a shelf. + std::pair result1 = getHitContact(actor, fCombatDistance, targetActors); - // Get the target to use for "on touch" effects, using the facing direction from Head node - osg::Vec3f origin = getActorHeadTransform(actor).getTrans(); + // Get the target to use for "on touch" effects, using the facing direction from Head node + osg::Vec3f origin = getActorHeadTransform(actor).getTrans(); - osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)) - * osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1)); + osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)) + * osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1)); - osg::Vec3f direction = orient * osg::Vec3f(0,1,0); - float distance = getMaxActivationDistance(); - osg::Vec3f dest = origin + direction * distance; + osg::Vec3f direction = orient * osg::Vec3f(0,1,0); + float distance = getMaxActivationDistance(); + osg::Vec3f dest = origin + direction * distance; - MWRender::RenderingManager::RayResult result2 = mRendering->castRay(origin, dest, true, true); + MWRender::RenderingManager::RayResult result2 = mRendering->castRay(origin, dest, true, true); - float dist1 = std::numeric_limits::max(); - float dist2 = std::numeric_limits::max(); + float dist1 = std::numeric_limits::max(); + float dist2 = std::numeric_limits::max(); - if (!result1.first.isEmpty() && result1.first.getClass().isActor()) - dist1 = (origin - result1.second).length(); - if (result2.mHit) - dist2 = (origin - result2.mHitPointWorld).length(); + if (!result1.first.isEmpty() && result1.first.getClass().isActor()) + dist1 = (origin - result1.second).length(); + if (result2.mHit) + dist2 = (origin - result2.mHitPointWorld).length(); - if (!result1.first.isEmpty() && result1.first.getClass().isActor()) - { - target = result1.first; - hitPosition = result1.second; - if (dist1 > getMaxActivationDistance()) - target = NULL; - } - else if (result2.mHit) - { - target = result2.mHitObject; - hitPosition = result2.mHitPointWorld; - if (dist2 > getMaxActivationDistance() && !target.isEmpty() && !target.getClass().canBeActivated(target)) - target = NULL; + if (!result1.first.isEmpty() && result1.first.getClass().isActor()) + { + target = result1.first; + hitPosition = result1.second; + if (dist1 > getMaxActivationDistance()) + target = NULL; + } + else if (result2.mHit) + { + target = result2.mHitObject; + hitPosition = result2.mHitPointWorld; + if (dist2 > getMaxActivationDistance() && !target.isEmpty() && !target.getClass().canBeActivated(target)) + target = NULL; + } } } std::string selectedSpell = stats.getSpells().getSelectedSpell(); - MWMechanics::CastSpell cast(actor, target); + MWMechanics::CastSpell cast(actor, target, false, manualSpell); cast.mHitPosition = hitPosition; if (!selectedSpell.empty()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 015a8b31b..941ab7a96 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -602,7 +602,7 @@ namespace MWWorld * @brief Cast the actual spell, should be called mid-animation * @param actor */ - void castSpell (const MWWorld::Ptr& actor) override; + void castSpell (const MWWorld::Ptr& actor, bool manualSpell=false) override; void launchMagicBolt (const std::string& spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection) override; void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, From 32bd294a8a135da6e6a8ce55e38449668d355238 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 12 Jul 2018 16:39:46 +0400 Subject: [PATCH 126/126] Add missing changelog entries --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea4a02085..7fde57f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ------ Bug #1990: Sunrise/sunset not set correct + Bug #2131: Lustidrike's spell misses the player every time Bug #2222: Fatigue's effect on selling price is backwards Bug #2326: After a bound item expires the last equipped item of that type is not automatically re-equipped Bug #2455: Creatures attacks degrade armor @@ -65,7 +66,9 @@ Bug #4495: Crossbow animations blending is buggy Bug #4496: SpellTurnLeft and SpellTurnRight animation groups are unused Bug #4497: File names starting with x or X are not classified as animation + Bug #4503: Cast and ExplodeSpell commands increase alteration skill Feature #2606: Editor: Implemented (optional) case sensitive global search + Feature #3083: Play animation when NPC is casting spell via script Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results Feature #3641: Editor: Limit FPS in 3d preview window Feature #4222: 360° screenshots