git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / client / dialogs / ScoreDialog.cpp
blob354990c8796125918d653538bec1a8ac020e35f5
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D 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 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D 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.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <dialogs/ScoreDialog.h>
22 #include <tank/TankSort.h>
23 #include <tank/TankContainer.h>
24 #include <tank/TankTeamScore.h>
25 #include <tank/TankColorGenerator.h>
26 #include <tank/TankScore.h>
27 #include <tank/TankState.h>
28 #include <tank/TankAvatar.h>
29 #include <tankai/TankAI.h>
30 #include <GLW/GLWFont.h>
31 #include <GLW/GLWWindowManager.h>
32 #include <GLW/GLWColors.h>
33 #include <client/ClientParams.h>
34 #include <graph/OptionsDisplay.h>
35 #include <common/OptionsTransient.h>
36 #include <common/OptionsScorched.h>
37 #include <common/Defines.h>
38 #include <engine/GameState.h>
39 #include <client/ClientState.h>
40 #include <client/ScorchedClient.h>
41 #include <client/ClientScoreHandler.h>
42 #include <server/ScorchedServer.h>
43 #include <lang/LangResource.h>
44 #include <stdio.h>
46 static const float rankLeft = 15.0f;
47 static const float iconLeft = 5.0f;
48 static const float nameLeft = 35.0f;
49 static const float livesLeft = 230.0f;
50 static const float killsLeft = 255.0f;
51 static const float assistsLeft = 280.0f;
52 static const float winsLeft = 305.0f;
53 static const float moneyLeft = 325.0f;
54 static const float scoreLeft = 405.0f;
55 static const float statsLeft = 475.0f;
56 static const float readyLeft = 515.0f;
57 static const float lineSpacer = 10.0f;
59 ScoreDialog *ScoreDialog::instance_ = 0;
60 ScoreDialog *ScoreDialog::instance2_ = 0;
62 ScoreDialog *ScoreDialog::instance()
64 if (!instance_)
66 instance_ = new ScoreDialog;
69 return instance_;
72 ScoreDialog *ScoreDialog::instance2()
74 if (!instance2_)
76 instance2_ = new ScoreDialog;
79 return instance2_;
82 ScoreDialog::ScoreDialog() :
83 GLWWindow("Score", 10.0f, 10.0f, 525.0f, 310.0f, eTransparent |eSmallTitle,
84 "Shows the current score for all players."),
85 lastScoreValue_(0), lastMoneyValue_(0), lastNoPlayers_(0)
90 ScoreDialog::~ScoreDialog()
95 void ScoreDialog::display()
97 GLWWindow::display();
98 calculateScores();
100 if (OptionsDisplay::instance()->getHideFinalScore() &&
101 ScorchedClient::instance()->getGameState().getState() ==
102 ClientState::StateScore)
104 GLWWindowManager::instance()->hideWindow(getId());
108 void ScoreDialog::calculateScores()
110 lastScoreValue_ = lastMoneyValue_ = 0;
111 std::map<unsigned int, Tank *> &tanks =
112 ScorchedClient::instance()->getTankContainer().getPlayingTanks();
113 std::map<unsigned int, Tank *>::iterator itor;
114 for (itor = tanks.begin();
115 itor != tanks.end();
116 itor++)
118 Tank *tank = (*itor).second;
119 lastMoneyValue_ += tank->getScore().getMoney();
120 lastScoreValue_ += tank->getScore().getScore();
123 lastNoPlayers_ = tanks.size();
124 sortedTanks_.clear();
125 TankSort::getSortedTanksIds(
126 ScorchedClient::instance()->getContext(), sortedTanks_);
129 void ScoreDialog::windowInit(const unsigned state)
131 needCentered_ = true;
134 void ScoreDialog::draw()
136 float h = sortedTanks_.size() * lineSpacer + 80.0f;
137 if (ScorchedClient::instance()->getOptionsGame().getTeams() > 1)
139 h += (lineSpacer * 2.0f) * (ScorchedClient::instance()->getOptionsGame().getTeams() - 1) +
140 lineSpacer * 2.0f;
142 setH(h);
144 static size_t noTanks = 0;
145 if (noTanks != sortedTanks_.size())
147 needCentered_ = true;
148 noTanks = sortedTanks_.size();
151 GLWWindow::draw();
152 GLState newState(GLState::TEXTURE_OFF | GLState::DEPTH_OFF);
154 bool finished = false;
155 if (ScorchedClient::instance()->getGameState().getState() ==
156 ClientState::StateScore)
158 finished = ClientScoreHandler::instance()->getFinalScore();
161 Vector white(0.9f, 0.9f, 1.0f);
162 bool server = (ClientParams::instance()->getConnectedToServer());
164 LANG_RESOURCE_VAR(CURRENT_RANKINGS, "CURRENT_RANKINGS", "Current Rankings");
165 LANG_RESOURCE_VAR(FINAL_RANKINGS, "FINAL_RANKINGS", "Final Rankings");
166 LANG_RESOURCE_VAR(WAITING_FOR_PLAYERS, "WAITING_FOR_PLAYERS", "Waiting for more players");
167 LANG_RESOURCE_VAR(WAITING_TO_JOIN, "WAITING_TO_JOIN", "Waiting to join game");
168 LangString SERVER_NAME = LANG_STRING(ScorchedClient::instance()->getOptionsGame().getServerName());
170 LangString *text = &CURRENT_RANKINGS;
171 if (finished)
173 text = &FINAL_RANKINGS;
175 else if (ScorchedClient::instance()->getGameState().getState() ==
176 ClientState::StateGetPlayers)
178 finished = true;
179 if (ScorchedClient::instance()->getTankContainer().getNoOfNonSpectatorTanks() <
180 ScorchedClient::instance()->getOptionsGame().getNoMinPlayers())
182 text = &WAITING_FOR_PLAYERS;
184 else
186 text = &WAITING_TO_JOIN;
189 else if (server)
191 text = &SERVER_NAME;
194 GLWFont::instance()->getGameShadowFont()->draw(
195 GLWColors::black,
197 x_ + 8.0f - 2.0f, y_ + h_ - 22.0f + 2.0f, 0.0f,
198 *text);
199 GLWFont::instance()->getGameFont()->draw(
200 white,
202 x_ + 8.0f, y_ + h_ - 22.0f, 0.0f,
203 *text);
206 if (!finished)
208 LangString buffer;
210 LANG_RESOURCE_VAR_2(ROUND_OF, "ROUND_OF", "Round {0} of {1}",
211 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsTransient().getCurrentRoundNo()),
212 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getNoRounds()));
213 buffer.append(ROUND_OF);
215 if (ScorchedClient::instance()->getOptionsGame().getNoMaxRoundTurns() > 0)
217 LANG_RESOURCE_VAR_2(MOVE_OF, "MOVE_OF", ",Move {0} of {1}",
218 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsTransient().getCurrentGameNo()),
219 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getNoMaxRoundTurns()));
220 buffer.append(MOVE_OF);
223 float roundsWidth = GLWFont::instance()->getGameFont()->getWidth(
224 10, buffer);
225 GLWFont::instance()->getGameFont()->draw(
226 white,
228 x_ + 470 - roundsWidth, y_ + h_ - 40.0f, 0.0f,
229 buffer);
232 LANG_RESOURCE_VAR(SCORE_NAME, "SCORE_NAME", "Name");
233 LANG_RESOURCE_VAR(SCORE_K, "SCORE_K", "K");
234 LANG_RESOURCE_VAR(SCORE_W, "SCORE_W", "W");
235 LANG_RESOURCE_VAR(SCORE_A, "SCORE_A", "A");
236 LANG_RESOURCE_VAR(SCORE_SCORE, "SCORE_SCORE", "Score");
237 LANG_RESOURCE_VAR(SCORE_RANK, "SCORE_RANK", "Rank");
238 LANG_RESOURCE_VAR(SCORE_L, "SCORE_L", "L");
240 float y = lineSpacer + 10.0f;
241 GLWFont::instance()->getGameFont()->draw(
242 white,
244 x_ + nameLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
245 SCORE_NAME);
246 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
247 LANG_RESOURCE("NAME", "Name"),
248 LANG_RESOURCE("NAME_TOOLTIP", "The name of the player"),
249 x_ + nameLeft, y_ + h_ - y - lineSpacer - 26.0f, 100.0f, 16.0f);
251 GLWFont::instance()->getGameFont()->draw(
252 white,
254 x_ + killsLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
255 SCORE_K);
256 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
257 LANG_RESOURCE("KILLS", "Kills"),
258 LANG_RESOURCE_1("KILL_TOOLTIP",
259 "The number of players this player has killed.\n{0} score awarded per kill.",
260 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getScorePerKill())),
261 x_ + killsLeft, y_ + h_ - y - lineSpacer - 26.0f, 20.0f, 16.0f);
263 GLWFont::instance()->getGameFont()->draw(
264 white,
266 x_ + winsLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
267 SCORE_W);
268 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
269 LANG_RESOURCE("WINS", "Wins"),
270 LANG_RESOURCE_1("WINS_TOOLTIP",
271 "The number of rounds this player has won.\n{0} score awarded per round won.",
272 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getScoreWonForRound())),
273 x_ + winsLeft, y_ + h_ - y - lineSpacer - 26.0f, 20.0f, 16.0f);
275 GLWFont::instance()->getGameFont()->draw(
276 white,
278 x_ + assistsLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
279 SCORE_A);
280 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
281 LANG_RESOURCE("ASSISTS", "Assists"),
282 LANG_RESOURCE_1("ASSISTS_TOOLTIP",
283 "The number of kills this player has assisted in.\n{0} score awarded per assist.",
284 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getScorePerAssist())),
285 x_ + assistsLeft, y_ + h_ - y - lineSpacer - 26.0f, 20.0f, 16.0f);
287 GLWFont::instance()->getGameFont()->draw(
288 white,
290 x_ + moneyLeft + 10, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
291 "$");
292 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
293 LANG_RESOURCE("MONEY", "Money"),
294 LANG_RESOURCE_1("MONEY_TOOLTIP", "The amount of money this player has.\n%{0} score awarded per dollar.",
295 S3D::formatStringBuffer("%.1f", float(ScorchedClient::instance()->getOptionsGame().getScorePerMoney()) / 1000.0f)),
296 x_ + moneyLeft, y_ + h_ - y - lineSpacer - 26.0f, 20.0f, 16.0f);
298 GLWFont::instance()->getGameFont()->draw(
299 white,
301 x_ + scoreLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
302 SCORE_SCORE);
303 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
304 LANG_RESOURCE("SCORE", "Score"),
305 LANG_RESOURCE("SCORE_TOOLTIP", "The current score for this player.\nCalculated from the number of kills, wins, money and bonus score awards."),
306 x_ + scoreLeft, y_ + h_ - y - lineSpacer - 26.0f, 80.0f, 16.0f);
308 GLWFont::instance()->getGameFont()->draw(
309 white,
311 x_ + statsLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
312 SCORE_RANK);
313 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
314 LANG_RESOURCE("RANK", "Rank"),
315 LANG_RESOURCE("RANK_TOOLTIP", "The current online ranking for this player."),
316 x_ + statsLeft, y_ + h_ - y - lineSpacer - 26.0f, 40.0f, 16.0f);
318 GLWFont::instance()->getGameFont()->draw(
319 white,
321 x_ + livesLeft, y_ + h_ - y - lineSpacer - 26.0f, 0.0f,
322 SCORE_L);
323 GLWToolTip::instance()->addToolTip(ToolTip::ToolTipHelp,
324 LANG_RESOURCE("LIVES", "Lives"),
325 LANG_RESOURCE_1("LIVES_TOOLTIP", "The current number of lives this player has left.\n{0} score awarded for each life remaining.",
326 S3D::formatStringBuffer("%i", ScorchedClient::instance()->getOptionsGame().getScoreWonForLives())),
327 x_ + livesLeft, y_ + h_ - y - lineSpacer - 26.0f, 20.0f, 16.0f);
328 y+= lineSpacer + lineSpacer;
330 int tmpLastScoreValue = 0;
331 int tmpLastMoneyValue = 0;
332 if (ScorchedClient::instance()->getOptionsGame().getTeams() > 1)
334 int winningTeam = TankSort::getWinningTeam(
335 ScorchedClient::instance()->getContext());
337 for (int i=0; i<ScorchedClient::instance()->getOptionsGame().getTeams(); i++)
339 bool someTeam = false;
340 std::list<unsigned int>::iterator itor;
341 for (itor = sortedTanks_.begin();
342 itor != sortedTanks_.end();
343 itor ++)
345 unsigned int playerId = (*itor);
346 Tank *current = ScorchedClient::instance()->getTankContainer().getTankById(playerId);
347 if (current && current->getTeam() == (i + 1) && !current->getState().getSpectator())
349 someTeam = true;
350 addLine(current, y, (char *)((winningTeam==(i+1))?"1":"2"), finished);
352 tmpLastScoreValue += current->getScore().getScore();
353 tmpLastMoneyValue += current->getScore().getMoney();
354 y+= lineSpacer;
357 if (someTeam)
359 addScoreLine(y,
360 TankColorGenerator::getTeamColor(i + 1),
361 ScorchedClient::instance()->getContext().getTankTeamScore().getScore(i+1));
362 y+= lineSpacer;
363 y+= lineSpacer;
367 else
369 // No Team
370 int rank = 1;
371 char strrank[10];
372 std::list<unsigned int>::iterator itor;
373 for (itor = sortedTanks_.begin();
374 itor != sortedTanks_.end();
375 itor ++, rank++)
377 unsigned int playerId = (*itor);
378 Tank *current = ScorchedClient::instance()->getTankContainer().getTankById(playerId);
379 if (current && !current->getState().getSpectator())
381 snprintf(strrank, 10, "%i", rank);
383 addLine(current, y, strrank, finished);
384 tmpLastScoreValue += current->getScore().getScore();
385 tmpLastMoneyValue += current->getScore().getMoney();
386 y+= lineSpacer;
390 y+= lineSpacer / 1.5f;
391 // Spectators
392 std::list<unsigned int>::iterator itor;
393 for (itor = sortedTanks_.begin();
394 itor != sortedTanks_.end();
395 itor ++)
397 unsigned int playerId = (*itor);
398 Tank *current = ScorchedClient::instance()->
399 getTankContainer().getTankById(playerId);
400 if (current && current->getState().getSpectator())
402 addLine(current, y, " ", false);
403 y+= lineSpacer;
407 std::map<unsigned int, Tank *> &realTanks =
408 ScorchedClient::instance()->getTankContainer().getPlayingTanks();
409 if (tmpLastScoreValue != lastScoreValue_ ||
410 tmpLastMoneyValue != lastMoneyValue_ ||
411 realTanks.size() != lastNoPlayers_)
413 calculateScores();
417 void ScoreDialog::addScoreLine(float y, Vector &color, int score)
419 float textX = x_;
420 float textY = y_ + h_ - y - lineSpacer - 30.0f;
422 // Print the name on the screen
423 GLWFont::instance()->getGameFont()->draw(
424 color,
426 textX + scoreLeft, textY, 0.0f,
427 S3D::formatStringBuffer("%i", score));
430 void ScoreDialog::addLine(Tank *current, float y, char *rank, bool finished)
432 float textX = x_;
433 float textY = y_ + h_ - y - lineSpacer - 25.0f;
434 bool currentPlayer = false;
436 // Print a highlight behind the current clients player
437 if (!current->getState().getSpectator() &&
438 current->getDestinationId() ==
439 ScorchedClient::instance()->getTankContainer().getCurrentDestinationId())
441 GLState state(GLState::BLEND_ON);
443 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
444 glBegin(GL_QUADS);
445 glVertex2f(x_ + w_ - 3.0f, textY + lineSpacer - 1.0f);
446 glVertex2f(x_ + 3.0f, textY + lineSpacer - 1.0f);
447 glVertex2f(x_ + 3.0f, textY - 1.0f);
448 glVertex2f(x_ + w_ - 3.0f, textY - 1.0f);
449 glEnd();
452 // Form the name
453 static LangString name;
455 // Max length 12
456 if (current->getTargetName().size() > 12)
457 name = current->getTargetName().substr(0, 12);
458 else
459 name = current->getTargetName();
461 if (finished && ! ClientParams::instance()->getConnectedToServer())
463 name.append(LANG_STRING(" ("));
464 Tank *serverTank =
465 ScorchedServer::instance()->getTankContainer().getTankById(
466 current->getPlayerId());
467 TankAI *tankAI = serverTank->getTankAI();
468 if (tankAI) name.append(LANG_STRING(tankAI->getName()));
469 else name.append(LANG_RESOURCE("HUMAN", "Human"));
470 name.append(LANG_STRING(")"));
472 else if (current->getState().getState() != TankState::sNormal)
474 name.append(LANG_STRING(" ("));
475 name.append(current->getState().getSmallStateLangString());
476 name.append(LANG_STRING(")"));
479 if (current->getState().getSpectator())
481 if (name.size() > 50) name = name.substr(0, 50); // Limit length
483 // Print the name on the screen
484 GLWFont::instance()->getGameFont()->draw(
485 current->getColor(),
487 textX + nameLeft, textY, 0.0f,
488 name);
489 GLWFont::instance()->getGameFont()->draw(
490 current->getColor(),
492 textX + readyLeft, textY, 0.0f,
493 S3D::formatStringBuffer("%2s",
494 ((current->getState().getReadyState() == TankState::SNotReady)?"*":" ")));
496 else
498 if (name.size() > 25) name = name.substr(0, 25); // Limit length
500 GLState state(GLState::TEXTURE_ON);
501 glColor3f(1.0f, 1.0f, 1.0f);
502 current->getAvatar().getTexture()->draw();
503 glBegin(GL_QUADS);
504 glTexCoord2f(0.0f, 0.0f);
505 glVertex2f(textX + iconLeft,
506 textY + 2.0f);
507 glTexCoord2f(1.0f, 0.0f);
508 glVertex2f(textX + iconLeft + 8.0f,
509 textY + 2.0f);
510 glTexCoord2f(1.0f, 1.0f);
511 glVertex2f(textX + iconLeft + 8.0f,
512 textY + 10.0f);
513 glTexCoord2f(0.0f, 1.0f);
514 glVertex2f(textX + iconLeft,
515 textY + 10.0f);
516 glEnd();
518 // Print the name on the screen
519 GLWFont::instance()->getGameFont()->draw(
520 current->getColor(),
522 textX + rankLeft, textY, 0.0f,
523 rank);
524 GLWFont::instance()->getGameFont()->drawWidth(
525 killsLeft - nameLeft,
526 current->getColor(),
528 textX + nameLeft, textY, 0.0f,
529 name);
530 GLWFont::instance()->getGameFont()->draw(
531 current->getColor(),
533 textX + killsLeft, textY, 0.0f,
534 S3D::formatStringBuffer("%i", current->getScore().getKills()));
535 GLWFont::instance()->getGameFont()->draw(
536 current->getColor(),
538 textX + moneyLeft, textY, 0.0f,
539 S3D::formatStringBuffer("$%i", current->getScore().getMoney()));
540 GLWFont::instance()->getGameFont()->draw(
541 current->getColor(),
543 textX + winsLeft, textY, 0.0f,
544 S3D::formatStringBuffer("%i", current->getScore().getWins()));
545 GLWFont::instance()->getGameFont()->draw(
546 current->getColor(),
548 textX + scoreLeft, textY, 0.0f,
549 S3D::formatStringBuffer("%i", current->getScore().getScore()));
550 GLWFont::instance()->getGameFont()->draw(
551 current->getColor(),
553 textX + assistsLeft, textY, 0.0f,
554 S3D::formatStringBuffer("%i", current->getScore().getAssists()));
555 GLWFont::instance()->getGameFont()->draw(
556 current->getColor(),
558 textX + readyLeft, textY, 0.0f,
559 ((current->getState().getReadyState() == TankState::SNotReady)?"*":" "));
560 if (current->getScore().getRank() >= 0)
562 GLWFont::instance()->getGameFont()->draw(
563 current->getColor(),
565 textX + statsLeft, textY, 0.0f,
566 S3D::formatStringBuffer("%i", current->getScore().getRank()));
568 GLWFont::instance()->getGameFont()->draw(
569 current->getColor(),
571 textX + livesLeft, textY, 0.0f,
572 S3D::formatStringBuffer("%i", current->getState().getLives()));