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