From 56881cb7c91e956831a42340528530f58f8e4456 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sat, 24 May 2014 23:05:30 +0400 Subject: [PATCH 1/7] fix bugs in aisequence::execute --- apps/openmw/mwmechanics/aisequence.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 980a23a3e..6d2c15549 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -137,7 +137,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) float nearestDist = std::numeric_limits::max(); Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for(std::list::iterator it = mPackages.begin(); it != mPackages.end();) { if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; @@ -147,7 +147,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) if (target.isEmpty()) { delete *it; - mPackages.erase(it++); + it = mPackages.erase(it); } else { @@ -159,20 +159,26 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration) nearestDist = distTo; itActualCombat = it; } + ++it; } } - // all targets disappeared - if (nearestDist == std::numeric_limits::max()) + if (!mPackages.empty()) + { + if (nearestDist < std::numeric_limits::max() && mPackages.begin() != itActualCombat) + { + // move combat package with nearest target to the front + mPackages.splice(mPackages.begin(), mPackages, itActualCombat); + } + + package = mPackages.front(); + mLastAiPackage = package->getTypeId(); + } + else { mDone = true; return; } - else if (mPackages.begin() != itActualCombat) - { - // move combat package with nearest target to the front - mPackages.splice(mPackages.begin(), mPackages, itActualCombat); - } } if (package->execute (actor,duration)) From c62187bd555e3bcdef232c5c3e1c949809b2e5ca Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 25 May 2014 13:31:46 +0400 Subject: [PATCH 2/7] fix bug at http://bugs.openmw.org/issues/1155 Though it still can happen sometimes but not in such stupid manner. --- apps/openmw/mwmechanics/aicombat.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 1027cc48a..9fe92f807 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -330,7 +330,7 @@ namespace MWMechanics bool isStuck = false; float speed = 0.0f; - if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f) + if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) * tReaction / 2) isStuck = true; mLastPos = pos; @@ -397,14 +397,10 @@ namespace MWMechanics { bool preferShortcut = false; bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); - - if(mReadyToAttack) isStuck = false; // check if shortcut is available - if(!isStuck - && (!mForceNoShortcut - || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST) - && inLOS) + if(inLOS && (!isStuck || mReadyToAttack) + && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) { if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed @@ -467,7 +463,7 @@ namespace MWMechanics mReadyToAttack = false; } - if(distToTarget > rangeAttack && !distantCombat) + if(!isStuck && distToTarget > rangeAttack && !distantCombat) { //special run attack; it shouldn't affect melee combat tactics if(actorCls.getMovementSettings(actor).mPosition[1] == 1) From 8fa7fcdbee3d63d61120526b24ef3b104c01e718 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Sun, 25 May 2014 21:03:37 +0400 Subject: [PATCH 3/7] fix bug http://bugs.openmw.org/issues/1335 (1304 as well) though fish detects if actor is swimming, but in MW it attacks even if the player is knee-deep in water --- apps/openmw/mwmechanics/actors.cpp | 8 +++++ apps/openmw/mwmechanics/aicombat.cpp | 29 +++++++++++++------ .../mwmechanics/mechanicsmanagerimp.cpp | 4 ++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 35667a23c..fe89fda11 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -191,6 +191,14 @@ namespace MWMechanics if (againstPlayer && creatureStats.isHostile()) return; // already fighting against player + // pure water creatures won't try to fight with the target on the ground + // except that creature is already hostile + if ((againstPlayer || !creatureStats.isHostile()) + && ((actor1.getClass().canSwim(actor1) && !actor1.getClass().canWalk(actor1) // pure water creature + && !MWBase::Environment::get().getWorld()->isSwimming(actor2)) + || (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target + return; + float fight; if (againstPlayer) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 9fe92f807..8f8188559 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -53,7 +53,7 @@ namespace // cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target; // magnitude of pits/obstacles is defined by PATHFIND_Z_REACH - bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offset) + bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offsetXY) { if((to - from).length() >= PATHFIND_CAUTION_DIST || abs(from.z - to.z) <= PATHFIND_Z_REACH) { @@ -61,7 +61,7 @@ namespace dir.z = 0; dir.normalise(); float verticalOffset = 200; // instead of '200' here we want the height of the actor - Ogre::Vector3 _from = from + dir*offset + Ogre::Vector3::UNIT_Z * verticalOffset; + Ogre::Vector3 _from = from + dir*offsetXY + Ogre::Vector3::UNIT_Z * verticalOffset; // cast up-down ray and find height in world space of hit float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1); @@ -149,13 +149,24 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description - if(actor.getClass().getCreatureStats(actor).isDead()) return true; + if(actor.getClass().getCreatureStats(actor).isDead()) + return true; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); if(target.getClass().getCreatureStats(target).isDead()) return true; + if (!actor.getClass().isNpc() && target == MWBase::Environment::get().getWorld()->getPlayerPtr() && + (actor.getClass().canSwim(actor) && !actor.getClass().canWalk(actor) // pure water creature + && !MWBase::Environment::get().getWorld()->isSwimming(target)) // Player moved out of water + || (!actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(target))) // creature can't swim to Player + { + actor.getClass().getCreatureStats(actor).setHostile(false); + actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); + return true; + } + //Update every frame if(mCombatMove) { @@ -327,6 +338,7 @@ namespace MWMechanics Ogre::Vector3 vActorPos(pos.pos); Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; + float distToTarget = vDirToTarget.length(); bool isStuck = false; float speed = 0.0f; @@ -342,16 +354,15 @@ namespace MWMechanics // determine vertical angle to target // if actor can move along z-axis it will control movement dir // if can't - it will control correct aiming - mMovement.mRotation[0] = getXAngleToDir(vDirToTarget); - - vDirToTarget.z = 0; - float distToTarget = vDirToTarget.length(); + mMovement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget); // (within strike dist) || (not quite strike dist while following) if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget); + + // if we preserve dir.z then horizontal angle can be inaccurate + mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); // (not quite strike dist while following) if (mFollowTarget && distToTarget > rangeAttack) @@ -405,7 +416,7 @@ namespace MWMechanics if(speed == 0.0f) speed = actorCls.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; // *2 - for reliability - preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); + preferShortcut = checkWayIsClear(vActorPos, vTargetPos, Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); } // don't use pathgrid when actor can move in 3 dimensions diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5a72c8883..c9a181461 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1024,7 +1024,9 @@ namespace MWMechanics void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) { - MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + if (ptr.getClass().isNpc()) + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) ptr.getClass().getCreatureStats(ptr).setHostile(true); From 4aab4bae6528af0caa5f0f98b5037383d3b6fa5a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 May 2014 10:14:24 +0200 Subject: [PATCH 4/7] minor cleanup and silenced a warning --- apps/openmw/mwmechanics/aicombat.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index d14251886..9ec770c9d 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -149,7 +149,7 @@ namespace MWMechanics bool AiCombat::execute (const MWWorld::Ptr& actor,float duration) { //General description - if(actor.getClass().getCreatureStats(actor).isDead()) + if(actor.getClass().getCreatureStats(actor).isDead()) return true; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); @@ -157,13 +157,16 @@ namespace MWMechanics if(target.getClass().getCreatureStats(target).isDead()) return true; - if (!actor.getClass().isNpc() && target == MWBase::Environment::get().getWorld()->getPlayerPtr() && - (actor.getClass().canSwim(actor) && !actor.getClass().canWalk(actor) // pure water creature - && !MWBase::Environment::get().getWorld()->isSwimming(target)) // Player moved out of water - || (!actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(target))) // creature can't swim to Player + const MWWorld::Class& actorClass = actor.getClass(); + MWBase::World& world = *MWBase::Environment::get().getWorld(); + + if ((!actorClass.isNpc() && target == world.getPlayerPtr() && + actorClass.canSwim(actor) && !actorClass.canWalk(actor) // pure water creature + && !world.isSwimming(target)) // Player moved out of water + || (!actorClass.canSwim(actor) && world.isSwimming(target))) // creature can't swim to Player { - actor.getClass().getCreatureStats(actor).setHostile(false); - actor.getClass().getCreatureStats(actor).setAttackingOrSpell(false); + actorClass.getCreatureStats(actor).setHostile(false); + actorClass.getCreatureStats(actor).setAttackingOrSpell(false); return true; } @@ -360,9 +363,9 @@ namespace MWMechanics if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) { //Melee and Close-up combat - + // if we preserve dir.z then horizontal angle can be inaccurate - mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); + mMovement.mRotation[2] = getZAngleToDir(Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0)); // (not quite strike dist while following) if (mFollowTarget && distToTarget > rangeAttack) @@ -408,7 +411,7 @@ namespace MWMechanics { bool preferShortcut = false; bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); - + // check if shortcut is available if(inLOS && (!isStuck || mReadyToAttack) && (!mForceNoShortcut || (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) From bfd91c0681ee766256a0295a2c3f8b0502397167 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 12:31:08 +0200 Subject: [PATCH 5/7] Fix potential NpcStats overwriting issue --- apps/openmw/mwmechanics/npcstats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 24e758e32..d50f2c5ae 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -496,10 +496,10 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state) mExpelled.insert (iter->first); if (iter->second.mRank >= 0) - mFactionRank.insert (std::make_pair (iter->first, iter->second.mRank)); + mFactionRank[iter->first] = iter->second.mRank; if (iter->second.mReputation) - mFactionReputation.insert (std::make_pair (iter->first, iter->second.mReputation)); + mFactionReputation[iter->first] = iter->second.mReputation; } mDisposition = state.mDisposition; From f629307f6050e69cfa295cee59ffbb00b9656591 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 16:43:19 +0200 Subject: [PATCH 6/7] Fix frame delay for sound listener position (Fixes #1180) --- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 727b200f5..43153612d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1375,11 +1375,11 @@ namespace MWWorld updateWeather(duration); - mWorldScene->update (duration, paused); - if (!paused) doPhysics (duration); + mWorldScene->update (duration, paused); + performUpdateSceneQueries (); updateWindowManager (); From 3cd835e61a4a2e1b8e9d28fee5fa1a570459a96d Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 May 2014 17:34:36 +0200 Subject: [PATCH 7/7] Fix bsa file loading not being case insensitive (Fixes #1178) --- apps/openmw/mwworld/esmstore.cpp | 2 +- components/files/collections.cpp | 35 ++++++++++++++++++----- files/mygui/openmw_settings_window.layout | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 1fdf3c5a5..fc2bd4d77 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -42,7 +42,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) for (int i = 0; i < esm.getIndex(); i++) { const std::string &candidate = allPlugins->at(i).getContext().filename; std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); - if (fname == fnamecandidate) { + if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { index = i; break; } diff --git a/components/files/collections.cpp b/components/files/collections.cpp index c6195d88c..a933eb682 100644 --- a/components/files/collections.cpp +++ b/components/files/collections.cpp @@ -1,6 +1,7 @@ - #include "collections.hpp" +#include + namespace Files { Collections::Collections() @@ -36,9 +37,19 @@ namespace Files for (Files::PathContainer::const_iterator iter = mDirectories.begin(); iter != mDirectories.end(); ++iter) { - const boost::filesystem::path path = *iter / file; - if (boost::filesystem::exists(path)) - return path.string(); + for (boost::filesystem::directory_iterator iter2 (*iter); + iter2!=boost::filesystem::directory_iterator(); ++iter2) + { + boost::filesystem::path path = *iter2; + + if (mFoldCase) + { + if (Misc::StringUtils::ciEqual(file, path.filename().string())) + return path.string(); + } + else if (path.filename().string() == file) + return path.string(); + } } throw std::runtime_error ("file " + file + " not found"); @@ -49,9 +60,19 @@ namespace Files for (Files::PathContainer::const_iterator iter = mDirectories.begin(); iter != mDirectories.end(); ++iter) { - const boost::filesystem::path path = *iter / file; - if (boost::filesystem::exists(path)) - return true; + for (boost::filesystem::directory_iterator iter2 (*iter); + iter2!=boost::filesystem::directory_iterator(); ++iter2) + { + boost::filesystem::path path = *iter2; + + if (mFoldCase) + { + if (Misc::StringUtils::ciEqual(file, path.filename().string())) + return true; + } + else if (path.filename().string() == file) + return true; + } } return false; diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 6119ab7b4..9ecae465c 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -417,7 +417,7 @@ - +