1 /*
2  * Copyright 2011, 2013, 2014, 2016 Peter Olsson
3  *
4  * This file is part of Brum Brum Rally.
5  *
6  * Brum Brum Rally is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Brum Brum Rally is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "ResultState.h"
21 #include "SurfaceBank.h"
22 #include "StateManager.h"
23 #include "Network.h"
24 #include "RaceState.h"
25 #include "NetworkMenu.h"
26 #include "MainMenu.h"
27 #include "str.h"
28 #include <cmath>
29 
ResultState(const RaceSetup & rs,Network * net,bool showPoints)30 ResultState::ResultState(const RaceSetup& rs, Network* net, bool showPoints)
31 :	raceSetup(rs),
32 	nextAction(false),
33 	quitAction(false),
34 	pointsAction(false),
35 	haveWinner(showPoints && rs.getCurrentTrack() == rs.getTracks()),
36 	winningCarRotation(0),
37 	winnerTextTimer(0),
38 	net(net)
39 {
40 	if (showPoints)
41 	{
42 		menu.setTitle(std::string(haveWinner ? "final " : "") + "Tournament table");
43 		raceSetup.sortPlayersByPoints();
44 	}
45 	else
46 	{
47 		menu.setTitle("Race Results" + (raceSetup.isTournament() ? " (" + int2string(raceSetup.getCurrentTrack()) + "/" + int2string(raceSetup.getTracks()) + ")" : ""));
48 		raceSetup.sortPlayersByTime();
49 	}
50 
51 	int y = 60;
52 	int ySpacing;
53 	switch (raceSetup.numberOfPlayers())
54 	{
55 	case 8:
56 		ySpacing = 15;
57 		break;
58 	case 7:
59 		ySpacing = 17;
60 		break;
61 	default:
62 		ySpacing = 20;
63 	}
64 	for (int i = 0; i < raceSetup.numberOfPlayers(); ++i)
65 	{
66 		if (!haveWinner || i > 0)
67 		{
68 			Surface carSurface = SurfaceBank::getCar(raceSetup.getPlayerCar(i));
69 			carSurface.draw(background, 92, y, PI_HALF);
70 		}
71 		Surface(raceSetup.getPlayerName(i), BIG_FONT, TEXT_COLOR, TEXT_BORDER_COLOR).draw(background, 102, y);
72 		Surface valueSurface(showPoints ? int2string(raceSetup.getPlayerPoints(i)) : time2string(raceSetup.getPlayerTime(i)), BIG_FONT, TEXT_COLOR, TEXT_BORDER_COLOR);
73 		valueSurface.draw(background, 207 - valueSurface.width() / 2, y);
74 		y += ySpacing;
75 	}
76 
77 	if (!net || net->isOwner())
78 	{
79 		if (raceSetup.isTournament())
80 		{
81 			if (showPoints)
82 			{
83 				if (raceSetup.getCurrentTrack() == raceSetup.getTracks())
84 				{
85 					menu.addItem("New tournament", &nextAction);
86 				}
87 				else
88 				{
89 					menu.addItem("Next Race", &nextAction);
90 				}
91 			}
92 			else
93 			{
94 				menu.addItem("Show points", &pointsAction);
95 			}
96 		}
97 		else
98 		{
99 			menu.addItem("New Race", &nextAction);
100 		}
101 	}
102 
103 
104 	if (net)
105 	{
106 		if (net->isOwner())
107 		{
108 			menu.addItem("End network game", &quitAction);
109 		}
110 		else
111 		{
112 			menu.addItem("Hide menu", &nextAction);
113 			menu.addItem("Leave network game", &quitAction);
114 		}
115 	}
116 	else
117 	{
118 		menu.addItem("Main menu", &quitAction);
119 	}
120 
121 	if (haveWinner)
122 	{
123 		const std::string winnerText = "Winner";
124 		Surface leftWinnerSurface(winnerText + " >", SMALL_FONT, WINNER_COLOR, TEXT_BORDER_COLOR);
125 		Surface rightWinnerSurface("< " + winnerText, SMALL_FONT, WINNER_COLOR, TEXT_BORDER_COLOR);
126 		leftWinnerTextRO.setSurface(leftWinnerSurface);
127 		rightWinnerTextRO.setSurface(rightWinnerSurface);
128 		winningCarRO.setSurface(SurfaceBank::getCar(raceSetup.getPlayerCar(0)));
129 
130 		leftWinnerTextRO.moveTo(28, 61);
131 		rightWinnerTextRO.moveTo(257, 61);
132 		winningCarRO.moveTo(92, 60);
133 
134 		addRenderObject(leftWinnerTextRO);
135 		addRenderObject(rightWinnerTextRO);
136 
137 		addRenderObject(winningCarRO);
138 	}
139 
140 	menu.addRenderObjects(this, CENTER_X, 200);
141 
142 	if (net)
143 	{
144 		if (!net->isOwner())
145 		{
146 			menu.hide();
147 		}
148 		net->setGameState(this);
149 	}
150 }
151 
update()152 void ResultState::update()
153 {
154 	if (net)
155 	{
156 		GameState* newState = net->getNewGameState();
157 		if (newState)
158 		{
159 			StateManager::getInstance().enter(newState, 0);
160 			return;
161 		}
162 		net->step();
163 	}
164 	menu.update();
165 	if (haveWinner)
166 	{
167 		winningCarRO.setRotation(5 * std::sin(winningCarRotation));
168 		winningCarRotation += 0.03;
169 
170 		leftWinnerTextRO.moveTo(28 + 15 * std::sin(3*winningCarRotation), 61);
171 		rightWinnerTextRO.moveTo(257 + 15 * std::sin(-3*winningCarRotation), 61);
172 
173 		++winnerTextTimer;
174 	}
175 }
176 
onEvent(const SDL_Event & event)177 void ResultState::onEvent(const SDL_Event& event)
178 {
179 	StateManager& sm = StateManager::getInstance();
180 
181 	if (net && net->onEvent(event))
182 	{
183 		return;
184 	}
185 
186 	MenuEvent me = sm.getMenuEvent(event);
187 	if (net && !net->isOwner() && me.type == MENU_ESC)
188 	{
189 		if (menu.isVisible())
190 		{
191 			menu.hide();
192 		}
193 		else
194 		{
195 			menu.show(this);
196 		}
197 		return;
198 	}
199 
200 	menu.onEvent(me);
201 	if (nextAction)
202 	{
203 		if (net)
204 		{
205 			if (net->isOwner())
206 			{
207 				net->startRace();
208 			}
209 			else
210 			{
211 				menu.hide();
212 				nextAction = false;
213 			}
214 		}
215 		else
216 		{
217 			// make so the cars start next track in reversed posion order
218 			raceSetup.sortPlayersByTime();
219 			raceSetup.reversePlayerOrder();
220 
221 			sm.enter(new RaceState(Map::generate(), raceSetup), 0);
222 		}
223 	}
224 	else if (quitAction)
225 	{
226 		if (net)
227 		{
228 			net->quitGame();
229 			sm.enter(new NetworkMenu(net), -1);
230 		}
231 		else
232 		{
233 			sm.enter(new MainMenu());
234 		}
235 	}
236 	else if (pointsAction)
237 	{
238 		if (net)
239 		{
240 			net->onShowPoints(raceSetup);
241 		}
242 		else
243 		{
244 			sm.enter(new ResultState(raceSetup, net, true), 0);
245 		}
246 	}
247 }
248