diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 73fa92529..71a45a92c 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -541,6 +541,8 @@ namespace MWBase /// Resets all actors in the current active cells to their original location within that cell. virtual void resetActors() = 0; + + virtual bool isWalkingOnWater (const MWWorld::Ptr& actor) = 0; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 0d88a2e10..7753dc568 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -230,7 +230,7 @@ namespace MWClass const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat(); const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat(); MWMechanics::DynamicStat fatigue = stats.getFatigue(); - const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr); + const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult; if (!weapon.isEmpty()) fatigueLoss += weapon.getClass().getWeight(weapon) * stats.getAttackStrength() * fWeaponFatigueMult; @@ -537,7 +537,7 @@ namespace MWClass const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects(); - const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr); + const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run); @@ -738,7 +738,7 @@ namespace MWClass { MWBase::World *world = MWBase::Environment::get().getWorld(); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - if(world->isUnderwater(ptr.getCell(), pos)) + if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) return 2; if(world->isOnGround(ptr)) return 0; @@ -748,7 +748,7 @@ namespace MWClass { MWBase::World *world = MWBase::Environment::get().getWorld(); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - if(world->isUnderwater(ptr.getCell(), pos)) + if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) return 3; if(world->isOnGround(ptr)) return 1; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5d5b8a689..4149d31d3 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -302,11 +302,11 @@ namespace MWClass Misc::StringUtils::toLower(faction); if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { - data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank; + data->mNpcStats.setFactionRank(faction, (int)ref->mBase->mNpdt52.mRank); } else { - data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt12.mRank; + data->mNpcStats.setFactionRank(faction, (int)ref->mBase->mNpdt12.mRank); } } @@ -495,7 +495,7 @@ namespace MWClass const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat(); const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat(); MWMechanics::DynamicStat fatigue = getCreatureStats(ptr).getFatigue(); - const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr); + const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult; if (!weapon.isEmpty()) fatigueLoss += weapon.getClass().getWeight(weapon) * getNpcStats(ptr).getAttackStrength() * fWeaponFatigueMult; @@ -911,7 +911,7 @@ namespace MWClass const NpcCustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects(); - const float normalizedEncumbrance = Npc::getEncumbrance(ptr) / Npc::getCapacity(ptr); + const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); bool sneaking = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak); bool running = ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run); @@ -927,7 +927,7 @@ namespace MWClass gmst.fAthleticsRunBonus->getFloat() + gmst.fBaseRunMultiplier->getFloat()); float moveSpeed; - if(normalizedEncumbrance >= 1.0f) + if(getEncumbrance(ptr) > getCapacity(ptr)) moveSpeed = 0.0f; else if(mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled()) @@ -1222,7 +1222,7 @@ namespace MWClass Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); if(world->isSwimming(ptr)) return "Swim Left"; - if(world->isUnderwater(ptr.getCell(), pos)) + if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) return "FootWaterLeft"; if(world->isOnGround(ptr)) { @@ -1249,7 +1249,7 @@ namespace MWClass Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); if(world->isSwimming(ptr)) return "Swim Right"; - if(world->isUnderwater(ptr.getCell(), pos)) + if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) return "FootWaterRight"; if(world->isOnGround(ptr)) { @@ -1274,7 +1274,7 @@ namespace MWClass { MWBase::World *world = MWBase::Environment::get().getWorld(); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - if(world->isUnderwater(ptr.getCell(), pos)) + if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) return "DefaultLandWater"; if(world->isOnGround(ptr)) return "Body Fall Medium"; diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 2888a6e08..629d99cc2 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -68,7 +68,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const return false; MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor); - std::map::iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction)); + std::map::const_iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction)); if (iter==stats.getFactionRanks().end()) return false; @@ -112,7 +112,7 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const if (!info.mPcFaction.empty()) { MWMechanics::NpcStats& stats = player.getClass().getNpcStats (player); - std::map::iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase (info.mPcFaction)); + std::map::const_iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase (info.mPcFaction)); if(iter==stats.getFactionRanks().end()) return false; @@ -379,7 +379,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty()) return 0; - std::pair faction = + const std::pair faction = *mActor.getClass().getNpcStats (mActor).getFactionRanks().begin(); int rank = getFactionRank (player, faction.first); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index a4e5bbc16..9ef926bd3 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -333,7 +333,8 @@ namespace MWGui float e1 = 0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(); float f1 = 0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(); - float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); + float dispositionTerm = gmst.find("fDispositionMod")->getFloat() * (clampedDisposition - 50); + float pcTerm = (dispositionTerm - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); float x = gmst.find("fBargainOfferMulti")->getFloat() * d + gmst.find("fBargainOfferBase")->getFloat(); if (buying) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 10cd34749..29b166a6a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -385,7 +385,7 @@ namespace MWInput { MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); mOverencumberedMessageDelay -= dt; - if (player.getClass().getEncumbrance(player) >= player.getClass().getCapacity(player)) + if (player.getClass().getEncumbrance(player) > player.getClass().getCapacity(player)) { mPlayer->setAutoMove (false); if (mOverencumberedMessageDelay <= 0) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 82f60221b..da6aec0be 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -445,9 +445,7 @@ namespace MWMechanics int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); - float capacity = ptr.getClass().getCapacity(ptr); - float encumbrance = ptr.getClass().getEncumbrance(ptr); - float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); + float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr); if (normalizedEncumbrance > 1) normalizedEncumbrance = 1; @@ -1447,6 +1445,8 @@ namespace MWMechanics continue; if (followTarget == actor) list.push_back(iter->first); + else + break; } else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) break; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 7c7ea0c95..f39a80d48 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1428,7 +1428,9 @@ void CharacterController::update(float duration) const MWWorld::Store &gmst = world->getStore().get(); const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat(); const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat(); - const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr); + float normalizedEncumbrance = mPtr.getClass().getNormalizedEncumbrance(mPtr); + if (normalizedEncumbrance > 1) + normalizedEncumbrance = 1; const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; DynamicStat fatigue = cls.getCreatureStats(mPtr).getFatigue(); fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index f48e82324..9225a5799 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -124,7 +124,7 @@ namespace MWMechanics const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); MWMechanics::DynamicStat fatigue = blockerStats.getFatigue(); - float normalizedEncumbrance = blocker.getClass().getEncumbrance(blocker) / blocker.getClass().getCapacity(blocker); + float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker); normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; fatigueLoss += weapon.getClass().getWeight(weapon) * attackerStats.getAttackStrength() * fWeaponFatigueBlockMult; diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 370c47b1f..13fc14318 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -69,9 +69,41 @@ const std::map& MWMechanics::NpcStats::getFactionRanks() const return mFactionRank; } -std::map& MWMechanics::NpcStats::getFactionRanks() +void MWMechanics::NpcStats::raiseRank(const std::string &faction) { - return mFactionRank; + const std::string lower = Misc::StringUtils::lowerCase(faction); + std::map::iterator it = mFactionRank.find(lower); + if (it != mFactionRank.end()) + { + // Does the next rank exist? + const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get().find(lower); + if (it->second+1 < 10 && !faction->mRanks[it->second+1].empty()) + it->second += 1; + } +} + +void MWMechanics::NpcStats::lowerRank(const std::string &faction) +{ + const std::string lower = Misc::StringUtils::lowerCase(faction); + std::map::iterator it = mFactionRank.find(lower); + if (it != mFactionRank.end()) + { + it->second = std::max(0, it->second-1); + } +} + +void MWMechanics::NpcStats::setFactionRank(const std::string &faction, int rank) +{ + const std::string lower = Misc::StringUtils::lowerCase(faction); + mFactionRank[lower] = rank; +} + +void MWMechanics::NpcStats::joinFaction(const std::string& faction) +{ + const std::string lower = Misc::StringUtils::lowerCase(faction); + std::map::iterator it = mFactionRank.find(lower); + if (it == mFactionRank.end()) + mFactionRank[lower] = 0; } bool MWMechanics::NpcStats::getExpelled(const std::string& factionID) const diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 4ea5d4578..ee897033b 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -70,7 +70,15 @@ namespace MWMechanics SkillValue& getSkill (int index); const std::map& getFactionRanks() const; - std::map& getFactionRanks(); + /// Increase the rank in this faction by 1, if such a rank exists. + void raiseRank(const std::string& faction); + /// Lower the rank in this faction by 1, if such a rank exists. + void lowerRank(const std::string& faction); + /// Join this faction, setting the initial rank to 0. + void joinFaction(const std::string& faction); + /// Warning: this function performs no check whether the rank exists, + /// and should be used in initial actor setup only. + void setFactionRank(const std::string& faction, int rank); const std::set& getExpelled() const { return mExpelled; } bool getExpelled(const std::string& factionID) const; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 373ca7af9..fab512a0d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -774,7 +774,7 @@ namespace MWMechanics static const float fFatigueSpellBase = store.get().find("fFatigueSpellBase")->getFloat(); static const float fFatigueSpellMult = store.get().find("fFatigueSpellMult")->getFloat(); DynamicStat fatigue = stats.getFatigue(); - const float normalizedEncumbrance = mCaster.getClass().getEncumbrance(mCaster) / mCaster.getClass().getCapacity(mCaster); + const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster); float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult); fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 12ba3c2da..625d0706f 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -728,7 +728,7 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co { MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager::PlayType type = MWBase::SoundManager::Play_TypeSfx; - if(evt.compare(10, evt.size()-10, "left") == 0 || evt.compare(10, evt.size()-10, "right") == 0) + if(evt.compare(10, evt.size()-10, "left") == 0 || evt.compare(10, evt.size()-10, "right") == 0 || evt.compare(10, evt.size()-10, "land") == 0) type = MWBase::SoundManager::Play_TypeFoot; sndMgr->playSound3D(mPtr, sound, volume, pitch, type); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6ed11b71f..4fbc55089 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -250,7 +250,6 @@ void RenderingManager::cellAdded (MWWorld::CellStore *store) mObjects->buildStaticGeometry (*store); sh::Factory::getInstance().unloadUnreferencedMaterials(); mDebugging->cellAdded(store); - waterAdded(store); } void RenderingManager::addObject (const MWWorld::Ptr& ptr){ @@ -421,18 +420,12 @@ void RenderingManager::postRenderTargetUpdate(const RenderTargetEvent &evt) mOcclusionQuery->setActive(false); } -void RenderingManager::waterAdded (MWWorld::CellStore *store) +void RenderingManager::setWaterEnabled(bool enable) { - if (store->getCell()->mData.mFlags & ESM::Cell::HasWater) - { - mWater->changeCell (store->getCell()); - mWater->setActive(true); - } - else - removeWater(); + mWater->setActive(enable); } -void RenderingManager::setWaterHeight(const float height) +void RenderingManager::setWaterHeight(float height) { mWater->setHeight(height); } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 2da084074..c3eedce7b 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -100,7 +100,6 @@ public: /// \todo this function should be removed later. Instead the rendering subsystems should track /// when rebatching is needed and update automatically at the end of each frame. void cellAdded (MWWorld::CellStore *store); - void waterAdded(MWWorld::CellStore *store); /// Clear all savegame-specific data (i.e. fog of war textures) void clear(); @@ -121,7 +120,8 @@ public: /// Updates an object's rotation void rotateObject (const MWWorld::Ptr& ptr); - void setWaterHeight(const float height); + void setWaterHeight(float height); + void setWaterEnabled(bool enabled); bool toggleWater(); bool toggleWorld(); diff --git a/apps/openmw/mwrender/weaponanimation.cpp b/apps/openmw/mwrender/weaponanimation.cpp index cd9ae16b8..a409e8807 100644 --- a/apps/openmw/mwrender/weaponanimation.cpp +++ b/apps/openmw/mwrender/weaponanimation.cpp @@ -81,7 +81,7 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor) const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat(); MWMechanics::CreatureStats& attackerStats = actor.getClass().getCreatureStats(actor); MWMechanics::DynamicStat fatigue = attackerStats.getFatigue(); - const float normalizedEncumbrance = actor.getClass().getEncumbrance(actor) / actor.getClass().getCapacity(actor); + const float normalizedEncumbrance = actor.getClass().getNormalizedEncumbrance(actor); float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult; if (!weapon->isEmpty()) fatigueLoss += weapon->getClass().getWeight(*weapon) * attackerStats.getAttackStrength() * fWeaponFatigueMult; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 21fee5f57..c43a010b4 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -310,7 +310,7 @@ namespace MWScript std::string InterpreterContext::getNPCRank() const { - std::map ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks(); + const std::map& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks(); std::map::const_iterator it = ranks.begin(); MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -348,7 +348,7 @@ namespace MWScript std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; - std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); + const std::map& ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); int rank = -1; if (it != ranks.end()) @@ -375,7 +375,7 @@ namespace MWScript std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; - std::map ranks = player.getClass().getNpcStats (player).getFactionRanks(); + const std::map& ranks = player.getClass().getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.find(factionId); int rank = -1; if (it != ranks.end()) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index c012cb12e..91f6d2abe 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -548,10 +548,7 @@ namespace MWScript if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) == player.getClass().getNpcStats(player).getFactionRanks().end()) - { - player.getClass().getNpcStats(player).getFactionRanks()[factionID] = 0; - } + player.getClass().getNpcStats(player).joinFaction(factionID); } } }; @@ -585,13 +582,11 @@ namespace MWScript MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) == player.getClass().getNpcStats(player).getFactionRanks().end()) { - player.getClass().getNpcStats(player).getFactionRanks()[factionID] = 0; + player.getClass().getNpcStats(player).joinFaction(factionID); } else { - player.getClass().getNpcStats(player).getFactionRanks()[factionID] = - std::min(player.getClass().getNpcStats(player).getFactionRanks()[factionID] +1, - 9); + player.getClass().getNpcStats(player).raiseRank(factionID); } } } @@ -624,11 +619,7 @@ namespace MWScript if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) != player.getClass().getNpcStats(player).getFactionRanks().end()) - { - player.getClass().getNpcStats(player).getFactionRanks()[factionID] = - std::max(0, player.getClass().getNpcStats(player).getFactionRanks()[factionID]-1); - } + player.getClass().getNpcStats(player).lowerRank(factionID); } } }; @@ -668,7 +659,7 @@ namespace MWScript { if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) != player.getClass().getNpcStats(player).getFactionRanks().end()) { - runtime.push(player.getClass().getNpcStats(player).getFactionRanks()[factionID]); + runtime.push(player.getClass().getNpcStats(player).getFactionRanks().at(factionID)); } else { @@ -1036,8 +1027,7 @@ namespace MWScript if (ptr == player) return; - std::map& ranks = ptr.getClass().getNpcStats(ptr).getFactionRanks (); - ranks[factionID] = std::min(9, ranks[factionID]+1); + ptr.getClass().getNpcStats(ptr).raiseRank(factionID); } }; @@ -1063,8 +1053,7 @@ namespace MWScript if (ptr == player) return; - std::map& ranks = ptr.getClass().getNpcStats(ptr).getFactionRanks (); - ranks[factionID] = std::max(0, ranks[factionID]-1); + ptr.getClass().getNpcStats(ptr).lowerRank(factionID); } }; diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 3368aa1c0..7fd6ba024 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -5,6 +5,23 @@ #include "../mwbase/mechanicsmanager.hpp" #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, @@ -16,8 +33,9 @@ namespace MWWorld void ActionTeleport::executeImp (const Ptr& actor) { //find any NPC that is following the actor and teleport him too - std::list followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor); - for(std::list::iterator it = followers.begin();it != followers.end();++it) + std::set followers; + getFollowers(actor, followers); + for(std::set::iterator it = followers.begin();it != followers.end();++it) { teleport(*it); } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index ebe08dc44..ea1c8827a 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -420,4 +420,13 @@ namespace MWWorld { throw std::runtime_error("this is not a door"); } + + float Class::getNormalizedEncumbrance(const Ptr &ptr) const + { + float capacity = getCapacity(ptr); + if (capacity == 0) + return 1.f; + + return getEncumbrance(ptr) / capacity; + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 8ac39eaa9..33b5f1e66 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -223,6 +223,9 @@ namespace MWWorld /// effects). Throws an exception, if the object can't hold other objects. /// (default implementation: throws an exception) + virtual float getNormalizedEncumbrance (const MWWorld::Ptr& ptr) const; + ///< Returns encumbrance re-scaled to capacity + virtual bool apply (const MWWorld::Ptr& ptr, const std::string& id, const MWWorld::Ptr& actor) const; ///< Apply \a id on \a ptr. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index f515f1efb..ecc679013 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -68,6 +68,7 @@ MWWorld::InventoryStore::InventoryStore() , mUpdatesEnabled (true) , mFirstAutoEquip(true) , mListener(NULL) + , mRechargingItemsUpToDate(false) { initSlots (mSlots); } @@ -80,6 +81,7 @@ MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) , mListener(store.mListener) , mUpdatesEnabled(store.mUpdatesEnabled) , mPermanentMagicEffectMagnitudes(store.mPermanentMagicEffectMagnitudes) + , mRechargingItemsUpToDate(false) { copySlots (store); } @@ -90,6 +92,7 @@ MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStor mMagicEffects = store.mMagicEffects; mFirstAutoEquip = store.mFirstAutoEquip; mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes; + mRechargingItemsUpToDate = false; ContainerStore::operator= (store); mSlots.clear(); copySlots (store); @@ -110,8 +113,6 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, autoEquip(actorPtr); } - updateRechargingItems(); - return retVal; } @@ -485,8 +486,6 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor mSelectedEnchantItem = end(); } - updateRechargingItems(); - return retCount; } @@ -606,6 +605,11 @@ void MWWorld::InventoryStore::updateRechargingItems() void MWWorld::InventoryStore::rechargeItems(float duration) { + if (!mRechargingItemsUpToDate) + { + updateRechargingItems(); + mRechargingItemsUpToDate = true; + } for (TRechargingItems::iterator it = mRechargingItems.begin(); it != mRechargingItems.end(); ++it) { if (it->first->getCellRef().getEnchantmentCharge() == -1 diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 41caae4e5..16d965cda 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -102,6 +102,8 @@ namespace MWWorld typedef std::vector > TRechargingItems; TRechargingItems mRechargingItems; + bool mRechargingItemsUpToDate; + void copySlots (const InventoryStore& store); void initSlots (TSlots& slots_); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index f35dba587..ec6f04be1 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -278,8 +278,10 @@ namespace MWWorld if (!ptr.getClass().canWalk(ptr) && !ptr.getClass().canFly(ptr) && !ptr.getClass().canSwim(ptr)) return position; - /* Anything to collide with? */ OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); + // Reset per-frame data + physicActor->setWalkingOnWater(false); + /* Anything to collide with? */ if(!physicActor || !physicActor->getCollisionMode()) { return position + (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * @@ -307,9 +309,6 @@ namespace MWWorld */ OEngine::Physic::ActorTracer tracer; - bool isOnGround = physicActor->getOnGround(); - if (movement.z > 0.f) - isOnGround = false; Ogre::Vector3 inertia(0.0f); Ogre::Vector3 velocity; @@ -426,8 +425,6 @@ namespace MWWorld if((ptr.getClass().canSwim(ptr) && !ptr.getClass().canWalk(ptr)) && newPosition.z > (waterlevel - halfExtents.z * 0.5)) newPosition = oldPosition; - else // Only on the ground if there's gravity - isOnGround = !(newPosition.z < waterlevel || isFlying); } else { @@ -444,10 +441,11 @@ namespace MWWorld } } - if (!(inertia.z > 0.f) && !(newPosition.z < waterlevel || isFlying)) + bool isOnGround = false; + if (!(inertia.z > 0.f) && !(newPosition.z < waterlevel)) { Ogre::Vector3 from = newPosition; - Ogre::Vector3 to = newPosition - (isOnGround ? + Ogre::Vector3 to = newPosition - (physicActor->getOnGround() ? Ogre::Vector3(0,0,sStepSize+2.f) : Ogre::Vector3(0,0,2.f)); tracer.doTrace(colobj, from, to, engine); if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) @@ -457,8 +455,11 @@ namespace MWWorld { standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName; } + if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Water) + physicActor->setWalkingOnWater(true); - newPosition.z = tracer.mEndPos.z + 1.0f; + if (!isFlying) + newPosition.z = tracer.mEndPos.z + 1.0f; isOnGround = true; } @@ -485,7 +486,7 @@ namespace MWWorld PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) : - mRender(_rend), mEngine(0), mTimeAccum(0.0f) + mRender(_rend), mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0) { // Create physics. shapeLoader is deleted by the physic engine NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); @@ -494,6 +495,8 @@ namespace MWWorld PhysicsSystem::~PhysicsSystem() { + if (mWaterCollisionObject.get()) + mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get()); delete mEngine; } @@ -661,9 +664,9 @@ namespace MWWorld Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); handleToMesh[node->getName()] = mesh; mEngine->createAndAdjustRigidBody( - mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, false, placeable); + mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, false, placeable); mEngine->createAndAdjustRigidBody( - mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true, placeable); + mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, true, placeable); } void PhysicsSystem::addActor (const Ptr& ptr) @@ -855,14 +858,8 @@ namespace MWWorld Ogre::Vector3(iter->first.getRefData().getPosition().pos))) waterCollision = true; - btStaticPlaneShape planeShape(btVector3(0,0,1), waterlevel); - btCollisionObject object; - object.setCollisionShape(&planeShape); - - // TODO: this seems to have a slight performance impact - if (waterCollision) - mEngine->mDynamicsWorld->addCollisionObject(&object, - 0xff, OEngine::Physic::CollisionType_Actor); + OEngine::Physic::PhysicActor *physicActor = mEngine->getCharacter(iter->first.getRefData().getHandle()); + physicActor->setCanWaterWalk(waterCollision); // 100 points of slowfall reduce gravity by 90% (this is just a guess) float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).getMagnitude() / 100.f) * 0.9f), 0.9f); @@ -871,9 +868,6 @@ namespace MWWorld world->isFlying(iter->first), waterlevel, slowFall, mEngine, mCollisions, mStandingCollisions); - if (waterCollision) - mEngine->mDynamicsWorld->removeCollisionObject(&object); - float heightDiff = newpos.z - oldHeight; if (heightDiff < 0) @@ -949,4 +943,48 @@ namespace MWWorld } } + void PhysicsSystem::disableWater() + { + if (mWaterEnabled) + { + mWaterEnabled = false; + updateWater(); + } + } + + void PhysicsSystem::enableWater(float height) + { + if (!mWaterEnabled || mWaterHeight != height) + { + mWaterEnabled = true; + mWaterHeight = height; + updateWater(); + } + } + + void PhysicsSystem::setWaterHeight(float height) + { + if (mWaterHeight != height) + { + mWaterHeight = height; + updateWater(); + } + } + + void PhysicsSystem::updateWater() + { + if (mWaterCollisionObject.get()) + { + mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get()); + } + + if (!mWaterEnabled) + return; + + mWaterCollisionObject.reset(new btCollisionObject()); + mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight)); + mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get()); + mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water, + OEngine::Physic::CollisionType_Actor); + } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index e66c179b0..7dc8acaa1 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -1,6 +1,8 @@ #ifndef GAME_MWWORLD_PHYSICSSYSTEM_H #define GAME_MWWORLD_PHYSICSSYSTEM_H +#include + #include #include @@ -32,6 +34,10 @@ namespace MWWorld PhysicsSystem (OEngine::Render::OgreRenderer &_rend); ~PhysicsSystem (); + void enableWater(float height); + void setWaterHeight(float height); + void disableWater(); + void addObject (const MWWorld::Ptr& ptr, bool placeable=false); void addActor (const MWWorld::Ptr& ptr); @@ -108,6 +114,8 @@ namespace MWWorld private: + void updateWater(); + OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; std::map handleToMesh; @@ -124,6 +132,12 @@ namespace MWWorld float mTimeAccum; + float mWaterHeight; + float mWaterEnabled; + + std::auto_ptr mWaterCollisionObject; + std::auto_ptr mWaterCollisionShape; + PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); }; diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index b04f67b00..afda6fe60 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -153,7 +153,8 @@ namespace MWWorld Ogre::Vector3 pos(it->mNode->getPosition()); Ogre::Vector3 newPos = pos + direction * duration * speed; - it->mSound->setPosition(newPos); + if (it->mSound.get()) + it->mSound->setPosition(newPos); it->mNode->setPosition(newPos); @@ -163,7 +164,8 @@ namespace MWWorld // TODO: use a proper btRigidBody / btGhostObject? btVector3 from(pos.x, pos.y, pos.z); btVector3 to(newPos.x, newPos.y, newPos.z); - std::vector > collisions = mPhysEngine.rayTest2(from, to); + + std::vector > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile); bool hit=false; for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) @@ -239,7 +241,7 @@ namespace MWWorld // TODO: use a proper btRigidBody / btGhostObject? btVector3 from(pos.x, pos.y, pos.z); btVector3 to(newPos.x, newPos.y, newPos.z); - std::vector > collisions = mPhysEngine.rayTest2(from, to); + std::vector > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile); bool hit=false; for (std::vector >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) @@ -408,6 +410,7 @@ namespace MWWorld MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); state.mSound = sndMgr->playManualSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + state.mSoundId = esm.mSound; mMagicBolts.push_back(state); return true; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c98485dc9..66c9f5b71 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -83,7 +83,12 @@ namespace ptr.getClass().insertObject (ptr, mPhysics); updateObjectLocalRotation(ptr, mPhysics, mRendering); - MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale()); + if (ptr.getRefData().getBaseNode()) + { + float scale = ptr.getCellRef().getScale(); + ptr.getClass().adjustScale(ptr, scale); + mRendering.scaleObject(ptr, Ogre::Vector3(scale)); + } ptr.getClass().adjustPosition (ptr, false); } catch (const std::exception& e) @@ -233,6 +238,15 @@ namespace MWWorld insertCell (*cell, true, loadingListener); mRendering.cellAdded (cell); + bool waterEnabled = cell->getCell()->hasWater(); + mRendering.setWaterEnabled(waterEnabled); + if (waterEnabled) + { + mPhysics->enableWater(cell->getWaterLevel()); + mRendering.setWaterHeight(cell->getWaterLevel()); + } + else + mPhysics->disableWater(); mRendering.configureAmbient(*cell); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 28a44d3ba..dd6e7d7fc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1660,6 +1660,7 @@ namespace MWWorld void World::setWaterHeight(const float height) { + mPhysics->setWaterHeight(height); mRendering->setWaterHeight(height); } @@ -1994,7 +1995,7 @@ namespace MWWorld Ogre::Vector3 playerPos(refdata.getPosition().pos); const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle()); - if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos)) + if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos) || isWalkingOnWater(player)) return 2; if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) || player.getClass().getNpcStats(player).isWerewolf()) @@ -3071,4 +3072,12 @@ namespace MWWorld cellstore->forEach(functor); } } + + bool World::isWalkingOnWater(const Ptr &actor) + { + OEngine::Physic::PhysicActor* physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); + if (physicActor && physicActor->isWalkingOnWater()) + return true; + return false; + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 1a25edbe5..a05d450d5 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -615,6 +615,8 @@ namespace MWWorld /// Resets all actors in the current active cells to their original location within that cell. virtual void resetActors(); + + virtual bool isWalkingOnWater (const MWWorld::Ptr& actor); }; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index b4d5e49a5..0c61253bf 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -74,6 +74,8 @@ namespace Physic , mExternalCollisionMode(true) , mForce(0.0f) , mScale(scale) + , mWalkingOnWater(false) + , mCanWaterWalk(false) { if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation)) { @@ -103,8 +105,7 @@ namespace Physic setPosition(position); setRotation(rotation); - mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, - CollisionType_Actor|CollisionType_World|CollisionType_HeightMap); + updateCollisionMask(); } PhysicActor::~PhysicActor() @@ -123,10 +124,22 @@ namespace Physic void PhysicActor::enableCollisionBody(bool collision) { - assert(mBody); - if(collision && !mExternalCollisionMode) enableCollisionBody(); - if(!collision && mExternalCollisionMode) disableCollisionBody(); - mExternalCollisionMode = collision; + if (mExternalCollisionMode != collision) + { + mExternalCollisionMode = collision; + updateCollisionMask(); + } + } + + void PhysicActor::updateCollisionMask() + { + mEngine->mDynamicsWorld->removeRigidBody(mBody); + int collisionMask = CollisionType_World | CollisionType_HeightMap; + if (mExternalCollisionMode) + collisionMask |= CollisionType_Actor | CollisionType_Projectile; + if (mCanWaterWalk) + collisionMask |= CollisionType_Water; + mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, collisionMask); } const Ogre::Vector3& PhysicActor::getPosition() const @@ -178,18 +191,23 @@ namespace Physic mOnGround = grounded; } - void PhysicActor::disableCollisionBody() + bool PhysicActor::isWalkingOnWater() const { - mEngine->mDynamicsWorld->removeRigidBody(mBody); - mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, - CollisionType_World|CollisionType_HeightMap); + return mWalkingOnWater; } - void PhysicActor::enableCollisionBody() + void PhysicActor::setWalkingOnWater(bool walkingOnWater) { - mEngine->mDynamicsWorld->removeRigidBody(mBody); - mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, - CollisionType_Actor|CollisionType_World|CollisionType_HeightMap); + mWalkingOnWater = walkingOnWater; + } + + void PhysicActor::setCanWaterWalk(bool waterWalk) + { + if (waterWalk != mCanWaterWalk) + { + mCanWaterWalk = waterWalk; + updateCollisionMask(); + } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -381,7 +399,7 @@ namespace Physic mHeightFieldMap [name] = hf; mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap, - CollisionType_Actor|CollisionType_Raycasting); + CollisionType_Actor|CollisionType_Raycasting|CollisionType_Projectile); } void PhysicEngine::removeHeightField(int x, int y) @@ -494,7 +512,7 @@ namespace Physic { assert (mRaycastingObjectMap.find(name) == mRaycastingObjectMap.end()); mRaycastingObjectMap[name] = body; - mDynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting); + mDynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_Projectile); } return body; @@ -800,10 +818,10 @@ namespace Physic return std::make_pair(false, 1); } - std::vector< std::pair > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to) + std::vector< std::pair > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to, int filterGroup) { MyRayResultCallback resultCallback1; - resultCallback1.m_collisionFilterGroup = 0xff; + resultCallback1.m_collisionFilterGroup = filterGroup; resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor|CollisionType_HeightMap; mDynamicsWorld->rayTest(from, to, resultCallback1); std::vector< std::pair > results = resultCallback1.results; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 0d280c4fe..a77b60ab6 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -46,7 +46,9 @@ namespace Physic CollisionType_World = 1<<0, // mShape; @@ -288,7 +301,7 @@ namespace Physic /** * Return all objects hit by a ray. */ - std::vector< std::pair > rayTest2(const btVector3 &from, const btVector3 &to); + std::vector< std::pair > rayTest2(const btVector3 &from, const btVector3 &to, int filterGroup=0xff); std::pair sphereCast (float radius, btVector3& from, btVector3& to); ///< @return (hit, relative distance)