diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index a2d6a9a2a..0b59acc8f 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1034,6 +1034,11 @@ void Kart::setRaceResult() FreeForAll* ffa = dynamic_cast(World::getWorld()); m_race_result = ffa->getKartAtPosition(1) == this; } + else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG) + { + CaptureTheFlag* ctf = dynamic_cast(World::getWorld()); + m_race_result = ctf->getKartCTFResult(getWorldKartId()); + } else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) { SoccerWorld* sw = dynamic_cast(World::getWorld()); diff --git a/src/modes/capture_the_flag.cpp b/src/modes/capture_the_flag.cpp index 8ee7848a3..7df82a517 100644 --- a/src/modes/capture_the_flag.cpp +++ b/src/modes/capture_the_flag.cpp @@ -60,8 +60,6 @@ CaptureTheFlag::~CaptureTheFlag() void CaptureTheFlag::init() { FreeForAll::init(); - const btTransform& red_pos = Track::getCurrentTrack()->getRedFlag(); - const btTransform& blue_pos = Track::getCurrentTrack()->getBlueFlag(); #ifndef SERVER_ONLY m_red_flag_node = irr_driver->addAnimatedMesh(m_red_flag_mesh, "red_flag"); @@ -69,14 +67,51 @@ void CaptureTheFlag::init() "blue_flag"); assert(m_red_flag_node); assert(m_blue_flag_node); - - m_red_flag_node->setPosition(Vec3(red_pos.getOrigin()).toIrrVector()); - Vec3 hpr; - hpr.setHPR(red_pos.getRotation()); - m_red_flag_node->setRotation(hpr.toIrrHPR()); - - m_blue_flag_node->setPosition(Vec3(blue_pos.getOrigin()).toIrrVector()); - hpr.setHPR(blue_pos.getRotation()); - m_blue_flag_node->setRotation(hpr.toIrrHPR()); #endif } // init + +//----------------------------------------------------------------------------- +void CaptureTheFlag::reset() +{ + FreeForAll::reset(); + m_red_trans = Track::getCurrentTrack()->getRedFlag(); + m_blue_trans = Track::getCurrentTrack()->getBlueFlag(); + m_red_scores = m_blue_scores = 0; + m_red_holder = m_blue_holder = -1; + +#ifndef SERVER_ONLY + m_red_flag_node->setPosition( + Vec3(m_red_trans.getOrigin()).toIrrVector()); + Vec3 hpr; + hpr.setHPR(m_red_trans.getRotation()); + m_red_flag_node->setRotation(hpr.toIrrHPR()); + + 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 +} // reset + +//----------------------------------------------------------------------------- +void CaptureTheFlag::update(int ticks) +{ + FreeForAll::update(ticks); +} // update + +// ---------------------------------------------------------------------------- +video::SColor CaptureTheFlag::getColor(unsigned int kart_id) const +{ + return getKartTeam(kart_id) == KART_TEAM_RED ? + video::SColor(255, 255, 0, 0) : video::SColor(255, 0, 0, 255); +} // getColor + +// ---------------------------------------------------------------------------- +bool CaptureTheFlag::isRaceOver() +{ + if (NetworkConfig::get()->isServer() && + (m_red_scores >= race_manager->getHitCaptureLimit() || + m_blue_scores >= race_manager->getHitCaptureLimit())) + return true; + return FreeForAll::isRaceOver(); +} // isRaceOver diff --git a/src/modes/capture_the_flag.hpp b/src/modes/capture_the_flag.hpp index 340aa71d9..adf49f296 100644 --- a/src/modes/capture_the_flag.hpp +++ b/src/modes/capture_the_flag.hpp @@ -42,6 +42,13 @@ private: irr::scene::IAnimatedMesh* m_blue_flag_mesh; + int m_red_scores, m_blue_scores, m_red_holder, m_blue_holder; + + btTransform m_red_trans, m_blue_trans; + + // ------------------------------------------------------------------------ + virtual video::SColor getColor(unsigned int kart_id) const OVERRIDE; + public: // ------------------------------------------------------------------------ CaptureTheFlag(); @@ -50,8 +57,40 @@ public: // ------------------------------------------------------------------------ virtual void init() OVERRIDE; // ------------------------------------------------------------------------ + virtual void reset() OVERRIDE; + // ------------------------------------------------------------------------ + virtual void update(int ticks) OVERRIDE; + // ------------------------------------------------------------------------ virtual bool hasTeam() const OVERRIDE { return true; } // ------------------------------------------------------------------------ + bool getKartCTFResult(unsigned int kart_id) const + { + if (m_red_scores == m_blue_scores) + return true; + + bool red_win = m_red_scores > m_blue_scores; + KartTeam team = getKartTeam(kart_id); + + if ((red_win && team == KART_TEAM_RED) || + (!red_win && team == KART_TEAM_BLUE)) + return true; + else + return false; + } + // ------------------------------------------------------------------------ + int getRedScore() const { return m_red_scores; } + // ------------------------------------------------------------------------ + int getBlueScore() const { return m_blue_scores; } + // ------------------------------------------------------------------------ + int getRedHolder() const { return m_red_holder; } + // ------------------------------------------------------------------------ + int getBlueHolder() const { return m_blue_holder; } + // ------------------------------------------------------------------------ + const Vec3& getRedFlag() const { return (Vec3&)m_red_trans.getOrigin(); } + // ------------------------------------------------------------------------ + const Vec3& getBlueFlag() const { return (Vec3&)m_blue_trans.getOrigin(); } + // ------------------------------------------------------------------------ + virtual bool isRaceOver() OVERRIDE; }; // CaptureTheFlag diff --git a/src/modes/free_for_all.cpp b/src/modes/free_for_all.cpp index 78831fcdd..bf900215f 100644 --- a/src/modes/free_for_all.cpp +++ b/src/modes/free_for_all.cpp @@ -172,6 +172,7 @@ void FreeForAll::getKartsDisplayInfo( RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i]; rank_info.lap = -1; rank_info.m_outlined_font = true; + rank_info.m_color = getColor(i); rank_info.m_text = m_karts[i]->getController()->getName() + L" (" + StringUtils::toWString(m_scores[i]) + L")"; } @@ -187,3 +188,9 @@ void FreeForAll::terminateRace() } // igetColor("font::normal"); +} // getColor diff --git a/src/modes/free_for_all.hpp b/src/modes/free_for_all.hpp index 7e3928676..3ca6e2939 100644 --- a/src/modes/free_for_all.hpp +++ b/src/modes/free_for_all.hpp @@ -31,6 +31,10 @@ private: bool m_count_down_reached_zero; std::vector m_scores; + + // ------------------------------------------------------------------------ + virtual video::SColor getColor(unsigned int kart_id) const; + public: // ------------------------------------------------------------------------ FreeForAll(); @@ -61,7 +65,6 @@ public: void setKartScoreFromServer(NetworkString& ns); // ------------------------------------------------------------------------ int getKartScore(int kart_id) const { return m_scores.at(kart_id); } - }; // FreeForAll diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index b65119bf0..59c6aadc2 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -38,14 +38,13 @@ using namespace irr; #include "guiengine/modaldialog.hpp" #include "guiengine/scalable_font.hpp" #include "io/file_manager.hpp" -#include "items/attachment.hpp" -#include "items/attachment_manager.hpp" #include "items/powerup_manager.hpp" #include "karts/abstract_kart.hpp" #include "karts/controller/controller.hpp" #include "karts/controller/spare_tire_ai.hpp" #include "karts/kart_properties.hpp" #include "karts/kart_properties_manager.hpp" +#include "modes/capture_the_flag.hpp" #include "modes/follow_the_leader.hpp" #include "modes/linear_world.hpp" #include "modes/world.hpp" @@ -266,7 +265,8 @@ void RaceGUI::renderGlobal(float dt) } if (!m_is_tutorial) drawGlobalPlayerIcons(m_map_height); - if(Track::getCurrentTrack()->isSoccer()) drawScores(); + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) + drawScores(); #endif } // renderGlobal @@ -514,6 +514,35 @@ void RaceGUI::drawGlobalMiniMap() track->drawMiniMap(dest); World *world = World::getWorld(); + + CaptureTheFlag *ctf = dynamic_cast(World::getWorld()); + if (ctf) + { + Vec3 draw_at; + track->mapPoint2MiniMap(ctf->getRedFlag(), &draw_at); + + video::ITexture* icon = + irr_driver->getTexture(FileManager::GUI, "red_flag.png"); + + core::rect rs(core::position2di(0, 0), icon->getSize()); + core::rect 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)), + 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))); + draw2DImage(icon, rp, rs, NULL, NULL, true); + + track->mapPoint2MiniMap(ctf->getBlueFlag(), &draw_at); + + icon = irr_driver->getTexture(FileManager::GUI, "blue_flag.png"); + + core::rect bs(core::position2di(0, 0), icon->getSize()); + core::rect 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)), + 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))); + draw2DImage(icon, bp, bs, NULL, NULL, true); + } + for(unsigned int i=0; igetNumKarts(); i++) { const AbstractKart *kart = world->getKart(i); @@ -1066,11 +1095,6 @@ void RaceGUI::drawLap(const AbstractKart* kart, if (kart->hasFinishedRace()) return; World *world = World::getWorld(); - if (!world->raceHasLaps()) return; - const int lap = world->getFinishedLapsOfKart(kart->getWorldKartId()); - - // don't display 'lap 0/..' at the start of a race - if (lap < 0 ) return; core::recti pos; @@ -1090,6 +1114,32 @@ void RaceGUI::drawLap(const AbstractKart* kart, - m_lap_width - 10; pos.LowerRightCorner.X = viewport.LowerRightCorner.X; + // Draw CTF scores with red score - blue score + CaptureTheFlag* ctf = dynamic_cast(World::getWorld()); + if (ctf) + { + gui::ScalableFont* font = GUIEngine::getHighresDigitFont(); + font->setScale(scaling.Y < 1.0f ? 0.5f: 1.0f); + core::stringw text = StringUtils::toWString(ctf->getRedScore()); + font->draw(text, pos, video::SColor(255, 255, 0, 0)); + core::dimension2du d = font->getDimension(text.c_str()); + pos += core::position2di(d.Width, 0); + text = L"-"; + font->draw(text, pos, video::SColor(255, 255, 255, 255)); + d = font->getDimension(text.c_str()); + pos += core::position2di(d.Width, 0); + text = StringUtils::toWString(ctf->getBlueScore()); + font->draw(text, pos, video::SColor(255, 0, 0, 255)); + font->setScale(1.0f); + return; + } + + if (!world->raceHasLaps()) return; + const int lap = world->getFinishedLapsOfKart(kart->getWorldKartId()); + + // don't display 'lap 0/..' at the start of a race + if (lap < 0 ) return; + static video::SColor color = video::SColor(255, 255, 255, 255); std::ostringstream out; out << lap + 1 << "/" << race_manager->getNumLaps(); diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp index 60d6fc5c5..7df7b783d 100644 --- a/src/states_screens/race_gui_base.cpp +++ b/src/states_screens/race_gui_base.cpp @@ -40,6 +40,7 @@ #include "karts/kart_properties.hpp" #include "karts/kart_properties_manager.hpp" #include "karts/rescue_animation.hpp" +#include "modes/capture_the_flag.hpp" #include "modes/linear_world.hpp" #include "modes/world.hpp" #include "states_screens/race_gui_multitouch.hpp" @@ -722,7 +723,8 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) // Icon width for the AI karts int ICON_WIDTH = ICON_PLAYER_WIDTH * 4 / 5; - WorldWithRank *world = (WorldWithRank*)(World::getWorld()); + WorldWithRank* world = dynamic_cast(World::getWorld()); + CaptureTheFlag* ctf = dynamic_cast(World::getWorld()); //initialize m_previous_icons_position if(m_previous_icons_position.size()==0) @@ -852,8 +854,7 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) if (info.m_outlined_font) { GUIEngine::getOutlineFont()->draw(info.m_text, pos, - GUIEngine::getSkin()->getColor("font::normal"), false, - false, NULL, true/*ignore RTL*/); + info.m_color, false, false, NULL, true/*ignore RTL*/); } else { @@ -877,6 +878,32 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) int w = kart->getController() ->isLocalPlayerController() ? ICON_PLAYER_WIDTH : ICON_WIDTH; + + // CTF + if (ctf) + { + if (ctf->getRedHolder() == (int)kart_id) + { + video::ITexture* red = + irr_driver->getTexture(FileManager::GUI, "red_flag.png"); + const core::rect rect(core::position2d(0, 0), + red->getSize()); + const core::rect pos1 + (x - 20, y - 10, x + w - 20, y + w - 30); + draw2DImage(red, pos1, rect, NULL, NULL, true); + } + else if (ctf->getBlueHolder() == (int)kart_id) + { + video::ITexture* blue = + irr_driver->getTexture(FileManager::GUI, "blue_flag.png"); + const core::rect rect(core::position2d(0, 0), + blue->getSize()); + const core::rect pos1 + (x - 20, y - 10, x + w - 20, y + w - 30); + draw2DImage(blue, pos1, rect, NULL, NULL, true); + } + } + const core::rect pos(x, y, x+w, y+w); //to bring to light the player's icon: add a background diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index c0a76a01e..26895f3a2 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -42,7 +42,7 @@ #include "karts/kart_properties_manager.hpp" #include "modes/cutscene_world.hpp" #include "modes/demo_world.hpp" -#include "modes/free_for_all.hpp" +#include "modes/capture_the_flag.hpp" #include "modes/overworld.hpp" #include "modes/soccer_world.hpp" #include "network/network_config.hpp" @@ -474,6 +474,158 @@ void RaceResultGUI::backToLobby() NetworkingLobby::getInstance()->addMoreServerInfo(L"--------------------"); } // backToLobby +//----------------------------------------------------------------------------- +void RaceResultGUI::displayCTFResults() +{ +#ifndef SERVER_ONLY + //Draw win text + core::stringw result_text; + video::SColor color = video::SColor(255, 255, 255, 255); + video::SColor red_color = video::SColor(255, 255, 0, 0); + gui::IGUIFont* font = GUIEngine::getTitleFont(); + int current_x = UserConfigParams::m_width / 2; + RowInfo *ri = &(m_all_row_infos[0]); + int current_y = (int)ri->m_y_pos; + CaptureTheFlag* ctf = dynamic_cast(World::getWorld()); + const int red_score = ctf->getRedScore(); + const int blue_score = ctf->getBlueScore(); + + GUIEngine::Widget *table_area = getWidget("result-table"); + int height = table_area->m_h + table_area->m_y; + + if (red_score > blue_score) + result_text = _("Red Team Wins"); + else if (blue_score > red_score) + result_text = _("Blue Team Wins"); + else + result_text = _("It's a draw"); + + core::rect pos(current_x, current_y, current_x, current_y); + font->draw(result_text.c_str(), pos, color, true, true); + + core::dimension2du rect = font->getDimension(result_text.c_str()); + + //Draw team scores: + current_y += rect.Height; + current_x /= 2; + irr::video::ITexture* red_icon = irr_driver->getTexture(FileManager::GUI, + "red_flag.png"); + irr::video::ITexture* blue_icon = irr_driver->getTexture(FileManager::GUI, + "blue_flag.png"); + + core::recti source_rect(core::vector2di(0, 0), red_icon->getSize()); + core::recti dest_rect(current_x, current_y, + current_x + red_icon->getSize().Width / 2, + current_y + red_icon->getSize().Height / 2); + draw2DImage(red_icon, dest_rect, source_rect, + NULL, NULL, true); + current_x += UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2; + dest_rect = core::recti(current_x, current_y, + current_x + red_icon->getSize().Width / 2, + current_y + red_icon->getSize().Height / 2); + draw2DImage(blue_icon, dest_rect, source_rect, + NULL, NULL, true); + + result_text = StringUtils::toWString(blue_score); + rect = font->getDimension(result_text.c_str()); + current_x += red_icon->getSize().Width / 4; + current_y += red_icon->getSize().Height / 2 + rect.Height / 4; + pos = core::rect(current_x, current_y, current_x, current_y); + font->draw(result_text.c_str(), pos, color, true, false); + + current_x -= UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2; + result_text = StringUtils::toWString(red_score); + pos = core::rect(current_x, current_y, current_x, current_y); + font->draw(result_text.c_str(), pos, color, true, false); + + int center_x = UserConfigParams::m_width / 2; + pos = core::rect(center_x, current_y, center_x, current_y); + font->draw("-", pos, color, true, false); + + // The red team player scores: + current_y += rect.Height / 2 + rect.Height / 4; + font = GUIEngine::getSmallFont(); + irr::video::ITexture* kart_icon; + + int prev_y = current_y; + const unsigned num_karts = ctf->getNumKarts(); + for (unsigned int i = 0; i < num_karts; i++) + { + AbstractKart* kart = ctf->getKartAtPosition(i + 1); + unsigned kart_id = kart->getWorldKartId(); + if (ctf->getKartTeam(kart_id) != KART_TEAM_RED) + continue; + result_text = kart->getController()->getName(); + + result_text.append(" "); + if (kart->isEliminated()) + { + result_text.append(_("Eliminated")); + } + else + { + result_text.append( + StringUtils::toWString(ctf->getKartScore(kart_id))); + } + rect = font->getDimension(result_text.c_str()); + current_y += rect.Height; + + if (current_y > height) break; + + pos = core::rect(current_x, current_y, current_x, current_y); + font->draw(result_text, pos, + kart->getController()->isLocalPlayerController() ? + red_color : color, true, false); + kart_icon = kart->getKartProperties()->getIconMaterial()->getTexture(); + source_rect = core::recti(core::vector2di(0, 0), kart_icon->getSize()); + irr::u32 offset_x = + (irr::u32)(font->getDimension(result_text.c_str()).Width / 1.5f); + dest_rect = core::recti(current_x - offset_x - 30, current_y, + current_x - offset_x, current_y + 30); + draw2DImage(kart_icon, dest_rect, source_rect, NULL, NULL, true); + } + + // The blue team player scores: + current_y = prev_y; + current_x += UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2; + for (unsigned int i = 0; i < num_karts; i++) + { + AbstractKart* kart = ctf->getKartAtPosition(i + 1); + unsigned kart_id = kart->getWorldKartId(); + if (ctf->getKartTeam(kart_id) != KART_TEAM_BLUE) + continue; + result_text = kart->getController()->getName(); + + result_text.append(" "); + if (kart->isEliminated()) + { + result_text.append(_("Eliminated")); + } + else + { + result_text.append( + StringUtils::toWString(ctf->getKartScore(kart_id))); + } + rect = font->getDimension(result_text.c_str()); + current_y += rect.Height; + + if (current_y > height) break; + + pos = core::rect(current_x, current_y, current_x, current_y); + font->draw(result_text, pos, + kart->getController()->isLocalPlayerController() ? + red_color : color, true, false); + kart_icon = kart->getKartProperties()->getIconMaterial()->getTexture(); + source_rect = core::recti(core::vector2di(0, 0), kart_icon->getSize()); + irr::u32 offset_x = (irr::u32) + (font->getDimension(result_text.c_str()).Width / 1.5f); + dest_rect = core::recti(current_x - offset_x - 30, current_y, + current_x - offset_x, current_y + 30); + draw2DImage(kart_icon, dest_rect, source_rect, NULL, NULL, true); + } +#endif +} + //----------------------------------------------------------------------------- void RaceResultGUI::onConfirm() { @@ -714,8 +866,6 @@ void RaceResultGUI::backToLobby() void RaceResultGUI::renderGlobal(float dt) { #ifndef SERVER_ONLY - bool isSoccerWorld = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER; - m_timer += dt; assert(World::getWorld()->getPhase() == WorldStatus::RESULT_DISPLAY_PHASE); unsigned int num_karts = (unsigned int)m_all_row_infos.size(); @@ -821,7 +971,16 @@ void RaceResultGUI::backToLobby() // Second phase: update X and Y positions for the various animations // ================================================================= float v = 0.9f*UserConfigParams::m_width / m_time_single_scroll; - if (!isSoccerWorld) + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) + { + displaySoccerResults(); + } + else if (race_manager->getMajorMode() == + RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG) + { + displayCTFResults(); + } + else { for (unsigned int i = 0; i < m_all_row_infos.size(); i++) { @@ -876,8 +1035,6 @@ void RaceResultGUI::backToLobby() displayOneEntry((unsigned int)x, (unsigned int)y, i, true); } // for i } - else - displaySoccerResults(); // Display highscores if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX || @@ -1135,14 +1292,7 @@ void RaceResultGUI::backToLobby() const bool own_goal = !(scorers.at(i).m_correct_goal); const int kart_id = scorers.at(i).m_id; - const int rm_id = kart_id - - (race_manager->getNumberOfKarts() - race_manager->getNumPlayers()); - - if (rm_id >= 0) - result_text = race_manager->getKartInfo(rm_id).getPlayerName(); - else - result_text = sw->getKart(kart_id)-> - getKartProperties()->getName(); + result_text = sw->getKart(kart_id)->getController()->getName(); if (own_goal) { @@ -1192,14 +1342,7 @@ void RaceResultGUI::backToLobby() const bool own_goal = !(scorers.at(i).m_correct_goal); const int kart_id = scorers.at(i).m_id; - const int rm_id = kart_id - - (race_manager->getNumberOfKarts() - race_manager->getNumPlayers()); - - if (rm_id >= 0) - result_text = race_manager->getKartInfo(rm_id).getPlayerName(); - else - result_text = sw->getKart(kart_id)-> - getKartProperties()->getName(); + result_text = sw->getKart(kart_id)->getController()->getName(); if (own_goal) { diff --git a/src/states_screens/race_result_gui.hpp b/src/states_screens/race_result_gui.hpp index e32a166e9..1a83729ff 100644 --- a/src/states_screens/race_result_gui.hpp +++ b/src/states_screens/race_result_gui.hpp @@ -192,6 +192,7 @@ private: void displayGPProgress(); void cleanupGPProgress(); void displayPostRaceInfo(); + void displayCTFResults(); void displaySoccerResults(); void displayScreenShots();