diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 0f414972fb..bd0d2ea4ad 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace osg @@ -200,6 +201,10 @@ namespace MWBase virtual std::list getEnemiesNearby(const MWWorld::Ptr& actor) = 0; + /// Recursive versions of above methods + virtual void getActorsFollowing(const MWWorld::Ptr& actor, std::set& out) = 0; + virtual void getActorsSidingWith(const MWWorld::Ptr& actor, std::set& out) = 0; + virtual void playerLoaded() = 0; virtual int countSavedGameRecords() const = 0; diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 8c55c37329..3063b3268f 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -55,7 +55,7 @@ namespace MWGui void TravelWindow::addDestination(const std::string& name,ESM::Position pos,bool interior) { - int price = 0; + int price; const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -70,14 +70,21 @@ namespace MWGui else { ESM::Position PlayerPos = player.getRefData().getPosition(); - float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) ); + float d = sqrt(pow(pos.pos[0] - PlayerPos.pos[0], 2) + pow(pos.pos[1] - PlayerPos.pos[1], 2) + pow(pos.pos[2] - PlayerPos.pos[2], 2)); price = static_cast(d / gmst.find("fTravelMult")->getFloat()); } - price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true); + + // Add price for the travelling followers + std::set followers; + MWWorld::ActionTeleport::getFollowersToTeleport(player, followers); + + // Apply followers cost, in vanilla one follower travels for free + price *= std::max(1, static_cast(followers.size())); MyGUI::Button* toAdd = mDestinationsView->createWidget("SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default); - toAdd->setEnabled(price<=playerGold); + toAdd->setEnabled(price <= playerGold); mCurrentY += sLineHeight; if(interior) toAdd->setUserString("interior","y"); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 23a6f497ff..af8a47ccf3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1482,6 +1482,20 @@ namespace MWMechanics return list; } + void Actors::getActorsFollowing(const MWWorld::Ptr &actor, std::set& out) { + std::list followers = getActorsFollowing(actor); + for(std::list::iterator it = followers.begin();it != followers.end();++it) + if (out.insert(*it).second) + getActorsFollowing(*it, out); + } + + void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out) { + std::list followers = getActorsSidingWith(actor); + for(std::list::iterator it = followers.begin();it != followers.end();++it) + if (out.insert(*it).second) + getActorsSidingWith(*it, out); + } + std::list Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor) { std::list list; diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 163995f6f9..20aef4c17c 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -123,6 +123,11 @@ namespace MWMechanics std::list getActorsSidingWith(const MWWorld::Ptr& actor); std::list getActorsFollowing(const MWWorld::Ptr& actor); + /// Recursive version of getActorsFollowing + void getActorsFollowing(const MWWorld::Ptr &actor, std::set& out); + /// Recursive version of getActorsSidingWith + void getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out); + /// Get the list of AiFollow::mFollowIndex for all actors following this target std::list getActorsFollowingIndices(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 97fa98b3b4..e552f4683c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -978,18 +978,6 @@ namespace MWMechanics } - void getFollowers (const MWWorld::Ptr& actor, std::set& out) - { - std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(actor); - for(std::list::iterator it = followers.begin();it != followers.end();++it) - { - if (out.insert(*it).second) - { - getFollowers(*it, out); - } - } - } - bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg, bool victimAware) { // NOTE: victim may be empty @@ -1013,7 +1001,7 @@ namespace MWMechanics // get the player's followers / allies (works recursively) that will not report crimes std::set playerFollowers; - getFollowers(player, playerFollowers); + getActorsSidingWith(player, playerFollowers); // Did anyone see it? bool crimeSeen = false; @@ -1437,6 +1425,14 @@ namespace MWMechanics return mActors.getEnemiesNearby(actor); } + void MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor, std::set& out) { + mActors.getActorsFollowing(actor, out); + } + + void MechanicsManager::getActorsSidingWith(const MWWorld::Ptr& actor, std::set& out) { + mActors.getActorsSidingWith(actor, out); + } + int MechanicsManager::countSavedGameRecords() const { return 1 // Death counter diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 04c67fcb63..ed06f58c5a 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -165,6 +165,11 @@ namespace MWMechanics virtual std::list getActorsFighting(const MWWorld::Ptr& actor); virtual std::list getEnemiesNearby(const MWWorld::Ptr& actor); + /// Recursive version of getActorsFollowing + virtual void getActorsFollowing(const MWWorld::Ptr& actor, std::set& out); + /// Recursive version of getActorsSidingWith + virtual void getActorsSidingWith(const MWWorld::Ptr& actor, std::set& out); + virtual bool toggleAI(); virtual bool isAIActive(); diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index c9315283dc..5162cac660 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -8,23 +8,6 @@ #include "player.hpp" -namespace -{ - - void getFollowers (const MWWorld::Ptr& actor, std::set& out) - { - std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); - for(std::list::iterator it = followers.begin();it != followers.end();++it) - { - if (out.insert(*it).second) - { - getFollowers(*it, out); - } - } - } - -} - namespace MWWorld { ActionTeleport::ActionTeleport (const std::string& cellName, @@ -37,21 +20,12 @@ namespace MWWorld { if (mTeleportFollowers) { - //find any NPC that is following the actor and teleport him too + // Find any NPCs that are following the actor and teleport them with him std::set followers; - getFollowers(actor, followers); - for(std::set::iterator it = followers.begin();it != followers.end();++it) - { - MWWorld::Ptr follower = *it; + getFollowersToTeleport(actor, followers); - std::string script = follower.getClass().getScript(follower); - if (!script.empty() && follower.getRefData().getLocals().getIntVar(script, "stayoutside") == 1) - continue; - - if ((follower.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3()).length2() - <= 800*800) - teleport(*it); - } + for (std::set::iterator it = followers.begin(); it != followers.end(); ++it) + teleport(*it); } teleport(actor); @@ -82,4 +56,21 @@ namespace MWWorld world->moveObject(actor,world->getInterior(mCellName),mPosition.pos[0],mPosition.pos[1],mPosition.pos[2]); } } + + void ActionTeleport::getFollowersToTeleport(const MWWorld::Ptr& actor, std::set& out) { + std::set followers; + MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor, followers); + + for(std::set::iterator it = followers.begin();it != followers.end();++it) + { + MWWorld::Ptr follower = *it; + + std::string script = follower.getClass().getScript(follower); + if (!script.empty() && follower.getRefData().getLocals().getIntVar(script, "stayoutside") == 1) + continue; + + if ((follower.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3()).length2() <= 800*800) + out.insert(follower); + } + } } diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index 6191ee9f6f..c582187502 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -1,6 +1,7 @@ #ifndef GAME_MWWORLD_ACTIONTELEPORT_H #define GAME_MWWORLD_ACTIONTELEPORT_H +#include #include #include @@ -23,9 +24,12 @@ namespace MWWorld public: - ActionTeleport (const std::string& cellName, const ESM::Position& position, bool teleportFollowers); - ///< If cellName is empty, an exterior cell is assumed. + /// If cellName is empty, an exterior cell is assumed. /// @param teleportFollowers Whether to teleport any following actors of the target actor as well. + ActionTeleport (const std::string& cellName, const ESM::Position& position, bool teleportFollowers); + + /// Outputs every actor follower who is in teleport range and wasn't ordered to not enter interiors + static void getFollowersToTeleport(const MWWorld::Ptr& actor, std::set& out); }; }