mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 02:56:44 +00:00 
			
		
		
		
	Fixes #417: Apply weather instantly when teleporting
Changed teleporting detection from "position tracking" to manually setting "teleportation" flag ( player->setTeleported(true) ). Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
This commit is contained in:
		
							parent
							
								
									c65f018760
								
							
						
					
					
						commit
						e9844e1b37
					
				
					 8 changed files with 92 additions and 91 deletions
				
			
		|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #include "../mwworld/containerstore.hpp" | #include "../mwworld/containerstore.hpp" | ||||||
|  | #include "../mwworld/player.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../mwrender/animation.hpp" | #include "../mwrender/animation.hpp" | ||||||
| 
 | 
 | ||||||
|  | @ -240,11 +241,15 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|             else if (effectId == ESM::MagicEffect::DivineIntervention) |             else if (effectId == ESM::MagicEffect::DivineIntervention) | ||||||
|             { |             { | ||||||
|  |                 MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  | 
 | ||||||
|                 // We need to be able to get the world location of an interior cell before implementing this
 |                 // We need to be able to get the world location of an interior cell before implementing this
 | ||||||
|                 // or alternatively, the last known exterior location of the player, which is how vanilla does it.
 |                 // or alternatively, the last known exterior location of the player, which is how vanilla does it.
 | ||||||
|             } |             } | ||||||
|             else if (effectId == ESM::MagicEffect::AlmsiviIntervention) |             else if (effectId == ESM::MagicEffect::AlmsiviIntervention) | ||||||
|             { |             { | ||||||
|  |                 MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  | 
 | ||||||
|                 // Same as above
 |                 // Same as above
 | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -254,6 +259,8 @@ namespace MWMechanics | ||||||
|             } |             } | ||||||
|             else if (effectId == ESM::MagicEffect::Recall) |             else if (effectId == ESM::MagicEffect::Recall) | ||||||
|             { |             { | ||||||
|  |                 MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  | 
 | ||||||
|                 // TODO
 |                 // TODO
 | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -43,10 +43,13 @@ namespace MWScript | ||||||
|                     ESM::Position pos; |                     ESM::Position pos; | ||||||
|                     MWBase::World *world = MWBase::Environment::get().getWorld(); |                     MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
| 
 | 
 | ||||||
|                     if (world->findExteriorPosition(cell, pos)) { |                     world->getPlayer().setTeleported(true); | ||||||
|  |                     if (world->findExteriorPosition(cell, pos)) | ||||||
|  |                     { | ||||||
|                         world->changeToExteriorCell(pos); |                         world->changeToExteriorCell(pos); | ||||||
|                     } |                     } | ||||||
|                     else { |                     else | ||||||
|  |                     { | ||||||
|                         // Change to interior even if findInteriorPosition()
 |                         // Change to interior even if findInteriorPosition()
 | ||||||
|                         // yields false. In this case position will be zero-point.
 |                         // yields false. In this case position will be zero-point.
 | ||||||
|                         world->findInteriorPosition(cell, pos); |                         world->findInteriorPosition(cell, pos); | ||||||
|  | @ -68,13 +71,14 @@ namespace MWScript | ||||||
|                     runtime.pop(); |                     runtime.pop(); | ||||||
| 
 | 
 | ||||||
|                     ESM::Position pos; |                     ESM::Position pos; | ||||||
| 
 |                     MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
|                     MWBase::Environment::get().getWorld()->indexToPosition (x, y, pos.pos[0], pos.pos[1], true); |                     world->getPlayer().setTeleported(true); | ||||||
|  |                     world->indexToPosition (x, y, pos.pos[0], pos.pos[1], true); | ||||||
|                     pos.pos[2] = 0; |                     pos.pos[2] = 0; | ||||||
| 
 | 
 | ||||||
|                     pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; |                     pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; | ||||||
| 
 | 
 | ||||||
|                     MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); |                     world->changeToExteriorCell (pos); | ||||||
|                 } |                 } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -207,6 +207,10 @@ namespace MWScript | ||||||
|                 virtual void execute (Interpreter::Runtime& runtime) |                 virtual void execute (Interpreter::Runtime& runtime) | ||||||
|                 { |                 { | ||||||
|                     MWWorld::Ptr ptr = R()(runtime); |                     MWWorld::Ptr ptr = R()(runtime); | ||||||
|  |                     if (ptr.getRefData().getHandle() == "player") | ||||||
|  |                     { | ||||||
|  |                         MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger); |                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger); | ||||||
|                     runtime.pop(); |                     runtime.pop(); | ||||||
|  | @ -271,6 +275,10 @@ namespace MWScript | ||||||
|                 virtual void execute (Interpreter::Runtime& runtime) |                 virtual void execute (Interpreter::Runtime& runtime) | ||||||
|                 { |                 { | ||||||
|                     MWWorld::Ptr ptr = R()(runtime); |                     MWWorld::Ptr ptr = R()(runtime); | ||||||
|  |                     if (ptr.getRefData().getHandle() == "player") | ||||||
|  |                     { | ||||||
|  |                         MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     Interpreter::Type_Float x = runtime[0].mFloat; |                     Interpreter::Type_Float x = runtime[0].mFloat; | ||||||
|                     runtime.pop(); |                     runtime.pop(); | ||||||
|  | @ -328,6 +336,10 @@ namespace MWScript | ||||||
|                 virtual void execute (Interpreter::Runtime& runtime) |                 virtual void execute (Interpreter::Runtime& runtime) | ||||||
|                 { |                 { | ||||||
|                     MWWorld::Ptr ptr = R()(runtime); |                     MWWorld::Ptr ptr = R()(runtime); | ||||||
|  |                     if (ptr.getRefData().getHandle() == "player") | ||||||
|  |                     { | ||||||
|  |                         MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                     Interpreter::Type_Float x = runtime[0].mFloat; |                     Interpreter::Type_Float x = runtime[0].mFloat; | ||||||
|                     runtime.pop(); |                     runtime.pop(); | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "../mwbase/environment.hpp" | #include "../mwbase/environment.hpp" | ||||||
| #include "../mwbase/world.hpp" | #include "../mwbase/world.hpp" | ||||||
|  | #include "player.hpp" | ||||||
| 
 | 
 | ||||||
| namespace MWWorld | namespace MWWorld | ||||||
| { | { | ||||||
|  | @ -14,9 +15,12 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     void ActionTeleport::executeImp (const Ptr& actor) |     void ActionTeleport::executeImp (const Ptr& actor) | ||||||
|     { |     { | ||||||
|  |         MWBase::World* world = MWBase::Environment::get().getWorld(); | ||||||
|  |         world->getPlayer().setTeleported(true); | ||||||
|  | 
 | ||||||
|         if (mCellName.empty()) |         if (mCellName.empty()) | ||||||
|             MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition); |             world->changeToExteriorCell (mPosition); | ||||||
|         else |         else | ||||||
|             MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, mPosition); |             world->changeToInteriorCell (mCellName, mPosition); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,7 +19,8 @@ namespace MWWorld | ||||||
|     Player::Player (const ESM::NPC *player, const MWBase::World& world) |     Player::Player (const ESM::NPC *player, const MWBase::World& world) | ||||||
|       : mCellStore(0), |       : mCellStore(0), | ||||||
|         mAutoMove(false), |         mAutoMove(false), | ||||||
|         mForwardBackward (0) |         mForwardBackward (0), | ||||||
|  |         mTeleported(false) | ||||||
|     { |     { | ||||||
|         mPlayer.mBase = player; |         mPlayer.mBase = player; | ||||||
|         mPlayer.mRef.mRefID = "player"; |         mPlayer.mRef.mRefID = "player"; | ||||||
|  | @ -145,4 +146,14 @@ namespace MWWorld | ||||||
|          MWWorld::Ptr ptr = getPlayer(); |          MWWorld::Ptr ptr = getPlayer(); | ||||||
|          return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState(); |          return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState(); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     bool Player::wasTeleported() const | ||||||
|  |     { | ||||||
|  |         return mTeleported; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Player::setTeleported(bool teleported) | ||||||
|  |     { | ||||||
|  |         mTeleported = teleported; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|         bool                    mAutoMove; |         bool                    mAutoMove; | ||||||
|         int                     mForwardBackward; |         int                     mForwardBackward; | ||||||
| 
 |         bool                    mTeleported; | ||||||
|     public: |     public: | ||||||
| 
 | 
 | ||||||
|         Player(const ESM::NPC *player, const MWBase::World& world); |         Player(const ESM::NPC *player, const MWBase::World& world); | ||||||
|  | @ -64,6 +64,9 @@ namespace MWWorld | ||||||
|         void yaw(float yaw); |         void yaw(float yaw); | ||||||
|         void pitch(float pitch); |         void pitch(float pitch); | ||||||
|         void roll(float roll); |         void roll(float roll); | ||||||
|  | 
 | ||||||
|  |         bool wasTeleported() const; | ||||||
|  |         void setTeleported(bool teleported); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -324,42 +324,7 @@ void WeatherManager::update(float duration) | ||||||
| 
 | 
 | ||||||
|     mWeatherUpdateTime -= timePassed; |     mWeatherUpdateTime -= timePassed; | ||||||
| 
 | 
 | ||||||
|     const bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior()); |     switchToNextWeather(false); | ||||||
|     if (!exterior) |  | ||||||
|     { |  | ||||||
|         mRendering->sunDisable(false); |  | ||||||
|         mRendering->skyDisable(); |  | ||||||
|         mRendering->getSkyManager()->setLightningStrength(0.f); |  | ||||||
|         stopSounds(true); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Exterior
 |  | ||||||
|     std::string regionstr = Misc::StringUtils::lowerCase(MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion); |  | ||||||
| 
 |  | ||||||
|     if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) |  | ||||||
|     { |  | ||||||
|         mCurrentRegion = regionstr; |  | ||||||
|         mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600; |  | ||||||
| 
 |  | ||||||
|         std::string weatherType = "clear"; |  | ||||||
| 
 |  | ||||||
|         if (mRegionOverrides.find(regionstr) != mRegionOverrides.end()) |  | ||||||
|             weatherType = mRegionOverrides[regionstr]; |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             // get weather probabilities for the current region
 |  | ||||||
|             const ESM::Region *region = |  | ||||||
|                     MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().search (regionstr); |  | ||||||
| 
 |  | ||||||
|             if (region != 0) |  | ||||||
|             { |  | ||||||
|                 weatherType = nextWeather(region); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         setWeather(weatherType, false); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (mNextWeather != "") |     if (mNextWeather != "") | ||||||
|     { |     { | ||||||
|  | @ -710,42 +675,42 @@ float WeatherManager::getWindSpeed() const | ||||||
| 
 | 
 | ||||||
| void WeatherManager::switchToNextWeather(bool instantly) | void WeatherManager::switchToNextWeather(bool instantly) | ||||||
| { | { | ||||||
|   const bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior()); |     MWBase::World* world = MWBase::Environment::get().getWorld(); | ||||||
|   if (!exterior) |     const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior()); | ||||||
|   { |     if (!exterior) | ||||||
|       mRendering->sunDisable(false); |     { | ||||||
|       mRendering->skyDisable(); |         mRendering->sunDisable(false); | ||||||
|       mRendering->getSkyManager()->setLightningStrength(0.f); |         mRendering->skyDisable(); | ||||||
|       stopSounds(true); |         mRendering->getSkyManager()->setLightningStrength(0.f); | ||||||
|       return; |         stopSounds(true); | ||||||
|   } |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|   // Exterior
 |     // Exterior
 | ||||||
|   std::string regionstr = Misc::StringUtils::lowerCase(MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion); |     std::string regionstr = Misc::StringUtils::lowerCase(world->getPlayer().getPlayer().getCell()->mCell->mRegion); | ||||||
| 
 | 
 | ||||||
|   if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) |     if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) | ||||||
|   { |     { | ||||||
|       mCurrentRegion = regionstr; |         mCurrentRegion = regionstr; | ||||||
|       mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600; |         mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600; | ||||||
| 
 | 
 | ||||||
|       std::string weatherType = "clear"; |         std::string weatherType = "clear"; | ||||||
| 
 | 
 | ||||||
|       if (mRegionOverrides.find(regionstr) != mRegionOverrides.end()) |         if (mRegionOverrides.find(regionstr) != mRegionOverrides.end()) | ||||||
|       { |         { | ||||||
|           weatherType = mRegionOverrides[regionstr]; |             weatherType = mRegionOverrides[regionstr]; | ||||||
|       } |         } | ||||||
|       else |         else | ||||||
|       { |         { | ||||||
|           // get weather probabilities for the current region
 |             // get weather probabilities for the current region
 | ||||||
|           const ESM::Region *region = |             const ESM::Region *region = world->getStore().get<ESM::Region>().search (regionstr); | ||||||
|                   MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().search (regionstr); |  | ||||||
| 
 | 
 | ||||||
|           if (region != 0) |             if (region != 0) | ||||||
|           { |             { | ||||||
|               weatherType = nextWeather(region); |                 weatherType = nextWeather(region); | ||||||
|           } |             } | ||||||
|       } |         } | ||||||
| 
 | 
 | ||||||
|       setWeather(weatherType, instantly); |         setWeather(weatherType, instantly); | ||||||
|   } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2247,19 +2247,14 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     void World::updateWeather(float duration) |     void World::updateWeather(float duration) | ||||||
|     { |     { | ||||||
|       static const float teleportationStepTreshold = 256.f; |         if (mPlayer->wasTeleported()) | ||||||
|       static ESM::Position lastPlayerPos; |         { | ||||||
|       ESM::Position currentPos = mPlayer->getPlayer().getRefData().getPosition(); |             mPlayer->setTeleported(false); | ||||||
| 
 |             mWeatherManager->switchToNextWeather(true); | ||||||
|       if (fabs(fabs(lastPlayerPos.pos[0]) - fabs(currentPos.pos[0])) >= teleportationStepTreshold |         } | ||||||
|           || fabs(fabs(lastPlayerPos.pos[1]) - fabs(currentPos.pos[1])) >= teleportationStepTreshold) |         else | ||||||
|       { |         { | ||||||
|         lastPlayerPos = currentPos; |             mWeatherManager->update (duration); | ||||||
|         mWeatherManager->switchToNextWeather(true); |         } | ||||||
|       } |  | ||||||
|       else |  | ||||||
|       { |  | ||||||
|         mWeatherManager->update (duration); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue