00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "eEventNotification.h"
00029 #include "eEventNotification.h"
00030 #include "gStuff.h"
00031 #include "eSoundMixer.h"
00032 #include "eGrid.h"
00033 #include "eTeam.h"
00034 #include "tSysTime.h"
00035 #include "gGame.h"
00036 #include "rTexture.h"
00037 #include "gWall.h"
00038 #include "rConsole.h"
00039 #include "gCycle.h"
00040 #include "eCoord.h"
00041 #include "eTimer.h"
00042 #include "gAIBase.h"
00043 #include "rSysdep.h"
00044 #include "rFont.h"
00045 #include "uMenu.h"
00046 #include "nConfig.h"
00047 #include "rScreen.h"
00048 #include "rViewport.h"
00049 #include "uInput.h"
00050 #include "ePlayer.h"
00051 #include "gSpawn.h"
00052 #include "uInput.h"
00053 #include "uInputQueue.h"
00054 #include "nNetObject.h"
00055 #include "tToDo.h"
00056 #include "gMenus.h"
00057 #include "gCamera.h"
00058 #include "gServerBrowser.h"
00059 #include "gServerFavorites.h"
00060 #include "gFriends.h"
00061 #include "gLogo.h"
00062 #include "gLanguageMenu.h"
00063 #include "nServerInfo.h"
00064 #include "gAICharacter.h"
00065 #include "tDirectories.h"
00066 #include "gTeam.h"
00067 #ifdef ENABLE_ZONESV2
00068 #include "zone/zZone.h"
00069 #endif
00070 #include "gWinZone.h"
00071 #include "eVoter.h"
00072 #include "tRecorder.h"
00073 #include "gStatistics.h"
00074
00075 #include "tXmlParser.h"
00076 #include "gParser.h"
00077 #include "nAuthentication.h"
00078
00079
00080
00081 #include "gRotation.h"
00082
00083 #include <math.h>
00084 #include <stdlib.h>
00085 #include <string>
00086 #include <fstream>
00087 #include <ctype.h>
00088 #include <time.h>
00089
00090 #include "nSocket.h"
00091
00092 #include "gArena.h"
00093 gArena Arena;
00094
00095 #ifdef KRAWALL_SERVER
00096 #include "nKrawall.h"
00097 #endif
00098
00099
00100 #ifndef DEDICATED
00101 #include "rSDL.h"
00102 #include <SDL_thread.h>
00103
00104 #ifdef DEBUG
00105 #ifndef WIN32
00106
00107
00108
00109 #endif
00110 #endif
00111 #endif
00112
00113 #ifdef DEBUG
00114
00115 #endif
00116
00117 tCONFIG_ENUM( gGameType );
00118 tCONFIG_ENUM( gFinishType );
00119
00120
00121 static REAL sg_extraRoundTime = 0.0f;
00122 static tSettingItem<REAL> sg_extraRoundTimeConf( "EXTRA_ROUND_TIME", sg_extraRoundTime );
00123
00124 static REAL sg_lastChatBreakTime = -1.0f;
00125 static tSettingItem<REAL> sg_lastChatBreakTimeConf( "LAST_CHAT_BREAK_TIME", sg_lastChatBreakTime );
00126
00127 #define DEFAULT_MAP "Anonymous/polygon/regular/square-1.0.1.aamap.xml"
00128 static tString mapfile(DEFAULT_MAP);
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 static nSettingItemWatched<tString> conf_mapfile("MAP_FILE",mapfile, nConfItemVersionWatcher::Group_Breaking, 8 );
00164
00165
00166
00167 class tSettingRotation: public tConfItemBase
00168 {
00169 public:
00170 tSettingRotation( char const * name )
00171 : tConfItemBase( name ),
00172 current_(0)
00173 {
00174 }
00175
00176
00177 int Size() const
00178 {
00179 return items_.Len();
00180 }
00181
00182
00183 tString const & Current() const
00184 {
00185 tASSERT( Size() > 0 && current_ >= 0 && current_ < Size() );
00186
00187 return items_[current_];
00188 }
00189
00190
00191 void Rotate()
00192 {
00193 if ( ++current_ >= items_.Len() )
00194 {
00195 current_ = 0;
00196 }
00197 }
00198 private:
00199 virtual void ReadVal( std::istream &is )
00200 {
00201 tString mapsT;
00202 mapsT.ReadLine (is);
00203 items_.SetLen (0);
00204
00205 int strpos = 0;
00206 int nextsemicolon = mapsT.StrPos(";");
00207
00208 if (nextsemicolon != -1)
00209 {
00210 do
00211 {
00212 tString const &map = mapsT.SubStr(strpos, nextsemicolon - strpos);
00213
00214 strpos = nextsemicolon + 1;
00215 nextsemicolon = mapsT.StrPos(strpos, ";");
00216
00217 items_.Insert(map);
00218 }
00219 while ((nextsemicolon = mapsT.StrPos(strpos, ";")) != -1);
00220 }
00221
00222
00223 if ( current_ >= items_.Len() )
00224 {
00225 current_ = 0;
00226 }
00227 }
00228
00229 virtual void WriteVal(std::ostream &s){}
00230 virtual bool Writable(){return false;}
00231 virtual bool Save(){return false;}
00232
00233 tArray<tString> items_;
00234 int current_;
00235 };
00236
00237 static tSettingRotation sg_mapRotation("MAP_ROTATION");
00238 static tSettingRotation sg_configRotation("CONFIG_ROTATION");
00239
00240
00241 static int rotationtype = 0;
00242 static tSettingItem<int> conf_rotationtype("ROTATION_TYPE",rotationtype);
00243
00244
00245 tString sg_GetCurrentTime( char const * szFormat )
00246 {
00247 char szTemp[128];
00248 time_t now;
00249 struct tm *pTime;
00250 now = time(NULL);
00251 pTime = localtime(&now);
00252 strftime(szTemp,sizeof(szTemp),szFormat,pTime);
00253 return tString(szTemp);
00254 }
00255
00256 void sg_PrintCurrentTime( char const * szFormat )
00257 {
00258 con << sg_GetCurrentTime(szFormat);
00259 }
00260
00261 void sg_PrintCurrentDate()
00262 {
00263 sg_PrintCurrentTime( "%Y%m%d");
00264 }
00265
00266 void sg_PrintCurrentTime()
00267 {
00268 sg_PrintCurrentTime( "%H%M%S" );
00269 }
00270
00271 void sg_Timestamp()
00272 {
00273 #ifdef DEDICATED
00274 sg_PrintCurrentTime( "Timestamp: %Y/%m/%d %H:%M:%S\n" );
00275 if ( tRecorder::IsRunning() )
00276 {
00277 con << "Uptime: " << int(tSysTimeFloat()) << " seconds.\n";
00278
00279 #ifdef DEBUG_X
00280
00281 static double breakTime = 0;
00282 if ( tSysTimeFloat() > breakTime )
00283 st_Breakpoint();
00284 #endif
00285 }
00286 #endif
00287 }
00288
00289 static REAL ded_idle=24;
00290 static tSettingItem<REAL> dedicaded_idle("DEDICATED_IDLE",ded_idle);
00291
00292 static float sg_gameTimeInterval=-1;
00293 static tSettingItem<float> sggti("LADDERLOG_GAME_TIME_INTERVAL",
00294 sg_gameTimeInterval);
00295
00296 #define MAXAI (gAICharacter::s_Characters.Len())
00297
00298 #define AUTO_AI_MAXFRAC 6
00299 #define AUTO_AI_WIN 3
00300 #define AUTO_AI_LOSE 1
00301
00302 gGameSettings::gGameSettings(int a_scoreWin,
00303 int a_limitTime, int a_limitRounds, int a_limitScore,
00304 int a_numAIs, int a_minPlayers, int a_AI_IQ,
00305 bool a_autoNum, bool a_autoIQ,
00306 int a_speedFactor, int a_sizeFactor,
00307 gGameType a_gameType, gFinishType a_finishType,
00308 int a_minTeams,
00309 int a_winZoneMinRoundTime, int a_winZoneMinLastDeath
00310 )
00311 :scoreWin(a_scoreWin),
00312 limitTime(a_limitTime), limitRounds(a_limitRounds), limitScore(a_limitScore),
00313 numAIs(a_numAIs), minPlayers(a_minPlayers), AI_IQ(a_AI_IQ),
00314 autoNum(a_autoNum), autoIQ(a_autoIQ),
00315 speedFactor(a_speedFactor), sizeFactor(a_sizeFactor),
00316 winZoneMinRoundTime( a_winZoneMinRoundTime ),winZoneMinLastDeath( a_winZoneMinLastDeath ),
00317 gameType(a_gameType), finishType(a_finishType),
00318 minTeams(a_minTeams)
00319 {
00320 autoAIFraction = AUTO_AI_MAXFRAC >> 1;
00321
00322 maxTeams = 16;
00323 minPlayersPerTeam = 1;
00324 maxPlayersPerTeam = 10;
00325 maxTeamImbalance = 1;
00326 balanceTeamsWithAIs = true;
00327 enforceTeamRulesOnQuit = false;
00328
00329 wallsStayUpDelay = 2.0f;
00330 wallsLength = -1.0f;
00331 explosionRadius = 4.0f;
00332 }
00333
00334 void gGameSettings::AutoAI(bool success){
00335 if (!autoNum && !autoIQ)
00336 return;
00337
00338 if (autoNum)
00339 {
00340 if (success)
00341 {
00342 autoAIFraction += AUTO_AI_WIN;
00343 while (autoAIFraction > AUTO_AI_MAXFRAC)
00344 {
00345 autoAIFraction -= AUTO_AI_MAXFRAC;
00346 if (numAIs < MAXAI) numAIs++;
00347 }
00348 }
00349 else
00350 {
00351 autoAIFraction -= AUTO_AI_LOSE;
00352 while (autoAIFraction < 0)
00353 {
00354 autoAIFraction += AUTO_AI_MAXFRAC;
00355 if (numAIs >= 2) numAIs--;
00356 }
00357 }
00358 }
00359
00360
00361 if (autoIQ)
00362 {
00363 if (!autoNum)
00364 AI_IQ += 4 * (success ? AUTO_AI_WIN : -AUTO_AI_LOSE);
00365 else
00366 {
00367 int total = numAIs * numAIs * AI_IQ;
00368
00369
00370
00371 if (success)
00372 if (total > 100)
00373 AI_IQ += AUTO_AI_WIN * 4;
00374 else
00375 AI_IQ += AUTO_AI_WIN;
00376 else
00377 if (total < 100)
00378 AI_IQ -= AUTO_AI_LOSE * 4;
00379 else
00380 AI_IQ -= AUTO_AI_LOSE;
00381 }
00382 }
00383
00384 if (AI_IQ > 100)
00385 AI_IQ = 100;
00386 if (AI_IQ < 0)
00387 AI_IQ = 0;
00388 }
00389
00390
00391 void gGameSettings::Menu()
00392 {
00393 uMenu GameSettings("$game_settings_menu_text");
00394
00395 uMenuItemInt wzmr
00396 (&GameSettings,
00397 "$game_menu_wz_mr_text",
00398 "$game_menu_wz_mr_help",
00399 winZoneMinRoundTime,0,1000,10);
00400
00401 uMenuItemInt wzmld
00402 (&GameSettings,
00403 "$game_menu_wz_ld_text",
00404 "$game_menu_wz_ld_help",
00405 winZoneMinLastDeath,0,1000,10);
00406
00407 uMenuItemToggle team_et
00408 (&GameSettings,
00409 "$game_menu_balance_quit_text",
00410 "$game_menu_balance_quit_help",
00411 enforceTeamRulesOnQuit);
00412
00413 uMenuItemToggle team_bt
00414 (&GameSettings,
00415 "$game_menu_balance_ais_text",
00416 "$game_menu_balance_ais_help",
00417 balanceTeamsWithAIs);
00418
00419 uMenuItemInt team_mi
00420 (&GameSettings,
00421 "$game_menu_imb_text",
00422 "$game_menu_imb_help",
00423 maxTeamImbalance,2,10);
00424
00425 uMenuItemInt team_maxp
00426 (&GameSettings,
00427 "$game_menu_max_players_text",
00428 "$game_menu_max_players_help",
00429 maxPlayersPerTeam,1,16);
00430
00431 uMenuItemInt team_minp
00432 (&GameSettings,
00433 "$game_menu_min_players_text",
00434 "$game_menu_min_players_help",
00435 minPlayersPerTeam,1,16);
00436
00437 uMenuItemInt team_max
00438 (&GameSettings,
00439 "$game_menu_max_teams_text",
00440 "$game_menu_max_teams_help",
00441 maxTeams,1,16);
00442
00443 uMenuItemInt team_min
00444 (&GameSettings,
00445 "$game_menu_min_teams_text",
00446 "$game_menu_min_teams_help",
00447 minTeams,1,16);
00448
00449 uMenuItemSelection<gFinishType> finisht
00450 (&GameSettings,"$game_menu_finish_text",
00451 "$game_menu_finish_help",finishType);
00452 finisht.NewChoice("$game_menu_finish_expr_text",
00453 "$game_menu_finish_expr_help",
00454 gFINISH_EXPRESS);
00455 finisht.NewChoice("$game_menu_finish_stop_text",
00456 "$game_menu_finish_stop_help",
00457 gFINISH_IMMEDIATELY);
00458 finisht.NewChoice("$game_menu_finish_fast_text",
00459 "$game_menu_finish_fast_help",
00460 gFINISH_SPEEDUP);
00461 finisht.NewChoice("$game_menu_finish_normal_text",
00462 "$game_menu_finish_normal_help",
00463 gFINISH_NORMAL);
00464
00465 uMenuItemSelection<gGameType> gamet
00466 (&GameSettings,"$game_menu_mode_text",
00467 "$game_menu_mode_help",gameType);
00468 gamet.NewChoice("$game_menu_mode_free_text",
00469 "$game_menu_mode_free_help",
00470 gFREESTYLE);
00471 gamet.NewChoice("$game_menu_mode_lms_text",
00472 "$game_menu_mode_lms_help",
00473 gDUEL);
00474
00475
00476
00477
00478
00479
00480 uMenuItemInt speedconf
00481 (&GameSettings,
00482 "$game_menu_speed_text",
00483 "$game_menu_speed_help",
00484 speedFactor,-10,10);
00485
00486 uMenuItemInt sizeconf
00487 (&GameSettings,
00488 "$game_menu_size_text",
00489 "$game_menu_size_help",
00490 sizeFactor,-10,10);
00491
00492 uMenuItemSelection<REAL> wsuconf
00493 (&GameSettings,
00494 "$game_menu_wallstayup_text",
00495 "$game_menu_wallstayup_help",
00496 wallsStayUpDelay);
00497 wsuconf.NewChoice( "$game_menu_wallstayup_infinite_text",
00498 "$game_menu_wallstayup_infinite_help",
00499 -1.0f );
00500 wsuconf.NewChoice( "$game_menu_wallstayup_immediate_text",
00501 "$game_menu_wallstayup_immediate_help",
00502 0.0f );
00503 wsuconf.NewChoice( "$game_menu_wallstayup_halfsecond_text",
00504 "$game_menu_wallstayup_halfsecond_help",
00505 0.5f );
00506 wsuconf.NewChoice( "$game_menu_wallstayup_second_text",
00507 "$game_menu_wallstayup_second_help",
00508 1.0f );
00509 wsuconf.NewChoice( "$game_menu_wallstayup_2second_text",
00510 "$game_menu_wallstayup_2second_help",
00511 2.0f );
00512 wsuconf.NewChoice( "$game_menu_wallstayup_4second_text",
00513 "$game_menu_wallstayup_4second_help",
00514 4.0f );
00515 wsuconf.NewChoice( "$game_menu_wallstayup_8second_text",
00516 "$game_menu_wallstayup_8second_help",
00517 8.0f );
00518 wsuconf.NewChoice( "$game_menu_wallstayup_16second_text",
00519 "$game_menu_wallstayup_16second_help",
00520 16.0f );
00521 wsuconf.NewChoice( "$game_menu_wallstayup_32second_text",
00522 "$game_menu_wallstayup_32second_help",
00523 32.0f );
00524
00525 uMenuItemSelection<REAL> wlconf
00526 (&GameSettings,
00527 "$game_menu_wallslength_text",
00528 "$game_menu_wallslength_help",
00529 wallsLength);
00530 wlconf.NewChoice( "$game_menu_wallslength_infinite_text",
00531 "$game_menu_wallslength_infinite_help",
00532 -1.0f );
00533 wlconf.NewChoice( "$game_menu_wallslength_25meter_text",
00534 "$game_menu_wallslength_25meter_help",
00535 25.0f );
00536 wlconf.NewChoice( "$game_menu_wallslength_50meter_text",
00537 "$game_menu_wallslength_50meter_help",
00538 50.0f );
00539 wlconf.NewChoice( "$game_menu_wallslength_100meter_text",
00540 "$game_menu_wallslength_100meter_help",
00541 100.0f );
00542 wlconf.NewChoice( "$game_menu_wallslength_200meter_text",
00543 "$game_menu_wallslength_200meter_help",
00544 200.0f );
00545 wlconf.NewChoice( "$game_menu_wallslength_300meter_text",
00546 "$game_menu_wallslength_300meter_help",
00547 300.0f );
00548 wlconf.NewChoice( "$game_menu_wallslength_400meter_text",
00549 "$game_menu_wallslength_400meter_help",
00550 400.0f );
00551 wlconf.NewChoice( "$game_menu_wallslength_600meter_text",
00552 "$game_menu_wallslength_600meter_help",
00553 600.0f );
00554 wlconf.NewChoice( "$game_menu_wallslength_800meter_text",
00555 "$game_menu_wallslength_800meter_help",
00556 800.0f );
00557 wlconf.NewChoice( "$game_menu_wallslength_1200meter_text",
00558 "$game_menu_wallslength_1200meter_help",
00559 1200.0f );
00560 wlconf.NewChoice( "$game_menu_wallslength_1600meter_text",
00561 "$game_menu_wallslength_1600meter_help",
00562 1600.0f );
00563
00564 uMenuItemSelection<REAL> erconf
00565 (&GameSettings,
00566 "$game_menu_exrad_text",
00567 "$game_menu_exrad_help",
00568 explosionRadius);
00569 erconf.NewChoice( "$game_menu_exrad_0_text",
00570 "$game_menu_exrad_0_help",
00571 0.0f );
00572 erconf.NewChoice( "$game_menu_exrad_2meters_text",
00573 "$game_menu_exrad_2meters_help",
00574 2.0f );
00575 erconf.NewChoice( "$game_menu_exrad_4meters_text",
00576 "$game_menu_exrad_4meters_help",
00577 4.0f );
00578 erconf.NewChoice( "$game_menu_exrad_8meters_text",
00579 "$game_menu_exrad_8meters_help",
00580 8.0f );
00581 erconf.NewChoice( "$game_menu_exrad_16meters_text",
00582 "$game_menu_exrad_16meters_help",
00583 16.0f );
00584 erconf.NewChoice( "$game_menu_exrad_32meters_text",
00585 "$game_menu_exrad_32meters_help",
00586 32.0f );
00587 erconf.NewChoice( "$game_menu_exrad_64meters_text",
00588 "$game_menu_exrad_64meters_help",
00589 64.0f );
00590 erconf.NewChoice( "$game_menu_exrad_128meters_text",
00591 "$game_menu_exrad_128meters_help",
00592 128.0f );
00593
00594 uMenuItemToggle autoiqconf
00595 (&GameSettings,
00596 "$game_menu_autoiq_text",
00597 "$game_menu_autoiq_help",
00598 autoIQ);
00599
00600 uMenuItemToggle autoaiconf
00601 (&GameSettings,
00602 "$game_menu_autoai_text",
00603 "$game_menu_autoai_help",
00604 autoNum);
00605
00606
00607 uMenuItemInt iqconf
00608 (&GameSettings,
00609 "$game_menu_iq_text",
00610 "$game_menu_iq_help",
00611 AI_IQ, 20, 100, 10);
00612
00613 uMenuItemInt mpconf
00614 (&GameSettings,
00615 "$game_menu_minplayers_text",
00616 "$game_menu_minplayers_help",
00617 minPlayers,0,MAXAI);
00618
00619 uMenuItemInt aiconf
00620 (&GameSettings,
00621 "$game_menu_ais_text",
00622 "$game_menu_ais_help",
00623 numAIs,0,MAXAI);
00624
00625
00626 GameSettings.Enter();
00627 }
00628
00629 gGameSettings singlePlayer(10,
00630 30, 10, 100000,
00631 1, 0, 30,
00632 true, true,
00633 0 , -3,
00634 gDUEL, gFINISH_IMMEDIATELY, 1,
00635 100000, 1000000);
00636
00637 gGameSettings multiPlayer(10,
00638 30, 10, 100,
00639 0, 4, 100,
00640 false, false,
00641 0 , -3,
00642 gDUEL, gFINISH_IMMEDIATELY, 2,
00643 60, 30 );
00644
00645 gGameSettings* sg_currentSettings = &singlePlayer;
00646
00647
00648
00649 static tSettingItem<int> mp_sw("SCORE_WIN" ,multiPlayer.scoreWin);
00650 static tSettingItem<int> mp_lt("LIMIT_TIME" ,multiPlayer.limitTime);
00651 static tSettingItem<int> mp_lr("LIMIT_ROUNDS",multiPlayer.limitRounds);
00652 static tSettingItem<int> mp_ls("LIMIT_SCORE" ,multiPlayer.limitScore);
00653
00654 static tConfItem<int> mp_na("NUM_AIS" ,multiPlayer.numAIs);
00655 static tConfItem<int> mp_mp("MIN_PLAYERS" ,multiPlayer.minPlayers);
00656 static tConfItem<int> mp_iq("AI_IQ" ,multiPlayer.AI_IQ);
00657
00658 static tConfItem<bool> mp_an("AUTO_AIS" ,multiPlayer.autoNum);
00659 static tConfItem<bool> mp_aq("AUTO_IQ" ,multiPlayer.autoIQ);
00660
00661 static tConfItem<int> mp_sf("SPEED_FACTOR",multiPlayer.speedFactor);
00662 static tConfItem<int> mp_zf("SIZE_FACTOR" ,multiPlayer.sizeFactor);
00663
00664 static tConfItem<gGameType> mp_gt("GAME_TYPE",multiPlayer.gameType);
00665 static tConfItem<gFinishType> mp_ft("FINISH_TYPE",multiPlayer.finishType);
00666
00667 static tConfItem<int> mp_wzmr("WIN_ZONE_MIN_ROUND_TIME",multiPlayer.winZoneMinRoundTime);
00668 static tConfItem<int> mp_wzld("WIN_ZONE_MIN_LAST_DEATH",multiPlayer.winZoneMinLastDeath);
00669
00670 static tConfItem<int> mp_tmin ("TEAMS_MIN", multiPlayer.minTeams);
00671 static tConfItem<int> mp_tmax ("TEAMS_MAX", multiPlayer.maxTeams);
00672 static tConfItem<int> mp_mtp ("TEAM_MIN_PLAYERS", multiPlayer.minPlayersPerTeam);
00673 static tConfItem<int> mp_tp ("TEAM_MAX_PLAYERS", multiPlayer.maxPlayersPerTeam);
00674 static tConfItem<int> mp_tib ("TEAM_MAX_IMBALANCE", multiPlayer.maxTeamImbalance);
00675 static tConfItem<bool> mp_tbai ("TEAM_BALANCE_WITH_AIS", multiPlayer.balanceTeamsWithAIs);
00676 static tConfItem<bool> mp_tboq ("TEAM_BALANCE_ON_QUIT", multiPlayer.enforceTeamRulesOnQuit);
00677
00678 static tConfItem<REAL> mp_wsu ("WALLS_STAY_UP_DELAY" , multiPlayer.wallsStayUpDelay);
00679 static tConfItem<REAL> mp_wl ("WALLS_LENGTH" , multiPlayer.wallsLength );
00680 static tConfItem<REAL> mp_er ("EXPLOSION_RADIUS" , multiPlayer.explosionRadius );
00681
00682 static tSettingItem<int> sp_sw("SP_SCORE_WIN" ,singlePlayer.scoreWin);
00683 static tSettingItem<int> sp_lt("SP_LIMIT_TIME" ,singlePlayer.limitTime);
00684 static tSettingItem<int> sp_lr("SP_LIMIT_ROUNDS",singlePlayer.limitRounds);
00685 static tSettingItem<int> sp_ls("SP_LIMIT_SCORE" ,singlePlayer.limitScore);
00686
00687 static tConfItem<int> sp_na("SP_NUM_AIS" ,singlePlayer.numAIs);
00688 static tConfItem<int> sp_mp("SP_MIN_PLAYERS" ,singlePlayer.minPlayers);
00689 static tConfItem<int> sp_iq("SP_AI_IQ" ,singlePlayer.AI_IQ);
00690
00691 static tConfItem<bool> sp_an("SP_AUTO_AIS" ,singlePlayer.autoNum);
00692 static tConfItem<bool> sp_aq("SP_AUTO_IQ" ,singlePlayer.autoIQ);
00693
00694 static tConfItem<int> sp_sf("SP_SPEED_FACTOR",singlePlayer.speedFactor);
00695 static tConfItem<int> sp_zf("SP_SIZE_FACTOR" ,singlePlayer.sizeFactor);
00696
00697 static tConfItem<gGameType> sp_gt("SP_GAME_TYPE",singlePlayer.gameType);
00698 static tConfItem<gFinishType> sp_ft("SP_FINISH_TYPE",singlePlayer.finishType);
00699
00700 static tConfItem<int> sp_wzmr("SP_WIN_ZONE_MIN_ROUND_TIME",singlePlayer.winZoneMinRoundTime);
00701 static tConfItem<int> sp_wzld("SP_WIN_ZONE_MIN_LAST_DEATH",singlePlayer.winZoneMinLastDeath);
00702
00703 static tConfItem<int> sp_tmin ("SP_TEAMS_MIN", singlePlayer.minTeams);
00704 static tConfItem<int> sp_tmax ("SP_TEAMS_MAX", singlePlayer.maxTeams);
00705 static tConfItem<int> sp_mtp ("SP_TEAM_MIN_PLAYERS", singlePlayer.minPlayersPerTeam);
00706 static tConfItem<int> sp_tp ("SP_TEAM_MAX_PLAYERS", singlePlayer.maxPlayersPerTeam);
00707 static tConfItem<int> sp_tib ("SP_TEAM_MAX_IMBALANCE", singlePlayer.maxTeamImbalance);
00708 static tConfItem<bool> sp_tbai ("SP_TEAM_BALANCE_WITH_AIS", singlePlayer.balanceTeamsWithAIs);
00709 static tConfItem<bool> sp_tboq ("SP_TEAM_BALANCE_ON_QUIT", singlePlayer.enforceTeamRulesOnQuit);
00710
00711 static tConfItem<REAL> sp_wsu ("SP_WALLS_STAY_UP_DELAY" , singlePlayer.wallsStayUpDelay);
00712 static tConfItem<REAL> sp_wl ("SP_WALLS_LENGTH" , singlePlayer.wallsLength );
00713 static tConfItem<REAL> sp_er ("SP_EXPLOSION_RADIUS" , singlePlayer.explosionRadius );
00714
00715 static void GameSettingsMP(){
00716 multiPlayer.Menu();
00717 }
00718
00719 static void GameSettingsSP(){
00720 singlePlayer.Menu();
00721 }
00722
00723 static void GameSettingsCurrent(){
00724 sg_currentSettings->Menu();
00725 }
00726
00727 static REAL sg_Timeout = 5.0f;
00728 static tConfItem<REAL> sg_ctimeout("GAME_TIMEOUT" , sg_Timeout );
00729
00730 bool sg_TalkToMaster = true;
00731 static tSettingItem<bool> sg_ttm("TALK_TO_MASTER",
00732 sg_TalkToMaster);
00733
00734 #define PREPARE_TIME 4
00735
00736 static bool just_connected=true;
00737 static bool sg_singlePlayer=0;
00738 static int winner=0;
00739 static int absolute_winner=0;
00740 static REAL lastTime_gameloop=0;
00741 static REAL lastTimeTimestep=0;
00742
00743 static int wishWinner = 0;
00744 static char const * wishWinnerMessage = "";
00745
00746 void sg_DeclareWinner( eTeam* team, char const * message )
00747 {
00748 if ( team && !winner )
00749 {
00750 wishWinner = team->TeamID() + 1;
00751 wishWinnerMessage = message;
00752 }
00753 }
00754
00755
00756 static tCONTROLLED_PTR(gGame) sg_currentGame;
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 #ifdef POWERPAK_DEB
00772 #include "PowerPak/poweruInput.h"
00773 #include "PowerPak/joystick.h"
00774 #endif
00775
00776 #include "rRender.h"
00777
00778
00779
00780 void exit_game_grid(eGrid *grid){
00781 grid->Clear();
00782 }
00783
00784 void exit_game_objects(eGrid *grid){
00785 sr_con.fullscreen=true;
00786
00787 su_prefetchInput=false;
00788
00789 int i;
00790 for (i=ePlayer::Num()-1;i>=0;i--){
00791 if (ePlayer::PlayerConfig(i))
00792 tDESTROY(ePlayer::PlayerConfig(i)->cam);
00793 }
00794
00795 eGameObject::DeleteAll(grid);
00796
00797 if (sn_GetNetState()!=nCLIENT)
00798 for (int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
00799 if (se_PlayerNetIDs(i))
00800 se_PlayerNetIDs(i)->ClearObject();
00801
00802 gNetPlayerWall::Clear();
00803
00804 exit_game_grid(grid);
00805 }
00806
00807 REAL exponent(int i)
00808 {
00809 int abs = i;
00810 if ( abs < 0 )
00811 abs = -abs;
00812
00813 REAL ret = 1;
00814 REAL fac = sqrtf(2);
00815
00816 while (abs > 0)
00817 {
00818 if ( 1 == (abs & 1) )
00819 ret *= fac;
00820
00821 fac *= fac;
00822 abs >>= 1;
00823 }
00824
00825 if (i < 0)
00826 ret = 1/ret;
00827
00828 return ret;
00829 }
00830
00831 #ifndef DEDICATED
00832 extern REAL stc_fastestSpeedRound;
00833 #endif
00834 extern bool sg_axesIndicator;
00835
00836 void init_game_grid(eGrid *grid, gParser *aParser){
00837 se_ResetGameTimer();
00838 se_PauseGameTimer(true);
00839
00840 #ifndef DEDICATED
00841 if (sr_glOut){
00842 sr_ResetRenderState();
00843
00844
00845
00846
00847
00848
00849 }
00850 stc_fastestSpeedRound = .0;
00851 #endif
00852
00853
00854
00855
00856
00857
00858 Arena.PrepareGrid(grid, aParser);
00859
00860 absolute_winner=winner=wishWinner=0;
00861 }
00862
00863 int sg_NumHumans()
00864 {
00865 int humans = 0;
00866 for (int i = se_PlayerNetIDs.Len()-1; i>=0; i--)
00867 {
00868 ePlayerNetID* p = se_PlayerNetIDs(i);
00869 if (p->IsHuman() && p->IsActive() && ( bool(p->CurrentTeam()) || bool(p->NextTeam()) ) )
00870 humans++;
00871 }
00872
00873 return humans;
00874 }
00875
00876 int sg_NumUsers()
00877 {
00878
00879 #ifdef DEDICATED
00880 return sn_NumUsers();
00881 #else
00882 return sn_NumUsers() + 1;
00883 #endif
00884 }
00885
00886 static void sg_copySettings()
00887 {
00888 eTeam::minTeams = sg_currentSettings->minTeams;
00889 eTeam::maxTeams = sg_currentSettings->maxTeams;
00890 eTeam::maxPlayers = sg_currentSettings->maxPlayersPerTeam;
00891 eTeam::minPlayers = sg_currentSettings->minPlayersPerTeam;
00892 eTeam::maxImbalance = sg_currentSettings->maxTeamImbalance;
00893 eTeam::balanceWithAIs = sg_currentSettings->balanceTeamsWithAIs;
00894 eTeam::enforceRulesOnQuit = sg_currentSettings->enforceTeamRulesOnQuit;
00895
00896 gCycle::SetWallsStayUpDelay ( sg_currentSettings->wallsStayUpDelay );
00897 gCycle::SetWallsLength ( sg_currentSettings->wallsLength );
00898 gCycle::SetExplosionRadius ( sg_currentSettings->explosionRadius );
00899 gCycle::SetSpeedMultiplier ( exponent( sg_currentSettings->speedFactor ) );
00900 gArena::SetSizeMultiplier ( exponent( sg_currentSettings->sizeFactor ) );
00901 }
00902
00903 void update_settings()
00904 {
00905 if (sn_GetNetState()!=nCLIENT)
00906 {
00907 #ifdef DEDICATED
00908
00909 {
00910 bool restarted = false;
00911
00912 REAL timeout = tSysTimeFloat() + 3.0f;
00913 while ( sg_NumHumans() <= 0 && sg_NumUsers() > 0 )
00914 {
00915 if ( !restarted && bool(sg_currentGame) )
00916 {
00917 sg_currentGame->StartNewMatch();
00918 restarted = true;
00919 }
00920
00921 if ( tSysTimeFloat() > timeout )
00922 {
00923 tOutput o("$gamestate_wait_players");
00924 sn_CenterMessage(o);
00925
00926 tOutput o2("$gamestate_wait_players_con");
00927 sn_ConsoleOut(o2);
00928
00929 timeout = tSysTimeFloat() + 10.0f;
00930
00931
00932 st_DoToDo();
00933 nAuthentication::OnBreak();
00934 }
00935
00936
00937 nMachine::KickSpectators();
00938 ePlayerNetID::RemoveChatbots();
00939
00940
00941 sn_BasicNetworkSystem.Select( 0.1f );
00942 gGame::NetSyncIdle();
00943
00944
00945 sr_Read_stdin();
00946 }
00947 }
00948
00949 if ( sg_NumUsers() <= 0 && bool( sg_currentGame ) )
00950 {
00951 sg_currentGame->NoLongerGoOn();
00952 }
00953
00954
00955 int humans = sg_NumHumans();
00956
00957 bool newsg_singlePlayer = (humans<=1);
00958 #else
00959 bool newsg_singlePlayer = (sn_GetNetState() == nSTANDALONE);
00960 #endif
00961 if (sg_singlePlayer != newsg_singlePlayer && bool( sg_currentGame ) )
00962 {
00963 sg_currentGame->StartNewMatch();
00964 }
00965 sg_singlePlayer=newsg_singlePlayer;
00966
00967 if (sg_singlePlayer)
00968 sg_currentSettings = &singlePlayer;
00969 else
00970 sg_currentSettings = &multiPlayer;
00971
00972 sg_copySettings();
00973 }
00974
00975
00976 for (int i = eTeam::teams.Len() - 1; i>=0; --i)
00977 eTeam::teams(i)->UpdateProperties();
00978 }
00979
00980 static int sg_spawnPointGroupSize=0;
00981 static tSettingItem< int > sg_spawnPointGroupSizeConf( "SPAWN_POINT_GROUP_SIZE", sg_spawnPointGroupSize );
00982
00983 void init_game_objects(eGrid *grid){
00984
00985
00986
00987
00988
00989
00990 if (sn_GetNetState()!=nCLIENT)
00991 {
00992
00993 gAIPlayer::SetNumberOfAIs(sg_currentSettings->numAIs,
00994 sg_currentSettings->minPlayers,
00995 sg_currentSettings->AI_IQ);
00996
00997 int spawnPointsUsed = 0;
00998 for (int t=eTeam::teams.Len()-1;t>=0;t--)
00999 {
01000 eTeam *team = eTeam::teams(t);
01001 team->Update();
01002
01003 gSpawnPoint *spawn = Arena.LeastDangerousSpawnPoint();
01004 spawnPointsUsed++;
01005
01006
01007
01008 if ( ( eTeam::teams(0)->IsHuman() || eTeam::teams(0)->NumPlayers() == 1 ) && sg_spawnPointGroupSize > 2 && ( spawnPointsUsed % sg_spawnPointGroupSize == sg_spawnPointGroupSize - 1 ) )
01009 {
01010
01011
01012
01013 if ( t == 2 || ( ( t % ( sg_spawnPointGroupSize - 1 ) ) == 0 && t < ( sg_spawnPointGroupSize - 1 ) * ( sg_spawnPointGroupSize - 1 ) ) )
01014 {
01015 eCoord pos, dir;
01016 spawn->Spawn( pos, dir );
01017 spawn = Arena.LeastDangerousSpawnPoint();
01018 spawnPointsUsed++;
01019 }
01020 }
01021
01022 int numPlayers = team->NumPlayers();
01023 for (int p = 0; p<numPlayers; ++p)
01024 {
01025 ePlayerNetID *pni=team->Player( p );
01026
01027 if ( !team->IsHuman() )
01028 {
01029 spawn = Arena.LeastDangerousSpawnPoint();
01030 spawnPointsUsed++;
01031 }
01032
01033
01034
01035
01036 if (!pni->IsActive())
01037 continue;
01038
01039 eCoord pos,dir;
01040 gCycle *cycle=NULL;
01041 if (sn_GetNetState()!=nCLIENT){
01042 #ifdef DEBUG
01043
01044 #endif
01045 spawn->Spawn(pos,dir);
01046 pni->Greet();
01047 cycle = new gCycle(grid, pos, dir, pni);
01048 pni->ControlObject(cycle);
01049 nNetObject::SyncAll();
01050 }
01051
01052
01053
01054
01055 }
01056 }
01057
01058
01059 #ifdef ALLOW_NO_TEAM
01060 for (int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
01061 ePlayerNetID *pni=se_PlayerNetIDs(p);
01062
01063 gSpawnPoint *spawn=Arena.LeastDangerousSpawnPoint();
01064
01065 if ( NULL == pni->CurrentTeam() )
01066 {
01067 #ifdef KRAWALL_SERVER
01068
01069 if (!pni->IsAuth())
01070 continue;
01071 #endif
01072
01073
01074 if (!pni->IsActive())
01075 continue;
01076
01077 eCoord pos,dir;
01078 gCycle *cycle=NULL;
01079 if (sn_GetNetState()!=nCLIENT){
01080 #ifdef DEBUG
01081
01082 #endif
01083 st_Breakpoint();
01084
01085 spawn->Spawn(pos,dir);
01086 pni->Greet();
01087 cycle = new gCycle(grid, pos, dir, pni, 0);
01088 pni->ControlObject(cycle);
01089 nNetObject::SyncAll();
01090 }
01091
01092
01093
01094
01095 }
01096 }
01097 #endif
01098 }
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 rITexture::LoadAll();
01184
01185
01186
01187 su_prefetchInput=true;
01188
01189 lastTime_gameloop=lastTimeTimestep=0;
01190
01191
01192 ePlayerNetID::ResetScoreDifferences();
01193 }
01194
01195 void init_game_camera(eGrid *grid){
01196 #ifndef DEDICATED
01197 for (int i=ePlayer::Num()-1;i>=0;i--)
01198 if (ePlayer::PlayerIsInGame(i)){
01199 ePlayerNetID *p=ePlayer::PlayerConfig(i)->netPlayer;
01200
01201 if ( sg_currentSettings->finishType == gFINISH_EXPRESS && ( sn_GetNetState() != nCLIENT ) )
01202 se_ResetGameTimer( -PREPARE_TIME/5 - sg_extraRoundTime );
01203 else
01204 se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
01205
01206
01207
01208 ePlayer::PlayerConfig(i)->cam=new gCamera(grid,
01209 ePlayer::PlayerViewport(i),
01210 p,
01211 ePlayer::PlayerConfig(i),
01212 CAMERA_SMART);
01213
01214 lastTime_gameloop=lastTimeTimestep=0;
01215 }
01216 #else
01217 se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
01218 se_PauseGameTimer(false);
01219 #endif
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 }
01234
01235 bool think=1;
01236
01237 #ifdef DEDICATED
01238 static int sg_dedicatedFPS = 40;
01239 static tSettingItem<int> sg_dedicatedFPSConf( "DEDICATED_FPS", sg_dedicatedFPS );
01240
01241 static REAL sg_dedicatedFPSIdleFactor = 2.0;
01242 static tSettingItem<REAL> sg_dedicatedFPSMinstepConf( "DEDICATED_FPS_IDLE_FACTOR", sg_dedicatedFPSIdleFactor );
01243 #endif
01244
01245 void s_Timestep(eGrid *grid, REAL time,bool cam){
01246 gNetPlayerWall::s_CopyIntoGrid();
01247 REAL minstep = 0;
01248 #ifdef DEDICATED
01249 minstep = 1.0/sg_dedicatedFPS;
01250
01251
01252
01253 eGameObject::SetMaxLazyLag( ( 1 + sg_dedicatedFPSIdleFactor )/( sg_dedicatedFPSIdleFactor * sg_dedicatedFPS ) );
01254 #endif
01255 eGameObject::s_Timestep(grid, time, minstep );
01256
01257 if (cam)
01258 eCamera::s_Timestep(grid, time);
01259
01260 lastTimeTimestep=time;
01261 }
01262
01263 #ifndef DEDICATED
01264 void RenderAllViewports(eGrid *grid){
01265 rViewportConfiguration *conf=rViewportConfiguration::CurrentViewportConfiguration();
01266
01267 if (sr_glOut){
01268 sr_ResetRenderState();
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 const tList<eCamera>& cameras = grid->Cameras();
01280
01281 for (int i=cameras.Len()-1;i>=0;i--){
01282 int p=sr_viewportBelongsToPlayer[i];
01283 conf->Select(i);
01284 rViewport *act=conf->Port(i);
01285 if (act && ePlayer::PlayerConfig(p))
01286 ePlayer::PlayerConfig(p)->Render();
01287 else con << "hey! viewport " << i << " does not exist!\n";
01288 }
01289
01290
01291 }
01292
01293 #ifdef POWERPAK_DEB
01294 if (pp_out){
01295 eGameObject::PPDisplayAll();
01296 PD_ShowDoubleBuffer();
01297 }
01298 #endif
01299 }
01300 #endif
01301
01302
01303 void Render(eGrid *grid, REAL time, bool swap=true){
01304 #ifdef DEBUG
01305
01306 #endif
01307
01308
01309 #ifndef DEDICATED
01310 if (sr_glOut){
01311 RenderAllViewports(grid);
01312
01313 sr_ResetRenderState(true);
01314 gLogo::Display();
01315
01316 if (swap){
01317 rSysDep::SwapGL();
01318 rSysDep::ClearGL();
01319 }
01320 }
01321 else
01322 {
01323 if ( swap )
01324 rSysDep::SwapGL();
01325
01326 tDelay( sn_defaultDelay );
01327 }
01328 #endif
01329 }
01330
01331 #ifdef DEDICATED
01332 static void cp(){
01333 std::ofstream s;
01334
01335 if ( tDirectories::Var().Open(s, "players.txt") ){
01336 if (se_PlayerNetIDs.Len()>0)
01337 s << tColoredString::RemoveColors(ePlayerNetID::Ranking( -1, false ));
01338 else{
01339 tOutput o;
01340
01341 int count=0;
01342 for (int i=MAXCLIENTS;i>0;i--)
01343 if (sn_Connections[i].socket)
01344 count++;
01345 if (count==0)
01346 o << "$online_activity_nobody";
01347 else if (count==1)
01348 o << "$online_activity_onespec";
01349 else
01350 {
01351 o.SetTemplateParameter(1, count);
01352 o << "$online_activity_manyspec";
01353 }
01354 o << "\n";
01355 s << o;
01356 }
01357 }
01358 }
01359 #endif
01360
01361
01362 static void own_game( nNetState enter_state ){
01363 tNEW(gGame);
01364 se_MakeGameTimer();
01365 #ifndef DEDICATED
01366 stc_fastestSpeedRound = .0;
01367 #endif
01368 sg_EnterGame( enter_state );
01369
01370
01371 ePlayerNetID::LogScoreDifferences();
01372 se_SaveToLadderLog(tString("GAME_END\n"));
01373 se_sendEventNotification(tString("Game end"), tString("The Game has ended"));
01374
01375 sg_currentGame=NULL;
01376 se_KillGameTimer();
01377 }
01378
01379 static void singlePlayer_game(){
01380 sn_SetNetState(nSTANDALONE);
01381
01382 update_settings();
01383 ePlayerNetID::CompleteRebuild();
01384
01385 own_game( nSTANDALONE );
01386 }
01387
01388 void sg_HostGame(){
01389
01390 gStats = new gStatistics();
01391
01392 {
01393
01394 tJUST_CONTROLLED_PTR< gGame > game = tNEW(gGame);
01395 game->Verify();
01396 }
01397
01398 if (sg_TalkToMaster)
01399 {
01400 nServerInfo::TellMasterAboutMe( gServerBrowser::CurrentMaster() );
01401 }
01402
01403 sn_SetNetState(nSERVER);
01404
01405 update_settings();
01406 ePlayerNetID::CompleteRebuild();
01407
01408 tAdvanceFrame();
01409
01410
01411 #ifdef DEDICATED
01412 static double startTime=tSysTimeFloat();
01413
01414 if ( sg_NumUsers() == 0)
01415 {
01416 cp();
01417 con << tOutput("$online_activity_napping") << "\n";
01418 sg_Timestamp();
01419
01420 int counter = -1;
01421
01422 int numPlayers = 0;
01423
01424 while (numPlayers == 0 &&
01425 (ded_idle<.0001 || tSysTimeFloat()<startTime + ded_idle * 3600 ) && !uMenu::quickexit ){
01426 sr_Read_stdin();
01427 st_DoToDo();
01428 gGame::NetSyncIdle();
01429
01430 sn_BasicNetworkSystem.Select( 1.0f );
01431
01432
01433 numPlayers = sg_NumUsers();
01434
01435
01436
01437
01438
01439
01440 if (counter <= 0)
01441 {
01442
01443 sn_BasicNetworkSystem.AccessListener().Listen(false);
01444 sn_BasicNetworkSystem.AccessListener().Listen(true);
01445 counter = 50;
01446 }
01447 }
01448
01449 if (sg_NumUsers() <= 0 && ded_idle>0.0001 &&
01450 tSysTimeFloat()>= startTime + ded_idle * 3600 )
01451 {
01452 sg_Timestamp();
01453 con << "Server exiting due to DEDICATED_IDLE after " << (tSysTimeFloat() - startTime)/3600 << " hours.\n";
01454 uMenu::quickexit = true;
01455 }
01456 }
01457 cp();
01458
01459 if (!uMenu::quickexit)
01460 #endif
01461
01462 own_game( nSERVER );
01463
01464 sn_SetNetState(nSTANDALONE);
01465
01466
01467 sn_BasicNetworkSystem.AccessListener().Listen(false);
01468
01469
01470 delete gStats;
01471 }
01472
01473 static tString sg_roundCenterMessage("");
01474 static tConfItemLine sn_roundCM_ci("ROUND_CENTER_MESSAGE",sg_roundCenterMessage);
01475
01476 static tString sg_roundConsoleMessage("");
01477 static tConfItemLine sn_roundCcM1_ci("ROUND_CONSOLE_MESSAGE",sg_roundConsoleMessage);
01478
01479 static bool sg_RequestedDisconnection = false;
01480
01481 static bool sg_NetworkError( const tOutput& title, const tOutput& message, REAL timeout )
01482 {
01483 tOutput message2 ( message );
01484
01485 if ( sn_DenyReason.Len() > 2 )
01486 {
01487 message2.AddLiteral("\n\n");
01488 message2.AddLocale("network_kill_preface");
01489 message2.AddLiteral("\n");
01490 message2.AddLiteral(sn_DenyReason);
01491 }
01492
01493 nServerInfoBase * redirect = sn_PeekRedirectTo();
01494 if ( redirect )
01495 {
01496 message2.Append( tOutput( "$network_redirect", redirect->GetConnectionName(), (int)redirect->GetPort() ) );
01497 }
01498
01499 return tConsole::Message( title, message2, timeout );
01500 }
01501
01502
01503 class gSettingsReverter
01504 {
01505 public:
01506 gSettingsReverter()
01507 {
01508
01509 nConfItemBase::s_SaveValues();
01510 nConfItemBase::s_RevertToDefaults();
01511 }
01512
01513 ~gSettingsReverter()
01514 {
01515
01516 nConfItemBase::s_RevertToSavedValues();
01517 }
01518 };
01519
01520
01521 void sg_Receive()
01522 {
01523 sn_Receive();
01524 if ( sn_GetNetState() == nSERVER )
01525 {
01526
01527
01528 sn_DiscardFromControlSocket();
01529 }
01530 }
01531
01532
01533 bool ConnectToServerCore(nServerInfoBase *server)
01534 {
01535 tASSERT( server );
01536
01537 ePlayerNetID::ClearAll();
01538
01539
01540 gSettingsReverter reverter;
01541
01542 sn_bigBrotherString = renderer_identification;
01543
01544 nNetObject::ClearAll();
01545
01546 just_connected=true;
01547
01548 rViewport::Update(MAX_PLAYERS);
01549
01550
01551 #ifndef DEDICATED
01552 rSysDep::SwapGL();
01553 rSysDep::ClearGL();
01554 rSysDep::SwapGL();
01555 rSysDep::ClearGL();
01556 #endif
01557
01558 sr_con.autoDisplayAtNewline=true;
01559 sr_con.fullscreen=true;
01560
01561 bool to=sr_textOut;
01562 sr_textOut=true;
01563
01564 tOutput o;
01565
01566 nConnectError error = nOK;
01567
01568 nNetObject::ClearAll();
01569
01570 o.SetTemplateParameter(1, server->GetName());
01571 o << "$network_connecting_to_server";
01572 con << o;
01573 error = server->Connect();
01574
01575 switch (error)
01576 {
01577 case nABORT:
01578 return false;
01579 break;
01580 case nOK:
01581 break;
01582 case nTIMEOUT:
01583 sg_NetworkError("$network_message_timeout_title", "$network_message_timeout_inter", 20);
01584 return false;
01585 break;
01586
01587 case nDENIED:
01588 sg_NetworkError("$network_message_denied_title", sn_DenyReason.Len() > 2 ? "$network_message_denied_inter2" : "$network_message_denied_inter", 20);
01589 return false;
01590 break;
01591 }
01592
01593
01594
01595 if (sn_GetNetState()==nCLIENT){
01596 REAL endTime=tSysTimeFloat()+30;
01597 con << tOutput("$network_connecting_gamestate");
01598 while (!sg_currentGame && tSysTimeFloat()<endTime && (sn_GetNetState() != nSTANDALONE)){
01599 tAdvanceFrame();
01600 sg_Receive();
01601 nNetObject::SyncAll();
01602 tAdvanceFrame();
01603 sn_SendPlanned();
01604 st_DoToDo();
01605
01606 #ifndef DEDICATED
01607 rSysDep::SwapGL();
01608 rSysDep::ClearGL();
01609 #endif
01610
01611 sn_Delay();
01612 }
01613 if (sg_currentGame){
01614 sr_con.autoDisplayAtNewline=false;
01615 sr_con.fullscreen=false;
01616
01617 con << tOutput("$network_syncing_gamestate");
01618 sg_EnterGame( nCLIENT );
01619 }
01620 else{
01621
01622 sg_NetworkError("$network_message_lateto_title", "$network_message_lateto_inter", 20);
01623 }
01624 }
01625
01626 bool ret = true;
01627
01628 if (!sg_RequestedDisconnection && !uMenu::quickexit)
01629 switch (sn_GetLastError())
01630 {
01631 case nOK:
01632 ret = sg_NetworkError("$network_message_abortconn_title",
01633 "$network_message_abortconn_inter", 20);
01634 break;
01635 default:
01636 ret = sg_NetworkError("$network_message_lostconn_title",
01637 "$network_message_lostconn_inter", 20);
01638 break;
01639 }
01640
01641 sr_con.autoDisplayAtNewline=false;
01642 sr_con.fullscreen=false;
01643
01644 sn_SetNetState(nSTANDALONE);
01645
01646 sg_currentGame = NULL;
01647 nNetObject::ClearAll();
01648 ePlayerNetID::ClearAll();
01649
01650 sr_textOut=to;
01651
01652 return ret;
01653 }
01654
01655 void ConnectToServer(nServerInfoBase *server)
01656 {
01657 bool okToRedirect = ConnectToServerCore( server );
01658
01659
01660
01661
01662
01663 while( okToRedirect )
01664 {
01665 std::auto_ptr< nServerInfoBase > redirectTo( sn_GetRedirectTo() );
01666
01667
01668 if ( !(&(*redirectTo)) )
01669 {
01670 break;
01671 }
01672
01673 okToRedirect = ConnectToServerCore( redirectTo.get() );
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694 }
01695 }
01696
01697 static tConfItem<int> mor("MAX_OUT_RATE",sn_maxRateOut);
01698 static tConfItem<int> mir("MAX_IN_RATE",sn_maxRateIn);
01699
01700
01701 static tConfItem<int> pc("PING_CHARITY",pingCharity);
01702
01703
01704 uMenu *sg_IngameMenu=NULL;
01705 uMenu *sg_HostMenu =NULL;
01706
01707 void ret_to_MainMenu(){
01708 sg_RequestedDisconnection = true;
01709
01710 if (sg_HostMenu)
01711 sg_HostMenu->Exit();
01712
01713 if (sg_IngameMenu)
01714 sg_IngameMenu->Exit();
01715
01716 sr_con.fullscreen=true;
01717 sr_con.autoDisplayAtNewline=true;
01718
01719 if (sg_currentGame)
01720 sg_currentGame->NoLongerGoOn();
01721
01722 sn_SetNetState(nSTANDALONE);
01723
01724 uMenu::SetIdle(NULL);
01725 }
01726
01727
01728
01729 void net_options(){
01730 uMenu net_menu("$network_opts_text");
01731
01732 uMenuItemInt high_port
01733 (&net_menu,"$network_opts_maxport_text",
01734 "$network_opts_maxport_help",
01735 gServerBrowser::highPort,1024,65536);
01736
01737 uMenuItemInt low_port
01738 (&net_menu,"$network_opts_minport_text",
01739 "$network_opts_minport_help",
01740 gServerBrowser::lowPort,1024,65536);
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 uMenuItemInt out_rate
01772 (&net_menu,"$network_opts_outrate_text",
01773 "$network_opts_outrate_help",
01774 sn_maxRateOut,1,20);
01775
01776
01777 uMenuItemInt in_rate
01778 (&net_menu,"$network_opts_inrate_text",
01779 "$network_opts_inrate_help",
01780 sn_maxRateIn,1,20);
01781
01782
01783 uMenuItemToggle po2
01784 (&net_menu,"$network_opts_predict_text",
01785 "$network_opts_predict_help",
01786 sr_predictObjects);
01787
01788 uMenuItemToggle lm2
01789 (&net_menu,"$network_opts_lagometer_text",
01790 "$network_opts_lagometer_help",
01791 sr_laggometer);
01792
01793 uMenuItemToggle ai
01794 (&net_menu,"$network_opts_axesindicator_text",
01795 "$network_opts_axesindicator_help",
01796 sg_axesIndicator);
01797
01798
01799 uMenuItemInt p_s
01800 (&net_menu,"$network_opts_pingchar_text",
01801 "$network_opts_pingchar_help",
01802 pingCharity,0,300,20);
01803
01804 net_menu.Enter();
01805
01806 if (gServerBrowser::lowPort > gServerBrowser::highPort)
01807 gServerBrowser::highPort = gServerBrowser::lowPort;
01808 }
01809
01810 void sg_HostGameMenu(){
01811 uMenu net_menu("$network_host_text");
01812
01813 sg_HostMenu = &net_menu;
01814
01815 uMenuItemInt port(&net_menu, "$network_host_port_text",
01816 "$network_host_port_help"
01817 ,reinterpret_cast<int &>(sn_serverPort), gServerBrowser::lowPort, gServerBrowser::highPort);
01818
01819 uMenuItemString serverName
01820 (&net_menu,"$network_host_name_text",
01821 "$network_host_name_help",
01822 sn_serverName);
01823
01824 uMenuItemFunction settings1
01825 (&net_menu,
01826 "$game_settings_menu_text",
01827 "$game_settings_menu_help",
01828 &GameSettingsMP);
01829
01830 uMenuItemFunction serv
01831 (&net_menu,"$network_host_host_text",
01832 "$network_host_host_help",&sg_HostGame);
01833
01834 net_menu.ReverseItems();
01835 net_menu.SetSelected(0);
01836 net_menu.Enter();
01837
01838 sg_HostMenu = NULL;
01839 }
01840
01841 #ifndef DEDICATED
01842 class gNetIdler: public rSysDep::rNetIdler
01843 {
01844 public:
01845 virtual bool Wait()
01846 {
01847 return sn_BasicNetworkSystem.Select( 0.1 );
01848 }
01849 virtual void Do()
01850 {
01851 tAdvanceFrame();
01852 sg_Receive();
01853 sn_SendPlanned();
01854 }
01855 };
01856 #endif
01857
01858 void net_game(){
01859 #ifndef DEDICATED
01860 uMenu net_menu("$network_menu_text");
01861
01862 uMenuItemFunction cust
01863 (&net_menu,"$network_custjoin_text",
01864 "$network_custjoin_help",&gServerFavorites::CustomConnectMenu);
01865
01866 uMenuItemFunction mas
01867 (&net_menu,"$masters_menu",
01868 "$masters_menu_help",&gServerFavorites::AlternativesMenu);
01869
01870 uMenuItemFunction fav
01871 (&net_menu,"$bookmarks_menu",
01872 "$bookmarks_menu_help",&gServerFavorites::FavoritesMenu);
01873
01874 uMenuItemFunction bud
01875 (&net_menu,"$friends_menu",
01876 "$friends_menu_help",&gFriends::FriendsMenu);
01877
01878 uMenuItemFunction opt
01879 (&net_menu,"$network_opts_text",
01880 "$network_opts_help",&net_options);
01881
01882
01883
01884
01885
01886
01887
01888 uMenuItemFunction inter
01889 (&net_menu,"$network_menu_internet_text",
01890 "$network_menu_internet_help",&gServerBrowser::BrowseMaster);
01891
01892 uMenuItemFunction lan
01893 (&net_menu,"$network_menu_lan_text",
01894 "$network_menu_lan_help",&gServerBrowser::BrowseLAN);
01895
01896 gNetIdler idler;
01897
01898 net_menu.Enter();
01899 rSysDep::StopNetSyncThread();
01900 #endif
01901 }
01902
01903
01904
01905 static void StartNewMatch(){
01906 if (sg_currentGame)
01907 sg_currentGame->StartNewMatch();
01908 if (sn_GetNetState()!=nCLIENT){
01909 sn_CenterMessage("$gamestate_reset_center");
01910 sn_ConsoleOut("$gamestate_reset_console");
01911 }
01912 }
01913
01914 static void StartNewMatch_conf(std::istream &){
01915 StartNewMatch();
01916 }
01917
01918 static tConfItemFunc snm("START_NEW_MATCH",&StartNewMatch_conf);
01919
01920 #ifdef DEDICATED
01921 static void Quit_conf(std::istream &){
01922
01923 if ( sg_currentGame )
01924 {
01925 sg_currentGame->NoLongerGoOn();
01926 }
01927
01928
01929 tRecorder::Playback("END");
01930 tRecorder::Record("END");
01931 uMenu::quickexit = true;
01932 }
01933
01934 static tConfItemFunc quit_conf("QUIT",&Quit_conf);
01935 static tConfItemFunc exit_conf("EXIT",&Quit_conf);
01936 #endif
01937
01938 void st_PrintPathInfo(tOutput &buf);
01939
01940 static void PlayerLogIn()
01941 {
01942 ePlayer::LogIn();
01943
01944 if ( sg_IngameMenu )
01945 {
01946 sg_IngameMenu->Exit();
01947 }
01948
01949 con << tOutput( "$player_authenticate_action" );
01950 }
01951
01952 void sg_DisplayVersionInfo() {
01953 tOutput versionInfo;
01954 versionInfo << "$version_info_version" << "\n";
01955 st_PrintPathInfo(versionInfo);
01956 versionInfo << "$version_info_misc_stuff";
01957 sg_FullscreenMessage("$version_info_title", versionInfo, 1000);
01958 }
01959
01960 void MainMenu(bool ingame){
01961
01962
01963 if (ingame)
01964 sr_con.SetHeight(2);
01965
01966
01967
01968 tOutput gametitle;
01969 if (!ingame)
01970 gametitle << "$game_menu_text";
01971 else
01972 gametitle << "$game_menu_ingame_text";
01973
01974 uMenu game_menu(gametitle);
01975
01976 uMenuItemFunction *reset=NULL;
01977
01978 if (ingame && sn_GetNetState()!=nCLIENT){
01979 reset=new uMenuItemFunction
01980 (&game_menu,"$game_menu_reset_text",
01981 "$game_menu_reset_help",
01982 &StartNewMatch);
01983 }
01984
01985 uMenuItemFunction *settings1=NULL;
01986
01987 if (!ingame)
01988 settings1=tNEW(uMenuItemFunction)
01989 (&game_menu,
01990 "$game_settings_menu_text",
01991 "$game_settings_menu_help",
01992 &GameSettingsSP);
01993 else
01994 settings1=tNEW(uMenuItemFunction)
01995 (&game_menu,
01996 "$game_settings_menu_text",
01997 "$game_settings_menu_help",
01998 &GameSettingsCurrent);
01999
02000 uMenuItemFunction *connect=NULL,*start=NULL,*sound=NULL;
02001
02002 if (!ingame){
02003 connect=new uMenuItemFunction
02004 (&game_menu,
02005 "$network_menu_text",
02006 "$network_menu_help",
02007 &net_game);
02008
02009 start= new uMenuItemFunction(&game_menu,"$game_menu_start_text",
02010 "$game_menu_start_help",&singlePlayer_game);
02011 }
02012
02013 tOutput title;
02014 title.SetTemplateParameter( 1, sn_programVersion );
02015 if (!ingame)
02016 title << "$main_menu_text";
02017 else
02018 title << "$ingame_menu_text";
02019
02020 uMenu MainMenu(title,false);
02021
02022 if (ingame)
02023 sg_IngameMenu = &MainMenu;
02024
02025 char const * extitle,* exhelp;
02026 if (!ingame){
02027 extitle="$main_menu_exit_text";
02028 exhelp="$main_menu_exit_help";
02029 }
02030 else{
02031 extitle="$ingame_menu_exit_text";
02032 exhelp="$ingame_menu_exit_help";
02033 }
02034
02035 uMenuItemExit exx(&MainMenu,extitle,
02036 exhelp);
02037
02038 uMenuItemFunction *return_to_main=NULL;
02039 if (ingame){
02040 if (sn_GetNetState()==nSTANDALONE)
02041 return_to_main=new uMenuItemFunction
02042 (&MainMenu,"$game_menu_exit_text",
02043 "$game_menu_exit_help",
02044 &ret_to_MainMenu);
02045 else if (sn_GetNetState()==nCLIENT)
02046 return_to_main=new uMenuItemFunction
02047 (&MainMenu,"$game_menu_disconnect_text",
02048 "$game_menu_disconnect_help",
02049 &ret_to_MainMenu);
02050 else
02051 return_to_main=new uMenuItemFunction
02052 (&MainMenu,
02053 "$game_menu_shutdown_text",
02054 "game_menu_shutdown_help",
02055 &ret_to_MainMenu);
02056 }
02057
02058 uMenuItemFunction * auth = 0;
02059 static nVersionFeature authentication( 15 );
02060 if ( sn_GetNetState() == nCLIENT && ingame && authentication.Supported(0) )
02061 {
02062 auth =tNEW(uMenuItemFunction)(&MainMenu,
02063 "$player_authenticate_text",
02064 "$player_authenticate_help",
02065 &PlayerLogIn );
02066 }
02067
02068 uMenuItemFunction abb(&MainMenu,
02069 "$main_menu_about_text",
02070 "$main_menu_about_help",
02071 &sg_DisplayVersionInfo);
02072
02073
02074 uMenu Settings("$system_settings_menu_text");
02075
02076 uMenuItemSubmenu subm_settings
02077 (&MainMenu,&Settings,
02078 "$system_settings_menu_help");
02079
02080
02081 uMenuItem* team = NULL;
02082 if ( ingame )
02083 {
02084 team = tNEW( uMenuItemFunction) ( &MainMenu,
02085 "$team_menu_title",
02086 "$team_menu_help",
02087 &gTeam::TeamMenu );
02088 }
02089
02090 uMenuItemFunction *se_PlayerMenu=NULL;
02091
02092
02093 se_PlayerMenu= new uMenuItemFunction
02094 (&MainMenu,"$player_mainmenu_text",
02095 "$player_mainmenu_help",
02096 &sg_PlayerMenu);
02097
02098 uMenuItemFunction *player_police=NULL;
02099 uMenuItemFunction *voting=NULL;
02100 if ( ingame && sn_GetNetState() != nSTANDALONE )
02101 {
02102 player_police = tNEW( uMenuItemFunction )( &MainMenu, "$player_police_text", "$player_police_help", ePlayerNetID::PoliceMenu );
02103
02104 if ( eVoter::VotingPossible() )
02105 voting = tNEW( uMenuItemFunction )( &MainMenu, "$voting_menu_text", "$voting_menu_help", eVoter::VotingMenu );
02106 }
02107
02108 uMenu misc("$misc_menu_text");
02109
02110
02111
02112 uMenuItemFunction language
02113 (&misc,"$language_menu_title",
02114 "$language_menu_help",
02115 &sg_LanguageMenu);
02116
02117 uMenuItemFunction global_key
02118 (&misc,"$misc_global_key_text",
02119 "$misc_global_key_help",
02120 &su_InputConfigGlobal);
02121
02122 uMenuItemToggle wrap
02123 (&misc,"$misc_menuwrap_text",
02124 "$misc_menuwrap_help",
02125 uMenu::wrap);
02126
02127 uMenuItemToggle to2
02128 (&misc,"$misc_textout_text",
02129 "$misc_textout_help",sr_textOut);
02130
02131
02132
02133 uMenuItemToggle mp
02134 (&misc,"$misc_moviepack_text",
02135 "$misc_moviepack_help",sg_moviepackUse);
02136
02137
02138 uMenuItemSubmenu misc_sm
02139 (&Settings,&misc,
02140 "$misc_menu_help");
02141
02142 sound = new uMenuItemFunction
02143 (&Settings,"$sound_menu_text",
02144 "$sound_menu_help",&se_SoundMenu);
02145
02146 uMenuItemSubmenu subm
02147 (&Settings,&sg_screenMenu,
02148 "$display_settings_menu_help");
02149
02150 uMenuItemSubmenu *gamemenuitem = NULL;
02151 if (sn_GetNetState() != nCLIENT)
02152 {
02153 char const * gamehelp;
02154 if (!ingame)
02155 gamehelp="$game_menu_main_help";
02156 else
02157 gamehelp="$game_menu_ingame_help";
02158
02159 gamemenuitem = tNEW(uMenuItemSubmenu) (&MainMenu,
02160 &game_menu,
02161 gamehelp
02162 );
02163 }
02164
02165 if (!ingame)
02166 {
02167 rViewport::Update(MAX_PLAYERS);
02168
02169 }
02170
02171 MainMenu.Enter();
02172
02173 if (settings1)
02174 delete settings1;
02175 if (team)
02176 delete team;
02177 if (gamemenuitem)
02178 delete gamemenuitem;
02179 if (sound)
02180 delete sound;
02181 if (connect)
02182 delete connect;
02183 if (start)
02184 delete start;
02185 if (return_to_main)
02186 delete return_to_main;
02187 if (se_PlayerMenu)
02188 delete se_PlayerMenu;
02189 if (reset)
02190 delete reset;
02191 if ( player_police )
02192 delete player_police;
02193 if ( voting )
02194 delete voting;
02195
02196 if (ingame)
02197 sg_IngameMenu=NULL;
02198
02199 if (ingame)
02200 {
02201 gLogo::SetDisplayed(false);
02202 sr_con.SetHeight(7);
02203 }
02204
02205 if ( auth )
02206 {
02207 delete auth;
02208 }
02209 }
02210
02211
02212
02213
02214
02215 #define GS_CREATED 0 // newborn baby
02216 #define GS_TRANSFER_SETTINGS 7
02217 #define GS_CREATE_GRID 10
02218 #define GS_CREATE_OBJECTS 20
02219 #define GS_TRANSFER_OBJECTS 30
02220 #define GS_CAMERA 35
02221 #define GS_SYNCING 40
02222 #define GS_SYNCING2 41
02223 #define GS_SYNCING3 42
02224 #define GS_PLAY 50
02225 #define GS_DELETE_OBJECTS 60
02226 #define GS_DELETE_GRID 70
02227 #define GS_STATE_MAX 80
02228
02229 static bool sg_AbeforeB( int stateA, int stateB )
02230 {
02231 return ( ( GS_STATE_MAX + stateA - stateB ) % GS_STATE_MAX > GS_STATE_MAX >> 2 );
02232 }
02233
02234 #ifndef DEDICATED
02235 static void ingame_menu_cleanup();
02236 static void ingame_menu()
02237 {
02238
02239 try
02240 {
02241 se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
02242 if (sn_GetNetState()==nSTANDALONE)
02243 se_PauseGameTimer(true);
02244 MainMenu(true);
02245 }
02246 catch ( ... )
02247 {
02248 ingame_menu_cleanup();
02249 ret_to_MainMenu();
02250 sg_IngameMenu=NULL;
02251 sg_HostMenu=NULL;
02252 throw;
02253 }
02254 ingame_menu_cleanup();
02255 }
02256
02257 static void ingame_menu_cleanup()
02258 {
02259 if (sn_GetNetState()==nSTANDALONE)
02260 se_PauseGameTimer(false);
02261 se_ChatState(ePlayerNetID::ChatFlags_Menu, false);
02262 if ((bool(sg_currentGame) && sg_currentGame->GetState()!=GS_PLAY))
02263
02264 {
02265 rViewport::Update(MAX_PLAYERS);
02266 ePlayerNetID::Update();
02267 }
02268
02269 }
02270 #endif
02271
02272
02273 static nNOInitialisator<gGame> game_init(310,"game");
02274
02275 nDescriptor &gGame::CreatorDescriptor() const{
02276 return game_init;
02277 }
02278
02279
02280 void gGame::Init(){
02281 m_Mixer = eSoundMixer::GetMixer();
02282 grid = tNEW(eGrid());
02283 state=GS_CREATED;
02284 stateNext=GS_TRANSFER_SETTINGS;
02285 goon=true;
02286
02287 sg_currentGame=this;
02288 #ifdef DEBUG
02289
02290 #endif
02291 aParser = tNEW(gParser)(&Arena, grid);
02292
02293 rounds = 0;
02294 StartNewMatchNow();
02295 }
02296
02297
02298 void gGame::NoLongerGoOn(){
02299 goon=false;
02300
02301 if (sn_GetNetState()==nSERVER)
02302 RequestSync();
02303 }
02304
02305
02306 class gMapLoadConsoleFilter:public tConsoleFilter{
02307 public:
02308 gMapLoadConsoleFilter()
02309 {
02310 }
02311
02312 ~gMapLoadConsoleFilter()
02313 {
02314 }
02315
02316 tColoredString message_;
02317 private:
02318
02319 virtual int DoGetPriority() const{
02320 return -100;
02321 }
02322
02323
02324 virtual void DoFilterLine( tString &line )
02325 {
02326 message_ << line << "\n";
02327 }
02328 };
02329
02330 static void sg_ParseMap ( gParser * aParser, tString mapfile )
02331 {
02332 {
02333 gMapLoadConsoleFilter consoleLog;
02334 #ifdef DEBUG
02335 con << "Loading map " << mapfile << "...\n";
02336 #endif
02337 if (!aParser->LoadWithoutParsing(mapfile))
02338 {
02339 tOutput errorMessage( sn_GetNetState() == nCLIENT ? "$map_file_load_failure_server" : "$map_file_load_failure_self", mapfile );
02340
02341 #ifndef DEDICATED
02342 errorMessage << "\nLog:\n" << consoleLog.message_;
02343 #endif
02344
02345 con << errorMessage;
02346
02347 tOutput errorTitle("$map_file_load_failure_title");
02348
02349 if ( sn_GetNetState() != nSTANDALONE )
02350 {
02351 throw tGenericException( errorMessage, errorTitle );
02352 }
02353
02354 if (!aParser->LoadWithoutParsing(DEFAULT_MAP)) {
02355 errorMessage << "$map_file_load_failure_default";
02356 throw tGenericException( errorMessage, errorTitle );
02357 }
02358 }
02359 }
02360 }
02361
02362 static void sg_ParseMap ( gParser * aParser )
02363 {
02364 sg_ParseMap(aParser, mapfile);
02365 }
02366
02367 void gGame::Verify()
02368 {
02369
02370 sg_ParseMap( aParser );
02371 init_game_grid(grid, aParser);
02372 exit_game_grid(grid);
02373 }
02374
02375 gGame::gGame(){
02376 synced_ = true;
02377 gLogo::SetDisplayed(false);
02378 if (sn_GetNetState()!=nCLIENT)
02379 RequestSync();
02380 Init();
02381 }
02382
02383 gGame::gGame(nMessage &m):nNetObject(m){
02384 synced_ = false;
02385 Init();
02386 }
02387
02388
02389 gGame::~gGame(){
02390 #ifdef DEBUG
02391
02392 #endif
02393
02394
02395
02396 tASSERT( sg_currentGame != this );
02397
02398 exit_game_objects(grid);
02399 grid->Clear();
02400 ePlayerNetID::ThrowOutDisconnected();
02401
02402 delete aParser;
02403 }
02404
02405
02406 void gGame::WriteSync(nMessage &m){
02407 nNetObject::WriteSync(m);
02408 m.Write(stateNext);
02409 #ifdef DEBUG
02410
02411 #endif
02412 }
02413
02414 void gGame::ReadSync(nMessage &m){
02415 nNetObject::ReadSync(m);
02416
02417 unsigned short newState;
02418 m.Read(newState);
02419
02420 #ifdef DEBUG
02421 con << "Read gamestate " << newState << ".\n";
02422 #endif
02423
02424
02425 if ( sg_AbeforeB( stateNext, newState ) )
02426 stateNext = newState;
02427
02428 #ifdef DEBUG
02429
02430 #endif
02431 }
02432
02433
02434 void gGame::NetSync(){
02435
02436 if ( tRecorder::Playback("END") )
02437 {
02438 tRecorder::Record("END");
02439 uMenu::quickexit=true;
02440 }
02441
02442 #ifdef DEDICATED
02443 if (!sr_glOut && ePlayer::PlayerConfig(0)->cam)
02444 tERR_ERROR_INT("Someone messed with the camera!");
02445 #endif
02446 sg_Receive();
02447 nNetObject::SyncAll();
02448 tAdvanceFrame();
02449 sn_SendPlanned();
02450 }
02451
02452 void gGame::NetSyncIdle(){
02453 NetSync();
02454 sn_Delay();
02455 }
02456
02457 unsigned short client_gamestate[MAXCLIENTS+2];
02458
02459 static void client_gamestate_handler(nMessage &m){
02460 unsigned short state;
02461 m.Read( state );
02462 client_gamestate[m.SenderID()] = state;
02463 #ifdef DEBUG
02464
02465 #endif
02466 }
02467
02468 static nDescriptor client_gs(311,client_gamestate_handler,"client_gamestate");
02469
02470
02471
02472 void gGame::SyncState(unsigned short state){
02473 if (sn_GetNetState()==nSERVER){
02474
02475 bool firsttime=true;
02476 bool goon=true;
02477 REAL timeout=tSysTimeFloat()+sg_Timeout*.1;
02478
02479 sn_Sync(sg_Timeout*.1,true);
02480 NetSyncIdle();
02481
02482 while (goon && tSysTimeFloat()<timeout){
02483
02484
02485
02486
02487
02488 sn_Sync(sg_Timeout*.1,true);
02489 NetSyncIdle();
02490
02491 goon=false;
02492 for (int i=MAXCLIENTS;i>0;i--)
02493 if ( sn_Connections[i].socket )
02494 {
02495 int clientState = client_gamestate[i];
02496 if ( sg_AbeforeB( clientState, state ) )
02497 {
02498 goon=true;
02499 }
02500 }
02501 if (goon && firsttime){
02502 firsttime=false;
02503 #ifdef DEBUG
02504 con << "Waiting for users to enter gamestate " << state << '\n';
02505 if (sn_Connections[1].ackPending>2)
02506 con << "Ack_pending=" << sn_Connections[1].ackPending << ".\n";
02507 #endif
02508 }
02509 }
02510 }
02511 }
02512
02513
02514 void gGame::SetState(unsigned short act,unsigned short next){
02515 state=act;
02516 #ifdef DEBUG
02517
02518
02519 #endif
02520
02521 if (sn_GetNetState()==nSERVER){
02522 RequestSync();
02523 NetSyncIdle();
02524 SyncState(state);
02525 }
02526
02527 if (stateNext!=next){
02528 if (sn_GetNetState()!=nCLIENT || goon==false){
02529
02530 stateNext=next;
02531
02532 if (sn_GetNetState()==nSERVER){
02533 RequestSync();
02534 NetSyncIdle();
02535 }
02536 }
02537 }
02538 }
02539
02540
02541 extern REAL planned_rate_control[MAXCLIENTS+2];
02542 extern REAL sent_per_messid[100];
02543
02544 static REAL lastdeath=0;
02545 static bool roundOver=false;
02546
02547 static void sg_VoteMenuIdle()
02548 {
02549 if ( !uMenu::MenuActive() )
02550 {
02551 se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
02552 eVoter::VotingMenu();
02553 se_ChatState( ePlayerNetID::ChatFlags_Menu, false );
02554 }
02555 }
02556
02557 void gGame::StateUpdate(){
02558
02559
02560
02561
02562 while ( sg_AbeforeB( state, stateNext ) && goon )
02563 {
02564 #ifdef CONNECTION_STRESS
02565 if ( sg_ConnectionStress )
02566 {
02567 tRandomizer & randomizer = tRandomizer::GetInstance();
02568 int random = randomizer.Get( 16 );
02569 if ( random == 0 )
02570 {
02571 sg_RequestedDisconnection = true;
02572
02573 goon = false;
02574 }
02575
02576 se_ChatState( ePlayerNetID::ChatFlags_Away, 1 );
02577 }
02578 #endif
02579
02580
02581
02582 switch (state){
02583 case GS_DELETE_GRID:
02584
02585
02586 con << tOutput("$gamestate_deleting_grid");
02587
02588 sn_CenterMessage(sg_roundCenterMessage);
02589
02590
02591
02592 exit_game_objects(grid);
02593 nNetObject::ClearAllDeleted();
02594
02595 if (goon)
02596 SetState(GS_TRANSFER_SETTINGS,GS_CREATE_GRID);
02597 else
02598 state=GS_CREATE_GRID;
02599 break;
02600 case GS_CREATED:
02601 case GS_TRANSFER_SETTINGS:
02602
02603
02604
02605 if ( nCLIENT != sn_GetNetState() )
02606 {
02607 update_settings();
02608 ePlayerNetID::RemoveChatbots();
02609 }
02610
02611 rViewport::Update(MAX_PLAYERS);
02612
02613
02614 ePlayerNetID::LogScoreDifferences();
02615 se_SaveToLadderLog(tString("NEW_ROUND\n"));
02616 se_sendEventNotification(tString("New Round"), tString("Starting a new round"));
02617
02618
02619 nMachine::KickSpectators();
02620
02621
02622 if ( synced_ && sn_GetNetState() != nSERVER )
02623 ePlayerNetID::Update();
02624
02625
02626 exit_game_objects(grid);
02627
02628 nConfItemBase::s_SendConfig(false);
02629
02630
02631
02632 sn_Sync( sg_Timeout*.4, true );
02633
02634 SetState(GS_CREATE_GRID,GS_CAMERA);
02635 break;
02636
02637 case GS_CREATE_GRID:
02638
02639
02640 sg_ParseMap( aParser );
02641
02642 sn_Statistics();
02643 sg_Timestamp();
02644
02645 con << tOutput("$gamestate_creating_grid");
02646
02647 tAdvanceFrame();
02648
02649 init_game_grid(grid, aParser);
02650
02651 nNetObject::ClearAllDeleted();
02652
02653 SetState(GS_CREATE_OBJECTS,GS_CAMERA);
02654 break;
02655 case GS_CREATE_OBJECTS:
02656
02657
02658 lastdeath = -100;
02659 roundOver = false;
02660
02661
02662 if ( synced_ )
02663 ePlayerNetID::Update();
02664
02665 init_game_objects(grid);
02666
02667 ePlayerNetID::RankingLadderLog();
02668
02669
02670 {
02671 const tList<eGameObject>& gameObjects = Grid()->GameObjects();
02672 for (int i=gameObjects.Len()-1;i>=0;i--)
02673 {
02674 eGameObject * e = gameObjects(i);
02675 if ( e )
02676 {
02677 e->OnRoundBegin();
02678 }
02679 }
02680 }
02681
02682
02683 Analysis( -1000 );
02684
02685 s_Timestep(grid, se_GameTime(), false);
02686 SetState(GS_TRANSFER_OBJECTS,GS_CAMERA);
02687
02688 if (sn_GetNetState() == nCLIENT && just_connected){
02689 sn_Sync(sg_Timeout*.1,true);
02690 sn_Sync(sg_Timeout*.1,true);
02691 }
02692 just_connected=false;
02693
02694 #ifdef ENABLE_ZONESV2
02695 init_second_pass_zones(grid, aParser);
02696 #endif
02697 break;
02698 case GS_TRANSFER_OBJECTS:
02699
02700 rITexture::LoadAll();
02701
02702
02703
02704
02705
02706 if (sn_GetNetState()==nSERVER){
02707 bool goon=true;
02708 double timeout=tSysTimeFloat()+sg_Timeout*.4;
02709 while (goon && tSysTimeFloat()<timeout){
02710 NetSyncIdle();
02711 goon=false;
02712 for (int i=MAXCLIENTS;i>0;i--)
02713 if (sn_Connections[i].socket)
02714 for (int j=sn_netObjects.Len()-1;j>=0;j--)
02715 if (sn_netObjects(j) &&
02716 !sn_netObjects(j)->HasBeenTransmitted(i) &&
02717 sn_netObjects(j)->syncRequested(i))
02718 goon=true;
02719 }
02720 if (tSysTimeFloat()<timeout)
02721 con << tOutput("$gamestate_done");
02722 else{
02723 con << tOutput("$gamestate_timeout_intro");
02724 for (int i=MAXCLIENTS;i>0;i--)
02725 if (sn_Connections[i].socket)
02726 for (int j=sn_netObjects.Len()-1;j>=0;j--)
02727 if (sn_netObjects(j) && !sn_netObjects(j)->HasBeenTransmitted(i))
02728 {
02729 tOutput o;
02730 tString name;
02731 sn_netObjects(j)->PrintName( name );
02732 o.SetTemplateParameter(1, i);
02733 o.SetTemplateParameter(2, j);
02734 o.SetTemplateParameter(3, name);
02735 o << "$gamestate_timeout_message";
02736 con << o;
02737 }
02738 con << "\n\n\n";
02739 }
02740 }
02741
02742
02743 if ( sn_GetNetState() == nSERVER )
02744 while ( ePlayerNetID::WaitToLeaveChat() )
02745 {
02746 NetSyncIdle();
02747 se_SyncGameTimer();
02748 }
02749
02750 SetState(GS_CAMERA,GS_SYNCING);
02751 break;
02752 case GS_CAMERA:
02753
02754 rITexture::LoadAll();
02755
02756
02757 init_game_camera(grid);
02758 SetState(GS_SYNCING,GS_PLAY);
02759 break;
02760 case GS_SYNCING:
02761
02762 rITexture::LoadAll();
02763 SetState(GS_PLAY,GS_PLAY);
02764 if (sn_GetNetState()!=nCLIENT){
02765 if (rounds<=0){
02766 sn_ConsoleOut("$gamestate_resetnow_console");
02767 StartNewMatchNow();
02768 sn_CenterMessage("$gamestate_resetnow_center");
02769 se_SaveToScoreFile("$gamestate_resetnow_log");
02770 }
02771
02772 tOutput mess;
02773 if (rounds < sg_currentSettings->limitRounds)
02774 {
02775 mess.SetTemplateParameter(1, rounds+1);
02776 mess.SetTemplateParameter(2, sg_currentSettings->limitRounds);
02777 mess << "$gamestate_newround_console";
02778
02779 if (strlen(sg_roundConsoleMessage) > 2)
02780 sn_ConsoleOut(sg_roundConsoleMessage + "\n");
02781 }
02782 else
02783 mess << "$gamestate_newround_goldengoal";
02784 sn_ConsoleOut(mess);
02785
02786 se_SaveToScoreFile("$gamestate_newround_log");
02787 }
02788
02789
02790 se_PauseGameTimer(false);
02791 se_SyncGameTimer();
02792 sr_con.fullscreen=false;
02793 sr_con.autoDisplayAtNewline=false;
02794
02795 break;
02796 case GS_PLAY:
02797 sr_con.autoDisplayAtNewline=false;
02798 #ifdef DEDICATED
02799 {
02800
02801 cp();
02802
02803 if ( sg_NumUsers() <= 0 )
02804 goon = 0;
02805
02806 Analysis(0);
02807
02808 {
02809 std::ifstream s;
02810
02811
02812 if ( tDirectories::Config().Open(s, "everytime.cfg" ) )
02813 tConfItemBase::LoadAll(s);
02814
02815 s.close();
02816
02817 if ( tDirectories::Var().Open(s, "everytime.cfg" ) )
02818 tConfItemBase::LoadAll(s);
02819
02820
02821 tConfItemBase::LoadPlayback();
02822 }
02823 }
02824 #endif
02825
02826 nPingAverager::SetWeight(1E-20);
02827
02828 se_UserShowScores(false);
02829
02830
02831 if (rotationtype == 1)
02832 rotate();
02833 gRotation::HandleNewRound();
02834
02835
02836 sr_con.fullscreen=true;
02837 SetState(GS_DELETE_OBJECTS,GS_DELETE_GRID);
02838 break;
02839 case GS_DELETE_OBJECTS:
02840
02841 winDeathZone_ = NULL;
02842
02843 rViewport::Update(MAX_PLAYERS);
02844 if ( synced_ && sn_GetNetState() != nSERVER )
02845 ePlayerNetID::Update();
02846
02847
02848
02849
02850
02851 con << tOutput("$gamestate_deleting_objects");
02852 exit_game_objects(grid);
02853 st_ToDo( sg_VoteMenuIdle );
02854 nNetObject::ClearAllDeleted();
02855 SetState(GS_DELETE_GRID,GS_TRANSFER_SETTINGS);
02856 break;
02857 default:
02858 break;
02859 }
02860
02861
02862 nAuthentication::OnBreak();
02863
02864 if (sn_GetNetState()==nSERVER){
02865 NetSyncIdle();
02866 RequestSync();
02867 NetSyncIdle();
02868 }
02869 else if (sn_GetNetState()==nCLIENT){
02870 NetSyncIdle();
02871 nMessage *m=new nMessage(client_gs);
02872 m->Write(state);
02873 m->Send(0);
02874 #ifdef DEBUG
02875
02876 #endif
02877 NetSyncIdle();
02878 }
02879 }
02880 }
02881
02882
02883
02884
02885 #ifdef RESPAWN_HACK
02886
02887 static void sg_Respawn( REAL time, eGrid *grid, gArena & arena )
02888 {
02889 for ( int i = se_PlayerNetIDs.Len()-1; i >= 0; --i )
02890 {
02891 ePlayerNetID *p = se_PlayerNetIDs(i);
02892
02893 if ( !p->CurrentTeam() )
02894 continue;
02895
02896 eGameObject *e=p->Object();
02897
02898 if ( ( !e || !e->Alive() && e->DeathTime() < time - .5 ) && sn_GetNetState() != nCLIENT )
02899 {
02900 sg_RespawnPlayer(time, grid, &arena, p);
02901 }
02902 }
02903 }
02904 #endif
02905
02906 void sg_RespawnPlayer(eGrid *grid, gArena *arena, ePlayerNetID *p)
02907 {
02908 eGameObject *e=p->Object();
02909
02910 if ( ( !e || !e->Alive()) && sn_GetNetState() != nCLIENT )
02911 {
02912 eCoord pos,dir;
02913 if ( e )
02914 {
02915 dir = e->Direction();
02916 pos = e->Position();
02917 eWallRim::Bound( pos, 1 );
02918 eCoord displacement = pos - e->Position();
02919 if ( displacement.NormSquared() > .01 )
02920 {
02921 dir = displacement;
02922 dir.Normalize();
02923 }
02924 }
02925 else
02926 arena->LeastDangerousSpawnPoint()->Spawn( pos, dir );
02927 #ifdef DEBUG
02928
02929 #endif
02930 gCycle * cycle = new gCycle(grid, pos, dir, p);
02931 p->ControlObject(cycle);
02932
02933 sg_Timestamp();
02934 }
02935 }
02936
02937 gArena * sg_GetArena() {
02938 return &Arena;
02939 }
02940
02941
02942 static REAL sg_timestepMax = .2;
02943 static tSettingItem<REAL> sg_timestepMaxConf( "TIMESTEP_MAX", sg_timestepMax );
02944 static int sg_timestepMaxCount = 10;
02945 static tSettingItem<int> sg_timestepMaxCountConf( "TIMESTEP_MAX_COUNT", sg_timestepMaxCount );
02946
02947 void gGame::Timestep(REAL time,bool cam){
02948 #ifdef DEBUG
02949 tMemManBase::Check();
02950 #endif
02951
02952 #ifdef RESPAWN_HACK
02953 sg_Respawn(time,grid,Arena);
02954 #endif
02955
02956
02957 REAL dt = time - lastTimeTimestep;
02958 if ( dt < 0 )
02959 return;
02960 REAL lt = lastTimeTimestep;
02961
02962
02963 int number_of_steps=int(fabs((dt)/sg_timestepMax));
02964 if (number_of_steps<1)
02965 number_of_steps=1;
02966 if ( number_of_steps > sg_timestepMaxCount )
02967 {
02968 number_of_steps = sg_timestepMaxCount;
02969 }
02970
02971
02972 for (int i=1;i<=number_of_steps;i++)
02973 {
02974 REAL stepTime = lt + i * dt/number_of_steps;
02975 s_Timestep(grid, stepTime, cam);
02976 }
02977 }
02978
02979
02980 static bool sg_EnemyExists( int team )
02981 {
02982
02983 for ( int i = eTeam::teams.Len()-1; i>= 0; --i )
02984 {
02985 if ( i != team && eTeam::Enemies( eTeam::teams[i], eTeam::teams[team] ) )
02986 return true;
02987 }
02988
02989 return false;
02990 }
02991
02992 static REAL sg_winZoneRandomness = .8;
02993 static tSettingItem< REAL > sg_winZoneSpreadConf( "WIN_ZONE_RANDOMNESS", sg_winZoneRandomness );
02994
02995 void gGame::Analysis(REAL time){
02996 if ( nCLIENT == sn_GetNetState() )
02997 return;
02998
02999 static REAL wintimer=0;
03000
03001
03002 {
03003 static double nextTime = -1;
03004 if ( tSysTimeFloat() > nextTime || time < -10 )
03005 {
03006 nextTime = tSysTimeFloat() + 1.0;
03007 }
03008 else
03009 {
03010 return;
03011 }
03012 }
03013
03014
03015
03016
03017 if (tSysTimeFloat()-startTime>10){
03018 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<10 && warning<6){
03019 tOutput o("$gamestate_tensecond_warn");
03020 sn_CenterMessage(o);
03021 sn_ConsoleOut(o);
03022 warning=6;
03023 }
03024
03025
03026 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<30 && warning<5){
03027 tOutput o("$gamestate_30seconds_warn");
03028 sn_CenterMessage(o);
03029 sn_ConsoleOut(o);
03030 warning=5;
03031 }
03032
03033 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<60 && warning<4){
03034 tOutput o("$gamestate_minute_warn");
03035 sn_CenterMessage(o);
03036 sn_ConsoleOut(o);
03037 warning=4;
03038 }
03039
03040 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<2*60 && warning<3){
03041 tOutput o("$gamestate_2minutes_warn");
03042 sn_ConsoleOut(o);
03043 warning=3;
03044 }
03045
03046 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<5*60 && warning<2){
03047 tOutput o("$gamestate_5minutes_warn");
03048 sn_ConsoleOut(o);
03049 warning=2;
03050 }
03051
03052 if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<10*60 && warning<1){
03053 tOutput o("$gamestate_10minutes_warn");
03054 sn_ConsoleOut(o);
03055 warning=1;
03056 }
03057 }
03058
03059
03060 int active = 0;
03061 int i;
03062 for (i=se_PlayerNetIDs.Len()-1;i>=0;i--){
03063 ePlayerNetID *pni=se_PlayerNetIDs(i);
03064 if (pni->IsActive())
03065 active ++;
03066 }
03067
03068
03069 int alive_and_not_disconnected = 0;
03070 int alive=0;
03071 int ai_alive=0;
03072 int human_teams=0;
03073 int teams_alive=0;
03074 int last_alive=-1;
03075 int last_team_alive=-1;
03076 int last_alive_and_not_disconnected=-1;
03077 int humans = 0;
03078 int active_humans = 0;
03079 int ais = 0;
03080 REAL deathTime=0;
03081
03082 bool notyetloggedin = true;
03083
03084 for (i=eTeam::teams.Len()-1;i>=0;i--){
03085 eTeam *t = eTeam::teams(i);
03086
03087 humans += t->NumHumanPlayers();
03088 ais += t->NumAIPlayers();
03089
03090 if ( t->Alive() )
03091 {
03092 teams_alive++;
03093 last_team_alive = i;
03094 }
03095
03096 if ( t->NumHumanPlayers() > 0 )
03097 {
03098 human_teams++;
03099
03100 for (int j=t->NumPlayers()-1; j>=0; --j)
03101 {
03102 ePlayerNetID* p = t->Player(j);
03103 if (p->IsActive())
03104 active_humans++;
03105
03106 gCycle *g=dynamic_cast<gCycle *>(p->Object());
03107 if (g){
03108 notyetloggedin = false;
03109
03110 if (g->Alive())
03111 {
03112
03113 if ( p->IsHuman() )
03114 {
03115 alive++;
03116 if (p->IsActive())
03117 {
03118 last_alive_and_not_disconnected=i;
03119 alive_and_not_disconnected++;
03120 }
03121 }
03122 else
03123 ai_alive++;
03124
03125 last_alive=i;
03126 }
03127 else
03128 {
03129 REAL dt=g->DeathTime();
03130 if (dt>deathTime)
03131 deathTime=dt;
03132 }
03133 }
03134 #ifdef KRAWALL_SERVER
03135 else if (p->IsAuthenticated())
03136 notyetloggedin = false;
03137 #endif
03138 }
03139 }
03140 else
03141 {
03142 for (int j=t->NumPlayers()-1; j>=0; --j)
03143 {
03144 ePlayerNetID* p = t->Player(j);
03145
03146 gCycle *g=dynamic_cast<gCycle *>(p->Object());
03147 if (g){
03148 if (g->Alive())
03149 {
03150 ai_alive++;
03151 }
03152 }
03153 }
03154 }
03155 }
03156
03157 #ifdef DEDICATED
03158
03159 if (sg_NumUsers() <= 0)
03160 goon = false;
03161 #endif
03162
03163
03164 if (last_alive_and_not_disconnected >= 0)
03165 last_alive = last_alive_and_not_disconnected;
03166
03167
03168 if ( alive_and_not_disconnected <= 1 && alive > alive_and_not_disconnected )
03169 {
03170 for (int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
03171 {
03172 gCycle *g=dynamic_cast<gCycle *>(se_PlayerNetIDs(i)->Object());
03173 if (g && !se_PlayerNetIDs(i)->IsActive())
03174 {
03175 g->Kill();
03176 }
03177
03178
03179 }
03180 }
03181
03182
03183 if (notyetloggedin && humans > 0)
03184 alive++;
03185
03186
03187 static int all_alive_last=0;
03188 {
03189 int all_alive = ai_alive+alive;
03190 if (all_alive != all_alive_last)
03191 {
03192 all_alive_last = ai_alive+alive;
03193 lastdeath = time;
03194 }
03195 }
03196
03197 static nVersionFeature winZone(2);
03198
03199
03200
03201
03202
03203
03204
03205
03206 #ifndef ENABLE_ZONESV2
03207
03208 if ( winZone.Supported() && !bool( winDeathZone_ ) && winner == 0 && time - lastdeath > sg_currentSettings->winZoneMinLastDeath && time > sg_currentSettings->winZoneMinRoundTime )
03209 {
03210 winDeathZone_ = sg_CreateWinDeathZone( grid, Arena.GetRandomPos( sg_winZoneRandomness ) );
03211 }
03212 #endif
03213
03214 bool holdBackNextRound = false;
03215
03216
03217 {
03218 static int lastTeams = 0;
03219
03220
03221 int humanTeamsClamp = human_teams;
03222 if ( humanTeamsClamp > 2 )
03223 humanTeamsClamp = 2;
03224 if ( humanTeamsClamp != lastTeams )
03225 {
03226 StartNewMatch();
03227
03228 if ( time < -100 )
03229 {
03230 StartNewMatchNow();
03231 }
03232 else
03233 {
03234
03235 winner=-1;
03236 wintimer=time;
03237 }
03238 }
03239
03240 lastTeams=humanTeamsClamp;
03241 }
03242
03243
03244 if ( time-lastdeath < 1.0f )
03245 {
03246 holdBackNextRound = true;
03247 }
03248 else if (winner==0 && absolute_winner==0 ){
03249 if ( teams_alive <= 1 )
03250 {
03251 if ( sg_currentSettings->gameType!=gFREESTYLE )
03252 {
03253 if ( eTeam::teams.Len()>1 && teams_alive<=1 ){
03254 winner=last_team_alive+1;
03255 wintimer=time;
03256 }
03257 }
03258 else
03259 {
03260 if ( teams_alive < 1 )
03261 winner=-1;
03262 wintimer=time;
03263 }
03264 }
03265
03266 const char* survivor="$player_win_survivor";
03267 const char* messagetype = survivor;
03268
03269 if ( wishWinner )
03270 {
03271 wintimer=time;
03272 winner = wishWinner;
03273 wishWinner = 0;
03274 messagetype = wishWinnerMessage;
03275 }
03276
03277 if (winner <= 0 && alive <= 0 && ai_alive <= 0 && teams_alive <= 0){
03278 if ( se_mainGameTimer )
03279 se_mainGameTimer->speed = 1;
03280
03281
03282 winner=-1;
03283 wintimer=time;
03284 }
03285 else
03286 if (winner){
03287 if ( se_mainGameTimer )
03288 se_mainGameTimer->speed = 1;
03289 lastdeath = time;
03290
03291 tOutput message;
03292 message << "$gamestate_winner_winner";
03293
03294 if ( last_team_alive >= 0 )
03295 sg_currentSettings->AutoAI( eTeam::teams( last_team_alive )->NumHumanPlayers() > 0 );
03296
03297
03298 if ( ( sg_currentSettings->scoreWin != 0 || sg_currentSettings->gameType != gFREESTYLE ) && winner > 0 )
03299 {
03300
03301 if ( sg_EnemyExists( winner-1 ) || sg_currentSettings->gameType==gFREESTYLE )
03302 {
03303 #ifdef KRAWALL_SERVER_LEAGUE
03304
03305 if (!dynamic_cast<gAIPlayer*>(eTeam::teams(winner-1)))
03306 {
03307 tArray<tString> players;
03308 for (int i = eTeam::teams.Len()-1; i>=0; i--)
03309 if (i != winner-1 &&
03310 eTeam::teams(i)->Alive() &&
03311 eTeam::teams(i)->IsHuman() )
03312 {
03313 players[players.Len()] = eTeam::teams(i)->Name();
03314 }
03315
03316 players[players.Len()] = eTeam::teams(winner-1)->Name();
03317 if (players.Len() > 1)
03318 nKrawall::ServerRoundEnd(&players(0), players.Len());
03319 }
03320 #endif
03321
03322
03323 eTeam::teams[winner-1]->AddScore
03324 (sg_currentSettings->scoreWin,messagetype, tOutput());
03325 if (!sg_singlePlayer && eTeam::teams(winner-1)->NumHumanPlayers() >= 1 && gStats &&
03326 eTeam::teams(winner-1)->NumPlayers() >= 1 && eTeam::teams[winner-1]->NumHumanPlayers() > 0)
03327 {
03328
03329 for (int i = eTeam::teams[winner-1]->NumPlayers() - 1; i>=0; --i)
03330 {
03331 if (eTeam::teams[winner-1]->Player(i)->IsHuman())
03332 {
03333 gStats->won_rounds->add(eTeam::teams[winner-1]->Player(i)->GetName(), 1);
03334 }
03335 }
03336
03337 }
03338
03339
03340 tOutput message;
03341 message << "$gamestate_winner_winner";
03342 message << eTeam::teams[winner-1]->Name();
03343
03344 m_Mixer->PushButton(ROUND_WINNER);
03345
03346 sn_CenterMessage(message);
03347 message << '\n';
03348 se_SaveToScoreFile(message);
03349
03350 tString ladderLog;
03351 ladderLog << "ROUND_WINNER " << ePlayerNetID::FilterName( eTeam::teams[winner-1]->Name() ) << "\n";
03352 se_SaveToLadderLog( ladderLog );
03353 tString notificationMessage( ePlayerNetID::FilterName( eTeam::teams[winner-1]->Name() ) );
03354 notificationMessage << " has won the round";
03355 se_sendEventNotification(tString("Round winner"), notificationMessage);
03356 }
03357 }
03358
03359 if (sg_singlePlayer && gStats && se_PlayerNetIDs.Len() > 0 && se_PlayerNetIDs(0)->IsHuman())
03360 {
03361 gStats->highscores->greater(se_PlayerNetIDs(0)->GetName(), se_PlayerNetIDs(0)->Score());
03362 }
03363 winner = -1;
03364 }
03365 }
03366
03367 int winnerExtraRound = ( winner != 0 || alive == 0 ) ? 1 : 0;
03368
03369
03370
03371 if ( winner && !roundOver && time-lastdeath >= 2.0f )
03372 {
03373 roundOver = true;
03374
03375 const tList<eGameObject>& gameObjects = Grid()->GameObjects();
03376 for (int i=gameObjects.Len()-1;i>=0;i--)
03377 {
03378 eGameObject * e = gameObjects(i);
03379 if ( e )
03380 {
03381 e->OnRoundEnd();
03382 }
03383 }
03384 }
03385
03386
03387 if ( time-lastdeath < 2.0f )
03388 {
03389 holdBackNextRound = true;
03390 }
03391 else if (absolute_winner==0 &&
03392 sn_GetNetState()!=nCLIENT && se_PlayerNetIDs.Len()){
03393 ePlayerNetID::SortByScore();
03394 eTeam::SortByScore();
03395 if ( eTeam::teams.Len() > 0 )
03396 if (eTeam::teams.Len() <= 1
03397 || ( eTeam::teams(0)->Score() > eTeam::teams(1)->Score() && sg_EnemyExists(0))){
03398
03399
03400 if (eTeam::teams(0)->Score() >= sg_currentSettings->limitScore ||
03401 rounds + winnerExtraRound >= sg_currentSettings->limitRounds ||
03402 tSysTimeFloat()>=startTime+sg_currentSettings->limitTime*60 ||
03403 (active <= 1 && eTeam::teams.Len() > 1)
03404 )
03405 {
03406 bool declareChampion = true;
03407 if ( winner!=0 && wintimer > time - ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 4.0 ) )
03408 {
03409 declareChampion = false;
03410 holdBackNextRound= true;
03411 }
03412
03413 if ( declareChampion )
03414 {
03415 lastdeath = time + ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 6.0f );
03416
03417 {
03418 tOutput message;
03419 message.SetTemplateParameter(1, eTeam::teams[0]->Name() );
03420 message << "$gamestate_champ_center";
03421 sn_CenterMessage(message);
03422
03423 m_Mixer->PushButton(MATCH_WINNER);
03424 }
03425
03426 tOutput message;
03427 tColoredString name;
03428 name << eTeam::teams[0]->Name();
03429 name << tColoredString::ColorString(1,1,1);
03430
03431 tString ladderLog;
03432 ladderLog << "MATCH_WINNER " << ePlayerNetID::FilterName( eTeam::teams[0]->Name() ) << "\n";
03433 se_SaveToLadderLog( ladderLog );
03434 tString notificationMessage( ePlayerNetID::FilterName( eTeam::teams[0]->Name() ) );
03435 notificationMessage << " has won the match";
03436 se_sendEventNotification(tString("Match winner"), notificationMessage);
03437
03438
03439 message.SetTemplateParameter(1, name);
03440 message << "$gamestate_champ_console";
03441
03442 if (eTeam::teams(0)->Score() >=sg_currentSettings->limitScore)
03443 {
03444 message.SetTemplateParameter(1, eTeam::teams(0)->Score());
03445 message.SetTemplateParameter(2, sg_currentSettings->limitScore);
03446 message << "$gamestate_champ_scorehit";
03447 }
03448 else if ( tSysTimeFloat()>=startTime+sg_currentSettings->limitTime*60)
03449 {
03450 message.SetTemplateParameter(1, sg_currentSettings->limitTime);
03451 message << "$gamestate_champ_timehit";
03452 }
03453 else
03454 {
03455 message.SetTemplateParameter(1, rounds + 1);
03456 message << "$gamestate_champ_default";
03457 }
03458
03459 se_SaveToScoreFile(message);
03460 se_SaveToScoreFile("$gamestate_champ_finalscores");
03461 se_SaveToScoreFile(eTeam::Ranking( -1, false ));
03462 se_SaveToScoreFile(ePlayerNetID::Ranking( -1, false ));
03463 se_SaveToScoreFile(sg_GetCurrentTime( "Time: %Y/%m/%d %H:%M:%S\n" ));
03464 se_SaveToScoreFile("\n\n");
03465
03466 eTeam* winningTeam = eTeam::teams(0);
03467 if (!sg_singlePlayer && winningTeam->NumHumanPlayers() > 0 && winningTeam->NumHumanPlayers() > 0 && gStats)
03468 {
03469
03470 for (int i = winningTeam->NumPlayers() - 1; i>=0; --i)
03471 {
03472 if (winningTeam->Player(i)->IsHuman())
03473 {
03474 gStats->won_matches->add(winningTeam->Player(i)->GetName(), 1);
03475 }
03476 }
03477 }
03478
03479 sn_ConsoleOut(message);
03480
03481 m_Mixer->PushButton(MATCH_WINNER);
03482
03483 wintimer=time;
03484 absolute_winner=1;
03485
03486 if ( se_mainGameTimer )
03487 se_mainGameTimer->speed = 1;
03488
03489
03490 if (rotationtype == 2)
03491 rotate();
03492
03493 gRotation::HandleNewMatch();
03494
03495 StartNewMatch();
03496 }
03497 }
03498 }
03499 }
03500
03501
03502
03503 REAL fintime=6;
03504
03505 if (sg_currentSettings->finishType==gFINISH_EXPRESS)
03506 fintime=2.5;
03507
03508 if (( ( winner || absolute_winner ) && wintimer+fintime < time)
03509 || (((alive==0 && eTeam::teams.Len()>=
03510 #ifndef DEDICATED
03511 1
03512 #else
03513 0
03514 #endif
03515 )) && time-lastdeath >fintime-2
03516 #ifndef DEDICATED
03517 && humans > 0
03518 #endif
03519 )){
03520 #ifdef DEBUG
03521
03522
03523
03524
03525 #endif
03526 if (!holdBackNextRound &&
03527 (
03528 ( sg_currentSettings->finishType==gFINISH_IMMEDIATELY ||
03529 sg_currentSettings->finishType==gFINISH_EXPRESS ||
03530 absolute_winner || ( teams_alive <= 1 && time-lastdeath>4.0f ) ) ||
03531 ( winner && time - wintimer> 4.0f )
03532 )
03533 )
03534 {
03535 rounds++;
03536 SetState(GS_PLAY,GS_DELETE_OBJECTS);
03537 }
03538
03539 if ( !winner && !absolute_winner && sg_currentSettings->finishType==gFINISH_SPEEDUP && se_mainGameTimer)
03540 {
03541 se_mainGameTimer->speed*=1.01;
03542 if (se_mainGameTimer->speed>16)
03543 se_mainGameTimer->speed=16;
03544 }
03545
03546 }
03547 }
03548
03549 void rotate()
03550 {
03551 if ( sg_mapRotation.Size() > 0 )
03552 {
03553 conf_mapfile.Set( sg_mapRotation.Current() );
03554 sg_mapRotation.Rotate();
03555 }
03556
03557 if ( sg_configRotation.Size() > 0 )
03558 {
03559 st_Include( sg_configRotation.Current() );
03560 sg_configRotation.Rotate();
03561 }
03562 }
03563
03564 void gGame::StartNewMatch(){
03565
03566 if (sg_singlePlayer && gStats && se_PlayerNetIDs.Len() > 0 && se_PlayerNetIDs(0)->IsHuman())
03567 {
03568 gStats->highscores->greater(se_PlayerNetIDs(0)->GetName(), se_PlayerNetIDs(0)->Score());
03569 }
03570
03571 rounds=-100;
03572 }
03573
03574 void gGame::StartNewMatchNow(){
03575 if ( rounds != 0 )
03576 {
03577 se_SaveToLadderLog(tString("NEW_MATCH\n"));
03578 se_sendEventNotification(tString("New match"), tString("Starting a new match"));
03579 }
03580
03581
03582 rounds=0;
03583 warning=0;
03584 startTime=tSysTimeFloat()-10;
03585
03586 ePlayerNetID::ThrowOutDisconnected();
03587 ePlayerNetID::ResetScore();
03588 }
03589
03590 #ifdef DEBUG
03591 extern bool debug_grid;
03592
03593 bool simplify_grid=1;
03594 #endif
03595
03596 #ifndef DEDICATED
03597
03598 static uActionGlobal togglemousegrab( "TOGGLE_MOUSEGRAB" );
03599 static bool togglemousegrab_func(REAL x){
03600 if (x>0){
03601 su_mouseGrab = !su_mouseGrab;
03602 }
03603
03604 return true;
03605 }
03606 static uActionGlobalFunc togglemousegrab_action(&togglemousegrab,&togglemousegrab_func, true );
03607
03608
03609 static uActionGlobal pausegame( "PAUSE_GAME" );
03610 static bool pausegame_func(REAL x){
03611 static bool paused=false;
03612
03613 if (x>0){
03614 paused=!paused;
03615 se_PauseGameTimer(paused);
03616 }
03617
03618 return true;
03619 }
03620 static uActionGlobalFunc pausegame_action(&pausegame,&pausegame_func, true );
03621
03622
03623 static uActionGlobal reloadtextures( "RELOAD_TEXTURES" );
03624 static bool reloadtextures_func(REAL x){
03625 if (x>0){
03626 rITexture::UnloadAll();
03627 }
03628
03629 return true;
03630 }
03631 static uActionGlobalFunc reloadtextures_action(&reloadtextures,&reloadtextures_func, true );
03632
03633
03634 static uActionGlobal ingamemenu( "INGAME_MENU" );
03635 static bool ingamemenu_func(REAL x){
03636 if (x>0){
03637 st_ToDo(&ingame_menu);
03638 }
03639
03640 return true;
03641 }
03642 static uActionGlobalFunc ingamemenu_action(&ingamemenu,&ingamemenu_func, true );
03643 #endif // dedicated
03644
03645 bool gGame::GameLoop(bool input){
03646 nNetState netstate = sn_GetNetState();
03647
03648 #ifdef DEBUG
03649 grid->Check();
03650 if (simplify_grid)
03651 #endif
03652 grid->SimplifyAll(10);
03653
03654 #ifdef DEBUG
03655 grid->Check();
03656 #endif
03657
03658
03659
03660
03661 REAL gtime=0;
03662 REAL time=0;
03663 se_SyncGameTimer();
03664 if (state==GS_PLAY){
03665 if ( netstate != sn_GetNetState() )
03666 {
03667 return false;
03668 }
03669 gtime=se_GameTime();
03670 time=gtime;
03671
03672 if (sn_GetNetState()==nSTANDALONE && sg_IngameMenu)
03673 se_PauseGameTimer(true);
03674
03675 static int lastcountdown=0;
03676 int cd=int(floor(-time))+1;
03677 if (cd>=0 && cd<PREPARE_TIME && cd!=lastcountdown && se_mainGameTimer && se_mainGameTimer->IsSynced() ){
03678 lastcountdown=cd;
03679 tString s;
03680 s << cd;
03681
03682 switch (cd) {
03683 case 3:
03684 m_Mixer->PushButton(ANNOUNCER_3);
03685 break;
03686 case 2:
03687 m_Mixer->PushButton(ANNOUNCER_2);
03688 break;
03689 case 1:
03690 m_Mixer->PushButton(ANNOUNCER_1);
03691 break;
03692 case 0:
03693 m_Mixer->PushButton(ANNOUNCER_GO);
03694 break;
03695 }
03696 con.CenterDisplay(s,0);
03697 }
03698 }
03699
03700
03701 #ifndef DEDICATED
03702 if (input){
03703 su_HandleDelayedEvents();
03704
03705 SDL_Event tEvent;
03706
03707 uInputProcessGuard inputProcessGuard;
03708 while (su_GetSDLInput(tEvent,time)){
03709 if (time>gtime) time=gtime;
03710 if (time>lastTime_gameloop){
03711 Timestep(time);
03712 lastTime_gameloop=time;
03713 }
03714
03715
03716 if (!su_HandleEvent(tEvent, false))
03717 switch (tEvent.type){
03718 case SDL_MOUSEBUTTONDOWN:
03719 break;
03720 case SDL_KEYDOWN:
03721 switch (tEvent.key.keysym.sym){
03722
03723 case(27):
03724
03725 st_ToDo(&ingame_menu);
03726 break;
03727 #ifdef DEBUG
03728 case('d'):
03729 debug_grid=!debug_grid;
03730 break;
03731
03732 case('a'):
03733 simplify_grid=!simplify_grid;
03734 break;
03735
03736 case('l'):
03737 sr_glOut=!sr_glOut;
03738 break;
03739
03740 case('b'):
03741 st_Breakpoint();
03742 break;
03743
03744 case('t'):
03745 think=!think;
03746 break;
03747
03748
03749
03750
03751
03752
03753
03754 #endif
03755
03756 default:
03757 break;
03758 }
03759 break;
03760
03761 default:
03762 break;
03763 }
03764 }
03765
03766 su_InputSync();
03767 }
03768 #endif
03769
03770 if ( netstate != sn_GetNetState() )
03771 {
03772 return false;
03773 }
03774
03775
03776 sg_Receive();
03777 sn_SendPlanned();
03778
03779 bool synced = se_mainGameTimer && ( se_mainGameTimer->IsSynced() || ( stateNext >= GS_DELETE_OBJECTS || stateNext <= GS_CREATE_GRID ) );
03780
03781 if (!synced)
03782 {
03783
03784 for (int pi = MAX_PLAYERS-1; pi >= 0; --pi )
03785 {
03786 ePlayer * p = ePlayer::PlayerConfig(pi);
03787 if ( !p )
03788 break;
03789 ePlayerNetID * np = p->netPlayer;
03790 if ( !np )
03791 break;
03792 if ( np->Object() )
03793 {
03794 synced = true;
03795 break;
03796 }
03797 }
03798 }
03799 else if ( !synced_ )
03800 {
03801
03802 ePlayerNetID::Update();
03803
03804
03805 ePlayer::SendAuthNames();
03806
03807 synced_ = true;
03808 }
03809
03810 static float lastTime = -1;
03811
03812 if (sg_gameTimeInterval >= 0 && (gtime >= lastTime + sg_gameTimeInterval || (gtime < lastTime && gtime >= 0))) {
03813 tOutput out;
03814 out << "GAME_TIME " << gtime << '\n';
03815 se_SaveToLadderLog(out);
03816 lastTime = gtime;
03817 }
03818
03819 if (state==GS_PLAY){
03820 if (gtime<0 && gtime>-PREPARE_TIME+.3)
03821 eCamera::s_Timestep(grid, gtime);
03822 else{
03823
03824 nPingAverager::SetWeight(1);
03825
03826 if (gtime>=lastTime_gameloop){
03827
03828 #ifdef CONNECTION_STRESS
03829 if ( sg_ConnectionStress )
03830 {
03831 tRandomizer & randomizer = tRandomizer::GetInstance();
03832 int random = randomizer.Get( 1000 );
03833 if ( random == 0 )
03834 {
03835 sg_RequestedDisconnection = true;
03836
03837 goon = false;
03838 }
03839 }
03840 #endif
03841
03842
03843 Timestep(gtime,true);
03844 lastTime_gameloop=gtime;
03845 }
03846 lastTime_gameloop=gtime;
03847 }
03848
03849
03850
03851
03852
03853 if (sn_GetNetState()!=nCLIENT)
03854 {
03855
03856 for (int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
03857 {
03858 gAIPlayer *ai = dynamic_cast<gAIPlayer*>(se_PlayerNetIDs(i));
03859 if (ai && think)
03860 ai->Timestep(gtime);
03861 }
03862
03863 Analysis(gtime);
03864
03865
03866 if ( sn_GetNetState()==nSERVER && gtime < sg_lastChatBreakTime + 1 )
03867 se_PauseGameTimer( gtime < sg_lastChatBreakTime && ePlayerNetID::WaitToLeaveChat() );
03868 }
03869
03870
03871 nNetObject::SyncAll();
03872 sn_SendPlanned();
03873
03874 if ( gtime<=-PREPARE_TIME+.5 || !goon || !synced )
03875 {
03876 #ifndef DEDICATED
03877 if (input)
03878 {
03879 if ( !synced )
03880 {
03881 con.CenterDisplay(tString(tOutput("$network_login_sync")),0);
03882 }
03883
03884 if ( sr_glOut )
03885 rSysDep::ClearGL();
03886 }
03887
03888 if ( input )
03889 rSysDep::SwapGL();
03890 #endif
03891 }
03892 else
03893 Render(grid, gtime, input);
03894
03895 if ( netstate != sn_GetNetState() )
03896 {
03897 return false;
03898 }
03899
03900 return goon;
03901 }
03902 else{
03903
03904
03905
03906
03907
03908 #ifndef DEDICATED
03909
03910 nNetObject::SyncAll();
03911 sn_SendPlanned();
03912
03913 if (input)
03914 {
03915 if (sr_glOut)
03916 rSysDep::ClearGL();
03917 rSysDep::SwapGL();
03918 }
03919 #endif
03920 tDelay( 10000 );
03921 return goon;
03922 }
03923 }
03924
03925
03926 bool gGame::GridIsReady(int client){
03927 return HasBeenTransmitted(client) &&
03928 (client_gamestate[client]>=GS_TRANSFER_OBJECTS &&
03929 client_gamestate[client]<=GS_DELETE_OBJECTS);
03930 }
03931
03932 #include <fcntl.h>
03933 #include <stdio.h>
03934 #include <errno.h>
03935
03936 bool GameLoop(bool input=true){
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957 if (sn_GetNetState()==nSERVER){
03958 REAL t=tSysTimeFloat();
03959 for (int i=se_PlayerNetIDs.Len()-1;i>=0;i--){
03960 ePlayerNetID *p=se_PlayerNetIDs(i);
03961
03962
03963 nPingAverager const & averager = sn_Connections[p->Owner()].ping;
03964 REAL realping = averager.GetPing();
03965 REAL pingvariance = averager.GetSlowAverager().GetDataVariance() + realping * realping * .01;
03966
03967
03968 REAL deviation = realping - p->ping;
03969
03970
03971
03972 REAL relativedeviation = deviation * deviation / pingvariance;
03973
03974 if (0 == p->Owner())
03975 realping = 0;
03976
03977 if ( ( t - p->lastSync - 5 ) * relativedeviation > 5 ){
03978
03979 p->ping = realping;
03980 p->RequestSync(false);
03981 }
03982 }
03983 }
03984
03985 bool goon=false;
03986 if (sg_currentGame){
03987 tControlledPTR< nNetObject > keep( sg_currentGame );
03988 sg_currentGame->StateUpdate();
03989 goon=!uMenu::quickexit && bool(sg_currentGame) && sg_currentGame->GameLoop(input);
03990 }
03991 return goon;
03992 }
03993
03994 void gameloop_idle()
03995 {
03996 se_UserShowScores( false );
03997 sg_Receive();
03998 nNetObject::SyncAll();
03999 sn_SendPlanned();
04000 GameLoop(false);
04001 }
04002
04003 static void sg_EnterGameCleanup();
04004
04005 void sg_EnterGameCore( nNetState enter_state ){
04006 gLogo::SetBig(false);
04007
04008 sg_RequestedDisconnection = false;
04009
04010 sr_con.SetHeight(7);
04011
04012
04013 eSoundMixer* mixer = eSoundMixer::GetMixer();
04014 mixer->SetMode(GRID_TRACK);
04015
04016
04017 if ( sn_GetNetState() != nCLIENT )
04018 {
04019 sg_currentSettings = &singlePlayer;
04020 sg_copySettings();
04021
04022
04023 rotate();
04024 gRotation::HandleNewRound();
04025 gRotation::HandleNewMatch();
04026 }
04027
04028
04029
04030 uMenu::SetIdle(gameloop_idle);
04031 sr_con.autoDisplayAtSwap=true;
04032 bool goon=true;
04033 while (bool(sg_currentGame) && goon && sn_GetNetState()==enter_state){
04034 #ifdef DEDICATED // read input
04035 sr_Read_stdin();
04036
04037 if ( sn_BasicNetworkSystem.Select( 1.0 / ( sg_dedicatedFPSIdleFactor * sg_dedicatedFPS ) ) )
04038 {
04039
04040 tAdvanceFrame();
04041 sg_Receive();
04042 se_SyncGameTimer();
04043 REAL time=se_GameTime();
04044 sg_currentGame->StateUpdate();
04045 if ( time > 0 )
04046 {
04047
04048 eGameObject::s_Timestep(sg_currentGame->Grid(), time, 1E+10 );
04049
04050
04051 nNetObject::SyncAll();
04052 tAdvanceFrame();
04053 sn_SendPlanned();
04054 }
04055 }
04056 #endif
04057
04058
04059 tAdvanceFrame();
04060
04061 goon=GameLoop();
04062
04063 st_DoToDo();
04064 }
04065
04066 sg_EnterGameCleanup();
04067 }
04068
04069 void sg_EnterGameCleanup()
04070 {
04071
04072
04073 eSoundMixer* mixer = eSoundMixer::GetMixer();
04074 mixer->SetMode(GUI_TRACK);
04075
04076 sn_SetNetState( nSTANDALONE );
04077
04078
04079 gAIPlayer::ClearAll();
04080
04081
04082
04083
04084 gLogo::SetDisplayed(true);
04085 uMenu::SetIdle(NULL);
04086 sr_con.autoDisplayAtSwap=false;
04087 sr_con.fullscreen=false;
04088
04089
04090 nNetObject::ClearAll();
04091 ePlayerNetID::ClearAll();
04092 sg_currentGame = NULL;
04093 uMenu::exitToMain = false;
04094 }
04095
04096 void sg_EnterGame( nNetState enter_state )
04097 {
04098 try
04099 {
04100
04101 sg_EnterGameCore( enter_state );
04102 }
04103 catch (tException const & e)
04104 {
04105
04106 sg_EnterGameCleanup();
04107
04108
04109 tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
04110 }
04111
04112 #ifdef _MSC_VER
04113 #pragma warning ( disable : 4286 )
04114 catch (tGenericException const & e)
04115 {
04116
04117 sg_EnterGameCleanup();
04118
04119
04120 tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
04121 }
04122 #endif
04123
04124
04125 for ( int i = eTeam::teams.Len()-1; i>=0; --i )
04126 {
04127 tJUST_CONTROLLED_PTR< eTeam > t = eTeam::teams(i);
04128 }
04129 }
04130
04131 bool GridIsReady(int c){
04132 return bool(sg_currentGame) && sg_currentGame->GridIsReady(c);
04133 }
04134
04135
04136
04137 static bool notrans(){
04138 return !GridIsReady(eTransferInhibitor::User());
04139 }
04140
04141 static eTransferInhibitor inh(¬rans);
04142
04143
04144 void Activate(bool act){
04145 #ifdef DEBUG
04146 return;
04147 #endif
04148
04149
04150
04151 #ifndef WIN32
04152 #ifndef MACOSX
04153 if ( currentScreensetting.fullscreen && !act )
04154 {
04155 return;
04156 }
04157 #endif
04158 #endif
04159
04160 sr_Activate( act );
04161
04162 if (!tRecorder::IsRunning() )
04163 {
04164 if (sn_GetNetState()==nSTANDALONE)
04165 {
04166 se_PauseGameTimer(!act);
04167 }
04168
04169 se_ChatState( ePlayerNetID::ChatFlags_Away, !act);
04170 }
04171 }
04172
04173
04174
04175
04176
04177 static nVersionFeature sg_fullscreenMessages(14);
04178
04179 static void sg_FullscreenIdle()
04180 {
04181 tAdvanceFrame();
04182 se_SyncGameTimer();
04183 gGame::NetSync();
04184 if ( sg_currentGame )
04185 sg_currentGame->StateUpdate();
04186 }
04187
04188 void sg_ClientFullscreenMessage( tOutput const & title, tOutput const & message, REAL timeout ){
04189
04190 rPerFrameTask idle( sg_FullscreenIdle );
04191
04192
04193 ePlayerNetID::SpectateAll();
04194 se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
04195
04196
04197 uMenu::Message( title, message, timeout );
04198
04199
04200 #ifndef DEDICATED
04201 con << title << "\n" << message << "\n";
04202 #endif
04203
04204
04205 ePlayerNetID::SpectateAll(false);
04206 se_ChatState( ePlayerNetID::ChatFlags_Menu, false );
04207 }
04208
04209 static tString sg_fullscreenMessageTitle;
04210 static tString sg_fullscreenMessageMessage;
04211 static REAL sg_fullscreenMessageTimeout;
04212 static void sg_TodoClientFullscreenMessage()
04213 {
04214 sg_ClientFullscreenMessage( sg_fullscreenMessageTitle, sg_fullscreenMessageMessage, sg_fullscreenMessageTimeout );
04215 }
04216
04217 static void sg_ClientFullscreenMessage(nMessage &m){
04218 if (sn_GetNetState()!=nSERVER){
04219 sg_fullscreenMessageTimeout = 60;
04220
04221 m >> sg_fullscreenMessageTitle;
04222 m >> sg_fullscreenMessageMessage;
04223 m >> sg_fullscreenMessageTimeout;
04224
04225 st_ToDo( sg_TodoClientFullscreenMessage );
04226 }
04227 }
04228
04229 static nDescriptor sg_clientFullscreenMessage(312,sg_ClientFullscreenMessage,"client_fsm");
04230
04231
04232 void sg_FullscreenMessage(tOutput const & title, tOutput const & message, REAL timeout, int client){
04233 tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(sg_clientFullscreenMessage);
04234 *m << title;
04235 *m << message;
04236 *m << timeout;
04237
04238 tString complete( title );
04239 complete << "\n" << message << "\n";
04240
04241 if (client <= 0){
04242 if ( sg_fullscreenMessages.Supported() )
04243 m->BroadCast();
04244 else
04245 {
04246 for (int c = MAXCLIENTS; c > 0; --c)
04247 {
04248 if ( sn_Connections[c].socket )
04249 {
04250 if ( sg_fullscreenMessages.Supported(c) )
04251 m->Send(c);
04252 else
04253 sn_ConsoleOut(complete, c);
04254 }
04255 }
04256 }
04257
04258
04259 {
04260
04261 bool paused = se_mainGameTimer && se_mainGameTimer->speed < .0001;
04262 se_PauseGameTimer(true);
04263 gGame::NetSyncIdle();
04264
04265 REAL waitTo = tSysTimeFloat() + timeout;
04266 REAL waitToMin = tSysTimeFloat() + 1.0;
04267 sg_ClientFullscreenMessage( title, message, timeout );
04268
04269
04270 bool goon = true;
04271 while ( goon && waitTo > tSysTimeFloat() )
04272 {
04273 sg_FullscreenIdle();
04274 gameloop_idle();
04275 if ( se_GameTime() > sg_lastChatBreakTime )
04276 se_PauseGameTimer(true);
04277
04278
04279 if ( tSysTimeFloat() > waitToMin )
04280 {
04281 goon = false;
04282 for ( int i = se_PlayerNetIDs.Len()-1; i>=0; --i )
04283 {
04284 ePlayerNetID* player = se_PlayerNetIDs(i);
04285 if ( player->IsChatting() )
04286 goon = true;
04287 }
04288 }
04289 }
04290
04291
04292 se_PauseGameTimer(paused);
04293 gGame::NetSyncIdle();
04294 }
04295 }
04296 else
04297 {
04298 if ( sg_fullscreenMessages.Supported(client) )
04299 m->Send(client);
04300 else
04301 sn_ConsoleOut(complete, client);
04302 }
04303 }
04304
04305 static void sg_FullscreenMessageConf(std::istream &s)
04306 {
04307
04308 REAL timeout;
04309 s >> timeout;
04310
04311 if ( !s.good() || s.eof() )
04312 {
04313 con << "Usage: FULLSCREEN_MESSAGE <timeout> <message>\n";
04314 return;
04315 }
04316
04317
04318 tString message;
04319 message.ReadLine( s, true );
04320
04321 message += "\n";
04322
04323
04324 sg_FullscreenMessage( "$fullscreen_message_title", message , timeout );
04325 }
04326
04327 static tConfItemFunc sg_fullscreenMessageConf("FULLSCREEN_MESSAGE",&sg_FullscreenMessageConf);
04328
04329
04330
04331
04332
04333
04334 tString sg_greeting("");
04335 static tConfItemLine a_mod("MESSAGE_OF_DAY",sg_greeting);
04336
04337 tString sg_greetingTitle("");
04338 static tConfItemLine a_tod("TITLE_OF_DAY",sg_greetingTitle);
04339
04340 REAL sg_greetingTimeout=60;
04341 static tSettingItem< REAL > a_modt("MESSAGE_OF_DAY_TIMEOUT",sg_greetingTimeout);
04342
04343 static void LoginCallback(){
04344 client_gamestate[nCallbackLoginLogout::User()]=0;
04345 if ( nCallbackLoginLogout::Login() && nCallbackLoginLogout::User() > 0 )
04346 {
04347 if ( sg_greeting.Len()>1 )
04348 {
04349 if ( sg_greetingTitle.Len() <= 1 )
04350 sg_greetingTitle = "Server message";
04351
04352 sg_FullscreenMessage( sg_greetingTitle, sg_greeting, sg_greetingTimeout, nCallbackLoginLogout::User() );
04353 }
04354 }
04355 }
04356
04357 #ifdef ENABLE_ZONESV2
04358 void oldFortressAutomaticAssignment(zZone *zone, zMonitorPtr monitor);
04359
04360 void init_second_pass_zones(eGrid *grid, gParser *parser)
04361 {
04362 const tList<eGameObject>& gameObjects = grid->GameObjects();
04363 for (int i=gameObjects.Len()-1;i>=0;i--)
04364 {
04365 zZone *zone=dynamic_cast<zZone *>(gameObjects(i));
04366
04367 if (zone && zone->getOldFortressAutomaticAssignmentBehavior() == true)
04368 {
04369 zMonitorPtr monitor = parser->getMonitor(zone->getName());
04370 oldFortressAutomaticAssignment(zone, monitor);
04371 }
04372 }
04373 }
04374
04375 void oldFortressAutomaticAssignment(zZone *zone, zMonitorPtr monitor)
04376 {
04377 if (zone->getOldFortressAutomaticAssignmentBehavior() == true)
04378 {
04379
04380
04381 zone->setOldFortressAutomaticAssignmentBehavior( false );
04382
04383
04384 const tList<eGameObject>& gameObjects = zone->Grid()->GameObjects();
04385 gCycle * closest = NULL;
04386 REAL closestDistance = 0;
04387 eTeam * team;
04388 for (int i=gameObjects.Len()-1;i>=0;i--)
04389 {
04390 gCycle *other=dynamic_cast<gCycle *>(gameObjects(i));
04391
04392 if (other )
04393 {
04394
04395 eCoord otherpos = other->Position() - zone->GetPosition();
04396 REAL distance = otherpos.NormSquared();
04397 if ( !closest || distance < closestDistance )
04398 {
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409 {
04410 closest = other;
04411 closestDistance = distance;
04412 }
04413 }
04414 }
04415 }
04416
04417 if ( closest )
04418 {
04419
04420 team = closest->Player()->CurrentTeam();
04421 rColor teamColor;
04422 teamColor.r_ = team->R()/15.0;
04423 teamColor.g_ = team->G()/15.0;
04424 teamColor.b_ = team->B()/15.0;
04425 zone->getShape()->setColor(teamColor);
04426
04427
04428 {
04429
04430
04431
04432
04433
04434
04435
04436
04437 zEffectGroupPtr currentZoneEffect;
04438
04439
04440 zValidatorPtr validator;
04441 if (sg_singlePlayer) {
04442
04443 gVectorExtra< nNetObjectID > playerOwners;
04444 playerOwners.push_back(closest->Player()->ID());
04445 currentZoneEffect = zEffectGroupPtr(new zEffectGroup(playerOwners, gVectorExtra< nNetObjectID >()));
04446 validator = zValidatorPtr( new zValidatorOwner(_ignore, _ignore) );
04447 }
04448 else {
04449 gVectorExtra< nNetObjectID > teamOwners;
04450 teamOwners.push_back(team->ID());
04451 currentZoneEffect = zEffectGroupPtr(new zEffectGroup(gVectorExtra< nNetObjectID >(), teamOwners));
04452 validator = zValidatorPtr( new zValidatorOwnerTeam(_ignore, _ignore) );
04453 }
04454
04455 zMonitorInfluencePtr inflDefender = zMonitorInfluencePtr(new zMonitorInfluence( monitor ));
04456
04457 tPolynomial<nMessage> tpInfluenceSlide(2);
04458 tpInfluenceSlide[0] = -1.0 * sg_defendRate;
04459 inflDefender->setInfluenceSlide( tpInfluenceSlide );
04460
04461
04462
04463 validator->addMonitorInfluence( inflDefender );
04464 currentZoneEffect->addValidator( validator );
04465
04466
04467 if (sg_singlePlayer) {
04468
04469 validator = zValidatorPtr( new zValidatorAllButOwner(_ignore, _ignore) );
04470 }
04471 else {
04472 validator = zValidatorPtr( new zValidatorAllButTeamOwner(_ignore, _ignore) );
04473 }
04474
04475 zMonitorInfluencePtr inflAttaquer = zMonitorInfluencePtr(new zMonitorInfluence( monitor ));
04476
04477 tpInfluenceSlide[0] = -1.0 * sg_defendRate;
04478 inflAttaquer->setInfluenceSlide( tpInfluenceSlide );
04479
04480
04481 validator->addMonitorInfluence( inflAttaquer );
04482 currentZoneEffect->addValidator( validator );
04483
04484
04485
04486 zone->addEffectGroupInside( currentZoneEffect );
04487
04488 }
04489
04490 zone->RequestSync();
04491 }
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513 }
04514 }
04515 #endif
04516
04517
04518 static nCallbackLoginLogout lc(LoginCallback);
04519
04520