Merge branch 'master' of github.com:OpenMW/openmw

deque
MiroslavR 10 years ago
commit ff74d54e98

@ -1,37 +1,26 @@
os:
- linux
- osx
language: cpp
compiler:
- gcc
branches:
only:
- master
- /openmw-.*$/
before_install:
- pwd
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
- echo "yes" | sudo apt-add-repository ppa:openmw/openmw
- sudo apt-get update -qq
- sudo apt-get install -qq libgtest-dev google-mock
- sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
- sudo mkdir /usr/src/gtest/build
- cd /usr/src/gtest/build
- sudo cmake .. -DBUILD_SHARED_LIBS=1
- sudo make -j4
- sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
- sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_install.osx.sh; fi
before_script:
- cd -
- mkdir build
- cd build
- cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_script.linux.sh; fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script:
- cd ./build
- make -j4
after_script:
- ./openmw_test_suite
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
notifications:
recipients:
- lgromanowski+travis.ci@gmail.com
- corrmage+travis-ci@gmail.com
email:
on_success: change
on_failure: always

@ -0,0 +1,18 @@
#!/bin/sh
export CXX=g++
export CC=gcc
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
echo "yes" | sudo apt-add-repository ppa:openmw/openmw
sudo apt-get update -qq
sudo apt-get install -qq libgtest-dev google-mock
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1
sudo make -j4
sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so

@ -0,0 +1,9 @@
#!/bin/sh
export CXX=clang++
export CC=clang
brew tap openmw/openmw
brew update
brew unlink boost
brew install cmake openmw-mygui openmw-bullet openmw-sdl2 openmw-ffmpeg pkg-config qt unshield

@ -0,0 +1,5 @@
#!/bin/sh
mkdir build
cd build
cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE

@ -0,0 +1,5 @@
#!/bin/sh
mkdir build
cd build
cmake -DCMAKE_FRAMEWORK_PATH="/usr/local/lib/macosx/Release" -DCMAKE_EXE_LINKER_FLAGS="-F/usr/local/lib/macosx/Release" -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" -DCMAKE_BUILD_TYPE=Debug -DBUILD_MYGUI_PLUGIN=OFF -G"Unix Makefiles" ..

@ -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;
};
}

@ -230,7 +230,7 @@ namespace MWClass
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
MWMechanics::DynamicStat<float> 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;

@ -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<float> 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;
@ -914,7 +914,7 @@ namespace MWClass
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(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);
@ -930,7 +930,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())
@ -1225,7 +1225,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))
{
@ -1252,7 +1252,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))
{
@ -1277,7 +1277,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";

@ -68,7 +68,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
return false;
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor);
std::map<std::string, int>::iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction));
std::map<std::string, int>::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<std::string,int>::iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase (info.mPcFaction));
std::map<std::string,int>::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<std::string, int> faction =
const std::pair<std::string, int> faction =
*mActor.getClass().getNpcStats (mActor).getFactionRanks().begin();
int rank = getFactionRank (player, faction.first);

@ -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)

@ -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)

@ -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;

@ -1428,7 +1428,9 @@ void CharacterController::update(float duration)
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
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<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);

@ -124,7 +124,7 @@ namespace MWMechanics
const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat();
const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat();
MWMechanics::DynamicStat<float> 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;

@ -69,9 +69,41 @@ const std::map<std::string, int>& MWMechanics::NpcStats::getFactionRanks() const
return mFactionRank;
}
std::map<std::string, int>& MWMechanics::NpcStats::getFactionRanks()
void MWMechanics::NpcStats::raiseRank(const std::string &faction)
{
return mFactionRank;
const std::string lower = Misc::StringUtils::lowerCase(faction);
std::map<std::string, int>::iterator it = mFactionRank.find(lower);
if (it != mFactionRank.end())
{
// Does the next rank exist?
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().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<std::string, int>::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<std::string, int>::iterator it = mFactionRank.find(lower);
if (it == mFactionRank.end())
mFactionRank[lower] = 0;
}
bool MWMechanics::NpcStats::getExpelled(const std::string& factionID) const

@ -70,7 +70,15 @@ namespace MWMechanics
SkillValue& getSkill (int index);
const std::map<std::string, int>& getFactionRanks() const;
std::map<std::string, int>& 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<std::string>& getExpelled() const { return mExpelled; }
bool getExpelled(const std::string& factionID) const;

@ -774,7 +774,7 @@ namespace MWMechanics
static const float fFatigueSpellBase = store.get<ESM::GameSetting>().find("fFatigueSpellBase")->getFloat();
static const float fFatigueSpellMult = store.get<ESM::GameSetting>().find("fFatigueSpellMult")->getFloat();
DynamicStat<float> 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);

@ -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);
}

@ -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);
}

@ -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();

@ -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<float> 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;

@ -290,18 +290,15 @@ namespace MWScript
const std::string &name = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
int count = 0;
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
for (MWWorld::ContainerStoreIterator it = invStore.begin(MWWorld::ContainerStore::Type_Miscellaneous);
it != invStore.end(); ++it)
{
if (::Misc::StringUtils::ciEqual(it->getCellRef().getSoul(), name))
{
runtime.push(1);
return;
}
++count;
}
runtime.push(0);
runtime.push(count);
}
};

@ -310,7 +310,7 @@ namespace MWScript
std::string InterpreterContext::getNPCRank() const
{
std::map<std::string, int> ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
const std::map<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
std::map<std::string, int>::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<std::string, int> ranks = player.getClass().getNpcStats (player).getFactionRanks();
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
std::map<std::string, int>::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<std::string, int> ranks = player.getClass().getNpcStats (player).getFactionRanks();
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
std::map<std::string, int>::const_iterator it = ranks.find(factionId);
int rank = -1;
if (it != ranks.end())

@ -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<std::string, int>& 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<std::string, int>& ranks = ptr.getClass().getNpcStats(ptr).getFactionRanks ();
ranks[factionID] = std::max(0, ranks[factionID]-1);
ptr.getClass().getNpcStats(ptr).lowerRank(factionID);
}
};

@ -5,6 +5,23 @@
#include "../mwbase/mechanicsmanager.hpp"
#include "player.hpp"
namespace
{
void getFollowers (const MWWorld::Ptr& actor, std::set<MWWorld::Ptr>& out)
{
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
for(std::list<MWWorld::Ptr>::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<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
std::set<MWWorld::Ptr> followers;
getFollowers(actor, followers);
for(std::set<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
{
teleport(*it);
}

@ -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;
}
}

@ -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.

@ -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

@ -102,6 +102,8 @@ namespace MWWorld
typedef std::vector<std::pair<ContainerStoreIterator, float> > TRechargingItems;
TRechargingItems mRechargingItems;
bool mRechargingItemsUpToDate;
void copySlots (const InventoryStore& store);
void initSlots (TSlots& slots_);

@ -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,10 @@ 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());
if (!physicActor) // actor was already removed from the scene
continue;
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 +870,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 +945,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);
}
}

@ -1,6 +1,8 @@
#ifndef GAME_MWWORLD_PHYSICSSYSTEM_H
#define GAME_MWWORLD_PHYSICSSYSTEM_H
#include <memory>
#include <OgreVector3.h>
#include <btBulletCollisionCommon.h>
@ -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<std::string, std::string> handleToMesh;
@ -124,6 +132,12 @@ namespace MWWorld
float mTimeAccum;
float mWaterHeight;
float mWaterEnabled;
std::auto_ptr<btCollisionObject> mWaterCollisionObject;
std::auto_ptr<btCollisionShape> mWaterCollisionShape;
PhysicsSystem (const PhysicsSystem&);
PhysicsSystem& operator= (const PhysicsSystem&);
};

@ -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<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to);
std::vector<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile);
bool hit=false;
for (std::vector<std::pair<float, std::string> >::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<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to);
std::vector<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile);
bool hit=false;
for (std::vector<std::pair<float, std::string> >::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;

@ -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);
}

@ -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())
@ -3073,4 +3074,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;
}
}

@ -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);
};
}

@ -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<float, std::string> > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to)
std::vector< std::pair<float, std::string> > 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<float, const btCollisionObject*> > results = resultCallback1.results;

@ -46,7 +46,9 @@ namespace Physic
CollisionType_World = 1<<0, //<Collide with world objects
CollisionType_Actor = 1<<1, //<Collide sith actors
CollisionType_HeightMap = 1<<2, //<collide with heightmap
CollisionType_Raycasting = 1<<3 //Still used?
CollisionType_Raycasting = 1<<3,
CollisionType_Projectile = 1<<4,
CollisionType_Water = 1<<5
};
/**
@ -130,9 +132,20 @@ namespace Physic
return mBody;
}
/// Sets whether this actor should be able to collide with the water surface
void setCanWaterWalk(bool waterWalk);
/// Sets whether this actor has been walking on the water surface in the last frame
void setWalkingOnWater(bool walkingOnWater);
bool isWalkingOnWater() const;
private:
void disableCollisionBody();
void enableCollisionBody();
/// Removes then re-adds the collision body to the dynamics world
void updateCollisionMask();
bool mCanWaterWalk;
bool mWalkingOnWater;
boost::shared_ptr<btCollisionShape> mShape;
@ -288,7 +301,7 @@ namespace Physic
/**
* Return all objects hit by a ray.
*/
std::vector< std::pair<float, std::string> > rayTest2(const btVector3 &from, const btVector3 &to);
std::vector< std::pair<float, std::string> > rayTest2(const btVector3 &from, const btVector3 &to, int filterGroup=0xff);
std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
///< @return (hit, relative distance)

Loading…
Cancel
Save