Slaughter fish attacks when player only knee deep in water (Fixes #2076)

openmw-35
dteviot 10 years ago
parent 9d6efcecff
commit 7fe2f86d06

@ -392,6 +392,7 @@ namespace MWBase
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0; virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0; virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0; virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
virtual bool isWading(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0; virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const = 0; virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const = 0;

@ -348,9 +348,9 @@ namespace MWClass
// Self defense // Self defense
bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits. bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits.
if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
// (they have no movement or attacks anyway) // No retaliation for totally static creatures (they have no movement or attacks anyway)
&& !attacker.isEmpty()) if (isMobile(ptr) && !attacker.isEmpty())
{ {
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
} }

@ -309,8 +309,8 @@ namespace MWMechanics
// pure water creatures won't try to fight with the target on the ground // pure water creatures won't try to fight with the target on the ground
// except that creature is already hostile // except that creature is already hostile
if ((againstPlayer || !creatureStats.getAiSequence().isInCombat()) if ((againstPlayer || !creatureStats.getAiSequence().isInCombat())
&& ((actor1.getClass().canSwim(actor1) && !actor1.getClass().canWalk(actor1) // pure water creature && ((actor1.getClass().isPureWaterCreature(actor1)
&& !MWBase::Environment::get().getWorld()->isSwimming(actor2)) && !MWBase::Environment::get().getWorld()->isWading(actor2))
|| (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target || (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target
return; return;

@ -209,7 +209,7 @@ namespace MWMechanics
if (!actorClass.isNpc() && if (!actorClass.isNpc() &&
// 1. pure water creature and Player moved out of water // 1. pure water creature and Player moved out of water
((target == world->getPlayerPtr() && ((target == world->getPlayerPtr() &&
actorClass.canSwim(actor) && !actor.getClass().canWalk(actor) && !world->isSwimming(target)) actorClass.isPureWaterCreature(actor) && !world->isWading(target))
// 2. creature can't swim to target // 2. creature can't swim to target
|| (!actorClass.canSwim(actor) && world->isSwimming(target)))) || (!actorClass.canSwim(actor) && world->isSwimming(target))))
{ {

@ -383,6 +383,16 @@ namespace MWWorld
return false; return false;
} }
bool Class::isPureWaterCreature(const MWWorld::Ptr& ptr) const
{
return canSwim(ptr) && !canWalk(ptr);
}
bool Class::isMobile(const MWWorld::Ptr& ptr) const
{
return canSwim(ptr) || canWalk(ptr) || canFly(ptr);
}
int Class::getSkill(const MWWorld::Ptr& ptr, int skill) const int Class::getSkill(const MWWorld::Ptr& ptr, int skill) const
{ {
throw std::runtime_error("class does not support skills"); throw std::runtime_error("class does not support skills");

@ -308,6 +308,8 @@ namespace MWWorld
virtual bool canFly(const MWWorld::Ptr& ptr) const; virtual bool canFly(const MWWorld::Ptr& ptr) const;
virtual bool canSwim(const MWWorld::Ptr& ptr) const; virtual bool canSwim(const MWWorld::Ptr& ptr) const;
virtual bool canWalk(const MWWorld::Ptr& ptr) const; virtual bool canWalk(const MWWorld::Ptr& ptr) const;
bool isPureWaterCreature(const MWWorld::Ptr& ptr) const;
bool isMobile(const MWWorld::Ptr& ptr) const;
virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const; virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const;

@ -281,7 +281,7 @@ namespace MWWorld
// Early-out for totally static creatures // Early-out for totally static creatures
// (Not sure if gravity should still apply?) // (Not sure if gravity should still apply?)
if (!ptr.getClass().canWalk(ptr) && !ptr.getClass().canFly(ptr) && !ptr.getClass().canSwim(ptr)) if (!ptr.getClass().isMobile(ptr))
return position; return position;
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
@ -434,7 +434,7 @@ namespace MWWorld
if(result) if(result)
{ {
// don't let pure water creatures move out of water after stepMove // don't let pure water creatures move out of water after stepMove
if((ptr.getClass().canSwim(ptr) && !ptr.getClass().canWalk(ptr)) if (ptr.getClass().isPureWaterCreature(ptr)
&& newPosition.z > (waterlevel - halfExtents.z * 0.5)) && newPosition.z > (waterlevel - halfExtents.z * 0.5))
newPosition = oldPosition; newPosition = oldPosition;
} }

@ -1978,25 +1978,34 @@ namespace MWWorld
bool World::isSubmerged(const MWWorld::Ptr &object) const bool World::isSubmerged(const MWWorld::Ptr &object) const
{ {
const float *fpos = object.getRefData().getPosition().pos; return isUnderwater(object, 1.85f);
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle());
if(actor) pos.z += 1.85*actor->getHalfExtents().z;
return isUnderwater(object.getCell(), pos);
} }
bool bool
World::isSwimming(const MWWorld::Ptr &object) const World::isSwimming(const MWWorld::Ptr &object) const
{ {
/// \todo add check ifActor() - only actors can swim /// \todo add check ifActor() - only actors can swim
/// \fixme 3/4ths submerged?
return isUnderwater(object, 1.5f);
}
bool
World::isWading(const MWWorld::Ptr &object) const
{
return isUnderwater(object, 0.5f);
}
bool
World::isUnderwater(const MWWorld::Ptr &object, const float hightRatio) const
{
const float *fpos = object.getRefData().getPosition().pos; const float *fpos = object.getRefData().getPosition().pos;
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]); Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
/// \fixme 3/4ths submerged?
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle()); const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle());
if(actor) pos.z += actor->getHalfExtents().z * 1.5; if (actor)
{
pos.z += hightRatio*actor->getHalfExtents().z;
}
return isUnderwater(object.getCell(), pos); return isUnderwater(object.getCell(), pos);
} }

@ -139,6 +139,9 @@ namespace MWWorld
void loadContentFiles(const Files::Collections& fileCollections, void loadContentFiles(const Files::Collections& fileCollections,
const std::vector<std::string>& content, ContentLoader& contentLoader); const std::vector<std::string>& content, ContentLoader& contentLoader);
bool isUnderwater(const MWWorld::Ptr &object, const float hightRatio) const;
///< helper function for implementing isSwimming(), isSubmerged(), isWading()
bool mTeleportEnabled; bool mTeleportEnabled;
bool mLevitationEnabled; bool mLevitationEnabled;
bool mGoToJail; bool mGoToJail;
@ -454,6 +457,7 @@ namespace MWWorld
virtual bool isSubmerged(const MWWorld::Ptr &object) const; virtual bool isSubmerged(const MWWorld::Ptr &object) const;
virtual bool isSwimming(const MWWorld::Ptr &object) const; virtual bool isSwimming(const MWWorld::Ptr &object) const;
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const; virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const;
virtual bool isWading(const MWWorld::Ptr &object) const;
virtual bool isOnGround(const MWWorld::Ptr &ptr) const; virtual bool isOnGround(const MWWorld::Ptr &ptr) const;
virtual void togglePOV() { virtual void togglePOV() {

Loading…
Cancel
Save