From 9a8d5fc66796c0284bbc7b5158b7ba6a4bec95e5 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 2 Aug 2018 16:37:56 +0800 Subject: [PATCH] Improve swatter in network by locally add a swat event --- src/items/attachment.cpp | 26 ++--------------- src/items/attachment.hpp | 11 ++----- src/items/swatter.cpp | 62 ++++++++++++++++++++++++++-------------- src/items/swatter.hpp | 9 ++++-- src/karts/kart.cpp | 2 +- 5 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index accdfcdca..c84bd489c 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -47,7 +47,6 @@ /** Initialises the attachment each kart has. */ Attachment::Attachment(AbstractKart* kart) - : EventRewinder() { m_type = ATTACH_NOTHING; m_ticks_left = 0; @@ -148,7 +147,7 @@ void Attachment::set(AttachmentType type, int ticks, m_node->setMesh(attachment_manager->getMesh(ATTACH_NOLOKS_SWATTER)); else m_node->setMesh(attachment_manager->getMesh(type)); - m_plugin = new Swatter(m_kart, was_bomb, bomb_scene_node); + m_plugin = new Swatter(m_kart, was_bomb, bomb_scene_node, ticks); break; case ATTACH_BOMB: m_node->setMesh(attachment_manager->getMesh(type)); @@ -208,17 +207,6 @@ void Attachment::set(AttachmentType type, int ticks, } } m_node->setVisible(true); -#ifndef SERVER_ONLY - // Save event about the new attachment - RewindManager *rwm = RewindManager::get(); - if(rwm->isEnabled() && !rwm->isRewinding()) - { - // FIXME!!!! For now commented out - //BareNetworkString *buffer = new BareNetworkString(2); - //saveState(buffer); - //rwm->addEvent(this, buffer, /*confirmed*/true); - } -#endif } // set // ----------------------------------------------------------------------------- @@ -311,7 +299,7 @@ void Attachment::rewindTo(BareNetworkString *buffer) } // If playing kart animation, don't rewind to any attacment - if (is_removing_bomb) + if (is_removing_bomb || m_kart->getKartAnimation()) return; // Attaching an object can be expensive (loading new models, ...) @@ -331,16 +319,6 @@ void Attachment::rewindTo(BareNetworkString *buffer) /*disable_swatter_animation*/); } // rewindTo -// ----------------------------------------------------------------------------- -/** Called when going forwards in time during a rewind. - * \param buffer Buffer with the rewind information. - */ -void Attachment::rewind(BareNetworkString *buffer) -{ - // Event has same info as a state, so re-use the restore function - rewindTo(buffer); -} // rewind - // ----------------------------------------------------------------------------- /** Selects the new attachment. In order to simplify synchronisation with the * server, the new item is based on the current world time. diff --git a/src/items/attachment.hpp b/src/items/attachment.hpp index 56005df5a..ef2ed2d68 100644 --- a/src/items/attachment.hpp +++ b/src/items/attachment.hpp @@ -21,9 +21,7 @@ #include "config/stk_config.hpp" #include "items/attachment_plugin.hpp" -#include "network/event_rewinder.hpp" #include "utils/no_copy.hpp" -#include "utils/random_generator.hpp" #include using namespace irr; @@ -46,8 +44,7 @@ class SFXBase; * a scene node). * \ingroup items */ -class Attachment: public NoCopy, public scene::IAnimationEndCallBack, - public EventRewinder +class Attachment: public NoCopy, public scene::IAnimationEndCallBack { public: // Some loop in attachment.cpp depend on ATTACH_FIRST and ATTACH_MAX. @@ -102,15 +99,12 @@ private: * for certain attachments. */ AttachmentPlugin *m_plugin; - /** Pseudo random number generator. */ - RandomGenerator m_random; - /** Ticking sound for the bomb */ SFXBase *m_bomb_sound; /** Soung for exploding bubble gum shield */ SFXBase *m_bubble_explode_sound; - + public: Attachment(AbstractKart* kart); ~Attachment(); @@ -123,7 +117,6 @@ public: void set (AttachmentType type, int ticks, AbstractKart *previous_kart=NULL, bool disable_swatter_animation = false); - virtual void rewind(BareNetworkString *buffer); void rewindTo(BareNetworkString *buffer); void saveState(BareNetworkString *buffer) const; diff --git a/src/items/swatter.cpp b/src/items/swatter.cpp index 0269f170f..faced375b 100644 --- a/src/items/swatter.cpp +++ b/src/items/swatter.cpp @@ -40,6 +40,8 @@ #include "karts/kart_properties.hpp" #include "modes/world.hpp" #include "modes/soccer_world.hpp" +#include "network/network_config.hpp" +#include "network/rewind_manager.hpp" #define SWAT_POS_OFFSET core::vector3df(0.0, 0.2f, -0.4f) #define SWAT_ANGLE_MIN 45 @@ -56,14 +58,15 @@ * attachment scene node). */ Swatter::Swatter(AbstractKart *kart, bool was_bomb, - scene::ISceneNode* bomb_scene_node) - : AttachmentPlugin(kart) + scene::ISceneNode* bomb_scene_node, int ticks) + : AttachmentPlugin(kart), + m_swatter_start_ticks(World::getWorld()->getTicksSinceStart()), + m_swatter_end_ticks(World::getWorld()->getTicksSinceStart() + ticks) { m_animation_phase = SWATTER_AIMING; m_discard_now = false; m_target = NULL; m_closest_kart = NULL; - m_bomb_scene_node = bomb_scene_node; m_swat_bomb_frame = 0.0f; @@ -162,19 +165,29 @@ void Swatter::updateGrahpics(float dt) */ bool Swatter::updateAndTestFinished(int ticks) { + const int ticks_start = World::getWorld()->getTicksSinceStart(); if (m_removed_bomb_ticks != std::numeric_limits::max()) { - if (World::getWorld()->getTicksSinceStart() >= m_removed_bomb_ticks) + if (ticks_start >= m_removed_bomb_ticks) return true; return false; } // if removing bomb + if (RewindManager::get()->isRewinding()) + return false; + if (!m_discard_now) { switch (m_animation_phase) { case SWATTER_AIMING: { + // Avoid swatter near the start and the end lifetime of swatter + // to make sure all clients know the existence of swatter each other + if (ticks_start - m_swatter_start_ticks < 60 || + m_swatter_end_ticks - ticks_start < 60) + return false; + chooseTarget(); pointToTarget(); if(!m_target || !m_closest_kart) break; @@ -198,8 +211,7 @@ bool Swatter::updateAndTestFinished(int ticks) { // Start squashing m_animation_phase = SWATTER_TO_TARGET; - m_start_swat_ticks = - World::getWorld()->getTicksSinceStart() + 20; + m_start_swat_ticks = ticks_start + 20; // Setup the animation m_scene_node->setCurrentFrame(0.0f); m_scene_node->setLoopMode(false); @@ -207,14 +219,8 @@ bool Swatter::updateAndTestFinished(int ticks) #ifndef SERVER_ONLY // Play swat sound - const int wt = World::getWorld()->getTicksSinceStart(); - auto it = m_swat_sound_ticks.find(wt); - if (it == m_swat_sound_ticks.end()) - { - m_swat_sound->setPosition(swatter_pos); - m_swat_sound->play(); - m_swat_sound_ticks.insert(wt); - } + m_swat_sound->setPosition(swatter_pos); + m_swat_sound->play(); #endif } } @@ -223,15 +229,14 @@ bool Swatter::updateAndTestFinished(int ticks) { pointToTarget(); // Did we just finish the first part of the movement? - if (World::getWorld()->getTicksSinceStart() > m_start_swat_ticks) + if (ticks_start > m_start_swat_ticks) { m_start_swat_ticks = std::numeric_limits::max(); // Squash the karts and items around and // change the current phase squashThingsAround(); m_animation_phase = SWATTER_FROM_TARGET; - const int end_ticks = - World::getWorld()->getTicksSinceStart() + 60; + const int end_ticks = ticks_start + 60; if (race_manager ->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES || race_manager @@ -253,9 +258,9 @@ bool Swatter::updateAndTestFinished(int ticks) if (m_discard_now) { - return World::getWorld()->getTicksSinceStart() > m_end_swat_ticks; + return ticks_start > m_end_swat_ticks; } - else if (World::getWorld()->getTicksSinceStart() > m_end_swat_ticks) + else if (ticks_start > m_end_swat_ticks) { m_animation_phase = SWATTER_AIMING; m_end_swat_ticks = std::numeric_limits::max(); @@ -335,8 +340,23 @@ void Swatter::squashThingsAround() { const KartProperties *kp = m_kart->getKartProperties(); - m_closest_kart->setSquash(kp->getSwatterSquashDuration(), - kp->getSwatterSquashSlowdown()); + AbstractKart* closest_kart = m_closest_kart; + float duration = kp->getSwatterSquashDuration(); + float slowdown = kp->getSwatterSquashSlowdown(); + closest_kart->setSquash(duration, slowdown); + + // Locally add a event to replay the squash during rewind + if (NetworkConfig::get()->isNetworking() && + NetworkConfig::get()->isClient()) + { + RewindManager::get()->addRewindInfoEventFunction(new + RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(), + /*undo_function*/[](){}, + /*replay_function*/[closest_kart, duration, slowdown]() + { + closest_kart->setSquash(duration, slowdown); + })); + } // Handle achievement if the swatter is used by the current player if (m_kart->getController()->canGetAchievements()) diff --git a/src/items/swatter.hpp b/src/items/swatter.hpp index 76c1d8daa..24e089ba5 100644 --- a/src/items/swatter.hpp +++ b/src/items/swatter.hpp @@ -74,14 +74,17 @@ private: /** For some reason the built-in animation system doesn't work correctly here?? */ float m_swat_bomb_frame; - std::set m_swat_sound_ticks; - int m_start_swat_ticks; int m_end_swat_ticks; + + const int m_swatter_start_ticks; + + const int m_swatter_end_ticks; + public: Swatter(AbstractKart *kart, bool was_bomb, - scene::ISceneNode* bomb_scene_node); + scene::ISceneNode* bomb_scene_node, int ticks); virtual ~Swatter(); void updateGrahpics(float dt) OVERRIDE; bool updateAndTestFinished(int ticks) OVERRIDE; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index d94add348..855ee72ef 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -2953,7 +2953,7 @@ void Kart::updateGraphics(float dt) { m_squash_time -= dt; // If squasing time ends, reset the model - if (m_squash_time <= 0.0f) + if (m_squash_time <= 0.0f || !isSquashed()) { m_squash_time = std::numeric_limits::max(); m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));