Make flag a rewinder
It remove the capturing delay and allow ctf in local splitscreen
This commit is contained in:
parent
14389925fe
commit
d6946198c5
@ -23,9 +23,12 @@
|
|||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/controller/controller.hpp"
|
#include "karts/controller/controller.hpp"
|
||||||
#include "karts/kart_model.hpp"
|
#include "karts/kart_model.hpp"
|
||||||
|
#include "modes/ctf_flag.hpp"
|
||||||
#include "network/network_config.hpp"
|
#include "network/network_config.hpp"
|
||||||
#include "network/network_string.hpp"
|
#include "network/network_string.hpp"
|
||||||
#include "network/protocols/game_events_protocol.hpp"
|
#include "network/protocols/game_events_protocol.hpp"
|
||||||
|
#include "network/rewind_info.hpp"
|
||||||
|
#include "network/rewind_manager.hpp"
|
||||||
#include "network/server_config.hpp"
|
#include "network/server_config.hpp"
|
||||||
#include "network/stk_host.hpp"
|
#include "network/stk_host.hpp"
|
||||||
#include "physics/triangle_mesh.hpp"
|
#include "physics/triangle_mesh.hpp"
|
||||||
@ -35,8 +38,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
const Vec3 g_kart_flag_offset(0.0, 0.2f, -0.5f);
|
const float g_capture_length = 2.0f;
|
||||||
const float g_capture_length = 3.0f;
|
|
||||||
const int g_captured_score = 10;
|
const int g_captured_score = 10;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -80,8 +82,15 @@ CaptureTheFlag::~CaptureTheFlag()
|
|||||||
void CaptureTheFlag::init()
|
void CaptureTheFlag::init()
|
||||||
{
|
{
|
||||||
FreeForAll::init();
|
FreeForAll::init();
|
||||||
m_orig_red_trans = Track::getCurrentTrack()->getRedFlag();
|
const btTransform& orig_red = Track::getCurrentTrack()->getRedFlag();
|
||||||
m_orig_blue_trans = Track::getCurrentTrack()->getBlueFlag();
|
const btTransform& orig_blue = Track::getCurrentTrack()->getBlueFlag();
|
||||||
|
m_red_flag = std::make_shared<CTFFlag>(FC_RED, orig_red);
|
||||||
|
m_blue_flag = std::make_shared<CTFFlag>(FC_BLUE, orig_blue);
|
||||||
|
if (NetworkConfig::get()->isNetworking())
|
||||||
|
{
|
||||||
|
m_red_flag->rewinderAdd();
|
||||||
|
m_blue_flag->rewinderAdd();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
m_red_flag_node = irr_driver->addAnimatedMesh(m_red_flag_mesh, "red_flag");
|
m_red_flag_node = irr_driver->addAnimatedMesh(m_red_flag_mesh, "red_flag");
|
||||||
@ -96,13 +105,13 @@ void CaptureTheFlag::init()
|
|||||||
file_manager->getAsset(FileManager::GUI_ICON, "blue_arrow.png");
|
file_manager->getAsset(FileManager::GUI_ICON, "blue_arrow.png");
|
||||||
|
|
||||||
m_red_flag_indicator = irr_driver->addBillboard(
|
m_red_flag_indicator = irr_driver->addBillboard(
|
||||||
core::dimension2df(1.5f, 1.5f), red_path, NULL);
|
core::dimension2df(1.5f, 1.5f), red_path, NULL);
|
||||||
m_red_flag_indicator->setPosition(Vec3(
|
m_red_flag_indicator->setPosition(Vec3(
|
||||||
m_orig_red_trans(Vec3(0.0f, 2.5f, 0.0f))).toIrrVector());
|
orig_red(Vec3(0.0f, 2.5f, 0.0f))).toIrrVector());
|
||||||
m_blue_flag_indicator = irr_driver->addBillboard(
|
m_blue_flag_indicator = irr_driver->addBillboard(
|
||||||
core::dimension2df(1.5f, 1.5f), blue_path, NULL);
|
core::dimension2df(1.5f, 1.5f), blue_path, NULL);
|
||||||
m_blue_flag_indicator->setPosition(Vec3(
|
m_blue_flag_indicator->setPosition(Vec3(
|
||||||
m_orig_blue_trans(Vec3(0.0f, 2.5f, 0.0f))).toIrrVector());
|
orig_blue(Vec3(0.0f, 2.5f, 0.0f))).toIrrVector());
|
||||||
#endif
|
#endif
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
@ -110,53 +119,85 @@ void CaptureTheFlag::init()
|
|||||||
void CaptureTheFlag::reset(bool restart)
|
void CaptureTheFlag::reset(bool restart)
|
||||||
{
|
{
|
||||||
FreeForAll::reset(restart);
|
FreeForAll::reset(restart);
|
||||||
m_red_trans = m_orig_red_trans;
|
m_red_scores = m_blue_scores = 0;
|
||||||
m_blue_trans = m_orig_blue_trans;
|
|
||||||
m_red_return_ticks = m_blue_return_ticks = m_red_scores =
|
|
||||||
m_blue_scores = 0;
|
|
||||||
m_red_holder = m_blue_holder = -1;
|
|
||||||
updateFlagNodes();
|
|
||||||
m_swatter_reset_kart_ticks.clear();
|
m_swatter_reset_kart_ticks.clear();
|
||||||
|
m_last_captured_flag_ticks = 0;
|
||||||
|
m_red_flag_status = m_blue_flag_status = CTFFlag::IN_BASE;
|
||||||
|
m_red_flag->resetToBase();
|
||||||
|
m_blue_flag->resetToBase();
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
|
if (m_red_flag_node)
|
||||||
|
m_red_flag->updateFlagGraphics(m_red_flag_node);
|
||||||
|
if (m_blue_flag_node)
|
||||||
|
m_blue_flag->updateFlagGraphics(m_blue_flag_node);
|
||||||
|
#endif
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::updateGraphics(float dt)
|
void CaptureTheFlag::updateGraphics(float dt)
|
||||||
{
|
{
|
||||||
FreeForAll::updateGraphics(dt);
|
FreeForAll::updateGraphics(dt);
|
||||||
if (!NetworkConfig::get()->isNetworking() ||
|
|
||||||
NetworkConfig::get()->isClient())
|
|
||||||
{
|
|
||||||
if (m_red_holder != -1)
|
|
||||||
{
|
|
||||||
m_red_trans = getKart(m_red_holder)->getSmoothedTrans();
|
|
||||||
m_red_trans.setOrigin(m_red_trans(g_kart_flag_offset));
|
|
||||||
m_red_flag_node->setAnimationSpeed(fabsf(getKart(m_red_holder)
|
|
||||||
->getSpeed()) * 3.0f + 25.0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_red_flag_node->setAnimationSpeed(25.0f);
|
|
||||||
|
|
||||||
if (m_blue_holder != -1)
|
#ifndef SERVER_ONLY
|
||||||
|
if (m_red_flag_node)
|
||||||
|
m_red_flag->updateFlagGraphics(m_red_flag_node);
|
||||||
|
if (m_blue_flag_node)
|
||||||
|
m_blue_flag->updateFlagGraphics(m_blue_flag_node);
|
||||||
|
if (m_red_flag_indicator)
|
||||||
|
m_red_flag_indicator->setVisible(!m_red_flag->isInBase());
|
||||||
|
if (m_blue_flag_indicator)
|
||||||
|
m_blue_flag_indicator->setVisible(!m_blue_flag->isInBase());
|
||||||
|
|
||||||
|
core::stringw msg;
|
||||||
|
// Don't show flag has been returned message if there was scored event
|
||||||
|
// happening recently
|
||||||
|
const bool scored_recently =
|
||||||
|
getTicksSinceStart() > m_last_captured_flag_ticks &&
|
||||||
|
getTicksSinceStart() - m_last_captured_flag_ticks < 200;
|
||||||
|
if (m_red_flag_status != m_red_flag->getStatus())
|
||||||
|
{
|
||||||
|
if (m_red_flag->getHolder() != -1)
|
||||||
{
|
{
|
||||||
m_blue_trans = getKart(m_blue_holder)->getSmoothedTrans();
|
AbstractKart* kart = getKart(m_red_flag->getHolder());
|
||||||
m_blue_trans.setOrigin(m_blue_trans(g_kart_flag_offset));
|
const core::stringw& name = kart->getController()->getName();
|
||||||
m_blue_flag_node->setAnimationSpeed(fabsf(getKart(m_blue_holder)
|
// I18N: Show when a player gets the red flag in CTF
|
||||||
->getSpeed()) * 3.0f + 25.0f);
|
msg = _("%s has the red flag!", name);
|
||||||
|
if (kart->getController()->isLocalPlayerController())
|
||||||
|
SFXManager::get()->quickSound("wee");
|
||||||
}
|
}
|
||||||
else
|
else if (m_red_flag->isInBase() && !scored_recently)
|
||||||
m_blue_flag_node->setAnimationSpeed(25.0f);
|
{
|
||||||
m_red_flag_indicator->setVisible(!isRedFlagInBase());
|
// I18N: Show when the red flag is returned to its base in CTF
|
||||||
m_blue_flag_indicator->setVisible(!isBlueFlagInBase());
|
msg = _("The red flag has returned!");
|
||||||
|
}
|
||||||
|
m_red_flag_status = m_red_flag->getStatus();
|
||||||
}
|
}
|
||||||
|
else if (m_blue_flag_status != m_blue_flag->getStatus())
|
||||||
|
{
|
||||||
|
if (m_blue_flag->getHolder() != -1)
|
||||||
|
{
|
||||||
|
AbstractKart* kart = getKart(m_blue_flag->getHolder());
|
||||||
|
const core::stringw& name = kart->getController()->getName();
|
||||||
|
// I18N: Show when a player gets the blue flag in CTF
|
||||||
|
msg = _("%s has the blue flag!", name);
|
||||||
|
if (kart->getController()->isLocalPlayerController())
|
||||||
|
SFXManager::get()->quickSound("wee");
|
||||||
|
}
|
||||||
|
else if (m_blue_flag->isInBase() && !scored_recently)
|
||||||
|
{
|
||||||
|
// I18N: Show when the blue flag is returned to its base in CTF
|
||||||
|
msg = _("The blue flag has returned!");
|
||||||
|
}
|
||||||
|
m_blue_flag_status = m_blue_flag->getStatus();
|
||||||
|
}
|
||||||
|
if (!msg.empty())
|
||||||
|
m_race_gui->addMessage(msg, NULL, 1.5f);
|
||||||
|
#endif
|
||||||
} // updateGraphics
|
} // updateGraphics
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::update(int ticks)
|
void CaptureTheFlag::update(int ticks)
|
||||||
{
|
{
|
||||||
if (m_red_holder != -1 && m_blue_holder != -1 &&
|
|
||||||
m_red_holder == m_blue_holder)
|
|
||||||
Log::fatal("CaptureTheFlag", "Flag management messed up, abort.");
|
|
||||||
|
|
||||||
FreeForAll::update(ticks);
|
FreeForAll::update(ticks);
|
||||||
|
|
||||||
for (auto it = m_swatter_reset_kart_ticks.begin();
|
for (auto it = m_swatter_reset_kart_ticks.begin();
|
||||||
@ -189,88 +230,61 @@ void CaptureTheFlag::update(int ticks)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NetworkConfig::get()->isNetworking() ||
|
|
||||||
NetworkConfig::get()->isClient())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Update new flags position
|
// Update new flags position
|
||||||
if (m_red_holder != -1)
|
m_red_flag->update(ticks);
|
||||||
{
|
m_blue_flag->update(ticks);
|
||||||
m_red_trans = getKart(m_red_holder)->getTrans();
|
|
||||||
m_red_trans.setOrigin(m_red_trans(g_kart_flag_offset));
|
|
||||||
}
|
|
||||||
if (m_blue_holder != -1)
|
|
||||||
{
|
|
||||||
m_blue_trans = getKart(m_blue_holder)->getTrans();
|
|
||||||
m_blue_trans.setOrigin(m_blue_trans(g_kart_flag_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool red_flag_in_base =
|
if (m_red_flag->getHolder() != -1 && m_blue_flag->isInBase() &&
|
||||||
m_red_trans.getOrigin() == m_orig_red_trans.getOrigin();
|
(m_blue_flag->getBaseOrigin() - m_red_flag->getOrigin()).length() <
|
||||||
const bool blue_flag_in_base =
|
|
||||||
m_blue_trans.getOrigin() == m_orig_blue_trans.getOrigin();
|
|
||||||
|
|
||||||
// Check if not returning for too long
|
|
||||||
if (m_red_holder != -1 || red_flag_in_base)
|
|
||||||
m_red_return_ticks = 0;
|
|
||||||
else
|
|
||||||
m_red_return_ticks++;
|
|
||||||
|
|
||||||
if (m_blue_holder != -1 || blue_flag_in_base)
|
|
||||||
m_blue_return_ticks = 0;
|
|
||||||
else
|
|
||||||
m_blue_return_ticks++;
|
|
||||||
|
|
||||||
const int max_flag_return_timeout = stk_config->time2Ticks(
|
|
||||||
ServerConfig::m_flag_return_timemout);
|
|
||||||
if (m_red_holder == -1 && m_red_return_ticks > max_flag_return_timeout)
|
|
||||||
{
|
|
||||||
resetRedFlagToOrigin();
|
|
||||||
m_red_return_ticks = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_blue_holder == -1 && m_blue_return_ticks > max_flag_return_timeout)
|
|
||||||
{
|
|
||||||
resetBlueFlagToOrigin();
|
|
||||||
m_blue_return_ticks = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_red_holder != -1 && m_blue_holder == -1 &&
|
|
||||||
blue_flag_in_base &&
|
|
||||||
(m_orig_blue_trans.getOrigin() - m_red_trans.getOrigin()).length() <
|
|
||||||
g_capture_length)
|
g_capture_length)
|
||||||
{
|
{
|
||||||
// Blue team scored
|
// Blue team scored
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
if (!NetworkConfig::get()->isNetworking() ||
|
||||||
p.setSynchronous(true);
|
NetworkConfig::get()->isServer())
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_RESET)
|
{
|
||||||
.addUInt8(1 << 1 | 0) // Reset red flag
|
int red_holder = m_red_flag->getHolder();
|
||||||
.addUInt8((int8_t)m_red_holder);
|
int new_score = m_scores.at(red_holder) + g_captured_score;
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
m_scores.at(red_holder) = new_score;
|
||||||
m_scores.at(m_red_holder) += g_captured_score;
|
if (NetworkConfig::get()->isServer())
|
||||||
m_red_holder = -1;
|
{
|
||||||
m_red_trans = m_orig_red_trans;
|
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||||
m_blue_scores++;
|
p.setSynchronous(true);
|
||||||
return;
|
p.addUInt8(GameEventsProtocol::GE_CTF_SCORED)
|
||||||
|
.addUInt8((int8_t)red_holder)
|
||||||
|
.addUInt8(0/*red_team_scored*/)
|
||||||
|
.addUInt32(new_score);
|
||||||
|
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||||
|
}
|
||||||
|
ctfScored(red_holder, false/*red_team_scored*/, new_score);
|
||||||
|
}
|
||||||
|
m_last_captured_flag_ticks = World::getWorld()->getTicksSinceStart();
|
||||||
|
m_red_flag->resetToBase();
|
||||||
}
|
}
|
||||||
else if (m_blue_holder != -1 && m_red_holder == -1 &&
|
else if (m_blue_flag->getHolder() != -1 && m_red_flag->isInBase() &&
|
||||||
red_flag_in_base &&
|
(m_red_flag->getBaseOrigin() - m_blue_flag->getOrigin()).length() <
|
||||||
(m_orig_red_trans.getOrigin() - m_blue_trans.getOrigin()).length() <
|
|
||||||
g_capture_length)
|
g_capture_length)
|
||||||
{
|
{
|
||||||
// Red team scored
|
// Red team scored
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
if (!NetworkConfig::get()->isNetworking() ||
|
||||||
p.setSynchronous(true);
|
NetworkConfig::get()->isServer())
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_RESET)
|
{
|
||||||
.addUInt8(0 << 1 | 0) // Reset blue flag
|
int blue_holder = m_blue_flag->getHolder();
|
||||||
.addUInt8((int8_t)m_blue_holder);
|
int new_score = m_scores.at(blue_holder) + g_captured_score;
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
m_scores.at(blue_holder) = new_score;
|
||||||
m_scores.at(m_blue_holder) += g_captured_score;
|
if (NetworkConfig::get()->isServer())
|
||||||
m_blue_holder = -1;
|
{
|
||||||
m_blue_trans = m_orig_blue_trans;
|
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||||
m_red_scores++;
|
p.setSynchronous(true);
|
||||||
return;
|
p.addUInt8(GameEventsProtocol::GE_CTF_SCORED)
|
||||||
|
.addUInt8((int8_t)blue_holder)
|
||||||
|
.addUInt8(1/*red_team_scored*/)
|
||||||
|
.addUInt32(new_score);
|
||||||
|
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||||
|
}
|
||||||
|
ctfScored(blue_holder, true/*red_team_scored*/, new_score);
|
||||||
|
}
|
||||||
|
m_last_captured_flag_ticks = World::getWorld()->getTicksSinceStart();
|
||||||
|
m_blue_flag->resetToBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if red or blue flag is touched
|
// Test if red or blue flag is touched
|
||||||
@ -279,220 +293,108 @@ void CaptureTheFlag::update(int ticks)
|
|||||||
if (k->isEliminated() || k->getKartAnimation() || k->isSquashed())
|
if (k->isEliminated() || k->getKartAnimation() || k->isSquashed())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m_red_holder == -1 &&
|
if (m_red_flag->canBeCaptured() &&
|
||||||
(k->getXYZ() - m_red_trans.getOrigin()).length() <
|
(k->getXYZ() - m_red_flag->getOrigin()).length() <
|
||||||
g_capture_length)
|
g_capture_length)
|
||||||
{
|
{
|
||||||
uint8_t kart_id = (uint8_t)k->getWorldKartId();
|
uint8_t kart_id = (uint8_t)k->getWorldKartId();
|
||||||
if (getKartTeam(kart_id) == KART_TEAM_RED)
|
if (getKartTeam(kart_id) == KART_TEAM_RED)
|
||||||
{
|
{
|
||||||
if (!red_flag_in_base)
|
if (!m_red_flag->isInBase())
|
||||||
{
|
{
|
||||||
// Return the flag
|
// Return the flag
|
||||||
resetRedFlagToOrigin();
|
m_red_flag->resetToBase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get the flag
|
// Get the flag
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
m_red_flag->setCapturedByKart(kart_id);
|
||||||
p.setSynchronous(true);
|
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_ATTACH)
|
|
||||||
.addUInt8(1) // Attach red flag
|
|
||||||
.addUInt8(kart_id);
|
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
|
||||||
m_red_holder = kart_id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_blue_holder == -1 &&
|
if (m_blue_flag->canBeCaptured() &&
|
||||||
(k->getXYZ() - m_blue_trans.getOrigin()).length() <
|
(k->getXYZ() - m_blue_flag->getOrigin()).length() <
|
||||||
g_capture_length)
|
g_capture_length)
|
||||||
{
|
{
|
||||||
uint8_t kart_id = (uint8_t)k->getWorldKartId();
|
uint8_t kart_id = (uint8_t)k->getWorldKartId();
|
||||||
if (getKartTeam(kart_id) == KART_TEAM_BLUE)
|
if (getKartTeam(kart_id) == KART_TEAM_BLUE)
|
||||||
{
|
{
|
||||||
if (!blue_flag_in_base)
|
if (!m_blue_flag->isInBase())
|
||||||
{
|
{
|
||||||
// Return the flag
|
// Return the flag
|
||||||
resetBlueFlagToOrigin();
|
m_blue_flag->resetToBase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get the flag
|
// Get the flag
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
m_blue_flag->setCapturedByKart(kart_id);
|
||||||
p.setSynchronous(true);
|
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_ATTACH)
|
|
||||||
.addUInt8(0) // Attach blue flag
|
|
||||||
.addUInt8(kart_id);
|
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
|
||||||
m_blue_holder = kart_id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::resetRedFlagToOrigin()
|
int CaptureTheFlag::getRedHolder() const
|
||||||
{
|
{
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
return m_red_flag->getHolder();
|
||||||
p.setSynchronous(true);
|
} // getRedHolder
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_RESET)
|
|
||||||
.addUInt8(1 << 1 | 0) // Reset red flag to original
|
|
||||||
.addUInt8(((int8_t)-1));
|
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
|
||||||
m_red_trans = m_orig_red_trans;
|
|
||||||
} // resetRedFlagToOrigin
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::resetBlueFlagToOrigin()
|
int CaptureTheFlag::getBlueHolder() const
|
||||||
{
|
{
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
return m_blue_flag->getHolder();
|
||||||
p.setSynchronous(true);
|
} // getBlueHolder
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_RESET)
|
|
||||||
.addUInt8(0 << 1 | 0) // Reset blue flag to original
|
|
||||||
.addUInt8(((int8_t)-1));
|
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
|
||||||
m_blue_trans = m_orig_blue_trans;
|
|
||||||
} // resetBlueFlagToOrigin
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::updateFlagNodes()
|
bool CaptureTheFlag::isRedFlagInBase() const
|
||||||
{
|
{
|
||||||
#ifndef SERVER_ONLY
|
return m_red_flag->isInBase();
|
||||||
Vec3 hpr;
|
} // isRedFlagInBase
|
||||||
if (m_red_holder == -1)
|
|
||||||
{
|
|
||||||
m_red_flag_node->setPosition(
|
|
||||||
Vec3(m_red_trans.getOrigin()).toIrrVector());
|
|
||||||
hpr.setHPR(m_red_trans.getRotation());
|
|
||||||
m_red_flag_node->setRotation(hpr.toIrrHPR());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_blue_holder == -1)
|
|
||||||
{
|
|
||||||
m_blue_flag_node->setPosition(
|
|
||||||
Vec3(m_blue_trans.getOrigin()).toIrrVector());
|
|
||||||
hpr.setHPR(m_blue_trans.getRotation());
|
|
||||||
m_blue_flag_node->setRotation(hpr.toIrrHPR());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} // updateFlagNodes
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::attachFlag(NetworkString& ns)
|
bool CaptureTheFlag::isBlueFlagInBase() const
|
||||||
{
|
{
|
||||||
#ifndef SERVER_ONLY
|
return m_blue_flag->isInBase();
|
||||||
bool attach_red_flag = ns.getUInt8() == 1;
|
} // isBlueFlagInBase
|
||||||
unsigned kart_id = ns.getUInt8();
|
|
||||||
core::stringw get_msg;
|
// ----------------------------------------------------------------------------
|
||||||
const core::stringw& name = getKart(kart_id)->getController()
|
const Vec3& CaptureTheFlag::getRedFlag() const
|
||||||
->getName();
|
{
|
||||||
if (attach_red_flag)
|
return m_red_flag->getOrigin();
|
||||||
|
} // getRedFlag
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const Vec3& CaptureTheFlag::getBlueFlag() const
|
||||||
|
{
|
||||||
|
return m_blue_flag->getOrigin();
|
||||||
|
} // getBlueFlag
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void CaptureTheFlag::ctfScored(int kart_id, bool red_team_scored,
|
||||||
|
int new_score)
|
||||||
|
{
|
||||||
|
m_scores.at(kart_id) = new_score;
|
||||||
|
AbstractKart* kart = getKart(kart_id);
|
||||||
|
core::stringw scored_msg;
|
||||||
|
const core::stringw& name = kart->getController()->getName();
|
||||||
|
if (red_team_scored)
|
||||||
{
|
{
|
||||||
m_red_holder = kart_id;
|
scored_msg = _("%s captured the blue flag!", name);
|
||||||
m_red_flag_node->setParent(getKart(kart_id)->getNode());
|
m_red_scores++;
|
||||||
m_red_flag_node->setPosition(g_kart_flag_offset.toIrrVector());
|
|
||||||
m_red_flag_node->setRotation(core::vector3df(0.0f, 180.0f, 0.0f));
|
|
||||||
// I18N: Show when a player gets the flag in CTF
|
|
||||||
get_msg = _("%s has the red flag!", name);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_blue_holder = kart_id;
|
scored_msg = _("%s captured the red flag!", name);
|
||||||
m_blue_flag_node->setParent(getKart(kart_id)->getNode());
|
m_blue_scores++;
|
||||||
m_blue_flag_node->setPosition(g_kart_flag_offset.toIrrVector());
|
|
||||||
m_blue_flag_node->setRotation(core::vector3df(0.0f, 180.0f, 0.0f));
|
|
||||||
// I18N: Show when a player gets the flag in CTF
|
|
||||||
get_msg = _("%s has the blue flag!", name);
|
|
||||||
}
|
}
|
||||||
if (getKart(kart_id)->getController()->isLocalPlayerController())
|
|
||||||
SFXManager::get()->quickSound("wee");
|
|
||||||
m_race_gui->addMessage(get_msg, NULL, 1.5f);
|
|
||||||
#endif
|
|
||||||
} // attachFlag
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
void CaptureTheFlag::resetFlag(NetworkString& ns)
|
|
||||||
{
|
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
uint8_t reset_info = ns.getUInt8();
|
m_race_gui->addMessage(scored_msg, NULL, 3.0f);
|
||||||
bool reset_red_flag = (reset_info >> 1 & 1) == 1;
|
kart->getKartModel()
|
||||||
bool with_custom_transform = (reset_info & 1) == 1;
|
->setAnimation(KartModel::AF_WIN_START, true/*play_non_loop*/);
|
||||||
int8_t kart_id = ns.getUInt8();
|
m_scored_sound->play();
|
||||||
if (kart_id != -1)
|
|
||||||
{
|
|
||||||
core::stringw scored_msg;
|
|
||||||
AbstractKart* kart = getKart(kart_id);
|
|
||||||
const core::stringw& name = kart->getController()->getName();
|
|
||||||
if (reset_red_flag)
|
|
||||||
{
|
|
||||||
m_scores.at(kart_id) += g_captured_score;
|
|
||||||
m_red_holder = -1;
|
|
||||||
m_red_trans = m_orig_red_trans;
|
|
||||||
// I18N: Show when a player captured the flag in CTF
|
|
||||||
scored_msg = _("%s captured the red flag!", name);
|
|
||||||
m_red_flag_node->setParent(
|
|
||||||
irr_driver->getSceneManager()->getRootSceneNode());
|
|
||||||
m_blue_scores++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_scores.at(kart_id) += g_captured_score;
|
|
||||||
m_blue_holder = -1;
|
|
||||||
m_blue_trans = m_orig_blue_trans;
|
|
||||||
// I18N: Show when a player captured the flag in CTF
|
|
||||||
scored_msg = _("%s captured the blue flag!", name);
|
|
||||||
m_blue_flag_node->setParent(
|
|
||||||
irr_driver->getSceneManager()->getRootSceneNode());
|
|
||||||
m_red_scores++;
|
|
||||||
}
|
|
||||||
m_race_gui->addMessage(scored_msg, NULL, 3.0f);
|
|
||||||
kart->getKartModel()
|
|
||||||
->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/);
|
|
||||||
m_scored_sound->play();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core::stringw returned_msg;
|
|
||||||
if (reset_red_flag)
|
|
||||||
{
|
|
||||||
btTransform t = m_orig_red_trans;
|
|
||||||
// I18N: Show when the red flag is returned to its base in CTF
|
|
||||||
if (!with_custom_transform)
|
|
||||||
returned_msg = _("The red flag has returned!");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.setOrigin(ns.getVec3());
|
|
||||||
t.setRotation(ns.getQuat());
|
|
||||||
}
|
|
||||||
m_red_holder = -1;
|
|
||||||
m_red_trans = t;
|
|
||||||
m_red_flag_node->setParent(
|
|
||||||
irr_driver->getSceneManager()->getRootSceneNode());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
btTransform t = m_orig_blue_trans;
|
|
||||||
// I18N: Show when the blue flag is returned to its base in CTF
|
|
||||||
if (!with_custom_transform)
|
|
||||||
returned_msg = _("The blue flag has returned!");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t.setOrigin(ns.getVec3());
|
|
||||||
t.setRotation(ns.getQuat());
|
|
||||||
}
|
|
||||||
m_blue_holder = -1;
|
|
||||||
m_blue_trans = t;
|
|
||||||
m_blue_flag_node->setParent(
|
|
||||||
irr_driver->getSceneManager()->getRootSceneNode());
|
|
||||||
}
|
|
||||||
if (!returned_msg.empty())
|
|
||||||
m_race_gui->addMessage(returned_msg, NULL, 1.5f);
|
|
||||||
}
|
|
||||||
updateFlagNodes();
|
|
||||||
#endif
|
#endif
|
||||||
} // resetFlag
|
} // ctfScored
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
bool CaptureTheFlag::getDroppedFlagTrans(const btTransform& kt,
|
bool CaptureTheFlag::getDroppedFlagTrans(const btTransform& kt,
|
||||||
@ -545,48 +447,66 @@ bool CaptureTheFlag::isRaceOver()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void CaptureTheFlag::loseFlagForKart(int kart_id)
|
void CaptureTheFlag::loseFlagForKart(int kart_id)
|
||||||
{
|
{
|
||||||
if (!(m_red_holder == kart_id || m_blue_holder == kart_id))
|
if (!(m_red_flag->getHolder() == kart_id ||
|
||||||
|
m_blue_flag->getHolder() == kart_id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool reset_red_flag = m_red_holder == kart_id;
|
bool drop_red_flag = m_red_flag->getHolder() == kart_id;
|
||||||
btTransform dropped_trans = reset_red_flag ?
|
btTransform dropped_trans = drop_red_flag ?
|
||||||
m_orig_red_trans : m_orig_blue_trans;
|
m_red_flag->getBaseTrans() :
|
||||||
|
m_blue_flag->getBaseTrans();
|
||||||
bool succeed = getDroppedFlagTrans(getKart(kart_id)->getTrans(),
|
bool succeed = getDroppedFlagTrans(getKart(kart_id)->getTrans(),
|
||||||
&dropped_trans);
|
&dropped_trans);
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
if (drop_red_flag)
|
||||||
p.setSynchronous(true);
|
|
||||||
// If reset red flag
|
|
||||||
uint8_t reset_info = reset_red_flag ? 1 : 0;
|
|
||||||
reset_info <<= 1;
|
|
||||||
// With custom transform
|
|
||||||
if (succeed)
|
|
||||||
reset_info |= 1;
|
|
||||||
p.addUInt8(GameEventsProtocol::GE_CTF_RESET).addUInt8(reset_info)
|
|
||||||
.addUInt8(((int8_t)-1));
|
|
||||||
if (succeed)
|
|
||||||
{
|
{
|
||||||
p.add(Vec3(dropped_trans.getOrigin()))
|
if (succeed)
|
||||||
.add(dropped_trans.getRotation());
|
m_red_flag->dropFlagAt(dropped_trans);
|
||||||
}
|
else
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
m_red_flag->resetToBase();
|
||||||
if (reset_red_flag)
|
|
||||||
{
|
|
||||||
m_red_holder = -1;
|
|
||||||
m_red_trans = dropped_trans;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_blue_holder = -1;
|
if (succeed)
|
||||||
m_blue_trans = dropped_trans;
|
m_blue_flag->dropFlagAt(dropped_trans);
|
||||||
|
else
|
||||||
|
m_blue_flag->resetToBase();
|
||||||
|
}
|
||||||
|
if (NetworkConfig::get()->isNetworking() &&
|
||||||
|
NetworkConfig::get()->isClient())
|
||||||
|
{
|
||||||
|
RewindManager::get()->addRewindInfoEventFunction(new
|
||||||
|
RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(),
|
||||||
|
[](){},
|
||||||
|
/*replay_function*/[dropped_trans, drop_red_flag, succeed, this]()
|
||||||
|
{
|
||||||
|
if (drop_red_flag)
|
||||||
|
{
|
||||||
|
if (succeed)
|
||||||
|
m_red_flag->dropFlagAt(dropped_trans);
|
||||||
|
else
|
||||||
|
m_red_flag->resetToBase();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (succeed)
|
||||||
|
m_blue_flag->dropFlagAt(dropped_trans);
|
||||||
|
else
|
||||||
|
m_blue_flag->resetToBase();
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
} // loseFlagForKart
|
} // loseFlagForKart
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
bool CaptureTheFlag::kartHit(int kart_id, int hitter)
|
bool CaptureTheFlag::kartHit(int kart_id, int hitter)
|
||||||
{
|
{
|
||||||
if (!FreeForAll::kartHit(kart_id, hitter))
|
if (isRaceOver())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!NetworkConfig::get()->isNetworking() ||
|
||||||
|
NetworkConfig::get()->isServer())
|
||||||
|
handleScoreInServer(kart_id, hitter);
|
||||||
|
|
||||||
loseFlagForKart(kart_id);
|
loseFlagForKart(kart_id);
|
||||||
return true;
|
return true;
|
||||||
} // kartHit
|
} // kartHit
|
||||||
|
@ -31,6 +31,8 @@ namespace irr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CTFFlag;
|
||||||
|
|
||||||
class CaptureTheFlag : public FreeForAll
|
class CaptureTheFlag : public FreeForAll
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -48,16 +50,18 @@ private:
|
|||||||
|
|
||||||
SFXBase* m_scored_sound;
|
SFXBase* m_scored_sound;
|
||||||
|
|
||||||
int m_red_scores, m_blue_scores, m_red_holder, m_blue_holder;
|
int m_red_scores, m_blue_scores;
|
||||||
|
|
||||||
btTransform m_red_trans, m_blue_trans, m_orig_red_trans, m_orig_blue_trans;
|
/* Save the last captured flag ticks */
|
||||||
|
int m_last_captured_flag_ticks;
|
||||||
|
|
||||||
int m_red_return_ticks, m_blue_return_ticks;
|
/* Used in updateGraphics to add race gui message for flag */
|
||||||
|
int m_red_flag_status, m_blue_flag_status;
|
||||||
|
|
||||||
std::map<int, int> m_swatter_reset_kart_ticks;
|
std::map<int, int> m_swatter_reset_kart_ticks;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
std::shared_ptr<CTFFlag> m_red_flag, m_blue_flag;
|
||||||
void updateFlagNodes();
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool getDroppedFlagTrans(const btTransform& kt, btTransform* out) const;
|
bool getDroppedFlagTrans(const btTransform& kt, btTransform* out) const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -91,10 +95,6 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual const std::string& getIdent() const OVERRIDE;
|
virtual const std::string& getIdent() const OVERRIDE;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void attachFlag(NetworkString& ns);
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
void resetFlag(NetworkString& ns);
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
bool getKartCTFResult(unsigned int kart_id) const
|
bool getKartCTFResult(unsigned int kart_id) const
|
||||||
{
|
{
|
||||||
if (m_red_scores == m_blue_scores)
|
if (m_red_scores == m_blue_scores)
|
||||||
@ -114,25 +114,19 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
int getBlueScore() const { return m_blue_scores; }
|
int getBlueScore() const { return m_blue_scores; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
int getRedHolder() const { return m_red_holder; }
|
int getRedHolder() const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
int getBlueHolder() const { return m_blue_holder; }
|
int getBlueHolder() const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool isRedFlagInBase() const
|
bool isRedFlagInBase() const;
|
||||||
{
|
|
||||||
return m_red_holder == -1 &&
|
|
||||||
m_red_trans.getOrigin() == m_orig_red_trans.getOrigin();
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool isBlueFlagInBase() const
|
bool isBlueFlagInBase() const;
|
||||||
{
|
|
||||||
return m_blue_holder == -1 &&
|
|
||||||
m_blue_trans.getOrigin() == m_orig_blue_trans.getOrigin();
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
const Vec3& getRedFlag() const { return (Vec3&)m_red_trans.getOrigin(); }
|
const Vec3& getRedFlag() const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
const Vec3& getBlueFlag() const { return (Vec3&)m_blue_trans.getOrigin(); }
|
const Vec3& getBlueFlag() const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void ctfScored(int kart_id, bool red_team_scored, int new_score);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void loseFlagForKart(int kart_id);
|
void loseFlagForKart(int kart_id);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
122
src/modes/ctf_flag.cpp
Normal file
122
src/modes/ctf_flag.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2018 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "modes/ctf_flag.hpp"
|
||||||
|
#include "graphics/irr_driver.hpp"
|
||||||
|
#include "karts/abstract_kart.hpp"
|
||||||
|
#include "modes/world.hpp"
|
||||||
|
#include "network/network_string.hpp"
|
||||||
|
#include "utils/mini_glm.hpp"
|
||||||
|
|
||||||
|
#include "LinearMath/btQuaternion.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Position offset to attach in kart model
|
||||||
|
const Vec3 g_kart_flag_offset(0.0, 0.2f, -0.5f);
|
||||||
|
// ============================================================================
|
||||||
|
BareNetworkString* CTFFlag::saveState(std::vector<std::string>* ru)
|
||||||
|
{
|
||||||
|
using namespace MiniGLM;
|
||||||
|
ru->push_back(getUniqueIdentity());
|
||||||
|
BareNetworkString* buffer = new BareNetworkString();
|
||||||
|
buffer->addUInt8(m_flag_status);
|
||||||
|
if (m_flag_status == OFF_BASE)
|
||||||
|
{
|
||||||
|
Vec3 normal = quatRotate(m_flag_trans.getRotation(),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
buffer->add(m_flag_trans.getOrigin());
|
||||||
|
buffer->addUInt32(
|
||||||
|
compressVector3(Vec3(normal.normalize()).toIrrVector()));
|
||||||
|
buffer->addUInt16(m_ticks_since_off_base);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
} // saveState
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void CTFFlag::restoreState(BareNetworkString* buffer, int count)
|
||||||
|
{
|
||||||
|
using namespace MiniGLM;
|
||||||
|
m_flag_status = buffer->getUInt8();
|
||||||
|
if (m_flag_status == OFF_BASE)
|
||||||
|
{
|
||||||
|
Vec3 origin = buffer->getVec3();
|
||||||
|
uint32_t normal_packed = buffer->getUInt32();
|
||||||
|
Vec3 normal = decompressVector3(normal_packed);
|
||||||
|
m_flag_trans.setOrigin(origin);
|
||||||
|
m_flag_trans.setRotation(
|
||||||
|
shortestArcQuat(Vec3(0.0f, 1.0f, 0.0f), normal));
|
||||||
|
m_ticks_since_off_base = buffer->getUInt16();
|
||||||
|
}
|
||||||
|
updateFlagTrans(m_flag_trans);
|
||||||
|
} // restoreState
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void CTFFlag::updateFlagTrans(const btTransform& off_base_trans)
|
||||||
|
{
|
||||||
|
if (getHolder() != -1)
|
||||||
|
{
|
||||||
|
AbstractKart* k = World::getWorld()->getKart(getHolder());
|
||||||
|
m_flag_trans = k->getTrans();
|
||||||
|
m_flag_trans.setOrigin(m_flag_trans(g_kart_flag_offset));
|
||||||
|
}
|
||||||
|
else if (m_flag_status == OFF_BASE)
|
||||||
|
{
|
||||||
|
m_flag_trans = off_base_trans;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_flag_trans = m_flag_base_trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void CTFFlag::update(int ticks)
|
||||||
|
{
|
||||||
|
updateFlagTrans(m_flag_trans);
|
||||||
|
|
||||||
|
// Check if not returning for too long
|
||||||
|
if (m_flag_status != OFF_BASE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_ticks_since_off_base += ticks;
|
||||||
|
if (m_ticks_since_off_base > race_manager->getFlagReturnTicks())
|
||||||
|
{
|
||||||
|
resetToBase();
|
||||||
|
}
|
||||||
|
} // update
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void CTFFlag::updateFlagGraphics(irr::scene::IAnimatedMeshSceneNode* flag_node)
|
||||||
|
{
|
||||||
|
if (getHolder() != -1)
|
||||||
|
{
|
||||||
|
AbstractKart* k = World::getWorld()->getKart(getHolder());
|
||||||
|
flag_node->setParent(k->getNode());
|
||||||
|
flag_node->setPosition(g_kart_flag_offset.toIrrVector());
|
||||||
|
flag_node->setRotation(core::vector3df(0.0f, 180.0f, 0.0f));
|
||||||
|
flag_node->setAnimationSpeed(fabsf(k->getSpeed()) * 3.0f + 25.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag_node->setParent(
|
||||||
|
irr_driver->getSceneManager()->getRootSceneNode());
|
||||||
|
Vec3 hpr;
|
||||||
|
flag_node->setPosition(
|
||||||
|
Vec3(m_flag_trans.getOrigin()).toIrrVector());
|
||||||
|
hpr.setHPR(m_flag_trans.getRotation());
|
||||||
|
flag_node->setRotation(hpr.toIrrHPR());
|
||||||
|
flag_node->setAnimationSpeed(25.0f);
|
||||||
|
}
|
||||||
|
} // updateFlagPosition
|
137
src/modes/ctf_flag.hpp
Normal file
137
src/modes/ctf_flag.hpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2018 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_CTF_FLAG_HPP
|
||||||
|
#define HEADER_CTF_FLAG_HPP
|
||||||
|
|
||||||
|
#include "network/rewinder.hpp"
|
||||||
|
#include "utils/types.hpp"
|
||||||
|
#include "utils/vec3.hpp"
|
||||||
|
|
||||||
|
#include "LinearMath/btTransform.h"
|
||||||
|
|
||||||
|
enum FlagColor : unsigned int
|
||||||
|
{
|
||||||
|
FC_RED = 0,
|
||||||
|
FC_BLUE = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene
|
||||||
|
{
|
||||||
|
class IAnimatedMeshSceneNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class CTFFlag : public Rewinder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int IN_BASE = -1;
|
||||||
|
static const int OFF_BASE = -2;
|
||||||
|
private:
|
||||||
|
/* Either save the above 2 status, or kart id holder this flag. */
|
||||||
|
int8_t m_flag_status;
|
||||||
|
|
||||||
|
/* Currnet flag transformation. */
|
||||||
|
btTransform m_flag_trans;
|
||||||
|
|
||||||
|
/* Transformation of IN_BASE. */
|
||||||
|
const btTransform m_flag_base_trans;
|
||||||
|
|
||||||
|
/* If OFF_BASE of m_flag_status, save the ticks since off base, use for
|
||||||
|
* auto return base for a flag (see ServerConfig). */
|
||||||
|
uint16_t m_ticks_since_off_base;
|
||||||
|
|
||||||
|
FlagColor m_flag_color;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
CTFFlag(FlagColor fc, const btTransform& base_trans)
|
||||||
|
: Rewinder(fc == FC_RED ? "TR" : "TB"), m_flag_base_trans(base_trans)
|
||||||
|
{
|
||||||
|
// UID rewinder with "T" which is after "Kx" for kart so
|
||||||
|
// updateFlagTrans is called after kart is rewound
|
||||||
|
m_flag_status = IN_BASE;
|
||||||
|
m_flag_trans.setOrigin(Vec3(0.0f));
|
||||||
|
m_flag_trans.setRotation(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
m_flag_color = fc;
|
||||||
|
m_ticks_since_off_base = 0;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void saveTransform() {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void computeError() {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual BareNetworkString* saveState(std::vector<std::string>* ru);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void undoEvent(BareNetworkString* buffer) {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void rewindToEvent(BareNetworkString* buffer) {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void restoreState(BareNetworkString* buffer, int count);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void undoState(BareNetworkString* buffer) {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
int getHolder() const
|
||||||
|
{
|
||||||
|
if (m_flag_status >= 0)
|
||||||
|
return m_flag_status;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
int getStatus() const { return m_flag_status; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const Vec3& getOrigin() const { return (Vec3&)m_flag_trans.getOrigin(); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const Vec3& getBaseOrigin() const
|
||||||
|
{ return (Vec3&)m_flag_base_trans.getOrigin(); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const btTransform& getBaseTrans() const { return m_flag_base_trans; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void resetToBase()
|
||||||
|
{
|
||||||
|
m_flag_status = IN_BASE;
|
||||||
|
m_ticks_since_off_base = 0;
|
||||||
|
updateFlagTrans();
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setCapturedByKart(int kart_id)
|
||||||
|
{
|
||||||
|
m_flag_status = (int8_t)kart_id;
|
||||||
|
m_ticks_since_off_base = 0;
|
||||||
|
updateFlagTrans();
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void dropFlagAt(const btTransform& t)
|
||||||
|
{
|
||||||
|
m_flag_status = OFF_BASE;
|
||||||
|
m_ticks_since_off_base = 0;
|
||||||
|
m_flag_trans = t;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool isInBase() const { return m_flag_status == IN_BASE; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool canBeCaptured() const { return !(m_flag_status >= 0); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void update(int ticks);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void updateFlagTrans(const btTransform& off_base_trans = btTransform());
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void updateFlagGraphics(irr::scene::IAnimatedMeshSceneNode* flag_node);
|
||||||
|
}; // CTFFlag
|
||||||
|
#endif
|
||||||
|
|
@ -99,17 +99,37 @@ bool FreeForAll::kartHit(int kart_id, int hitter)
|
|||||||
if (isRaceOver())
|
if (isRaceOver())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
handleScoreInServer(kart_id, hitter);
|
||||||
p.setSynchronous(true);
|
|
||||||
p.addUInt8(GameEventsProtocol::GE_BATTLE_KART_SCORE);
|
|
||||||
if (kart_id == hitter || hitter == -1)
|
|
||||||
p.addUInt8((uint8_t)kart_id).addUInt32(--m_scores[kart_id]);
|
|
||||||
else
|
|
||||||
p.addUInt8((uint8_t)hitter).addUInt32(++m_scores[hitter]);
|
|
||||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
|
||||||
return true;
|
return true;
|
||||||
} // kartHit
|
} // kartHit
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Called when the score of kart needs updated.
|
||||||
|
* \param kart_id The world kart id of the kart that was hit.
|
||||||
|
* \param hitter The world kart id of the kart who hit(-1 if none).
|
||||||
|
*/
|
||||||
|
void FreeForAll::handleScoreInServer(int kart_id, int hitter)
|
||||||
|
{
|
||||||
|
int new_score = 0;
|
||||||
|
if (kart_id == hitter || hitter == -1)
|
||||||
|
new_score = --m_scores[kart_id];
|
||||||
|
else
|
||||||
|
new_score = ++m_scores[hitter];
|
||||||
|
|
||||||
|
if (NetworkConfig::get()->isNetworking() &&
|
||||||
|
NetworkConfig::get()->isServer())
|
||||||
|
{
|
||||||
|
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||||
|
p.setSynchronous(true);
|
||||||
|
p.addUInt8(GameEventsProtocol::GE_BATTLE_KART_SCORE);
|
||||||
|
if (kart_id == hitter || hitter == -1)
|
||||||
|
p.addUInt8((uint8_t)kart_id).addUInt32(new_score);
|
||||||
|
else
|
||||||
|
p.addUInt8((uint8_t)hitter).addUInt32(new_score);
|
||||||
|
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||||
|
}
|
||||||
|
} // handleScoreInServer
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void FreeForAll::setKartScoreFromServer(NetworkString& ns)
|
void FreeForAll::setKartScoreFromServer(NetworkString& ns)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,8 @@ protected:
|
|||||||
bool m_count_down_reached_zero;
|
bool m_count_down_reached_zero;
|
||||||
|
|
||||||
std::vector<int> m_scores;
|
std::vector<int> m_scores;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void handleScoreInServer(int kart_id, int hitter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -267,6 +267,8 @@ void ClientLobby::addAllPlayers(Event* event)
|
|||||||
int hit_capture_limit = data.getUInt32();
|
int hit_capture_limit = data.getUInt32();
|
||||||
float time_limit = data.getFloat();
|
float time_limit = data.getFloat();
|
||||||
m_game_setup->setHitCaptureTime(hit_capture_limit, time_limit);
|
m_game_setup->setHitCaptureTime(hit_capture_limit, time_limit);
|
||||||
|
uint16_t flag_return_timeout = data.getUInt16();
|
||||||
|
race_manager->setFlagReturnTicks(flag_return_timeout);
|
||||||
}
|
}
|
||||||
configRemoteKart(players);
|
configRemoteKart(players);
|
||||||
loadWorld();
|
loadWorld();
|
||||||
|
@ -79,18 +79,14 @@ bool GameEventsProtocol::notifyEvent(Event* event)
|
|||||||
ffa->setKartScoreFromServer(data);
|
ffa->setKartScoreFromServer(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GE_CTF_ATTACH:
|
case GE_CTF_SCORED:
|
||||||
{
|
{
|
||||||
if (!ctf)
|
if (!ctf)
|
||||||
throw std::invalid_argument("No CTF world");
|
throw std::invalid_argument("No CTF world");
|
||||||
ctf->attachFlag(data);
|
uint8_t kart_id = data.getUInt8();
|
||||||
break;
|
bool red_team_scored = data.getUInt8() == 1;
|
||||||
}
|
int new_score = data.getUInt32();
|
||||||
case GE_CTF_RESET:
|
ctf->ctfScored(kart_id, red_team_scored, new_score);
|
||||||
{
|
|
||||||
if (!ctf)
|
|
||||||
throw std::invalid_argument("No CTF world");
|
|
||||||
ctf->resetFlag(data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GE_STARTUP_BOOST:
|
case GE_STARTUP_BOOST:
|
||||||
|
@ -16,9 +16,8 @@ public:
|
|||||||
GE_RESET_BALL = 3,
|
GE_RESET_BALL = 3,
|
||||||
GE_PLAYER_GOAL = 4,
|
GE_PLAYER_GOAL = 4,
|
||||||
GE_BATTLE_KART_SCORE = 5,
|
GE_BATTLE_KART_SCORE = 5,
|
||||||
GE_CTF_ATTACH = 6,
|
GE_CTF_SCORED = 6,
|
||||||
GE_CTF_RESET = 7,
|
GE_STARTUP_BOOST = 7,
|
||||||
GE_STARTUP_BOOST = 8,
|
|
||||||
}; // GameEventType
|
}; // GameEventType
|
||||||
private:
|
private:
|
||||||
int m_last_finished_position;
|
int m_last_finished_position;
|
||||||
|
@ -595,6 +595,10 @@ void ServerLobby::asynchronousUpdate()
|
|||||||
auto hcl = getHitCaptureLimit((float)players.size());
|
auto hcl = getHitCaptureLimit((float)players.size());
|
||||||
load_world_message->addUInt32(hcl.first).addFloat(hcl.second);
|
load_world_message->addUInt32(hcl.first).addFloat(hcl.second);
|
||||||
m_game_setup->setHitCaptureTime(hcl.first, hcl.second);
|
m_game_setup->setHitCaptureTime(hcl.first, hcl.second);
|
||||||
|
uint16_t flag_return_time = (uint16_t)stk_config->time2Ticks(
|
||||||
|
ServerConfig::m_flag_return_timemout);
|
||||||
|
load_world_message->addUInt16(flag_return_time);
|
||||||
|
race_manager->setFlagReturnTicks(flag_return_time);
|
||||||
}
|
}
|
||||||
configRemoteKart(players);
|
configRemoteKart(players);
|
||||||
|
|
||||||
|
@ -261,6 +261,15 @@ void loadServerLobbyFromConfig()
|
|||||||
if (m_voting_timeout == 20.0f)
|
if (m_voting_timeout == 20.0f)
|
||||||
m_voting_timeout = 30.0f;
|
m_voting_timeout = 30.0f;
|
||||||
|
|
||||||
|
if (stk_config->time2Ticks(m_flag_return_timemout) > 65535)
|
||||||
|
{
|
||||||
|
float timeout = m_flag_return_timemout;
|
||||||
|
// in CTFFlag it uses 16bit unsigned integer for timeout
|
||||||
|
Log::warn("ServerConfig", "Invalid %f m_flag_return_timemout which "
|
||||||
|
"is too large, use default value.", timeout);
|
||||||
|
m_flag_return_timemout.revertToDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
int frequency_in_config = m_state_frequency;
|
int frequency_in_config = m_state_frequency;
|
||||||
if (frequency_in_config <= 0 ||
|
if (frequency_in_config <= 0 ||
|
||||||
frequency_in_config > stk_config->getPhysicsFPS())
|
frequency_in_config > stk_config->getPhysicsFPS())
|
||||||
|
@ -81,6 +81,7 @@ RaceManager::RaceManager()
|
|||||||
m_have_kart_last_position_on_overworld = false;
|
m_have_kart_last_position_on_overworld = false;
|
||||||
m_num_local_players = 0;
|
m_num_local_players = 0;
|
||||||
m_hit_capture_limit = 0;
|
m_hit_capture_limit = 0;
|
||||||
|
m_flag_return_ticks = stk_config->time2Ticks(20.0f);
|
||||||
setMaxGoal(0);
|
setMaxGoal(0);
|
||||||
setTimeTarget(0.0f);
|
setTimeTarget(0.0f);
|
||||||
setReverseTrack(false);
|
setReverseTrack(false);
|
||||||
|
@ -356,6 +356,7 @@ private:
|
|||||||
unsigned int m_num_spare_tire_karts;
|
unsigned int m_num_spare_tire_karts;
|
||||||
unsigned int m_num_finished_karts;
|
unsigned int m_num_finished_karts;
|
||||||
unsigned int m_num_finished_players;
|
unsigned int m_num_finished_players;
|
||||||
|
unsigned m_flag_return_ticks;
|
||||||
int m_coin_target;
|
int m_coin_target;
|
||||||
float m_time_target;
|
float m_time_target;
|
||||||
int m_goal_target;
|
int m_goal_target;
|
||||||
@ -896,7 +897,10 @@ public:
|
|||||||
return m_minor_mode == MINOR_MODE_SOCCER ||
|
return m_minor_mode == MINOR_MODE_SOCCER ||
|
||||||
m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG;
|
m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG;
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setFlagReturnTicks(unsigned ticks) { m_flag_return_ticks = ticks; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
unsigned getFlagReturnTicks() const { return m_flag_return_ticks; }
|
||||||
}; // RaceManager
|
}; // RaceManager
|
||||||
|
|
||||||
extern RaceManager *race_manager;
|
extern RaceManager *race_manager;
|
||||||
|
@ -532,8 +532,10 @@ void RaceGUI::drawGlobalMiniMap()
|
|||||||
lower_y -(int)(draw_at.getY()-(m_minimap_player_size/2.2f)));
|
lower_y -(int)(draw_at.getY()-(m_minimap_player_size/2.2f)));
|
||||||
draw2DImage(m_red_flag, rp, rs, NULL, NULL, true, true);
|
draw2DImage(m_red_flag, rp, rs, NULL, NULL, true, true);
|
||||||
}
|
}
|
||||||
|
Vec3 pos = ctf_world->getRedHolder() == -1 ? ctf_world->getRedFlag() :
|
||||||
|
ctf_world->getKart(ctf_world->getRedHolder())->getSmoothedTrans().getOrigin();
|
||||||
|
|
||||||
track->mapPoint2MiniMap(ctf_world->getRedFlag(), &draw_at);
|
track->mapPoint2MiniMap(pos, &draw_at);
|
||||||
core::rect<s32> rs(core::position2di(0, 0), m_red_flag->getSize());
|
core::rect<s32> rs(core::position2di(0, 0), m_red_flag->getSize());
|
||||||
core::rect<s32> rp(m_map_left+(int)(draw_at.getX()-(m_minimap_player_size/1.4f)),
|
core::rect<s32> rp(m_map_left+(int)(draw_at.getX()-(m_minimap_player_size/1.4f)),
|
||||||
lower_y -(int)(draw_at.getY()+(m_minimap_player_size/2.2f)),
|
lower_y -(int)(draw_at.getY()+(m_minimap_player_size/2.2f)),
|
||||||
@ -553,7 +555,10 @@ void RaceGUI::drawGlobalMiniMap()
|
|||||||
draw2DImage(m_blue_flag, rp, rs, NULL, NULL, true, true);
|
draw2DImage(m_blue_flag, rp, rs, NULL, NULL, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
track->mapPoint2MiniMap(ctf_world->getBlueFlag(), &draw_at);
|
pos = ctf_world->getBlueHolder() == -1 ? ctf_world->getBlueFlag() :
|
||||||
|
ctf_world->getKart(ctf_world->getBlueHolder())->getSmoothedTrans().getOrigin();
|
||||||
|
|
||||||
|
track->mapPoint2MiniMap(pos, &draw_at);
|
||||||
core::rect<s32> bs(core::position2di(0, 0), m_blue_flag->getSize());
|
core::rect<s32> bs(core::position2di(0, 0), m_blue_flag->getSize());
|
||||||
core::rect<s32> bp(m_map_left+(int)(draw_at.getX()-(m_minimap_player_size/1.4f)),
|
core::rect<s32> bp(m_map_left+(int)(draw_at.getX()-(m_minimap_player_size/1.4f)),
|
||||||
lower_y -(int)(draw_at.getY()+(m_minimap_player_size/2.2f)),
|
lower_y -(int)(draw_at.getY()+(m_minimap_player_size/2.2f)),
|
||||||
|
Loading…
Reference in New Issue
Block a user