From a6216d883fd6dc4de9339b1c61f8bb22b00c591b Mon Sep 17 00:00:00 2001 From: Allofich Date: Wed, 31 Aug 2016 01:05:54 +0900 Subject: [PATCH 1/5] 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; From 6c3cad238b0f1aee8c5dd68dda6eb0686cc87720 Mon Sep 17 00:00:00 2001 From: Allofich Date: Wed, 31 Aug 2016 17:14:16 +0900 Subject: [PATCH 2/5] Use castByPlayer bool --- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 19527076b..7778b8693 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -393,7 +393,7 @@ namespace MWMechanics if (!world->isWaterWalkingCastableOnTarget(target)) { - if (caster == getPlayer()) + if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox ("#{sMagicInvalidEffect}"); continue; } From f25c65260cc7f2d101180afe1d3576d0c5ce3475 Mon Sep 17 00:00:00 2001 From: Allofich Date: Wed, 31 Aug 2016 17:22:45 +0900 Subject: [PATCH 3/5] Limit sMagicinvalidEffect to self-cast spells --- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 7778b8693..fb473b0db 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -393,7 +393,7 @@ namespace MWMechanics if (!world->isWaterWalkingCastableOnTarget(target)) { - if (castByPlayer) + if (castByPlayer && caster == target) MWBase::Environment::get().getWindowManager()->messageBox ("#{sMagicInvalidEffect}"); continue; } From 22b11c5947c3ec023556c4ca6222ec954f6d27e7 Mon Sep 17 00:00:00 2001 From: Allofich Date: Wed, 31 Aug 2016 23:56:31 +0900 Subject: [PATCH 4/5] Move Water Walking check into checkEffectTarget() --- apps/openmw/mwmechanics/spellcasting.cpp | 33 +++++++++++------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index fb473b0db..797c42fe4 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -259,7 +259,7 @@ namespace MWMechanics } /// Check if the given affect can be applied to the target. If \a castByPlayer, emits a message box on failure. - bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, bool castByPlayer) + bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, const MWWorld::Ptr& caster, bool castByPlayer) { switch (effectId) { @@ -291,8 +291,20 @@ namespace MWMechanics return false; } break; - } + case ESM::MagicEffect::WaterWalking: + if (target.getClass().isPureWaterCreature(target)) + return false; + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (!world->isWaterWalkingCastableOnTarget(target)) + { + if (castByPlayer && caster == target) + MWBase::Environment::get().getWindowManager()->messageBox ("#{sMagicInvalidEffect}"); + return false; + } + break; + } return true; } @@ -383,23 +395,8 @@ 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 (castByPlayer && caster == target) - MWBase::Environment::get().getWindowManager()->messageBox ("#{sMagicInvalidEffect}"); - continue; - } - } - if (!checkEffectTarget(effectIt->mEffectID, target, castByPlayer)) + if (!checkEffectTarget(effectIt->mEffectID, target, caster, castByPlayer)) continue; // caster needs to be an actor for linked effects (e.g. Absorb) From b99c2c54d8e7314b629977bbaebbe896b88187df Mon Sep 17 00:00:00 2001 From: Allofich Date: Thu, 1 Sep 2016 03:34:55 +0900 Subject: [PATCH 5/5] Allow Water Walking on non-submerged creatures --- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 797c42fe4..cdf8a2a67 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -292,7 +292,7 @@ namespace MWMechanics } break; case ESM::MagicEffect::WaterWalking: - if (target.getClass().isPureWaterCreature(target)) + if (target.getClass().isPureWaterCreature(target) && MWBase::Environment::get().getWorld()->isSwimming(target)) return false; MWBase::World *world = MWBase::Environment::get().getWorld();