1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
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>
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()
66 instance_
= new ScoreDialog
;
72 ScoreDialog
*ScoreDialog::instance2()
76 instance2_
= new ScoreDialog
;
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()
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();
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) +
144 static size_t noTanks
= 0;
145 if (noTanks
!= sortedTanks_
.size())
147 needCentered_
= true;
148 noTanks
= sortedTanks_
.size();
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
;
173 text
= &FINAL_RANKINGS
;
175 else if (ScorchedClient::instance()->getGameState().getState() ==
176 ClientState::StateGetPlayers
)
179 if (ScorchedClient::instance()->getTankContainer().getNoOfNonSpectatorTanks() <
180 ScorchedClient::instance()->getOptionsGame().getNoMinPlayers())
182 text
= &WAITING_FOR_PLAYERS
;
186 text
= &WAITING_TO_JOIN
;
194 GLWFont::instance()->getGameShadowFont()->draw(
197 x_
+ 8.0f
- 2.0f
, y_
+ h_
- 22.0f
+ 2.0f
, 0.0f
,
199 GLWFont::instance()->getGameFont()->draw(
202 x_
+ 8.0f
, y_
+ h_
- 22.0f
, 0.0f
,
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(
225 GLWFont::instance()->getGameFont()->draw(
228 x_
+ 470 - roundsWidth
, y_
+ h_
- 40.0f
, 0.0f
,
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(
244 x_
+ nameLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
254 x_
+ killsLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
266 x_
+ winsLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
278 x_
+ assistsLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
290 x_
+ moneyLeft
+ 10, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
301 x_
+ scoreLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
311 x_
+ statsLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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(
321 x_
+ livesLeft
, y_
+ h_
- y
- lineSpacer
- 26.0f
, 0.0f
,
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();
345 unsigned int playerId
= (*itor
);
346 Tank
*current
= ScorchedClient::instance()->getTankContainer().getTankById(playerId
);
347 if (current
&& current
->getTeam() == (i
+ 1) && !current
->getState().getSpectator())
350 addLine(current
, y
, (char *)((winningTeam
==(i
+1))?"1":"2"), finished
);
352 tmpLastScoreValue
+= current
->getScore().getScore();
353 tmpLastMoneyValue
+= current
->getScore().getMoney();
360 TankColorGenerator::getTeamColor(i
+ 1),
361 ScorchedClient::instance()->getContext().getTankTeamScore().getScore(i
+1));
372 std::list
<unsigned int>::iterator itor
;
373 for (itor
= sortedTanks_
.begin();
374 itor
!= sortedTanks_
.end();
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();
390 y
+= lineSpacer
/ 1.5f
;
392 std::list
<unsigned int>::iterator itor
;
393 for (itor
= sortedTanks_
.begin();
394 itor
!= sortedTanks_
.end();
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);
407 std::map
<unsigned int, Tank
*> &realTanks
=
408 ScorchedClient::instance()->getTankContainer().getPlayingTanks();
409 if (tmpLastScoreValue
!= lastScoreValue_
||
410 tmpLastMoneyValue
!= lastMoneyValue_
||
411 realTanks
.size() != lastNoPlayers_
)
417 void ScoreDialog::addScoreLine(float y
, Vector
&color
, int score
)
420 float textY
= y_
+ h_
- y
- lineSpacer
- 30.0f
;
422 // Print the name on the screen
423 GLWFont::instance()->getGameFont()->draw(
426 textX
+ scoreLeft
, textY
, 0.0f
,
427 S3D::formatStringBuffer("%i", score
));
430 void ScoreDialog::addLine(Tank
*current
, float y
, char *rank
, bool finished
)
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
);
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
);
453 static LangString name
;
456 if (current
->getTargetName().size() > 12)
457 name
= current
->getTargetName().substr(0, 12);
459 name
= current
->getTargetName();
461 if (finished
&& ! ClientParams::instance()->getConnectedToServer())
463 name
.append(LANG_STRING(" ("));
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(
487 textX
+ nameLeft
, textY
, 0.0f
,
489 GLWFont::instance()->getGameFont()->draw(
492 textX
+ readyLeft
, textY
, 0.0f
,
493 S3D::formatStringBuffer("%2s",
494 ((current
->getState().getReadyState() == TankState::SNotReady
)?"*":" ")));
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();
504 glTexCoord2f(0.0f
, 0.0f
);
505 glVertex2f(textX
+ iconLeft
,
507 glTexCoord2f(1.0f
, 0.0f
);
508 glVertex2f(textX
+ iconLeft
+ 8.0f
,
510 glTexCoord2f(1.0f
, 1.0f
);
511 glVertex2f(textX
+ iconLeft
+ 8.0f
,
513 glTexCoord2f(0.0f
, 1.0f
);
514 glVertex2f(textX
+ iconLeft
,
518 // Print the name on the screen
519 GLWFont::instance()->getGameFont()->draw(
522 textX
+ rankLeft
, textY
, 0.0f
,
524 GLWFont::instance()->getGameFont()->drawWidth(
525 killsLeft
- nameLeft
,
528 textX
+ nameLeft
, textY
, 0.0f
,
530 GLWFont::instance()->getGameFont()->draw(
533 textX
+ killsLeft
, textY
, 0.0f
,
534 S3D::formatStringBuffer("%i", current
->getScore().getKills()));
535 GLWFont::instance()->getGameFont()->draw(
538 textX
+ moneyLeft
, textY
, 0.0f
,
539 S3D::formatStringBuffer("$%i", current
->getScore().getMoney()));
540 GLWFont::instance()->getGameFont()->draw(
543 textX
+ winsLeft
, textY
, 0.0f
,
544 S3D::formatStringBuffer("%i", current
->getScore().getWins()));
545 GLWFont::instance()->getGameFont()->draw(
548 textX
+ scoreLeft
, textY
, 0.0f
,
549 S3D::formatStringBuffer("%i", current
->getScore().getScore()));
550 GLWFont::instance()->getGameFont()->draw(
553 textX
+ assistsLeft
, textY
, 0.0f
,
554 S3D::formatStringBuffer("%i", current
->getScore().getAssists()));
555 GLWFont::instance()->getGameFont()->draw(
558 textX
+ readyLeft
, textY
, 0.0f
,
559 ((current
->getState().getReadyState() == TankState::SNotReady
)?"*":" "));
560 if (current
->getScore().getRank() >= 0)
562 GLWFont::instance()->getGameFont()->draw(
565 textX
+ statsLeft
, textY
, 0.0f
,
566 S3D::formatStringBuffer("%i", current
->getScore().getRank()));
568 GLWFont::instance()->getGameFont()->draw(
571 textX
+ livesLeft
, textY
, 0.0f
,
572 S3D::formatStringBuffer("%i", current
->getState().getLives()));