00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ServerShotFinishedState.h>
00022 #include <server/ScorchedServer.h>
00023 #include <server/ServerState.h>
00024 #include <server/ServerTooFewPlayersStimulus.h>
00025 #include <server/ServerMessageHandler.h>
00026 #include <server/ServerNextShotState.h>
00027 #include <server/ServerChannelManager.h>
00028 #include <server/ServerShotState.h>
00029 #include <server/ServerCommon.h>
00030 #include <common/Logger.h>
00031 #include <common/StatsLogger.h>
00032 #include <common/OptionsScorched.h>
00033 #include <common/OptionsTransient.h>
00034 #include <coms/ComsScoreMessage.h>
00035 #include <coms/ComsPlayerStateMessage.h>
00036 #include <coms/ComsMessageSender.h>
00037 #include <coms/ComsSyncCheckMessage.h>
00038 #include <tank/TankColorGenerator.h>
00039 #include <tank/TankContainer.h>
00040 #include <tank/TankTeamScore.h>
00041 #include <tank/TankSort.h>
00042 #include <tank/TankState.h>
00043 #include <tank/TankScore.h>
00044 #include <lua/LUAScriptHook.h>
00045
00046 float ServerShotFinishedState::speed_(1.0f);
00047
00048 ServerShotFinishedState::ServerShotFinishedState(ServerShotState *shotState) :
00049 GameStateI("ServerShotFinishedState"),
00050 shotState_(shotState)
00051 {
00052 ScorchedServer::instance()->getLUAScriptHook().addHookProvider("server_score");
00053 }
00054
00055 ServerShotFinishedState::~ServerShotFinishedState()
00056 {
00057 }
00058
00059 void ServerShotFinishedState::enterState(const unsigned state)
00060 {
00061
00062 if (ScorchedServer::instance()->getOptionsGame().getAutoSendSyncCheck())
00063 {
00064 ServerCommon::serverLog("Sending auto synccheck");
00065
00066 std::list<unsigned int> destinations;
00067 std::set<unsigned int> &playing = shotState_->getPlaying();
00068 std::set<unsigned int>::iterator itor;
00069 for (itor = playing.begin();
00070 itor != playing.end();
00071 itor++)
00072 {
00073 destinations.push_back(*itor);
00074 }
00075 ComsSyncCheckMessage syncCheck;
00076 ComsMessageSender::sendToMultipleClients(syncCheck, destinations);
00077 }
00078
00079
00080 ServerMessageHandler::instance()->destroyTaggedPlayers();
00081
00082 totalTime_ = 0.0f;
00083 waitTime_ = 0.0f;
00084
00085
00086 if (ServerNextShotState::getRoundFinished() ||
00087 ((ScorchedServer::instance()->getOptionsTransient().getCurrentGameNo() >
00088 ScorchedServer::instance()->getOptionsGame().getNoMaxRoundTurns()) &&
00089 ScorchedServer::instance()->getOptionsGame().getNoMaxRoundTurns() > 0))
00090 {
00091
00092
00093
00094 bool finalScore = scoreWinners();
00095 if (finalScore)
00096 {
00097 waitTime_ = (float) ScorchedServer::instance()->
00098 getOptionsGame().getScoreTime();
00099 }
00100 else
00101 {
00102 waitTime_ = (float) ScorchedServer::instance()->
00103 getOptionsGame().getRoundScoreTime();
00104 }
00105
00106 ComsPlayerStateMessage playerMessage(true, true);
00107 ComsMessageSender::sendToAllPlayingClients(playerMessage);
00108 ComsScoreMessage message(finalScore);
00109 ComsMessageSender::sendToAllPlayingClients(message);
00110
00111 if (finalScore)
00112 {
00113 ServerCommon::serverLog("Final scores -------");
00114 std::map<unsigned int, Tank *> &tanks =
00115 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00116 std::map<unsigned int, Tank *>::iterator itor;
00117 for (itor = tanks.begin();
00118 itor != tanks.end();
00119 itor++)
00120 {
00121 Tank *tank = (*itor).second;
00122 ServerCommon::serverLog(S3D::formatStringBuffer("%s - %s",
00123 tank->getCStrName().c_str(),
00124 tank->getScore().getScoreString()));
00125 }
00126 ServerCommon::serverLog("--------------------");
00127 }
00128 }
00129 }
00130
00131 bool ServerShotFinishedState::acceptStateChange(const unsigned state,
00132 const unsigned nextState,
00133 float frameTime)
00134 {
00135 totalTime_ += frameTime * speed_;
00136 if (totalTime_ > waitTime_)
00137 {
00138 if (ServerTooFewPlayersStimulus::instance()->acceptStateChange(state,
00139 ServerState::ServerStateTooFewPlayers, 0.0f))
00140 {
00141 ScorchedServer::instance()->getGameState().stimulate(
00142 ServerState::ServerStimulusTooFewPlayers);
00143 }
00144 else return true;
00145 }
00146 return false;
00147 }
00148
00149 bool ServerShotFinishedState::scoreWinners()
00150 {
00151
00152 float interest = float(ScorchedServer::instance()->
00153 getOptionsGame().getInterest()) / 100.0f;
00154 std::map<unsigned int, Tank *> &playingTank =
00155 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00156
00157 int moneyWonForRound =
00158 ScorchedServer::instance()->getOptionsGame().getMoneyWonForRound();
00159 int moneyWonForLives =
00160 ScorchedServer::instance()->getOptionsGame().getMoneyWonForLives();
00161 int scoreWonForRound =
00162 ScorchedServer::instance()->getOptionsGame().getScoreWonForRound();
00163 int scoreWonForLives =
00164 ScorchedServer::instance()->getOptionsGame().getScoreWonForLives();
00165
00166
00167 std::map<unsigned int, Tank *>::iterator itor;
00168 for (itor = playingTank.begin();
00169 itor != playingTank.end();
00170 itor++)
00171 {
00172 Tank *tank = (*itor).second;
00173 if (tank->getState().getSpectator()) continue;
00174 if (tank->getAlive())
00175 tank->getScore().setScore(
00176 tank->getScore().getScore() + (scoreWonForLives * tank->getState().getLives()));
00177 }
00178
00179
00180 if (ScorchedServer::instance()->getOptionsGame().getTeams() > 1)
00181 {
00182
00183
00184 std::map<unsigned int, Tank *>::iterator itor;
00185 for (itor = playingTank.begin();
00186 itor != playingTank.end();
00187 itor++)
00188 {
00189 Tank *tank = (*itor).second;
00190 if (tank->getState().getSpectator()) continue;
00191
00192 if (tank->getAlive())
00193 {
00194 ScorchedServer::instance()->getContext().getTankTeamScore().addScore(
00195 scoreWonForLives * tank->getState().getLives(), tank->getTeam());
00196 }
00197 }
00198
00199 std::set<int> winningTeams;
00200 int winningTeam =
00201 ScorchedServer::instance()->getContext().getTankTeamScore().getWonGame();
00202 if (winningTeam != 0)
00203 {
00204 winningTeams.insert(winningTeam);
00205 ScorchedServer::instance()->getContext().getTankTeamScore().addScore(
00206 scoreWonForRound, winningTeam);
00207 }
00208 else
00209 {
00210 for (itor = playingTank.begin();
00211 itor != playingTank.end();
00212 itor++)
00213 {
00214 Tank *tank = (*itor).second;
00215 if (tank->getState().getSpectator()) continue;
00216
00217 if (tank->getAlive())
00218 {
00219 if (winningTeams.find(tank->getTeam()) == winningTeams.end())
00220 {
00221 ScorchedServer::instance()->getContext().getTankTeamScore().addScore(
00222 scoreWonForRound, tank->getTeam());
00223 winningTeams.insert(tank->getTeam());
00224
00225 }
00226 }
00227 }
00228 }
00229
00230 for (itor = playingTank.begin();
00231 itor != playingTank.end();
00232 itor++)
00233 {
00234 Tank *tank = (*itor).second;
00235 if (tank->getState().getSpectator()) continue;
00236
00237 if (winningTeams.find(tank->getTeam()) != winningTeams.end())
00238 {
00239 StatsLogger::instance()->tankWon(tank);
00240 tank->getScore().setMoney(
00241 tank->getScore().getMoney() + moneyWonForRound);
00242 tank->getScore().setMoney(
00243 tank->getScore().getMoney() + (moneyWonForLives * tank->getState().getLives()));
00244 tank->getScore().setWins(
00245 tank->getScore().getWins() + 1);
00246 }
00247 }
00248 }
00249 else
00250 {
00251
00252 bool tankWon = false;
00253 std::map<unsigned int, Tank *>::iterator itor;
00254 for (itor = playingTank.begin();
00255 itor != playingTank.end();
00256 itor++)
00257 {
00258 Tank *tank = (*itor).second;
00259 if (tank->getState().getSpectator()) continue;
00260
00261 if (tank->getScore().getWonGame())
00262 {
00263 StatsLogger::instance()->tankWon(tank);
00264 tank->getScore().setMoney(
00265 tank->getScore().getMoney() + moneyWonForRound);
00266 tank->getScore().setMoney(
00267 tank->getScore().getMoney() + (moneyWonForLives * tank->getState().getLives()));
00268 tank->getScore().setWins(
00269 tank->getScore().getWins() + 1);
00270 tank->getScore().setScore(
00271 tank->getScore().getScore() + scoreWonForRound);
00272
00273 tankWon = true;
00274 }
00275 }
00276
00277 if (!tankWon)
00278 {
00279 for (itor = playingTank.begin();
00280 itor != playingTank.end();
00281 itor++)
00282 {
00283 Tank *tank = (*itor).second;
00284 if (tank->getState().getSpectator()) continue;
00285
00286 if (tank->getAlive())
00287 {
00288 StatsLogger::instance()->tankWon(tank);
00289 tank->getScore().setMoney(
00290 tank->getScore().getMoney() + moneyWonForRound);
00291 tank->getScore().setMoney(
00292 tank->getScore().getMoney() + (moneyWonForLives * tank->getState().getLives()));
00293 tank->getScore().setWins(
00294 tank->getScore().getWins() + 1);
00295 tank->getScore().setScore(
00296 tank->getScore().getScore() + scoreWonForRound);
00297 }
00298 }
00299 }
00300 }
00301
00302
00303 {
00304 std::map<unsigned int, Tank *>::iterator itor;
00305 for (itor = playingTank.begin();
00306 itor != playingTank.end();
00307 itor++)
00308 {
00309 Tank *tank = (*itor).second;
00310 if (tank->getState().getSpectator()) continue;
00311
00312 int addMoney = int(float(tank->getScore().getMoney()) * interest) +
00313 ScorchedServer::instance()->getOptionsGame().getMoneyPerRound();
00314 tank->getScore().setMoney(tank->getScore().getMoney() + addMoney);
00315
00316
00317 if (tank->getState().getState() == TankState::sNormal)
00318 {
00319 tank->getState().setState(TankState::sDead);
00320 }
00321 }
00322 }
00323
00324
00325 bool overAllWinner = false;
00326 if (ScorchedServer::instance()->getOptionsTransient().getCurrentRoundNo() >=
00327 ScorchedServer::instance()->getOptionsGame().getNoRounds())
00328 {
00329 overAllWinner = true;
00330 }
00331 else
00332 {
00333 if (ServerTooFewPlayersStimulus::instance()->acceptStateChange(0,
00334 ServerState::ServerStateTooFewPlayers, 0.0f))
00335 {
00336 if (ScorchedServer::instance()->getOptionsTransient().getCurrentRoundNo() >
00337 ScorchedServer::instance()->getOptionsGame().getNoRounds() / 2 &&
00338 ScorchedServer::instance()->getOptionsTransient().getCurrentRoundNo() > 2)
00339 {
00340 overAllWinner = true;
00341 }
00342 }
00343 }
00344
00345
00346 ScorchedServer::instance()->getLUAScriptHook().callHook("server_score",
00347 overAllWinner);
00348
00349
00350
00351 std::map<unsigned int, Tank *> &tanks =
00352 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00353 for (itor = tanks.begin();
00354 itor != tanks.end();
00355 itor++)
00356 {
00357 Tank *tank = (*itor).second;
00358
00359
00360 int newMoney = tank->getScore().getTotalMoneyEarnedStat();
00361 int scoreAdded = (newMoney *
00362 ScorchedServer::instance()->getOptionsGame().getScorePerMoney())
00363 / 1000;
00364 tank->getScore().setScore(tank->getScore().getScore() + scoreAdded);
00365
00366
00367 StatsLogger::instance()->updateStats(tank);
00368
00369
00370 tank->getScore().resetTotalEarnedStats();
00371
00372
00373 StatsLogger::TankRank rank = StatsLogger::instance()->tankRank(tank);
00374 tank->getScore().setRank(rank.rank);
00375 }
00376
00377
00378 if (overAllWinner)
00379 {
00380 scoreOverallWinner();
00381 }
00382 return overAllWinner;
00383 }
00384
00385 void ServerShotFinishedState::scoreOverallWinner()
00386 {
00387 StatsLogger::instance()->periodicUpdate();
00388
00389 if (ScorchedServer::instance()->getOptionsGame().getTeams() == 1)
00390 {
00391 std::list<Tank *> sortedTanks;
00392 std::map<unsigned int, Tank *> &tanks =
00393 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00394 std::map<unsigned int, Tank *>::iterator itor;
00395 for (itor = tanks.begin();
00396 itor != tanks.end();
00397 itor++)
00398 {
00399 Tank *current = (*itor).second;
00400 if (!current->getState().getSpectator() &&
00401 current->getState().getState() != TankState::sPending &&
00402 current->getState().getState() != TankState::sInitializing &&
00403 current->getState().getState() != TankState::sLoading)
00404 {
00405 sortedTanks.push_back(current);
00406 }
00407 }
00408
00409 TankSort::getSortedTanks(sortedTanks, ScorchedServer::instance()->getContext());
00410 if (!sortedTanks.empty())
00411 {
00412 Tank *topScore = *(sortedTanks.begin());
00413
00414 LangString names;
00415 std::list<Tank *> winners;
00416 std::list<Tank *>::iterator scoreitor;
00417 for (scoreitor = sortedTanks.begin();
00418 scoreitor != sortedTanks.end();
00419 scoreitor++)
00420 {
00421 Tank *current = *scoreitor;
00422 if (topScore->getScore().getScore() ==
00423 current->getScore().getScore())
00424 {
00425 winners.push_back(current);
00426 if (!names.empty()) names.append(LANG_STRING(","));
00427 names.append(current->getTargetName());
00428
00429
00430 StatsLogger::instance()->tankOverallWinner(current);
00431 }
00432 }
00433
00434 if (winners.size() == 1)
00435 {
00436 ServerChannelManager::instance()->sendText(
00437 ChannelText("banner",
00438 "PLAYER_OVERALL_WINNER",
00439 "{0} is the overall winner!",
00440 names),
00441 true);
00442 }
00443 else
00444 {
00445 ServerChannelManager::instance()->sendText(
00446 ChannelText("banner",
00447 "PLAYERS_OVERALL_WINNERS",
00448 "{0} are the overall winners!",
00449 names),
00450 true);
00451 }
00452 }
00453 }
00454 else
00455 {
00456 int winningTeam = TankSort::getWinningTeam(
00457 ScorchedServer::instance()->getContext());
00458 if (winningTeam == 0)
00459 {
00460 ServerChannelManager::instance()->sendText(
00461 ChannelText("banner",
00462 "GAME_DRAWN",
00463 "The game is a draw!"),
00464 true);
00465 }
00466 else
00467 {
00468 ServerChannelManager::instance()->sendText(
00469 ChannelText("banner",
00470 "TEAM_OVERALL_WINNER",
00471 "{0} team is the overall winner!",
00472 TankColorGenerator::getTeamName(winningTeam)),
00473 true);
00474 }
00475
00476
00477 if (winningTeam != 0)
00478 {
00479 std::map<unsigned int, Tank *> &tanks =
00480 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00481 std::map<unsigned int, Tank *>::iterator itor;
00482 for (itor = tanks.begin();
00483 itor != tanks.end();
00484 itor++)
00485 {
00486 Tank *tank = (*itor).second;
00487 if (tank->getTeam() == winningTeam)
00488 {
00489 if (!tank->getState().getSpectator() &&
00490 tank->getState().getState() != TankState::sPending &&
00491 tank->getState().getState() != TankState::sInitializing &&
00492 tank->getState().getState() != TankState::sLoading)
00493 {
00494 StatsLogger::instance()->tankOverallWinner(tank);
00495 }
00496 }
00497 }
00498 }
00499 }
00500 }