mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-11-04 07:56:45 +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/player.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwrender/animation.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -240,11 +241,15 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            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
 | 
			
		||||
                // or alternatively, the last known exterior location of the player, which is how vanilla does it.
 | 
			
		||||
            }
 | 
			
		||||
            else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
 | 
			
		||||
            {
 | 
			
		||||
                MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
 | 
			
		||||
 | 
			
		||||
                // Same as above
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -254,6 +259,8 @@ namespace MWMechanics
 | 
			
		|||
            }
 | 
			
		||||
            else if (effectId == ESM::MagicEffect::Recall)
 | 
			
		||||
            {
 | 
			
		||||
                MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
 | 
			
		||||
 | 
			
		||||
                // TODO
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,10 +43,13 @@ namespace MWScript
 | 
			
		|||
                    ESM::Position pos;
 | 
			
		||||
                    MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
 | 
			
		||||
                    if (world->findExteriorPosition(cell, pos)) {
 | 
			
		||||
                    world->getPlayer().setTeleported(true);
 | 
			
		||||
                    if (world->findExteriorPosition(cell, pos))
 | 
			
		||||
                    {
 | 
			
		||||
                        world->changeToExteriorCell(pos);
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // Change to interior even if findInteriorPosition()
 | 
			
		||||
                        // yields false. In this case position will be zero-point.
 | 
			
		||||
                        world->findInteriorPosition(cell, pos);
 | 
			
		||||
| 
						 | 
				
			
			@ -68,13 +71,14 @@ namespace MWScript
 | 
			
		|||
                    runtime.pop();
 | 
			
		||||
 | 
			
		||||
                    ESM::Position pos;
 | 
			
		||||
 | 
			
		||||
                    MWBase::Environment::get().getWorld()->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
 | 
			
		||||
                    MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
                    world->getPlayer().setTeleported(true);
 | 
			
		||||
                    world->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
 | 
			
		||||
                    pos.pos[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)
 | 
			
		||||
                {
 | 
			
		||||
                    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);
 | 
			
		||||
                    runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			@ -271,6 +275,10 @@ namespace MWScript
 | 
			
		|||
                virtual void execute (Interpreter::Runtime& 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;
 | 
			
		||||
                    runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			@ -328,6 +336,10 @@ namespace MWScript
 | 
			
		|||
                virtual void execute (Interpreter::Runtime& 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;
 | 
			
		||||
                    runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
 | 
			
		||||
#include "../mwbase/environment.hpp"
 | 
			
		||||
#include "../mwbase/world.hpp"
 | 
			
		||||
#include "player.hpp"
 | 
			
		||||
 | 
			
		||||
namespace MWWorld
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -14,9 +15,12 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
    void ActionTeleport::executeImp (const Ptr& actor)
 | 
			
		||||
    {
 | 
			
		||||
        MWBase::World* world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        world->getPlayer().setTeleported(true);
 | 
			
		||||
 | 
			
		||||
        if (mCellName.empty())
 | 
			
		||||
            MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition);
 | 
			
		||||
            world->changeToExteriorCell (mPosition);
 | 
			
		||||
        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)
 | 
			
		||||
      : mCellStore(0),
 | 
			
		||||
        mAutoMove(false),
 | 
			
		||||
        mForwardBackward (0)
 | 
			
		||||
        mForwardBackward (0),
 | 
			
		||||
        mTeleported(false)
 | 
			
		||||
    {
 | 
			
		||||
        mPlayer.mBase = player;
 | 
			
		||||
        mPlayer.mRef.mRefID = "player";
 | 
			
		||||
| 
						 | 
				
			
			@ -145,4 +146,14 @@ namespace MWWorld
 | 
			
		|||
         MWWorld::Ptr ptr = getPlayer();
 | 
			
		||||
         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;
 | 
			
		||||
        int                     mForwardBackward;
 | 
			
		||||
 | 
			
		||||
        bool                    mTeleported;
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        Player(const ESM::NPC *player, const MWBase::World& world);
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +64,9 @@ namespace MWWorld
 | 
			
		|||
        void yaw(float yaw);
 | 
			
		||||
        void pitch(float pitch);
 | 
			
		||||
        void roll(float roll);
 | 
			
		||||
 | 
			
		||||
        bool wasTeleported() const;
 | 
			
		||||
        void setTeleported(bool teleported);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -324,42 +324,7 @@ void WeatherManager::update(float duration)
 | 
			
		|||
 | 
			
		||||
    mWeatherUpdateTime -= timePassed;
 | 
			
		||||
 | 
			
		||||
    const bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior());
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
    switchToNextWeather(false);
 | 
			
		||||
 | 
			
		||||
    if (mNextWeather != "")
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -710,42 +675,42 @@ float WeatherManager::getWindSpeed() const
 | 
			
		|||
 | 
			
		||||
void WeatherManager::switchToNextWeather(bool instantly)
 | 
			
		||||
{
 | 
			
		||||
  const bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior());
 | 
			
		||||
  if (!exterior)
 | 
			
		||||
  {
 | 
			
		||||
      mRendering->sunDisable(false);
 | 
			
		||||
      mRendering->skyDisable();
 | 
			
		||||
      mRendering->getSkyManager()->setLightningStrength(0.f);
 | 
			
		||||
      stopSounds(true);
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
    MWBase::World* world = MWBase::Environment::get().getWorld();
 | 
			
		||||
    const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
 | 
			
		||||
    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);
 | 
			
		||||
    // Exterior
 | 
			
		||||
    std::string regionstr = Misc::StringUtils::lowerCase(world->getPlayer().getPlayer().getCell()->mCell->mRegion);
 | 
			
		||||
 | 
			
		||||
  if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
 | 
			
		||||
  {
 | 
			
		||||
      mCurrentRegion = regionstr;
 | 
			
		||||
      mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600;
 | 
			
		||||
    if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
 | 
			
		||||
    {
 | 
			
		||||
        mCurrentRegion = regionstr;
 | 
			
		||||
        mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600;
 | 
			
		||||
 | 
			
		||||
      std::string weatherType = "clear";
 | 
			
		||||
        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 (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
 | 
			
		||||
        {
 | 
			
		||||
            weatherType = mRegionOverrides[regionstr];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // get weather probabilities for the current region
 | 
			
		||||
            const ESM::Region *region = world->getStore().get<ESM::Region>().search (regionstr);
 | 
			
		||||
 | 
			
		||||
          if (region != 0)
 | 
			
		||||
          {
 | 
			
		||||
              weatherType = nextWeather(region);
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
            if (region != 0)
 | 
			
		||||
            {
 | 
			
		||||
                weatherType = nextWeather(region);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      setWeather(weatherType, instantly);
 | 
			
		||||
  }
 | 
			
		||||
        setWeather(weatherType, instantly);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2247,19 +2247,14 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
    void World::updateWeather(float duration)
 | 
			
		||||
    {
 | 
			
		||||
      static const float teleportationStepTreshold = 256.f;
 | 
			
		||||
      static ESM::Position lastPlayerPos;
 | 
			
		||||
      ESM::Position currentPos = mPlayer->getPlayer().getRefData().getPosition();
 | 
			
		||||
 | 
			
		||||
      if (fabs(fabs(lastPlayerPos.pos[0]) - fabs(currentPos.pos[0])) >= teleportationStepTreshold
 | 
			
		||||
          || fabs(fabs(lastPlayerPos.pos[1]) - fabs(currentPos.pos[1])) >= teleportationStepTreshold)
 | 
			
		||||
      {
 | 
			
		||||
        lastPlayerPos = currentPos;
 | 
			
		||||
        mWeatherManager->switchToNextWeather(true);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        mWeatherManager->update (duration);
 | 
			
		||||
      }
 | 
			
		||||
        if (mPlayer->wasTeleported())
 | 
			
		||||
        {
 | 
			
		||||
            mPlayer->setTeleported(false);
 | 
			
		||||
            mWeatherManager->switchToNextWeather(true);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mWeatherManager->update (duration);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue