From a6216d883fd6dc4de9339b1c61f8bb22b00c591b Mon Sep 17 00:00:00 2001 From: Allofich Date: Wed, 31 Aug 2016 01:05:54 +0900 Subject: [PATCH] Don't allow casting Water Walking in deep water --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwmechanics/spellcasting.cpp | 15 +++++++++++++++ apps/openmw/mwworld/worldimp.cpp | 13 +++++++++++++ apps/openmw/mwworld/worldimp.hpp | 1 + 4 files changed, 30 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 82d5ddd5e..549931b9a 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -385,6 +385,7 @@ namespace MWBase ///Is the head of the creature underwater? virtual bool isSubmerged(const MWWorld::ConstPtr &object) const = 0; virtual bool isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const = 0; + virtual bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const = 0; virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0; virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const = 0; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 61365be97..19527076b 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -383,6 +383,21 @@ namespace MWMechanics } else canCastAnEffect = true; + + if (magicEffect->mIndex == ESM::MagicEffect::WaterWalking) + { + if (target.getClass().isPureWaterCreature(target)) + continue; + + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (!world->isWaterWalkingCastableOnTarget(target)) + { + if (caster == getPlayer()) + MWBase::Environment::get().getWindowManager()->messageBox ("#{sMagicInvalidEffect}"); + continue; + } + } if (!checkEffectTarget(effectIt->mEffectID, target, castByPlayer)) continue; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b178e6e52..5652b2d78 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2077,6 +2077,19 @@ namespace MWWorld return pos.z() < cell->getWaterLevel(); } + bool World::isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const + { + const MWWorld::CellStore* cell = target.getCell(); + if (!cell->getCell()->hasWater()) + return true; + + // Based on observations from the original engine, the depth + // limit at which water walking can still be cast on a target + // in water appears to be the same as what the highest swimmable + // z position would be with SwimHeightScale + 1. + return !isUnderwater(target, mSwimHeightScale + 1); + } + bool World::isOnGround(const MWWorld::Ptr &ptr) const { return mPhysics->isOnGround(ptr); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index aa67c9ea8..da665e27c 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -481,6 +481,7 @@ namespace MWWorld virtual bool isSwimming(const MWWorld::ConstPtr &object) const; virtual bool isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const; virtual bool isWading(const MWWorld::ConstPtr &object) const; + virtual bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const; virtual bool isOnGround(const MWWorld::Ptr &ptr) const; virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const;