diff --git a/src/graphics/sp/sp_mesh_node.hpp b/src/graphics/sp/sp_mesh_node.hpp index 1565024f2..a8e48cf62 100644 --- a/src/graphics/sp/sp_mesh_node.hpp +++ b/src/graphics/sp/sp_mesh_node.hpp @@ -138,6 +138,14 @@ public: return NULL; } // ------------------------------------------------------------------------ + void resetFirstRenderInfo(std::shared_ptr ri) + { + m_render_info.clear(); + m_first_render_info = ri; + m_render_info.resize(getMesh()->getMeshBufferCount(), + m_first_render_info); + } + // ------------------------------------------------------------------------ void setGlowColor(const video::SColorf& color) { m_glow_color = color; } // ------------------------------------------------------------------------ const video::SColorf& getGlowColor() const { return m_glow_color; } diff --git a/src/modes/capture_the_flag.cpp b/src/modes/capture_the_flag.cpp index 15bd72278..1799e3d97 100644 --- a/src/modes/capture_the_flag.cpp +++ b/src/modes/capture_the_flag.cpp @@ -84,13 +84,6 @@ void CaptureTheFlag::init() FreeForAll::init(); const btTransform& orig_red = Track::getCurrentTrack()->getRedFlag(); const btTransform& orig_blue = Track::getCurrentTrack()->getBlueFlag(); - m_red_flag = std::make_shared(FC_RED, orig_red); - m_blue_flag = std::make_shared(FC_BLUE, orig_blue); - if (NetworkConfig::get()->isNetworking()) - { - m_red_flag->rewinderAdd(); - m_blue_flag->rewinderAdd(); - } #ifndef SERVER_ONLY m_red_flag_node = irr_driver->addAnimatedMesh(m_red_flag_mesh, "red_flag"); @@ -115,11 +108,28 @@ void CaptureTheFlag::init() m_blue_flag_indicator->setPosition(Vec3( orig_blue(Vec3(0.0f, 2.5f, 0.0f))).toIrrVector()); #endif + + m_red_flag = std::make_shared(FC_RED, orig_red); + m_blue_flag = std::make_shared(FC_BLUE, orig_blue); + if (NetworkConfig::get()->isNetworking()) + { + m_red_flag->rewinderAdd(); + m_blue_flag->rewinderAdd(); + } + +#ifndef SERVER_ONLY + m_red_flag->initFlagRenderInfo(m_red_flag_node); + m_blue_flag->initFlagRenderInfo(m_blue_flag_node); +#endif } // init // ---------------------------------------------------------------------------- void CaptureTheFlag::reset(bool restart) { + // 5 bits for kart id (with -1 and -2 flag status) + if (m_karts.size() > 29) + Log::fatal("CaptureTheFlag", "Too many karts"); + FreeForAll::reset(restart); m_red_scores = m_blue_scores = 0; m_swatter_reset_kart_ticks.clear(); @@ -238,6 +248,7 @@ void CaptureTheFlag::update(int ticks) m_blue_flag->update(ticks); if (m_red_flag->getHolder() != -1 && m_blue_flag->isInBase() && + m_blue_flag->isActivated() && (m_blue_flag->getBaseOrigin() - m_red_flag->getOrigin()).length() < g_capture_length) { @@ -265,9 +276,10 @@ void CaptureTheFlag::update(int ticks) m_red_scores, new_blue_scores); } m_last_captured_flag_ticks = World::getWorld()->getTicksSinceStart(); - m_red_flag->resetToBase(); + m_red_flag->resetToBase(360/*deactivated_ticks*/); } else if (m_blue_flag->getHolder() != -1 && m_red_flag->isInBase() && + m_red_flag->isActivated() && (m_red_flag->getBaseOrigin() - m_blue_flag->getOrigin()).length() < g_capture_length) { @@ -295,7 +307,7 @@ void CaptureTheFlag::update(int ticks) new_red_scores, m_blue_scores); } m_last_captured_flag_ticks = World::getWorld()->getTicksSinceStart(); - m_blue_flag->resetToBase(); + m_blue_flag->resetToBase(360/*deactivated_ticks*/); } // Test if red or blue flag is touched @@ -314,7 +326,7 @@ void CaptureTheFlag::update(int ticks) if (!m_red_flag->isInBase()) { // Return the flag - m_red_flag->resetToBase(); + m_red_flag->resetToBase(360/*deactivated_ticks*/); } } else @@ -333,7 +345,7 @@ void CaptureTheFlag::update(int ticks) if (!m_blue_flag->isInBase()) { // Return the flag - m_blue_flag->resetToBase(); + m_blue_flag->resetToBase(360/*deactivated_ticks*/); } } else @@ -477,14 +489,14 @@ void CaptureTheFlag::loseFlagForKart(int kart_id) if (succeed) m_red_flag->dropFlagAt(dropped_trans); else - m_red_flag->resetToBase(); + m_red_flag->resetToBase(360/*deactivated_ticks*/); } else { if (succeed) m_blue_flag->dropFlagAt(dropped_trans); else - m_blue_flag->resetToBase(); + m_blue_flag->resetToBase(360/*deactivated_ticks*/); } } // loseFlagForKart diff --git a/src/modes/ctf_flag.cpp b/src/modes/ctf_flag.cpp index 4cbb7e594..23fd932d1 100644 --- a/src/modes/ctf_flag.cpp +++ b/src/modes/ctf_flag.cpp @@ -17,6 +17,8 @@ #include "modes/ctf_flag.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/render_info.hpp" +#include "graphics/sp/sp_mesh_node.hpp" #include "karts/abstract_kart.hpp" #include "modes/world.hpp" #include "network/network_string.hpp" @@ -32,7 +34,11 @@ BareNetworkString* CTFFlag::saveState(std::vector* ru) { ru->push_back(getUniqueIdentity()); BareNetworkString* buffer = new BareNetworkString(); - buffer->addUInt8(m_flag_status); + int flag_status_unsigned = m_flag_status + 2; + flag_status_unsigned &= 31; + // Max 2047 for m_deactivated_ticks set by resetToBase + flag_status_unsigned |= m_deactivated_ticks << 5; + buffer->addUInt16((uint16_t)flag_status_unsigned); if (m_flag_status == OFF_BASE) { buffer->addInt24(m_off_base_compressed[0]) @@ -48,7 +54,10 @@ BareNetworkString* CTFFlag::saveState(std::vector* ru) void CTFFlag::restoreState(BareNetworkString* buffer, int count) { using namespace MiniGLM; - m_flag_status = buffer->getUInt8(); + unsigned flag_status_unsigned = buffer->getUInt16(); + int flag_status = flag_status_unsigned & 31; + m_flag_status = (int8_t)(flag_status - 2); + m_deactivated_ticks = flag_status_unsigned >> 5; if (m_flag_status == OFF_BASE) { m_off_base_compressed[0] = buffer->getInt24(); @@ -83,6 +92,9 @@ void CTFFlag::update(int ticks) { updateFlagTrans(m_flag_trans); + if (m_deactivated_ticks > 0) + m_deactivated_ticks -= ticks; + // Check if not returning for too long if (m_flag_status != OFF_BASE) return; @@ -116,8 +128,29 @@ void CTFFlag::updateFlagGraphics(irr::scene::IAnimatedMeshSceneNode* flag_node) flag_node->setRotation(hpr.toIrrHPR()); flag_node->setAnimationSpeed(25.0f); } + +#ifndef SERVER_ONLY + if (m_flag_render_info) + { + if (m_deactivated_ticks > 0) + m_flag_render_info->setTransparent(true); + else + m_flag_render_info->setTransparent(false); + } +#endif + } // updateFlagPosition +// ---------------------------------------------------------------------------- +void CTFFlag::initFlagRenderInfo(irr::scene::IAnimatedMeshSceneNode* flag_node) +{ + SP::SPMeshNode* spmn = dynamic_cast(flag_node); + if (!spmn) + return; + m_flag_render_info = std::make_shared(0.0f, true); + spmn->resetFirstRenderInfo(m_flag_render_info); +} // initFlagRenderInfo + // ---------------------------------------------------------------------------- void CTFFlag::dropFlagAt(const btTransform& t) { diff --git a/src/modes/ctf_flag.hpp b/src/modes/ctf_flag.hpp index 02ca1f5b8..42b666d43 100644 --- a/src/modes/ctf_flag.hpp +++ b/src/modes/ctf_flag.hpp @@ -31,6 +31,8 @@ enum FlagColor : unsigned int FC_BLUE = 1 }; +class RenderInfo; + namespace irr { namespace scene @@ -61,6 +63,11 @@ private: /* Set by dropFlagAt to pre-compressed the dropped flag transformation. */ int m_off_base_compressed[4]; + + /* Determine if the flag should be drawn translucently */ + std::shared_ptr m_flag_render_info; + + uint16_t m_deactivated_ticks; public: // ------------------------------------------------------------------------ CTFFlag(FlagColor fc, const btTransform& base_trans) @@ -108,8 +115,12 @@ public: // ------------------------------------------------------------------------ const btTransform& getBaseTrans() const { return m_flag_base_trans; } // ------------------------------------------------------------------------ - void resetToBase() + void resetToBase(uint16_t deactivated_ticks = 0) { + // 11 bit for deactivated_ticks saved with flag status (5 bits) + if (deactivated_ticks > 2047) + deactivated_ticks = 2047; + m_deactivated_ticks = deactivated_ticks; m_flag_status = IN_BASE; m_ticks_since_off_base = 0; updateFlagTrans(); @@ -126,13 +137,18 @@ public: // ------------------------------------------------------------------------ bool isInBase() const { return m_flag_status == IN_BASE; } // ------------------------------------------------------------------------ - bool canBeCaptured() const { return !(m_flag_status >= 0); } + bool isActivated() const { return m_deactivated_ticks == 0; } + // ------------------------------------------------------------------------ + bool canBeCaptured() const + { return !(m_flag_status >= 0) && isActivated(); } // ------------------------------------------------------------------------ void update(int ticks); // ------------------------------------------------------------------------ void updateFlagTrans(const btTransform& off_base_trans = btTransform()); // ------------------------------------------------------------------------ void updateFlagGraphics(irr::scene::IAnimatedMeshSceneNode* flag_node); + // ------------------------------------------------------------------------ + void initFlagRenderInfo(irr::scene::IAnimatedMeshSceneNode* flag_node); }; // CTFFlag #endif