diff --git a/scripts/microbe_stage/microbe_replacement.lua b/scripts/microbe_stage/microbe_replacement.lua index f5445af14e2..62ab40ba5c5 100644 --- a/scripts/microbe_stage/microbe_replacement.lua +++ b/scripts/microbe_stage/microbe_replacement.lua @@ -11,6 +11,7 @@ end function MicrobeReplacementSystem:activate() activeCreatureId = Engine:playerData():activeCreature() if Engine:playerData():isBoolSet("edited_microbe") then + Engine:playerData():setBool("edited_microbe", false); workingMicrobe = Microbe(Entity(activeCreatureId, GameState.MICROBE_EDITOR)) if workingMicrobe:getCompoundAmount(CompoundRegistry.getCompoundId("atp")) == 0 then workingMicrobe:storeCompound(CompoundRegistry.getCompoundId("atp"), 10) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 2b09b416e8c..9d17616cb55 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,9 @@ struct Engine::Implementation : public Ogre::WindowEventListener { Engine& engine ) : m_engine(engine), m_rng(), - m_playerData("player") + m_playerData("player"), + m_nextShutdownSystems(new std::map), + m_prevShutdownSystems(new std::map) { } @@ -413,6 +416,9 @@ struct Engine::Implementation : public Ogre::WindowEventListener { bool m_quitRequested = false; + std::map* m_nextShutdownSystems; + std::map* m_prevShutdownSystems; + struct Graphics { std::unique_ptr root; @@ -488,6 +494,8 @@ Engine::luaBindings() { .def("load", &Engine::load) .def("save", &Engine::save) .def("quit", &Engine::quit) + .def("timedSystemShutdown", &Engine::timedSystemShutdown) + .def("isSystemTimedShutdown", &Engine::isSystemTimedShutdown) .property("componentFactory", &Engine::componentFactory) .property("keyboard", &Engine::keyboard) .property("mouse", &Engine::mouse) @@ -640,6 +648,13 @@ Engine::setCurrentGameState( ) { assert(gameState != nullptr && "GameState must not be null"); m_impl->m_nextGameState = gameState; + for (auto& pair : *m_impl->m_prevShutdownSystems){ + //Make sure systems are deactivated before any potential reactivations + pair.first->deactivate(); + } + m_impl->m_prevShutdownSystems = m_impl->m_nextShutdownSystems; + m_impl->m_nextShutdownSystems = m_impl->m_prevShutdownSystems; + m_impl->m_nextShutdownSystems->clear(); } PlayerData& @@ -710,8 +725,36 @@ Engine::update( } assert(m_impl->m_currentGameState != nullptr); m_impl->m_currentGameState->update(milliseconds); + // Update any timed shutdown systems + auto itr = m_impl->m_prevShutdownSystems->begin(); + while (itr != m_impl->m_prevShutdownSystems->end()) { + int updateTime = std::min(itr->second, milliseconds); + itr->first->update(updateTime); + itr->second = itr->second - updateTime; + if (itr->second == 0) { + // Remove systems that had timed out + itr->first->deactivate(); + m_impl->m_prevShutdownSystems->erase(itr++); + } else { + ++itr; + } + } if (not m_impl->m_serialization.loadFile.empty()) { m_impl->loadSavegame(); } } +void +Engine::timedSystemShutdown( + System& system, + int milliseconds +) { + (*m_impl->m_nextShutdownSystems)[&system] = milliseconds; +} + +bool +Engine::isSystemTimedShutdown( + System& system +) const { + return m_impl->m_prevShutdownSystems->find(&system) != m_impl->m_prevShutdownSystems->end(); +} diff --git a/src/engine/engine.h b/src/engine/engine.h index a93a3f04301..9125af5b945 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -64,6 +64,8 @@ class Engine { * - Engine::load() * - Engine::save() * - Engine::quit() + * - Engine::timedSystemShutdown() + * - Engine::isSystemTimedShutdown() * - Engine::componentFactory() (as property) * - Engine::keyboard() (as property) * - Engine::mouse() (as property) @@ -270,11 +272,48 @@ class Engine { int milliseconds ); + /** + * @brief Keeps a system alive after being shut down for a specified amount of time + * + * Note that this causes update to be called for the specified duration so be careful + * to ensure that the system is not enabled or it will get update calls twice. + * + * @param system + * The system to keep updated + * + * @param milliseconds + * The number of milliseconds to keep the system updated for + */ + void + timedSystemShutdown( + System& system, + int milliseconds + ); + + /** + * @brief Returns whether the specified system has already been set for a timed shutdown + * + * @param system + * The system to check for + * + * @return + */ + bool + isSystemTimedShutdown( + System& system + ) const; + /** * @brief Transfers an entity from one gamestate to another * + * @param oldEntityId + * The id of the entity to transfer in the old entitymanager * + * @param oldEntityManager + * The old entitymanager which is currently handling the entity * + * @param newGameState + * The new gamestate to transfer the entity to */ EntityId transferEntityGameState( diff --git a/src/engine/entity_filter.cpp b/src/engine/entity_filter.cpp index 200798d5d13..8b33d6447c3 100644 --- a/src/engine/entity_filter.cpp +++ b/src/engine/entity_filter.cpp @@ -288,6 +288,11 @@ EntityFilter::removedEntities() { return m_impl->m_removedEntities; } +template +EntityManager* +EntityFilter::entityManager() { + return m_impl->m_entityManager; +} template void diff --git a/src/engine/entity_filter.h b/src/engine/entity_filter.h index cd6331c8b81..44b748f4c21 100644 --- a/src/engine/entity_filter.h +++ b/src/engine/entity_filter.h @@ -211,6 +211,14 @@ class EntityFilter { std::unordered_set& removedEntities(); + /** + * @brief Gets the current entiyManager + * + * @return + */ + EntityManager* + entityManager(); + /** * @brief Sets the entity manager this filter applies to * diff --git a/src/sound/sound_source_system.cpp b/src/sound/sound_source_system.cpp index 6b55ccce812..21f2d7518fb 100644 --- a/src/sound/sound_source_system.cpp +++ b/src/sound/sound_source_system.cpp @@ -300,7 +300,7 @@ struct SoundSourceSystem::Implementation { removeSoundsForEntity( EntityId entityId ) { - EntityManager& entityManager = Game::instance().engine().currentGameState()->entityManager(); + EntityManager& entityManager = *m_entities.entityManager(); SoundSourceComponent* soundSource = static_cast(entityManager.getComponent(entityId, SoundSourceComponent::TYPE_ID)); for (const auto& pair : soundSource->m_sounds) { Sound* sound = pair.second.get(); @@ -430,13 +430,16 @@ SoundSourceSystem::activate() { void SoundSourceSystem::deactivate() { - System::deactivate(); - auto& soundManager = OgreOggSound::OgreOggSoundManager::getSingleton(); - m_impl->removeAllSounds(); - for (auto& value : m_impl->m_entities) { - std::get<0>(value.second)->m_ambientSoundCountdown = 0; + if (this->engine()->isSystemTimedShutdown(*this)) { + System::deactivate(); + m_impl->removeAllSounds(); + } + else { + for (auto& value : m_impl->m_entities) { + std::get<0>(value.second)->m_ambientSoundCountdown = 1500; + } + this->engine()->timedSystemShutdown(*this, 1500); } - soundManager.setSceneManager(nullptr); }