1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2004-2015 SuperTuxKart-Team 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 3 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 #ifndef SOCCER_WORLD_HPP 20 #define SOCCER_WORLD_HPP 21 22 #include "modes/world_with_rank.hpp" 23 #include "states_screens/race_gui_base.hpp" 24 #include "karts/abstract_kart.hpp" 25 26 #include <IMesh.h> 27 #include <string> 28 29 class AbstractKart; 30 class BallGoalData; 31 class Controller; 32 class NetworkString; 33 class TrackObject; 34 class TrackSector; 35 36 /** \brief An implementation of WorldWithRank, to provide the soccer game mode 37 * Notice: In soccer world, true goal means blue, false means red. 38 * \ingroup modes 39 */ 40 class SoccerWorld : public WorldWithRank 41 { 42 public: 43 struct ScorerData 44 { 45 /** World ID of kart which scores. */ 46 unsigned int m_id; 47 /** Whether this goal is socred correctly (identify for own goal). */ 48 bool m_correct_goal; 49 /** Time goal. */ 50 float m_time; 51 /** Kart ident which scores. */ 52 std::string m_kart; 53 /** Player name which scores. */ 54 core::stringw m_player; 55 /** Country code of player. */ 56 std::string m_country_code; 57 /** Handicap of player. */ 58 HandicapLevel m_handicap_level; 59 }; // ScorerData 60 61 private: 62 class KartDistanceMap 63 { 64 public: 65 /** World ID of kart. */ 66 unsigned int m_kart_id; 67 /** Distance to ball from kart */ 68 float m_distance; 69 operator <(const KartDistanceMap & r) const70 bool operator < (const KartDistanceMap& r) const 71 { 72 return m_distance < r.m_distance; 73 } KartDistanceMap(unsigned int kart_id=0,float distance=0.0f)74 KartDistanceMap(unsigned int kart_id = 0, float distance = 0.0f) 75 { 76 m_kart_id = kart_id; 77 m_distance = distance; 78 } 79 }; // KartDistanceMap 80 81 std::vector<KartDistanceMap> m_red_kdm; 82 std::vector<KartDistanceMap> m_blue_kdm; 83 std::unique_ptr<BallGoalData> m_bgd; 84 85 /** Keep a pointer to the track object of soccer ball */ 86 TrackObject* m_ball; 87 btRigidBody* m_ball_body; 88 89 /** Number of goals needed to win */ 90 int m_goal_target; 91 bool m_count_down_reached_zero; 92 93 SFXBase *m_goal_sound; 94 95 /** Counts ticks when the ball is off track, so a reset can be 96 * triggered if the ball is off for more than 2 seconds. */ 97 int m_ball_invalid_timer; 98 int m_ball_hitter; 99 100 /** Goals data of each team scored */ 101 std::vector<ScorerData> m_red_scorers; 102 std::vector<ScorerData> m_blue_scorers; 103 104 /** Data generated from navmesh */ 105 TrackSector* m_ball_track_sector; 106 107 float m_ball_heading; 108 109 std::vector<int> m_team_icon_draw_id; 110 111 std::vector<btTransform> m_goal_transforms; 112 /** Function to update the location the ball on the polygon map */ 113 void updateBallPosition(int ticks); 114 /** Function to update data for AI usage. */ 115 void updateAIData(); 116 /** Get number of teammates in a team, used by starting position assign. */ 117 int getTeamNum(KartTeam team) const; 118 119 /** Profiling usage */ 120 int m_frame_count; 121 std::vector<int> m_goal_frame; 122 123 int m_reset_ball_ticks; 124 int m_ticks_back_to_own_goal; 125 126 void resetKartsToSelfGoals(); 127 128 public: 129 130 SoccerWorld(); 131 virtual ~SoccerWorld(); 132 133 virtual void init() OVERRIDE; 134 virtual void onGo() OVERRIDE; 135 136 // clock events 137 virtual bool isRaceOver() OVERRIDE; 138 virtual void countdownReachedZero() OVERRIDE; 139 virtual void terminateRace() OVERRIDE; 140 141 // overriding World methods 142 virtual void reset(bool restart=false) OVERRIDE; 143 144 virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; 145 virtual btTransform getRescueTransform(unsigned int rescue_pos) const 146 OVERRIDE; useFastMusicNearEnd() const147 virtual bool useFastMusicNearEnd() const OVERRIDE { return false; } 148 virtual void getKartsDisplayInfo( 149 std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE; 150 raceHasLaps()151 virtual bool raceHasLaps() OVERRIDE { return false; } 152 153 virtual void enterRaceOverState() OVERRIDE; 154 155 virtual const std::string& getIdent() const OVERRIDE; 156 157 virtual void update(int ticks) OVERRIDE; 158 shouldDrawTimer() const159 bool shouldDrawTimer() const OVERRIDE { return !isStartPhase(); } 160 // ------------------------------------------------------------------------ 161 void onCheckGoalTriggered(bool first_goal); 162 // ------------------------------------------------------------------------ 163 void setBallHitter(unsigned int kart_id); 164 // ------------------------------------------------------------------------ 165 /** Get the soccer result of kart in soccer world (including AIs) */ 166 bool getKartSoccerResult(unsigned int kart_id) const; 167 // ------------------------------------------------------------------------ getScore(KartTeam team) const168 int getScore(KartTeam team) const 169 { 170 return (int)(team == KART_TEAM_BLUE ? m_blue_scorers.size() 171 : m_red_scorers.size()); 172 } 173 // ------------------------------------------------------------------------ getScorers(KartTeam team) const174 const std::vector<ScorerData>& getScorers(KartTeam team) const 175 { return (team == KART_TEAM_BLUE ? m_blue_scorers : m_red_scorers); } 176 // ------------------------------------------------------------------------ 177 int getBallNode() const; 178 // ------------------------------------------------------------------------ getBallPosition() const179 const Vec3& getBallPosition() const 180 { return (Vec3&)m_ball_body->getCenterOfMassTransform().getOrigin(); } 181 // ------------------------------------------------------------------------ ballNotMoving() const182 bool ballNotMoving() const 183 { 184 return (m_ball_body->getLinearVelocity().x() == 0.0f || 185 m_ball_body->getLinearVelocity().z() == 0.0f); 186 } 187 // ------------------------------------------------------------------------ getBallHeading() const188 float getBallHeading() const 189 { return m_ball_heading; } 190 // ------------------------------------------------------------------------ 191 float getBallDiameter() const; 192 // ------------------------------------------------------------------------ 193 bool ballApproachingGoal(KartTeam team) const; 194 // ------------------------------------------------------------------------ 195 Vec3 getBallAimPosition(KartTeam team, bool reverse = false) const; 196 // ------------------------------------------------------------------------ 197 bool isCorrectGoal(unsigned int kart_id, bool first_goal) const; 198 // ------------------------------------------------------------------------ getBallChaser(KartTeam team) const199 int getBallChaser(KartTeam team) const 200 { 201 // Only AI call this function, so each team should have at least a kart 202 assert(m_blue_kdm.size() > 0 && m_red_kdm.size() > 0); 203 return (team == KART_TEAM_BLUE ? m_blue_kdm[0].m_kart_id : 204 m_red_kdm[0].m_kart_id); 205 } 206 // ------------------------------------------------------------------------ 207 /** Get the AI who will attack the other team ball chaser. */ 208 int getAttacker(KartTeam team) const; 209 // ------------------------------------------------------------------------ 210 void handlePlayerGoalFromServer(const NetworkString& ns); 211 // ------------------------------------------------------------------------ 212 void handleResetBallFromServer(const NetworkString& ns); 213 // ------------------------------------------------------------------------ hasTeam() const214 virtual bool hasTeam() const OVERRIDE { return true; } 215 // ------------------------------------------------------------------------ getGameStartedProgress() const216 virtual std::pair<uint32_t, uint32_t> getGameStartedProgress() const 217 OVERRIDE 218 { 219 std::pair<uint32_t, uint32_t> progress( 220 std::numeric_limits<uint32_t>::max(), 221 std::numeric_limits<uint32_t>::max()); 222 if (RaceManager::get()->hasTimeTarget()) 223 { 224 progress.first = (uint32_t)m_time; 225 } 226 else if (m_red_scorers.size() > m_blue_scorers.size()) 227 { 228 progress.second = (uint32_t)((float)m_red_scorers.size() / 229 (float)RaceManager::get()->getMaxGoal() * 100.0f); 230 } 231 else 232 { 233 progress.second = (uint32_t)((float)m_blue_scorers.size() / 234 (float)RaceManager::get()->getMaxGoal() * 100.0f); 235 } 236 return progress; 237 } 238 // ------------------------------------------------------------------------ 239 virtual void saveCompleteState(BareNetworkString* bns, 240 STKPeer* peer) OVERRIDE; 241 // ------------------------------------------------------------------------ 242 virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; 243 // ------------------------------------------------------------------------ isGoalPhase() const244 virtual bool isGoalPhase() const OVERRIDE 245 { 246 int diff = m_ticks_back_to_own_goal - getTicksSinceStart(); 247 return diff > 0 && diff < stk_config->time2Ticks(3.0f); 248 } 249 // ------------------------------------------------------------------------ getKartAtDrawingPosition(unsigned int p) const250 AbstractKart* getKartAtDrawingPosition(unsigned int p) const OVERRIDE 251 { return getKart(m_team_icon_draw_id[p - 1]); } 252 // ------------------------------------------------------------------------ getBall() const253 TrackObject* getBall() const { return m_ball; } 254 }; // SoccerWorld 255 256 257 #endif 258