diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 23f0b6b6..8b72a80c 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1243,18 +1243,12 @@ void Entity::Update(const float deltaTime) { // If the timer is expired, erase it and dont increment the position because the next timer will be at the same position. // Before: [0, 1, 2, 3, ..., n] // timerPosition ^ - // After: [0, 1, n, ..., n - 1] 2 is expired and removed now + // After: [0, 1, 3, ..., n] // timerPosition ^ if (timer.GetTime() <= 0) { // Remove the timer from the list of timers first so that scripts and events can remove timers without causing iterator invalidation auto timerName = timer.GetName(); - // We don't need to copy the element if there is only 1 element nor do we need to copy if we are on the last element. - // This is a clever removal trick that avoids having to copy the entire vector and instead replaces this now expired - // element with the last element in the vector and then removes the last element. - if (m_Timers.size() > 1 && timerPosition < m_Timers.size() - 1) { - m_Timers[timerPosition] = m_Timers[m_Timers.size() - 1]; - } - m_Timers.erase(m_Timers.end() - 1); + m_Timers.erase(m_Timers.begin() + timerPosition); for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { script->OnTimerDone(this, timerName); } @@ -1270,26 +1264,31 @@ void Entity::Update(const float deltaTime) { // If the timer is expired, erase it and dont increment the position because the next timer will be at the same position. // Before: [0, 1, 2, 3, ..., n] // timerPosition ^ - // After: [0, 1, n, ..., n - 1] 2 is expired and removed now + // After: [0, 1, 3, ..., n] // timerPosition ^ auto& callbackTimer = m_CallbackTimers[timerPosition]; callbackTimer.Update(deltaTime); if (callbackTimer.GetTime() <= 0) { // Remove the timer from the list of timers first so that callbacks can remove timers without causing iterator invalidation auto callback = callbackTimer.GetCallback(); - // We don't need to copy the element if there is only 1 element nor do we need to copy if we are on the last element. - // This is a clever removal trick that avoids having to copy the entire vector and instead replaces this now expired - // element with the last element in the vector and then removes the last element. - if (m_CallbackTimers.size() > 1 && timerPosition < m_CallbackTimers.size() - 1) { - m_CallbackTimers[timerPosition] = m_CallbackTimers[m_CallbackTimers.size() - 1]; - } - m_CallbackTimers.erase(m_CallbackTimers.end() - 1); + m_CallbackTimers.erase(m_CallbackTimers.begin() + timerPosition); callback(); } else { timerPosition++; } } + // Add pending timers to the list of timers so they start next tick. + if (!m_PendingTimers.empty()) { + m_Timers.insert(m_Timers.end(), m_PendingTimers.begin(), m_PendingTimers.end()); + m_PendingTimers.clear(); + } + + if (!m_PendingCallbackTimers.empty()) { + m_CallbackTimers.insert(m_CallbackTimers.end(), m_PendingCallbackTimers.begin(), m_PendingCallbackTimers.end()); + m_PendingCallbackTimers.clear(); + } + if (IsSleeping()) { Sleep(); @@ -1725,11 +1724,11 @@ void Entity::RemoveParent() { } void Entity::AddTimer(std::string name, float time) { - m_Timers.emplace_back(name, time); + m_PendingTimers.emplace_back(name, time); } void Entity::AddCallbackTimer(float time, std::function callback) { - m_CallbackTimers.emplace_back(time, callback); + m_PendingCallbackTimers.emplace_back(time, callback); } bool Entity::HasTimer(const std::string& name) { @@ -1738,6 +1737,7 @@ bool Entity::HasTimer(const std::string& name) { void Entity::CancelCallbackTimers() { m_CallbackTimers.clear(); + m_PendingCallbackTimers.clear(); } void Entity::ScheduleKillAfterUpdate(Entity* murderer) { @@ -1759,7 +1759,9 @@ void Entity::CancelTimer(const std::string& name) { void Entity::CancelAllTimers() { m_Timers.clear(); + m_PendingTimers.clear(); m_CallbackTimers.clear(); + m_PendingCallbackTimers.clear(); } bool Entity::IsPlayer() const { diff --git a/dGame/Entity.h b/dGame/Entity.h index e4ec71ab..36621d5c 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -330,7 +330,9 @@ protected: std::unordered_map m_Components; std::vector m_Timers; + std::vector m_PendingTimers; std::vector m_CallbackTimers; + std::vector m_PendingCallbackTimers; bool m_ShouldDestroyAfterUpdate = false;