3
*************************************************************************
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
6
Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
8
**************************************************************************
10
This program is free software; you can redistribute it and/or
11
modify it under the terms of the GNU General Public License
12
as published by the Free Software Foundation; either version 2
13
of the License, or (at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
***************************************************************************
47
#include "rViewport.h"
53
#include "uInputQueue.h"
54
#include "nNetObject.h"
58
#include "gServerBrowser.h"
59
#include "gServerFavorites.h"
61
#include "gLanguageMenu.h"
62
#include "nServerInfo.h"
63
#include "gAICharacter.h"
64
#include "tDirectories.h"
68
#include "tRecorder.h"
71
#include "tResourceManager.h"
89
#include <SDL_thread.h>
95
//static bool fullscreen=1;
101
//#define CONNECTION_STRESS
104
tCONFIG_ENUM( gGameType );
105
tCONFIG_ENUM( gFinishType );
107
// extra round pause time
108
static REAL sg_extraRoundTime = 0.0f;
109
static tSettingItem<REAL> sg_extraRoundTimeConf( "EXTRA_ROUND_TIME", sg_extraRoundTime );
111
static REAL sg_lastChatBreakTime = -1.0f;
112
static tSettingItem<REAL> sg_lastChatBreakTimeConf( "LAST_CHAT_BREAK_TIME", sg_lastChatBreakTime );
114
static tString mapuri("0");
115
static nSettingItem<tString> conf_mapuri("MAP_URI",mapuri);
117
#define DEFAULT_MAP "Anonymous/polygon/regular/square-1.0.1.aamap.xml"
118
static tString mapfile(DEFAULT_MAP);
119
static nSettingItemWatched<tString> conf_mapfile("MAP_FILE",mapfile, nConfItemVersionWatcher::Group_Breaking, 8 );
121
// bool globalingame=false;
122
tString sg_GetCurrentTime( char *szFormat )
128
pTime = localtime(&now);
129
strftime(szTemp,sizeof(szTemp),szFormat,pTime);
130
return tString(szTemp);
133
void sg_PrintCurrentTime( char *szFormat )
135
con << sg_GetCurrentTime(szFormat);
138
void sg_PrintCurrentDate()
140
sg_PrintCurrentTime( "%Y%m%d");
143
void sg_PrintCurrentTime()
145
sg_PrintCurrentTime( "%H%M%S" );
151
sg_PrintCurrentTime( "Timestamp: %Y/%m/%d %H:%M:%S\n" );
152
if ( tRecorder::IsRunning() )
154
con << "Uptime: " << int(tSysTimeFloat()) << " seconds.\n";
157
// to set breakpoints at specific round starts
158
static double breakTime = 0;
159
if ( tSysTimeFloat() > breakTime )
166
static REAL ded_idle=24;
167
static tSettingItem<REAL> dedicaded_idle("DEDICATED_IDLE",ded_idle);
170
static eWavData intro("moviesounds/intro.wav");
171
static eWavData extro("moviesounds/extro.wav");
174
#define MAXAI (gAICharacter::s_Characters.Len())
176
#define AUTO_AI_MAXFRAC 6
177
#define AUTO_AI_WIN 3
178
#define AUTO_AI_LOSE 1
180
gGameSettings::gGameSettings(int a_scoreWin,
181
int a_limitTime, int a_limitRounds, int a_limitScore,
182
int a_numAIs, int a_minPlayers, int a_AI_IQ,
183
bool a_autoNum, bool a_autoIQ,
184
int a_speedFactor, int a_sizeFactor,
185
gGameType a_gameType, gFinishType a_finishType,
187
int a_winZoneMinRoundTime, int a_winZoneMinLastDeath
189
:scoreWin(a_scoreWin),
190
limitTime(a_limitTime), limitRounds(a_limitRounds), limitScore(a_limitScore),
191
numAIs(a_numAIs), minPlayers(a_minPlayers), AI_IQ(a_AI_IQ),
192
autoNum(a_autoNum), autoIQ(a_autoIQ),
193
speedFactor(a_speedFactor), sizeFactor(a_sizeFactor),
194
winZoneMinRoundTime( a_winZoneMinRoundTime ),winZoneMinLastDeath( a_winZoneMinLastDeath ),
195
gameType(a_gameType), finishType(a_finishType),
198
autoAIFraction = AUTO_AI_MAXFRAC >> 1;
201
minPlayersPerTeam = 1;
202
maxPlayersPerTeam = 10;
203
maxTeamImbalance = 1;
204
balanceTeamsWithAIs = true;
205
enforceTeamRulesOnQuit = false;
207
wallsStayUpDelay = 2.0f;
209
explosionRadius = 4.0f;
212
void gGameSettings::AutoAI(bool success){
213
if (!autoNum && !autoIQ)
220
autoAIFraction += AUTO_AI_WIN;
221
while (autoAIFraction > AUTO_AI_MAXFRAC)
223
autoAIFraction -= AUTO_AI_MAXFRAC;
224
if (numAIs < MAXAI) numAIs++;
229
autoAIFraction -= AUTO_AI_LOSE;
230
while (autoAIFraction < 0)
232
autoAIFraction += AUTO_AI_MAXFRAC;
233
if (numAIs >= 2) numAIs--;
242
AI_IQ += 4 * (success ? AUTO_AI_WIN : -AUTO_AI_LOSE);
245
int total = numAIs * numAIs * AI_IQ;
246
// try to keep total around 100: that is either 10 dumb AIs or
251
AI_IQ += AUTO_AI_WIN * 4;
253
AI_IQ += AUTO_AI_WIN;
256
AI_IQ -= AUTO_AI_LOSE * 4;
258
AI_IQ -= AUTO_AI_LOSE;
269
void gGameSettings::Menu()
271
uMenu GameSettings("$game_settings_menu_text");
275
"$game_menu_wz_mr_text",
276
"$game_menu_wz_mr_help",
277
winZoneMinRoundTime,0,1000,10);
281
"$game_menu_wz_ld_text",
282
"$game_menu_wz_ld_help",
283
winZoneMinLastDeath,0,1000,10);
285
uMenuItemToggle team_et
287
"$game_menu_balance_quit_text",
288
"$game_menu_balance_quit_help",
289
enforceTeamRulesOnQuit);
291
uMenuItemToggle team_bt
293
"$game_menu_balance_ais_text",
294
"$game_menu_balance_ais_help",
295
balanceTeamsWithAIs);
299
"$game_menu_imb_text",
300
"$game_menu_imb_help",
301
maxTeamImbalance,2,10);
303
uMenuItemInt team_maxp
305
"$game_menu_max_players_text",
306
"$game_menu_max_players_help",
307
maxPlayersPerTeam,1,16);
309
uMenuItemInt team_minp
311
"$game_menu_min_players_text",
312
"$game_menu_min_players_help",
313
minPlayersPerTeam,1,16);
315
uMenuItemInt team_max
317
"$game_menu_max_teams_text",
318
"$game_menu_max_teams_help",
321
uMenuItemInt team_min
323
"$game_menu_min_teams_text",
324
"$game_menu_min_teams_help",
327
uMenuItemSelection<gFinishType> finisht
328
(&GameSettings,"$game_menu_finish_text",
329
"$game_menu_finish_help",finishType);
330
finisht.NewChoice("$game_menu_finish_expr_text",
331
"$game_menu_finish_expr_help",
333
finisht.NewChoice("$game_menu_finish_stop_text",
334
"$game_menu_finish_stop_help",
335
gFINISH_IMMEDIATELY);
336
finisht.NewChoice("$game_menu_finish_fast_text",
337
"$game_menu_finish_fast_help",
339
finisht.NewChoice("$game_menu_finish_normal_text",
340
"$game_menu_finish_normal_help",
343
uMenuItemSelection<gGameType> gamet
344
(&GameSettings,"$game_menu_mode_text",
345
"$game_menu_mode_help",gameType);
346
gamet.NewChoice("$game_menu_mode_free_text",
347
"$game_menu_mode_free_help",
349
gamet.NewChoice("$game_menu_mode_lms_text",
350
"$game_menu_mode_lms_help",
353
gamet.NewChoice("$game_menu_mode_team_text",
354
"$game_menu_mode_team_help",
358
uMenuItemInt speedconf
360
"$game_menu_speed_text",
361
"$game_menu_speed_help",
364
uMenuItemInt sizeconf
366
"$game_menu_size_text",
367
"$game_menu_size_help",
370
uMenuItemSelection<REAL> wsuconf
372
"$game_menu_wallstayup_text",
373
"$game_menu_wallstayup_help",
375
wsuconf.NewChoice( "$game_menu_wallstayup_infinite_text",
376
"$game_menu_wallstayup_infinite_help",
378
wsuconf.NewChoice( "$game_menu_wallstayup_immediate_text",
379
"$game_menu_wallstayup_immediate_help",
381
wsuconf.NewChoice( "$game_menu_wallstayup_halfsecond_text",
382
"$game_menu_wallstayup_halfsecond_help",
384
wsuconf.NewChoice( "$game_menu_wallstayup_second_text",
385
"$game_menu_wallstayup_second_help",
387
wsuconf.NewChoice( "$game_menu_wallstayup_2second_text",
388
"$game_menu_wallstayup_2second_help",
390
wsuconf.NewChoice( "$game_menu_wallstayup_4second_text",
391
"$game_menu_wallstayup_4second_help",
393
wsuconf.NewChoice( "$game_menu_wallstayup_8second_text",
394
"$game_menu_wallstayup_8second_help",
396
wsuconf.NewChoice( "$game_menu_wallstayup_16second_text",
397
"$game_menu_wallstayup_16second_help",
399
wsuconf.NewChoice( "$game_menu_wallstayup_32second_text",
400
"$game_menu_wallstayup_32second_help",
403
uMenuItemSelection<REAL> wlconf
405
"$game_menu_wallslength_text",
406
"$game_menu_wallslength_help",
408
wlconf.NewChoice( "$game_menu_wallslength_infinite_text",
409
"$game_menu_wallslength_infinite_help",
411
wlconf.NewChoice( "$game_menu_wallslength_25meter_text",
412
"$game_menu_wallslength_25meter_help",
414
wlconf.NewChoice( "$game_menu_wallslength_50meter_text",
415
"$game_menu_wallslength_50meter_help",
417
wlconf.NewChoice( "$game_menu_wallslength_100meter_text",
418
"$game_menu_wallslength_100meter_help",
420
wlconf.NewChoice( "$game_menu_wallslength_200meter_text",
421
"$game_menu_wallslength_200meter_help",
423
wlconf.NewChoice( "$game_menu_wallslength_300meter_text",
424
"$game_menu_wallslength_300meter_help",
426
wlconf.NewChoice( "$game_menu_wallslength_400meter_text",
427
"$game_menu_wallslength_400meter_help",
429
wlconf.NewChoice( "$game_menu_wallslength_600meter_text",
430
"$game_menu_wallslength_600meter_help",
432
wlconf.NewChoice( "$game_menu_wallslength_800meter_text",
433
"$game_menu_wallslength_800meter_help",
435
wlconf.NewChoice( "$game_menu_wallslength_1200meter_text",
436
"$game_menu_wallslength_1200meter_help",
438
wlconf.NewChoice( "$game_menu_wallslength_1600meter_text",
439
"$game_menu_wallslength_1600meter_help",
442
uMenuItemSelection<REAL> erconf
444
"$game_menu_exrad_text",
445
"$game_menu_exrad_help",
447
erconf.NewChoice( "$game_menu_exrad_0_text",
448
"$game_menu_exrad_0_help",
450
erconf.NewChoice( "$game_menu_exrad_2meters_text",
451
"$game_menu_exrad_2meters_help",
453
erconf.NewChoice( "$game_menu_exrad_4meters_text",
454
"$game_menu_exrad_4meters_help",
456
erconf.NewChoice( "$game_menu_exrad_8meters_text",
457
"$game_menu_exrad_8meters_help",
459
erconf.NewChoice( "$game_menu_exrad_16meters_text",
460
"$game_menu_exrad_16meters_help",
462
erconf.NewChoice( "$game_menu_exrad_32meters_text",
463
"$game_menu_exrad_32meters_help",
465
erconf.NewChoice( "$game_menu_exrad_64meters_text",
466
"$game_menu_exrad_64meters_help",
468
erconf.NewChoice( "$game_menu_exrad_128meters_text",
469
"$game_menu_exrad_128meters_help",
472
uMenuItemToggle autoiqconf
474
"$game_menu_autoiq_text",
475
"$game_menu_autoiq_help",
478
uMenuItemToggle autoaiconf
480
"$game_menu_autoai_text",
481
"$game_menu_autoai_help",
487
"$game_menu_iq_text",
488
"$game_menu_iq_help",
493
"$game_menu_minplayers_text",
494
"$game_menu_minplayers_help",
499
"$game_menu_ais_text",
500
"$game_menu_ais_help",
504
GameSettings.Enter();
507
gGameSettings singlePlayer(10,
512
gDUEL, gFINISH_IMMEDIATELY, 1,
515
gGameSettings multiPlayer(10,
520
gDUEL, gFINISH_IMMEDIATELY, 2,
523
gGameSettings* sg_currentSettings = &singlePlayer;
527
static tSettingItem<int> mp_sw("SCORE_WIN" ,multiPlayer.scoreWin);
528
static tSettingItem<int> mp_lt("LIMIT_TIME" ,multiPlayer.limitTime);
529
static tSettingItem<int> mp_lr("LIMIT_ROUNDS",multiPlayer.limitRounds);
530
static tSettingItem<int> mp_ls("LIMIT_SCORE" ,multiPlayer.limitScore);
532
static tConfItem<int> mp_na("NUM_AIS" ,multiPlayer.numAIs);
533
static tConfItem<int> mp_mp("MIN_PLAYERS" ,multiPlayer.minPlayers);
534
static tConfItem<int> mp_iq("AI_IQ" ,multiPlayer.AI_IQ);
536
static tConfItem<bool> mp_an("AUTO_AIS" ,multiPlayer.autoNum);
537
static tConfItem<bool> mp_aq("AUTO_IQ" ,multiPlayer.autoIQ);
539
static tConfItem<int> mp_sf("SPEED_FACTOR",multiPlayer.speedFactor);
540
static tConfItem<int> mp_zf("SIZE_FACTOR" ,multiPlayer.sizeFactor);
542
static tConfItem<gGameType> mp_gt("GAME_TYPE",multiPlayer.gameType);
543
static tConfItem<gFinishType> mp_ft("FINISH_TYPE",multiPlayer.finishType);
545
static tConfItem<int> mp_wzmr("WIN_ZONE_MIN_ROUND_TIME",multiPlayer.winZoneMinRoundTime);
546
static tConfItem<int> mp_wzld("WIN_ZONE_MIN_LAST_DEATH",multiPlayer.winZoneMinLastDeath);
548
static tConfItem<int> mp_tmin ("TEAMS_MIN", multiPlayer.minTeams);
549
static tConfItem<int> mp_tmax ("TEAMS_MAX", multiPlayer.maxTeams);
550
static tConfItem<int> mp_mtp ("TEAM_MIN_PLAYERS", multiPlayer.minPlayersPerTeam);
551
static tConfItem<int> mp_tp ("TEAM_MAX_PLAYERS", multiPlayer.maxPlayersPerTeam);
552
static tConfItem<int> mp_tib ("TEAM_MAX_IMBALANCE", multiPlayer.maxTeamImbalance);
553
static tConfItem<bool> mp_tbai ("TEAM_BALANCE_WITH_AIS", multiPlayer.balanceTeamsWithAIs);
554
static tConfItem<bool> mp_tboq ("TEAM_BALANCE_ON_QUIT", multiPlayer.enforceTeamRulesOnQuit);
556
static tConfItem<REAL> mp_wsu ("WALLS_STAY_UP_DELAY" , multiPlayer.wallsStayUpDelay);
557
static tConfItem<REAL> mp_wl ("WALLS_LENGTH" , multiPlayer.wallsLength );
558
static tConfItem<REAL> mp_er ("EXPLOSION_RADIUS" , multiPlayer.explosionRadius );
560
static tSettingItem<int> sp_sw("SP_SCORE_WIN" ,singlePlayer.scoreWin);
561
static tSettingItem<int> sp_lt("SP_LIMIT_TIME" ,singlePlayer.limitTime);
562
static tSettingItem<int> sp_lr("SP_LIMIT_ROUNDS",singlePlayer.limitRounds);
563
static tSettingItem<int> sp_ls("SP_LIMIT_SCORE" ,singlePlayer.limitScore);
565
static tConfItem<int> sp_na("SP_NUM_AIS" ,singlePlayer.numAIs);
566
static tConfItem<int> sp_mp("SP_MIN_PLAYERS" ,singlePlayer.minPlayers);
567
static tConfItem<int> sp_iq("SP_AI_IQ" ,singlePlayer.AI_IQ);
569
static tConfItem<bool> sp_an("SP_AUTO_AIS" ,singlePlayer.autoNum);
570
static tConfItem<bool> sp_aq("SP_AUTO_IQ" ,singlePlayer.autoIQ);
572
static tConfItem<int> sp_sf("SP_SPEED_FACTOR",singlePlayer.speedFactor);
573
static tConfItem<int> sp_zf("SP_SIZE_FACTOR" ,singlePlayer.sizeFactor);
575
static tConfItem<gGameType> sp_gt("SP_GAME_TYPE",singlePlayer.gameType);
576
static tConfItem<gFinishType> sp_ft("SP_FINISH_TYPE",singlePlayer.finishType);
578
static tConfItem<int> sp_wzmr("SP_WIN_ZONE_MIN_ROUND_TIME",singlePlayer.winZoneMinRoundTime);
579
static tConfItem<int> sp_wzld("SP_WIN_ZONE_MIN_LAST_DEATH",singlePlayer.winZoneMinLastDeath);
581
static tConfItem<int> sp_tmin ("SP_TEAMS_MIN", singlePlayer.minTeams);
582
static tConfItem<int> sp_tmax ("SP_TEAMS_MAX", singlePlayer.maxTeams);
583
static tConfItem<int> sp_mtp ("SP_TEAM_MIN_PLAYERS", singlePlayer.minPlayersPerTeam);
584
static tConfItem<int> sp_tp ("SP_TEAM_MAX_PLAYERS", singlePlayer.maxPlayersPerTeam);
585
static tConfItem<int> sp_tib ("SP_TEAM_MAX_IMBALANCE", singlePlayer.maxTeamImbalance);
586
static tConfItem<bool> sp_tbai ("SP_TEAM_BALANCE_WITH_AIS", singlePlayer.balanceTeamsWithAIs);
587
static tConfItem<bool> sp_tboq ("SP_TEAM_BALANCE_ON_QUIT", singlePlayer.enforceTeamRulesOnQuit);
589
static tConfItem<REAL> sp_wsu ("SP_WALLS_STAY_UP_DELAY" , singlePlayer.wallsStayUpDelay);
590
static tConfItem<REAL> sp_wl ("SP_WALLS_LENGTH" , singlePlayer.wallsLength );
591
static tConfItem<REAL> sp_er ("SP_EXPLOSION_RADIUS" , singlePlayer.explosionRadius );
593
static void GameSettingsMP(){
597
static void GameSettingsSP(){
601
static void GameSettingsCurrent(){
602
sg_currentSettings->Menu();
605
static REAL sg_Timeout = 5.0f;
606
static tConfItem<REAL> sg_ctimeout("GAME_TIMEOUT" , sg_Timeout );
608
bool sg_TalkToMaster = true;
609
static tSettingItem<bool> sg_ttm("TALK_TO_MASTER",
612
class gHighscoresBase{
614
static tList<gHighscoresBase> highscoreList;
616
tArray<tString> highName;
618
char* highscore_file;
622
// find the player at position i
623
ePlayerNetID *online(int p){
624
for (int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
625
if (se_PlayerNetIDs(i)->IsHuman() && !strcmp(se_PlayerNetIDs(i)->GetUserName(),highName[p]))
626
return se_PlayerNetIDs(i);
631
// i is the active player, j the passive one
632
virtual void swap_entries(int i,int j){
633
Swap(highName[i],highName[j]);
635
// swap: i is now the passive player
637
// send the poor guy who just dropped a message
638
ePlayerNetID *p=online(i);
641
name << *p << tColoredString::ColorString(1,.5,.5);
644
message.SetTemplateParameter(1, static_cast<const char *>(name));
645
message.SetTemplateParameter(2, static_cast<const char *>(highName[j]));
646
message.SetTemplateParameter(3, i+1);
647
message.SetTemplateParameter(4, desc);
650
message << "$league_message_rose" ;
652
message << "$league_message_dropped" ;
658
sn_ConsoleOut(s,p->Owner());
664
void load_Name(std::istream &s,int i){
666
while (s.good() && !s.eof() && isspace(c))
670
// read and filter name
673
ePlayerNetID::FilterName( name, highName[i] );
676
void save_Name(std::ostream &s,int i){
683
virtual void Save()=0;
684
virtual void Load()=0;
686
// returns if i should stay above j
687
virtual bool inorder(int i,int j)=0;
690
// since single score items travel up the
691
// score ladder, this is the most efficient sort algorithm:
693
for(int i=1;i<highName.Len();i++)
694
for(int j=i;j>=1 && !inorder(j-1,j);j--)
699
int checkPos(int found){
702
while(newpos>0 && !inorder(newpos-1,newpos)){
703
swap_entries(newpos,newpos-1);
708
while(newpos<highName.Len()-1 && !inorder(newpos,newpos+1)){
709
swap_entries(newpos,newpos+1);
718
int Find(const char *name,bool force=false){
719
int found=highName.Len();
720
for(int i=found-1;i>=0 ;i--)
721
if(highName[i].Len()<=1 || !strcmp(highName[i],name)){
725
if (force && highName[found].Len()<=1)
726
highName[found]=name;
731
gHighscoresBase(char *name,char *sd,int max=0)
732
:id(-1),highscore_file(name),desc(sd),maxSize(max){
733
highscoreList.Add(this,id);
736
virtual ~gHighscoresBase(){
737
highscoreList.Remove(this,id);
740
virtual void greet_this(ePlayerNetID *p,tOutput &o){
743
int f=Find(p->GetUserName())+1;
744
int l=highName.Len();
746
o.SetTemplateParameter(1, f);
747
o.SetTemplateParameter(2, l);
748
o.SetTemplateParameter(3, desc);
751
o << "$league_message_greet";
753
o << "$league_message_greet_new";
758
static void Greet(ePlayerNetID *p,tOutput &o){
759
o << "$league_message_greet_intro";
760
for(int i=highscoreList.Len()-1;i>=0;i--){
761
highscoreList(i)->greet_this(p,o);
763
o << "$league_message_greet_sep" << " ";
765
o << " " << "$league_message_greet_lastsep" << " ";
770
static void SaveAll(){
771
for(int i=highscoreList.Len()-1;i>=0;i--)
772
highscoreList(i)->Save();
775
static void LoadAll(){
776
for(int i=highscoreList.Len()-1;i>=0;i--)
777
highscoreList(i)->Load();
782
tString GreetHighscores()
785
gHighscoresBase::Greet(eCallbackGreeting::Greeted(),o);
791
static eCallbackGreeting g(GreetHighscores);
793
tList<gHighscoresBase> gHighscoresBase::highscoreList;
795
template<class T>class highscores: public gHighscoresBase{
797
tArray<T> high_score;
799
virtual void swap_entries(int i,int j){
800
Swap(high_score[i],high_score[j]);
801
gHighscoresBase::swap_entries(i,j);
806
tTextFileRecorder stream( tDirectories::Var(), highscore_file );
808
while ( !stream.EndOfFile() )
810
std::stringstream s( stream.GetLine() );
813
// con << highName[i] << " " << high_score[i] << '\n';
818
// returns if i should stay above j
819
virtual bool inorder(int i,int j)
821
return (highName[j].Len()<=1 || high_score[i]>=high_score[j]);
830
tString filename(highscore_file);
831
if ( tRecorder::IsPlayingBack() )
833
filename += ".playback";
836
if ( tDirectories::Var().Open ( s, filename ) )
839
int max=high_score.Len();
840
if (maxSize && max>maxSize)
842
while (i<max && highName[i].Len()>1){
844
mess << high_score[i];
845
mess.SetPos(10, false );
851
//save_Name(std::cout,i);
857
void checkPos(int found,const tString &name,T score){
859
// find the name in the list
862
message.SetTemplateParameter(1, name);
863
message.SetTemplateParameter(2, desc);
864
message.SetTemplateParameter(3, score);
866
if (highName[found].Len()<=1){
867
highName[found]=name;
868
message << "$highscore_message_entered";
869
high_score[found]=score;
872
else if (score>high_score[found]){
873
message << "$highscore_message_improved";
874
high_score[found]=score;
880
int newpos=gHighscoresBase::checkPos(found);
882
message.SetTemplateParameter(4, newpos + 1);
884
if (newpos!=found || isnew)
886
message << "$highscore_message_move_top";
888
message << "$highscore_message_move_pos";
891
message << "$highscore_message_stay_top";
893
message << "$highscore_message_stay_pos";
897
ePlayerNetID *p=online(newpos);
900
sn_ConsoleOut(tString(message),p->Owner());
904
void Add( ePlayerNetID* player,T AddScore)
907
tString const & name = player->GetUserName();
908
int f=Find(name,true);
909
checkPos(f,name,AddScore+high_score[f]);
912
void Add( eTeam* team,T AddScore)
914
if ( team->NumHumanPlayers() > 0 )
916
for ( int i = team->NumPlayers() - 1 ; i>=0; --i )
918
ePlayerNetID* player = team->Player( i );
919
if ( player->IsHuman() )
921
this->Add( player, AddScore );
927
void Check(const ePlayerNetID* player,T score){
929
tString name = player->GetUserName();
930
int len = high_score.Len();
931
if (len<=0 || score>high_score[len-1]){
932
// find the name in the list
933
int found=Find(name,true);
934
checkPos(found,name,score);
938
highscores(char *name,char *sd,int max=0)
939
:gHighscoresBase(name,sd,max){
943
virtual ~highscores(){
950
static REAL ladder_min_bet=1;
951
static tSettingItem<REAL> ldd_mb("LADDER_MIN_BET",
954
static REAL ladder_perc_bet=10;
955
static tSettingItem<REAL> ldd_pb("LADDER_PERCENT_BET",
958
static REAL ladder_tax=1;
959
static tSettingItem<REAL> ldd_tex("LADDER_TAX",
962
static REAL ladder_lose_perc_on_load=.2;
963
static tSettingItem<REAL> ldd_lpl("LADDER_LOSE_PERCENT_ON_LOAD",
964
ladder_lose_perc_on_load);
966
static REAL ladder_lose_min_on_load=.2;
967
static tSettingItem<REAL> ldd_lml("LADDER_LOSE_MIN_ON_LOAD",
968
ladder_lose_min_on_load);
970
static REAL ladder_gain_extra=1;
971
static tSettingItem<REAL> ldd_ga("LADDER_GAIN_EXTRA",
975
class ladder: public highscores<REAL>{
978
highscores<REAL>::Load();
982
int end=highName.Len();
984
for(int i=highName.Len()-1;i>=0;i--){
986
// make them lose some points
988
REAL loss=ladder_lose_perc_on_load*high_score[i]*.01;
989
if (loss<ladder_lose_min_on_load)
990
loss=ladder_lose_min_on_load;
997
// remove the bugggers with less than 0 points
998
highName.SetLen(end);
999
high_score.SetLen(end);
1002
void checkPos(int found,const tString &name,REAL score){
1005
message.SetTemplateParameter(1, name);
1006
message.SetTemplateParameter(2, desc);
1007
message.SetTemplateParameter(3, score);
1009
// find the name in the list
1011
if (highName[found].Len()<=1){
1012
highName[found]=name;
1013
message << "$ladder_message_entered";
1014
high_score[found]=score;
1018
REAL diff=score-high_score[found];
1019
message.SetTemplateParameter(5, static_cast<float>(fabs(diff)));
1022
message << "$ladder_message_gained";
1024
message << "$ladder_message_lost";
1026
high_score[found]=score;
1030
int newpos=gHighscoresBase::checkPos(found);
1032
message.SetTemplateParameter(4, newpos + 1);
1034
if (newpos!=found || isnew)
1036
message << "$ladder_message_move_top";
1038
message << "$ladder_message_move_pos";
1041
message << "$ladder_message_stay_top";
1043
message << "$ladder_message_stay_pos";
1047
ePlayerNetID *p=online(newpos);
1050
sn_ConsoleOut(tString(message),p->Owner());
1056
void Add(const tString &name,REAL AddScore){
1057
int found=Find(name,true);
1058
checkPos(found,name,AddScore+high_score[found]);
1061
// ladder mechanics: what happens if someone wins?
1062
void winner( eTeam *winningTeam ){
1063
tASSERT( winningTeam );
1065
// AI won? bail out.
1066
if ( winningTeam->NumHumanPlayers() <= 0 )
1071
// only do something in multiplayer mode
1075
tArray<ePlayerNetID*> active;
1077
for(i=se_PlayerNetIDs.Len()-1;i>=0;i--)
1079
ePlayerNetID* p=se_PlayerNetIDs(i);
1081
// only take enemies of the current winners (and the winners themselves) into the list
1082
if (p->IsHuman() && ( p->CurrentTeam() == winningTeam || eTeam::Enemies( winningTeam, p ) ) )
1085
active[active.Len()] = p;
1089
// only one active player? quit.
1090
if ( active.Len() <= 1 )
1101
for(i=active.Len()-1;i>=0;i--){
1103
nums[i]=Find(active(i)->GetUserName(),true);
1105
if (high_score[nums[i]]<0)
1106
high_score[nums[i]]=0;
1108
bet[i]=high_score[nums[i]]*ladder_perc_bet*.01;
1109
if (bet[i]<ladder_min_bet)
1110
bet[i]=ladder_min_bet;
1114
pot-=pot*ladder_tax*.01; // you have to pay to the bank :-)
1116
// now bet[i] tells us how much player nums[i] has betted
1117
// and pot is the overall bet. Add something to it, prop to
1118
// the winners ping+ping charity:
1120
// take the bet from the losers and give it to the winner
1121
for(i=active.Len()-1; i>=0; i--)
1123
ePlayerNetID* player = active(i);
1124
if(player->CurrentTeam() == winningTeam )
1126
REAL pc=player->ping + player->pingCharity*.001;
1129
if (pc>1) // add sensible bounds
1132
REAL potExtra = pc*ladder_gain_extra;
1134
if ( player->Object() && player->Object()->Alive() )
1139
Add(player->GetUserName(), ( pot / winningTeam->NumHumanPlayers() + potExtra ) - bet[i] );
1143
Add(player->GetUserName(),-bet[i]);
1148
ladder(char *name,char *sd,int max=0)
1149
:highscores<REAL>(name,sd,max){
1159
static highscores<int> highscore("highscores.txt","$highscore_description",100);
1160
static highscores<int> highscore_won_rounds("won_rounds.txt",
1161
"$won_rounds_description");
1162
static highscores<int> highscore_won_matches("won_matches.txt",
1163
"$won_matches_description");
1164
static ladder highscore_ladder("ladder.txt",
1165
"$ladder_description");
1167
#define PREPARE_TIME 4
1169
static bool just_connected=true;
1170
static bool sg_singlePlayer=0;
1171
static int winner=0;
1172
static int absolute_winner=0;
1173
static REAL lastTime_gameloop=0;
1174
static REAL lastTimeTimestep=0;
1176
static int wishWinner = 0;
1177
static char const * wishWinnerMessage = "";
1179
void sg_DeclareWinner( eTeam* team, char const * message )
1181
if ( team && !winner )
1183
wishWinner = team->TeamID() + 1;
1184
wishWinnerMessage = message;
1189
if (sg_singlePlayer)
1190
if(se_PlayerNetIDs.Len()>0 && se_PlayerNetIDs(0)->IsHuman())
1191
highscore.Check(se_PlayerNetIDs(0),se_PlayerNetIDs(0)->Score());
1195
static tCONTROLLED_PTR(gGame) sg_currentGame;
1200
static gCycle *Cycle(int id){
1201
eGameObject *object=NULL;
1202
for(int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
1203
if (se_PlayerNetIDs[i]->pID==id && se_PlayerNetIDs[i]->Object())
1204
object=se_PlayerNetIDs[i]->Object();
1206
return dynamic_cast<gCycle *>(object);
1211
#include "PowerPak/poweruInput.h"
1212
#include "PowerPak/joystick.h"
1215
#include "rRender.h"
1223
void exit_game_grid(eGrid *grid){
1227
void exit_game_objects(eGrid *grid){
1228
sr_con.fullscreen=true;
1230
su_prefetchInput=false;
1233
for(i=ePlayer::Num()-1;i>=0;i--){
1234
if (ePlayer::PlayerConfig(i))
1235
tDESTROY(ePlayer::PlayerConfig(i)->cam);
1239
gNetPlayerWall::Clear();
1241
if (sn_GetNetState()!=nCLIENT)
1242
for(int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
1243
if(se_PlayerNetIDs(i))
1244
se_PlayerNetIDs(i)->ClearObject();
1246
eGameObject::DeleteAll(grid);
1248
exit_game_grid(grid);
1251
REAL exponent(int i)
1258
REAL fac = sqrtf(2);
1262
if ( 1 == (abs & 1) )
1276
void init_game_grid(eGrid *grid, gParser *aParser){
1277
se_ResetGameTimer();
1278
se_PauseGameTimer(true);
1282
sr_ResetRenderState();
1284
// rSysDep::ClearGL();
1286
// glViewport (0, 0, static_cast<GLsizei>(sr_screenWidth), static_cast<GLsizei>(sr_screenHeight));
1288
// rSysDep::SwapGL();
1297
Arena.PrepareGrid(grid, aParser);
1299
absolute_winner=winner=wishWinner=0;
1305
for (int i = se_PlayerNetIDs.Len()-1; i>=0; i--)
1307
ePlayerNetID* p = se_PlayerNetIDs(i);
1308
if (p->IsHuman() && p->IsActive() && ( bool(p->CurrentTeam()) || bool(p->NextTeam()) ) )
1317
// return se_PlayerNetIDs.Len() ;
1319
return sn_NumUsers();
1321
return sn_NumUsers() + 1;
1325
static void sg_copySettings()
1327
eTeam::minTeams = sg_currentSettings->minTeams;
1328
eTeam::maxTeams = sg_currentSettings->maxTeams;
1329
eTeam::maxPlayers = sg_currentSettings->maxPlayersPerTeam;
1330
eTeam::minPlayers = sg_currentSettings->minPlayersPerTeam;
1331
eTeam::maxImbalance = sg_currentSettings->maxTeamImbalance;
1332
eTeam::balanceWithAIs = sg_currentSettings->balanceTeamsWithAIs;
1333
eTeam::enforceRulesOnQuit = sg_currentSettings->enforceTeamRulesOnQuit;
1335
gCycle::SetWallsStayUpDelay ( sg_currentSettings->wallsStayUpDelay );
1336
gCycle::SetWallsLength ( sg_currentSettings->wallsLength );
1337
gCycle::SetExplosionRadius ( sg_currentSettings->explosionRadius );
1338
gCycle::SetSpeedMultiplier ( exponent( sg_currentSettings->speedFactor ) );
1339
gArena::SetSizeMultiplier ( exponent( sg_currentSettings->sizeFactor ) );
1342
void update_settings()
1344
if (sn_GetNetState()!=nCLIENT)
1347
// wait for players to join
1349
bool restarted = false;
1351
REAL timeout = tSysTimeFloat() + 3.0f;
1352
while ( sg_NumHumans() <= 0 && sg_NumUsers() > 0 )
1354
if ( !restarted && bool(sg_currentGame) )
1356
sg_currentGame->StartNewMatch();
1360
if ( tSysTimeFloat() > timeout )
1362
tOutput o("$gamestate_wait_players");
1363
sn_CenterMessage(o);
1365
tOutput o2("$gamestate_wait_players_con");
1368
timeout = tSysTimeFloat() + 10.0f;
1370
// kick spectators and chatbots
1371
nMachine::KickSpectators();
1372
ePlayerNetID::RemoveChatbots();
1375
gGame::NetSyncIdle();
1379
if ( sg_NumUsers() <= 0 && bool( sg_currentGame ) )
1381
sg_currentGame->NoLongerGoOn();
1384
// count the active players
1385
int humans = sg_NumHumans();
1387
bool newsg_singlePlayer = (humans<=1);
1389
bool newsg_singlePlayer = (sn_GetNetState() == nSTANDALONE);
1391
if (sg_singlePlayer != newsg_singlePlayer && bool( sg_currentGame ) )
1393
sg_currentGame->StartNewMatch();
1395
sg_singlePlayer=newsg_singlePlayer;
1397
if (sg_singlePlayer)
1398
sg_currentSettings = &singlePlayer;
1400
sg_currentSettings = &multiPlayer;
1405
// update team properties
1406
for (int i = eTeam::teams.Len() - 1; i>=0; --i)
1407
eTeam::teams(i)->UpdateProperties();
1410
static int sg_spawnPointGroupSize=0;
1411
static tSettingItem< int > sg_spawnPointGroupSizeConf( "SPAWN_POINT_GROUP_SIZE", sg_spawnPointGroupSize );
1413
void init_game_objects(eGrid *grid){
1415
static REAL r[MAX_PLAYERS]={1,.2,.2,1};
1416
static REAL g[MAX_PLAYERS]={.2,1,.2,1};
1417
static REAL b[MAX_PLAYERS]={.2,.2,1,.2};
1420
if (sn_GetNetState()!=nCLIENT)
1422
// update team settings
1423
gAIPlayer::SetNumberOfAIs(sg_currentSettings->numAIs,
1424
sg_currentSettings->minPlayers,
1425
sg_currentSettings->AI_IQ);
1427
int spawnPointsUsed = 0;
1428
for(int t=eTeam::teams.Len()-1;t>=0;t--)
1430
eTeam *team = eTeam::teams(t);
1433
gSpawnPoint *spawn = Arena.LeastDangerousSpawnPoint();
1436
// if the spawn points are grouped, make sure the last player is not in a goup of his
1437
// own by skipping one spawnpoint
1438
if ( ( eTeam::teams(0)->IsHuman() || eTeam::teams(0)->NumPlayers() == 1 ) && sg_spawnPointGroupSize > 2 && ( spawnPointsUsed % sg_spawnPointGroupSize == sg_spawnPointGroupSize - 1 ) )
1440
// the next spawn point is the last of this group. Skip it if
1441
// either only two players are left (and the one would need to play alone)
1442
// or we can fill the remaining groups well with one player short.
1443
if ( t == 2 || ( ( t % ( sg_spawnPointGroupSize - 1 ) ) == 0 && t < ( sg_spawnPointGroupSize - 1 ) * ( sg_spawnPointGroupSize - 1 ) ) )
1446
spawn->Spawn( pos, dir );
1447
spawn = Arena.LeastDangerousSpawnPoint();
1452
int numPlayers = team->NumPlayers();
1453
for (int p = 0; p<numPlayers; ++p)
1455
ePlayerNetID *pni=team->Player( p );
1457
if ( !team->IsHuman() )
1459
spawn = Arena.LeastDangerousSpawnPoint();
1463
// bool isHuman = pni->IsHuman();
1465
#ifdef KRAWALL_SERVER
1466
// don't allow unknown players to play
1471
// don't give inactive players a cycle
1472
if (!pni->IsActive())
1477
if (sn_GetNetState()!=nCLIENT){
1479
// std::cout << "spawning player " << pni->name << '\n';
1481
spawn->Spawn(pos,dir);
1483
cycle = new gCycle(grid, pos, dir, pni, 0);
1484
pni->ControlObject(cycle);
1485
nNetObject::SyncAll();
1487
// int i=se_PlayerNetIDs(p)->pID;
1489
// se_ResetGameTimer();
1490
// se_PauseGameTimer(true);
1495
#ifdef ALLOW_NO_TEAM
1496
for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
1497
ePlayerNetID *pni=se_PlayerNetIDs(p);
1499
gSpawnPoint *spawn=Arena.LeastDangerousSpawnPoint();
1501
if ( NULL == pni->CurrentTeam() )
1503
#ifdef KRAWALL_SERVER
1504
// don't allow unknown players to play
1509
// don't give inactive players a cycle
1510
if (!pni->IsActive())
1515
if (sn_GetNetState()!=nCLIENT){
1517
//con << "spawning player " << se_PlayerNetIDs[p]->name << '\n';
1521
spawn->Spawn(pos,dir);
1523
cycle = new gCycle(grid, pos, dir, pni, 0);
1524
pni->ControlObject(cycle);
1525
nNetObject::SyncAll();
1527
// int i=se_PlayerNetIDs(p)->pID;
1529
// se_ResetGameTimer();
1530
// se_PauseGameTimer(true);
1537
for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
1538
ePlayerNetID *pni=se_PlayerNetIDs(p);
1540
bool isHuman = pni->IsHuman();
1542
#ifdef KRAWALL_SERVER
1543
// don't allow unknown players to play
1548
// don't give inactive players a cycle
1549
if (!pni->IsActive())
1554
if (sn_GetNetState()!=nCLIENT){
1556
//con << "spawning player " << se_PlayerNetIDs[p]->name << '\n';
1558
spawn->Spawn(pos,dir);
1560
cycle = new gCycle(grid, pos, dir, pni, 0);
1561
pni->ControlObject(cycle);
1562
nNetObject::SyncAll();
1564
// int i=se_PlayerNetIDs(p)->pID;
1566
se_ResetGameTimer();
1567
se_PauseGameTimer(true);
1569
if (sg_currentSettings->gameType==gHUMAN_VS_AI){
1571
// Cycle(p)->team=1;
1574
spawn=Arena.LeastDangerousSpawnPoint();
1585
//con << "new eSpawnPoint.\n";
1589
spawn=Arena.LeastDangerousSpawnPoint();
1596
// Cycle(p)->team=p+1;
1601
// spawn=Arena.LeastDangerousSpawnPoint();
1604
static REAL rgb[MAXAI][3]={
1619
rITexture::LoadAll();
1620
// se_ResetGameTimer();
1621
// se_PauseGameTimer(true);
1623
su_prefetchInput=true;
1625
lastTime_gameloop=lastTimeTimestep=0;
1627
// reset scores, all players that are spawned need to get ladder points
1628
ePlayerNetID::ResetScoreDifferences();
1631
void init_game_camera(eGrid *grid){
1633
for(int i=ePlayer::Num()-1;i>=0;i--)
1634
if (ePlayer::PlayerIsInGame(i)){
1635
ePlayerNetID *p=ePlayer::PlayerConfig(i)->netPlayer;
1637
if ( sg_currentSettings->finishType == gFINISH_EXPRESS && ( sn_GetNetState() != nCLIENT ) )
1638
se_ResetGameTimer( -PREPARE_TIME/5 - sg_extraRoundTime );
1640
se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
1642
// se_PauseGameTimer(true);
1644
ePlayer::PlayerConfig(i)->cam=new gCamera(grid,
1645
ePlayer::PlayerViewport(i),
1647
ePlayer::PlayerConfig(i),
1650
lastTime_gameloop=lastTimeTimestep=0;
1653
se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
1654
se_PauseGameTimer(false);
1657
for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
1658
int i=se_PlayerNetIDs(p)->pID;
1660
se_ResetGameTimer(-PREPARE_TIME);
1661
se_PauseGameTimer(true);
1664
playerConfig[i]->cam=new eCamera(PlayerViewport(i),
1665
se_PlayerNetIDs(p),CAMERA_SMART);
1674
void s_Timestep(eGrid *grid, REAL time,bool cam){
1675
gNetPlayerWall::s_CopyIntoGrid();
1677
eGameObject::s_Timestep(grid, time);
1680
eCamera::s_Timestep(grid, time);
1683
lastTimeTimestep=time;
1687
void RenderAllViewports(eGrid *grid){
1688
rViewportConfiguration *conf=rViewportConfiguration::CurrentViewportConfiguration();
1691
sr_ResetRenderState();
1693
// enable distance based fog
1695
glFogi( GL_FOG_MODE, GL_EXP );
1696
glFogf( GL_FOG_DENSITY, .01/gArena::SizeMultiplier() );
1697
GLfloat black[3]={0,0,0};
1698
glFogfv( GL_FOG_COLOR, black );
1702
const tList<eCamera>& cameras = grid->Cameras();
1704
for(int i=cameras.Len()-1;i>=0;i--){
1705
int p=sr_viewportBelongsToPlayer[i];
1707
rViewport *act=conf->Port(i);
1708
if (act && ePlayer::PlayerConfig(p))
1709
ePlayer::PlayerConfig(p)->Render();
1710
else con << "hey! viewport " << i << " does not exist!\n";
1713
// glDisable( GL_FOG );
1718
eGameObject::PPDisplayAll();
1719
PD_ShowDoubleBuffer();
1726
void Render(eGrid *grid, REAL time, bool swap=true){
1728
// eFace::UpdateVisAll(10);
1734
RenderAllViewports(grid);
1736
sr_ResetRenderState(true);
1743
(!sr_highRim && !sr_lowerSky && !sr_upperSky) ||
1744
sr_floorDetail<rFLOOR_TEXTURE ||
1745
sr_floorMirror==rMIRROR_OBJECTS){
1764
if ( tDirectories::Var().Open(s, "players.txt") ){
1765
if (se_PlayerNetIDs.Len()>0)
1766
s << tColoredString::RemoveColors(ePlayerNetID::Ranking( -1, false ));
1771
for(int i=MAXCLIENTS;i>0;i--)
1772
if (sn_Connections[i].socket)
1775
o << "$online_activity_nobody";
1777
o << "$online_activity_onespec";
1780
o.SetTemplateParameter(1, count);
1781
o << "$online_activity_manyspec";
1791
static void own_game( nNetState enter_state ){
1794
sg_EnterGame( enter_state );
1796
// write scores one last time
1797
ePlayerNetID::LogScoreDifferences();
1798
se_SaveToLadderLog(tString("GAME_END\n"));
1800
sg_currentGame=NULL;
1804
static void singlePlayer_game(){
1805
sn_SetNetState(nSTANDALONE);
1808
ePlayerNetID::CompleteRebuild();
1810
own_game( nSTANDALONE );
1815
// create a game to check map once
1816
tJUST_CONTROLLED_PTR< gGame > game = tNEW(gGame);
1820
if (sg_TalkToMaster)
1821
nServerInfo::TellMasterAboutMe();
1823
sn_SetNetState(nSERVER);
1826
ePlayerNetID::CompleteRebuild();
1832
static double startTime=tSysTimeFloat();
1834
if ( sg_NumUsers() == 0)
1837
con << tOutput("$online_activity_napping") << "\n";
1844
while(numPlayers == 0 &&
1845
(ded_idle<.0001 || tSysTimeFloat()<startTime + ded_idle * 3600 ) && !uMenu::quickexit ){
1847
gGame::NetSyncIdle();
1851
// std::cout the players who are logged in:
1852
numPlayers = sg_NumUsers();
1854
for (int i = se_PlayerNetIDs.Len()-1; i>=0; i--)
1855
if (se_PlayerNetIDs(i)->IsAuth())
1861
// restart network, just in case we lost the input socket
1862
sn_BasicNetworkSystem.AccessListener().Listen(false);
1863
sn_BasicNetworkSystem.AccessListener().Listen(true);
1868
if (sg_NumUsers() <= 0 && ded_idle>0.0001 &&
1869
tSysTimeFloat()>= startTime + ded_idle * 3600 )
1871
uMenu::quickexit = true;
1876
if (!uMenu::quickexit)
1879
own_game( nSERVER );
1881
sn_SetNetState(nSTANDALONE);
1883
// close listening sockets
1884
sn_BasicNetworkSystem.AccessListener().Listen(false);
1887
static tString sg_roundCenterMessage("");
1888
static tConfItemLine sn_roundCM_ci("ROUND_CENTER_MESSAGE",sg_roundCenterMessage);
1890
static tString sg_roundConsoleMessage("");
1891
static tConfItemLine sn_roundCcM1_ci("ROUND_CONSOLE_MESSAGE",sg_roundConsoleMessage);
1893
static bool sg_RequestedDisconnection = false;
1895
static void sg_NetworkError( const tOutput& title, const tOutput& message, REAL timeout )
1897
if ( sn_DenyReason.Len() > 2 )
1899
tOutput message2 ( message );
1900
message2.AddLiteral("\n\n");
1901
message2.AddLocale("network_kill_preface");
1902
message2.AddLiteral("\n");
1903
message2.AddLiteral(sn_DenyReason);
1904
tConsole::Message( title, message2, timeout );
1908
tConsole::Message( title, message, timeout );
1912
// revert settings to defaults in the current scope
1913
class gSettingsReverter
1918
// restore default configuration of network settings, saving your settings
1919
nConfItemBase::s_SaveValues();
1920
nConfItemBase::s_RevertToDefaults();
1923
~gSettingsReverter()
1925
// restore saved values
1926
nConfItemBase::s_RevertToSavedValues();
1930
void ConnectToServer(nServerInfoBase *server)
1934
ePlayerNetID::ClearAll();
1936
// revert to default settings, restore current vlaues on exit
1937
gSettingsReverter reverter;
1939
sn_bigBrotherString = renderer_identification;
1941
nNetObject::ClearAll();
1943
just_connected=true;
1945
rViewport::Update(MAX_PLAYERS);
1946
// ePlayerNetID::Update();
1956
sr_con.autoDisplayAtNewline=true;
1957
sr_con.fullscreen=true;
1964
nConnectError error = nOK;
1966
nNetObject::ClearAll();
1968
o.SetTemplateParameter(1, server->GetName());
1969
o << "$network_connecting_to_server";
1971
error = server->Connect();
1978
sg_NetworkError("$network_message_timeout_title", "$network_message_timeout_inter", 20);
1986
sg_NetworkError("$network_message_denied_title", sn_DenyReason.Len() > 2 ? "$network_message_denied_inter2" : "$network_message_denied_inter", 20);
1998
// ePlayerNetID::CompleteRebuild();
2000
if (sn_GetNetState()==nCLIENT){
2001
REAL endTime=tSysTimeFloat()+30;
2002
con << tOutput("$network_connecting_gamestate");
2003
while (!sg_currentGame && tSysTimeFloat()<endTime && (sn_GetNetState() != nSTANDALONE)){
2005
nNetObject::SyncAll();
2013
tAdvanceFrame(sn_defaultDelay);
2015
if (sg_currentGame){
2016
sr_con.autoDisplayAtNewline=false;
2017
sr_con.fullscreen=false;
2019
con << tOutput("$network_syncing_gamestate");
2020
sg_EnterGame( nCLIENT );
2023
//con << "Timeout. Try again!\n";
2024
sg_NetworkError("$network_message_lateto_title", "$network_message_lateto_inter", 20);
2029
if (!sg_RequestedDisconnection && !uMenu::quickexit)
2030
switch (sn_GetLastError())
2033
sg_NetworkError("$network_message_abortconn_title",
2034
"$network_message_abortconn_inter", 20);
2037
sg_NetworkError("$network_message_lostconn_title",
2038
"$network_message_lostconn_inter", 20);
2042
sr_con.autoDisplayAtNewline=false;
2043
sr_con.fullscreen=false;
2045
sn_SetNetState(nSTANDALONE);
2047
sg_currentGame = NULL;
2048
nNetObject::ClearAll();
2049
ePlayerNetID::ClearAll();
2054
static tConfItem<int> mor("MAX_OUT_RATE",sn_maxRateOut);
2055
static tConfItem<int> mir("MAX_IN_RATE",sn_maxRateIn);
2058
static tConfItem<int> pc("PING_CHARITY",pingCharity);
2061
uMenu *sg_IngameMenu=NULL;
2062
uMenu *sg_HostMenu =NULL;
2064
void ret_to_MainMenu(){
2065
sg_RequestedDisconnection = true;
2068
sg_HostMenu->Exit();
2071
sg_IngameMenu->Exit();
2073
sr_con.fullscreen=true;
2074
sr_con.autoDisplayAtNewline=true;
2077
sg_currentGame->NoLongerGoOn();
2079
sn_SetNetState(nSTANDALONE);
2081
uMenu::SetIdle(NULL);
2087
uMenu net_menu("$network_opts_text");
2089
uMenuItemInt high_port
2090
(&net_menu,"$network_opts_maxport_text",
2091
"$network_opts_maxport_help",
2092
gServerBrowser::highPort,1024,65536);
2094
uMenuItemInt low_port
2095
(&net_menu,"$network_opts_minport_text",
2096
"$network_opts_minport_help",
2097
gServerBrowser::lowPort,1024,65536);
2100
uMenuItemFunction delpw(&net_menu,
2101
"$network_opts_deletepw_text",
2102
"$network_opts_deletepw_help",
2103
&se_DeletePasswords);
2105
uMenuItemSelection<int> storepw(&net_menu,
2106
"$login_storepw_text",
2107
"$login_storepw_help",
2108
se_PasswordStorageMode);
2109
storepw.NewChoice("$login_storepw_dont_text",
2110
"$login_storepw_dont_help",
2112
storepw.NewChoice("$login_storepw_mem_text",
2113
"$login_storepw_mem_help",
2115
storepw.NewChoice("$login_storepw_disk_text",
2116
"$login_storepw_disk_help",
2121
uMenuItemToggle master
2122
(&net_menu,"$network_opts_master_text",
2123
"$network_opts_master_help",
2128
uMenuItemInt out_rate
2129
(&net_menu,"$network_opts_outrate_text",
2130
"$network_opts_outrate_help",
2131
sn_maxRateOut,1,20);
2134
uMenuItemInt in_rate
2135
(&net_menu,"$network_opts_inrate_text",
2136
"$network_opts_inrate_help",
2141
(&net_menu,"$network_opts_predict_text",
2142
"$network_opts_predict_help",
2146
(&net_menu,"$network_opts_lagometer_text",
2147
"$network_opts_lagometer_help",
2152
(&net_menu,"$network_opts_pingchar_text",
2153
"$network_opts_pingchar_help",
2154
pingCharity,0,300,20);
2158
if (gServerBrowser::lowPort > gServerBrowser::highPort)
2159
gServerBrowser::highPort = gServerBrowser::lowPort;
2162
void sg_HostGameMenu(){
2163
uMenu net_menu("$network_host_text");
2165
sg_HostMenu = &net_menu;
2167
uMenuItemInt port(&net_menu, "$network_host_port_text",
2168
"$network_host_port_help"
2169
,reinterpret_cast<int &>(sn_serverPort), gServerBrowser::lowPort, gServerBrowser::highPort);
2171
uMenuItemString serverName
2172
(&net_menu,"$network_host_name_text",
2173
"$network_host_name_help",
2176
uMenuItemFunction settings1
2178
"$game_settings_menu_text",
2179
"$game_settings_menu_help",
2182
uMenuItemFunction serv
2183
(&net_menu,"$network_host_host_text",
2184
"$network_host_host_help",&sg_HostGame);
2186
net_menu.ReverseItems();
2187
net_menu.SetSelected(0);
2195
uMenu net_menu("$network_menu_text");
2197
uMenuItemFunction cust
2198
(&net_menu,"$network_custjoin_text",
2199
"$network_custjoin_help",&gServerFavorites::CustomConnectMenu);
2202
uMenuItemFunction fav
2203
(&net_menu,"$bookmarks_menu",
2204
"$bookmarks_menu_help",&gServerFavorites::FavoritesMenu);
2206
uMenuItemFunction opt
2207
(&net_menu,"$network_opts_text",
2208
"$network_opts_help",&net_options);
2211
uMenuItemFunction serv
2212
(&net_menu,"$network_host_text",
2213
"$network_host_help",&sg_HostGameMenu);
2216
uMenuItemFunction inter
2217
(&net_menu,"$network_menu_internet_text",
2218
"$network_menu_internet_help",&gServerBrowser::BrowseMaster);
2220
uMenuItemFunction lan
2221
(&net_menu,"$network_menu_lan_text",
2222
"$network_menu_lan_help",&gServerBrowser::BrowseLAN);
2229
static void StartNewMatch(){
2231
sg_currentGame->StartNewMatch();
2232
if (sn_GetNetState()!=nCLIENT){
2233
sn_CenterMessage("$gamestate_reset_center");
2234
sn_ConsoleOut("$gamestate_reset_console");
2238
static void StartNewMatch_conf(std::istream &){
2242
static tConfItemFunc snm("START_NEW_MATCH",&StartNewMatch_conf);
2245
static void Quit_conf(std::istream &){
2247
if ( sg_currentGame )
2249
sg_currentGame->NoLongerGoOn();
2252
// mark end of recording
2253
tRecorder::Playback("END");
2254
tRecorder::Record("END");
2255
uMenu::quickexit = true;
2258
static tConfItemFunc quit_conf("QUIT",&Quit_conf);
2259
static tConfItemFunc exit_conf("EXIT",&Quit_conf);
2263
void MainMenu(bool ingame){
2264
// update_settings();
2267
sr_con.SetHeight(2);
2269
gLogo::SetDisplayed(true);
2273
gametitle << "$game_menu_text";
2275
gametitle << "$game_menu_ingame_text";
2277
uMenu game_menu(gametitle);
2279
uMenuItemFunction *reset=NULL;
2281
if(ingame && sn_GetNetState()!=nCLIENT){
2282
reset=new uMenuItemFunction
2283
(&game_menu,"$game_menu_reset_text",
2284
"$game_menu_reset_help",
2288
uMenuItemFunction *settings1=NULL;
2291
settings1=tNEW(uMenuItemFunction)
2293
"$game_settings_menu_text",
2294
"$game_settings_menu_help",
2297
settings1=tNEW(uMenuItemFunction)
2299
"$game_settings_menu_text",
2300
"$game_settings_menu_help",
2301
&GameSettingsCurrent);
2303
uMenuItemFunction *connect=NULL,*start=NULL,*sound=NULL;
2306
connect=new uMenuItemFunction
2308
"$network_menu_text",
2309
"$network_menu_help",
2312
start= new uMenuItemFunction(&game_menu,"$game_menu_start_text",
2313
"$game_menu_start_help",&singlePlayer_game);
2317
title.SetTemplateParameter( 1, sn_programVersion );
2319
title << "$main_menu_text";
2321
title << "$ingame_menu_text";
2323
uMenu MainMenu(title,false);
2326
sg_IngameMenu = &MainMenu;
2328
char *extitle,*exhelp;
2330
extitle="$main_menu_exit_text";
2331
exhelp="$main_menu_exit_help";
2334
extitle="$ingame_menu_exit_text";
2335
exhelp="$ingame_menu_exit_help";
2338
uMenuItemExit exx(&MainMenu,extitle,
2342
uMenuItemFunction *return_to_main=NULL;
2345
if (sn_GetNetState()==nSTANDALONE)
2346
return_to_main=new uMenuItemFunction
2347
(&MainMenu,"$game_menu_exit_text",
2348
"$game_menu_exit_help",
2350
else if (sn_GetNetState()==nCLIENT)
2351
return_to_main=new uMenuItemFunction
2352
(&MainMenu,"$game_menu_disconnect_text",
2353
"$game_menu_disconnect_help",
2356
return_to_main=new uMenuItemFunction
2358
"$game_menu_shutdown_text",
2359
"game_menu_shutdown_help",
2365
uMenu Settings("$system_settings_menu_text");
2367
uMenuItemSubmenu subm_settings
2368
(&MainMenu,&Settings,
2369
"$system_settings_menu_help");
2372
uMenuItem* team = NULL;
2375
team = tNEW( uMenuItemFunction) ( &MainMenu,
2381
uMenuItemFunction *se_PlayerMenu=NULL;
2384
se_PlayerMenu= new uMenuItemFunction
2385
(&MainMenu,"$player_mainmenu_text",
2386
"$player_mainmenu_help",
2389
uMenuItemFunction *player_police=NULL;
2390
uMenuItemFunction *voting=NULL;
2391
if ( ingame && sn_GetNetState() != nSTANDALONE )
2393
player_police = tNEW( uMenuItemFunction )( &MainMenu, "$player_police_text", "$player_police_help", ePlayerNetID::PoliceMenu );
2395
if ( eVoter::VotingPossible() )
2396
voting = tNEW( uMenuItemFunction )( &MainMenu, "$voting_menu_text", "$voting_menu_help", eVoter::VotingMenu );
2399
uMenu misc("$misc_menu_text");
2401
// misc.SetCenter(.25);
2403
uMenuItemFunction language
2404
(&misc,"$language_menu_title",
2405
"$language_menu_help",
2408
uMenuItemFunction global_key
2409
(&misc,"$misc_global_key_text",
2410
"$misc_global_key_help",
2411
&su_InputConfigGlobal);
2413
uMenuItemToggle wrap
2414
(&misc,"$misc_menuwrap_text",
2415
"$misc_menuwrap_help",
2419
(&misc,"$misc_textout_text",
2420
"$misc_textout_help",sr_textOut);
2425
(&misc,"$misc_moviepack_text",
2426
"$misc_moviepack_help",sg_moviepackUse);
2429
uMenuItemSubmenu misc_sm
2433
sound = new uMenuItemFunction
2434
(&Settings,"$sound_menu_text",
2435
"$sound_menu_help",&se_SoundMenu);
2437
uMenuItemSubmenu subm
2438
(&Settings,&sg_screenMenu,
2439
"$display_settings_menu_help");
2441
uMenuItemSubmenu *gamemenuitem = NULL;
2442
if (sn_GetNetState() != nCLIENT)
2446
gamehelp="$game_menu_main_help";
2448
gamehelp="$game_menu_ingame_help";
2450
gamemenuitem = tNEW(uMenuItemSubmenu) (&MainMenu,
2458
rViewport::Update(MAX_PLAYERS);
2459
// ePlayerNetID::Update();
2469
delete gamemenuitem;
2477
delete return_to_main;
2479
delete se_PlayerMenu;
2482
if ( player_police )
2483
delete player_police;
2492
gLogo::SetDisplayed(false);
2493
sr_con.SetHeight(7);
2501
#define GS_CREATED 0 // newborn baby
2502
#define GS_TRANSFER_SETTINGS 7
2503
#define GS_CREATE_GRID 10
2504
#define GS_CREATE_OBJECTS 20
2505
#define GS_TRANSFER_OBJECTS 30
2506
#define GS_CAMERA 35
2507
#define GS_SYNCING 40
2508
#define GS_SYNCING2 41
2509
#define GS_SYNCING3 42
2511
#define GS_DELETE_OBJECTS 60
2512
#define GS_DELETE_GRID 70
2513
#define GS_STATE_MAX 80
2515
static bool sg_AbeforeB( int stateA, int stateB )
2517
return ( ( GS_STATE_MAX + stateA - stateB ) % GS_STATE_MAX > GS_STATE_MAX >> 2 );
2521
static void ingame_menu_cleanup();
2522
static void ingame_menu()
2524
// globalingame=true;
2527
se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
2528
if (sn_GetNetState()==nSTANDALONE)
2529
se_PauseGameTimer(true);
2534
ingame_menu_cleanup();
2540
ingame_menu_cleanup();
2543
static void ingame_menu_cleanup()
2545
if (sn_GetNetState()==nSTANDALONE)
2546
se_PauseGameTimer(false);
2547
se_ChatState(ePlayerNetID::ChatFlags_Menu, false);
2548
if ((bool(sg_currentGame) && sg_currentGame->GetState()!=GS_PLAY))
2549
// || se_PlayerNetIDs.Len()==0)
2551
rViewport::Update(MAX_PLAYERS);
2552
ePlayerNetID::Update();
2554
// globalingame=false;
2559
static nNOInitialisator<gGame> game_init(310,"game");
2561
nDescriptor &gGame::CreatorDescriptor() const{
2567
grid = tNEW(eGrid());
2569
stateNext=GS_TRANSFER_SETTINGS;
2572
sg_currentGame=this;
2574
// con << "Game created.\n";
2576
aParser = tNEW(gParser)(&Arena, grid);
2583
void gGame::NoLongerGoOn(){
2585
// stateNext=GS_DELETE_OBJECTS;
2586
if (sn_GetNetState()==nSERVER)
2590
// console with filter for remote admin output redirection
2591
class gMapLoadConsoleFilter:public tConsoleFilter{
2593
gMapLoadConsoleFilter()
2597
~gMapLoadConsoleFilter()
2601
tColoredString message_; // the console log for the error message
2603
// we want to come first
2604
virtual int DoGetPriority() const{ return -100; }
2606
// don't actually filter; take line and add it to the potential error message
2607
virtual void DoFilterLine( tString &line )
2609
message_ << line << "\n";
2613
static void sg_ParseMap ( gParser * aParser )
2617
gMapLoadConsoleFilter consoleLog;
2620
con << "Message stats:\n";
2621
for(int i=0;i<40;i++){
2622
con << i << ":" << sent_per_messid[i] << '\n';
2623
sent_per_messid[i]=0;
2627
con << "Loading map " << mapfile << "...\n";
2629
mapFD = tResourceManager::openResource(mapuri, mapfile);
2631
if (!mapFD || !aParser->LoadAndValidateMapXML("", mapFD, mapfile))
2633
tOutput errorMessage( sn_GetNetState() == nCLIENT ? "$map_file_load_failure_server" : "$map_file_load_failure_self", mapfile );
2636
errorMessage << "\nLog:\n" << consoleLog.message_;
2639
con << errorMessage;
2641
tOutput errorTitle("$map_file_load_failure_title");
2643
if ( sn_GetNetState() != nSTANDALONE )
2645
throw tGenericException( errorMessage, errorTitle );
2648
mapFD = tResourceManager::openResource("", DEFAULT_MAP);
2649
if (!mapFD || !aParser->LoadAndValidateMapXML("", mapFD, DEFAULT_MAP)) {
2650
errorMessage << "$map_file_load_failure_default";
2651
throw tGenericException( errorMessage, errorTitle );
2659
void gGame::Verify()
2661
// test map and load map settings
2662
sg_ParseMap( aParser );
2663
init_game_grid(grid, aParser);
2664
exit_game_grid(grid);
2669
gLogo::SetDisplayed(false);
2670
if (sn_GetNetState()!=nCLIENT)
2675
gGame::gGame(nMessage &m):nNetObject(m){
2683
//con << "deleting game...\n";
2685
//stateNext=GS_CREATE_GRID;
2688
tASSERT( sg_currentGame != this );
2690
exit_game_objects(grid);
2692
ePlayerNetID::ThrowOutDisconnected();
2698
void gGame::WriteSync(nMessage &m){
2699
nNetObject::WriteSync(m);
2702
//con << "Wrote game state " << stateNext << ".\n";
2706
void gGame::ReadSync(nMessage &m){
2707
nNetObject::ReadSync(m);
2709
unsigned short newState;
2713
con << "Read gamestate " << newState << ".\n";
2716
// only update the state if it does not go back a few steps
2717
if ( sg_AbeforeB( stateNext, newState ) )
2718
stateNext = newState;
2721
//con << "Read game state " << stateNext << ".\n";
2726
void gGame::NetSync(){
2727
// find end of recording in playback
2728
if ( tRecorder::Playback("END") )
2730
tRecorder::Record("END");
2731
uMenu::quickexit=true;
2735
if (!sr_glOut && ePlayer::PlayerConfig(0)->cam)
2736
tERR_ERROR_INT("Someone messed with the camera!");
2738
nNetObject::SyncAll();
2741
void gGame::NetSyncIdle(){
2744
tAdvanceFrame( sn_defaultDelay );
2748
unsigned short client_gamestate[MAXCLIENTS+2];
2750
static void client_gamestate_handler(nMessage &m){
2751
unsigned short state;
2753
client_gamestate[m.SenderID()] = state;
2755
// con << "User " << m.SenderID() << " is in Mode " << state << '\n';
2759
static nDescriptor client_gs(311,client_gamestate_handler,"client_gamestate");
2763
void gGame::SyncState(unsigned short state){
2764
if (sn_GetNetState()==nSERVER){
2766
bool firsttime=true;
2768
REAL timeout=tSysTimeFloat()+sg_Timeout*.1;
2770
sn_Sync(sg_Timeout*.1,true);
2773
while(goon && tSysTimeFloat()<timeout){
2776
sg_currentGame->RequestSync();
2779
sn_Sync(sg_Timeout*.1,true);
2783
for(int i=MAXCLIENTS;i>0;i--)
2784
if ( sn_Connections[i].socket )
2786
int clientState = client_gamestate[i];
2787
if ( sg_AbeforeB( clientState, state ) )
2792
if (goon && firsttime){
2795
con << "Waiting for users to enter gamestate " << state << '\n';
2796
if (sn_Connections[1].ackPending>2)
2797
con << "Ack_pending=" << sn_Connections[1].ackPending << ".\n";
2805
void gGame::SetState(unsigned short act,unsigned short next){
2808
//con << "Entering gamestate " << state
2809
//<< ", next state: " << next << '\n';
2812
if (sn_GetNetState()==nSERVER){
2818
if (stateNext!=next){
2819
if (sn_GetNetState()!=nCLIENT || goon==false){
2823
if (sn_GetNetState()==nSERVER){
2832
extern REAL planned_rate_control[MAXCLIENTS+2];
2833
extern REAL sent_per_messid[100];
2835
static REAL lastdeath=0;
2837
void gGame::StateUpdate(){
2839
// if (state==GS_CREATED)
2840
// stateNext=GS_CREATE_GRID;
2842
while ( sg_AbeforeB( state, stateNext ) && goon )
2844
#ifdef CONNECTION_STRESS
2845
if ( sg_ConnectionStress )
2847
tRandomizer & randomizer = tRandomizer::GetInstance();
2848
int random = randomizer.Get( 16 );
2851
sg_RequestedDisconnection = true;
2852
// sn_SetNetState( nSTANDALONE );
2856
se_ChatState( ePlayerNetID::ChatFlags_Away, 1 );
2860
// unsigned short int mes1 = 1, mes2 = 1, mes3 = 1, mes4 = 1, mes5 = 1;
2863
case GS_DELETE_GRID:
2864
sr_con.autoDisplayAtNewline=true;
2866
con << tOutput("$gamestate_deleting_grid");
2867
// sn_ConsoleOut(sg_roundCenterMessage + "\n");
2868
sn_CenterMessage(sg_roundCenterMessage);
2870
// for (unsigned short int mycy = 0; mycy > sg_roundConsoleMessage5.Len(); c++)
2872
exit_game_objects(grid);
2875
SetState(GS_TRANSFER_SETTINGS,GS_CREATE_GRID);
2877
state=GS_CREATE_GRID;
2880
case GS_TRANSFER_SETTINGS:
2881
sr_con.autoDisplayAtNewline=true;
2883
// transfer game settings
2884
if ( nCLIENT != sn_GetNetState() )
2887
ePlayerNetID::RemoveChatbots();
2890
rViewport::Update(MAX_PLAYERS);
2892
// log scores before players get renamed
2893
ePlayerNetID::LogScoreDifferences();
2894
se_SaveToLadderLog(tString("NEW_ROUND\n"));
2897
nMachine::KickSpectators();
2899
// rename players as per request
2900
if ( synced_ && sn_GetNetState() != nSERVER )
2901
ePlayerNetID::Update();
2903
nConfItemBase::s_SendConfig(false);
2904
sn_Sync( sg_Timeout*.1, true );
2906
SetState(GS_CREATE_GRID,GS_CAMERA);
2909
case GS_CREATE_GRID:
2910
sr_con.autoDisplayAtNewline=true;
2912
sg_ParseMap( aParser );
2917
con << tOutput("$gamestate_creating_grid");
2921
init_game_grid(grid, aParser);
2923
nNetObject::ClearAllDeleted();
2925
SetState(GS_CREATE_OBJECTS,GS_CAMERA);
2927
case GS_CREATE_OBJECTS:
2928
// con << "Creating objects...\n";
2932
// rename players as per request
2934
ePlayerNetID::Update();
2936
init_game_objects(grid);
2937
s_Timestep(grid, se_GameTime(), false);
2938
SetState(GS_TRANSFER_OBJECTS,GS_CAMERA);
2940
if (sn_GetNetState() == nCLIENT && just_connected){
2941
sn_Sync(sg_Timeout*.1,true);
2942
sn_Sync(sg_Timeout*.1,true);
2944
just_connected=false;
2947
case GS_TRANSFER_OBJECTS:
2948
// con << "Transferring objects...\n";
2949
rITexture::LoadAll();
2950
// se_ResetGameTimer();
2951
// se_PauseGameTimer(true);
2955
if(sn_GetNetState()==nSERVER){
2957
double timeout=tSysTimeFloat()+sg_Timeout*.4;
2958
while(goon && tSysTimeFloat()<timeout){
2961
for(int i=MAXCLIENTS;i>0;i--)
2962
if (sn_Connections[i].socket)
2963
for(int j=sn_netObjects.Len()-1;j>=0;j--)
2964
if (sn_netObjects(j) &&
2965
!sn_netObjects(j)->HasBeenTransmitted(i) &&
2966
sn_netObjects(j)->syncRequested(i))
2969
if (tSysTimeFloat()<timeout)
2970
con << tOutput("$gamestate_done");
2972
con << tOutput("$gamestate_timeout_intro");
2973
for(int i=MAXCLIENTS;i>0;i--)
2974
if (sn_Connections[i].socket)
2975
for(int j=sn_netObjects.Len()-1;j>=0;j--)
2976
if (sn_netObjects(j) && !sn_netObjects(j)->HasBeenTransmitted(i))
2980
sn_netObjects(j)->PrintName( name );
2981
o.SetTemplateParameter(1, i);
2982
o.SetTemplateParameter(2, j);
2983
o.SetTemplateParameter(3, name);
2984
o << "$gamestate_timeout_message";
2991
// wait for players to ready
2992
if ( sn_GetNetState() == nSERVER )
2993
while ( ePlayerNetID::WaitToLeaveChat() )
2999
SetState(GS_CAMERA,GS_SYNCING);
3002
// con << "Setting camera position...\n";
3003
rITexture::LoadAll();
3004
// se_ResetGameTimer(-PREPARE_TIME);
3005
// se_PauseGameTimer(true);
3006
init_game_camera(grid);
3007
SetState(GS_SYNCING,GS_PLAY);
3010
// con << "Syncing timer...\n";
3011
rITexture::LoadAll();
3012
SetState(GS_PLAY,GS_PLAY);
3013
if (sn_GetNetState()!=nCLIENT){
3015
sn_ConsoleOut("$gamestate_resetnow_console");
3017
sn_CenterMessage("$gamestate_resetnow_center");
3018
se_SaveToScoreFile("$gamestate_resetnow_log");
3022
if (rounds < sg_currentSettings->limitRounds)
3024
mess.SetTemplateParameter(1, rounds+1);
3025
mess.SetTemplateParameter(2, sg_currentSettings->limitRounds);
3026
mess << "$gamestate_newround_console";
3028
if (strlen(sg_roundConsoleMessage) > 2)
3029
sn_ConsoleOut(sg_roundConsoleMessage + "\n");
3032
mess << "$gamestate_newround_goldengoal";
3033
sn_ConsoleOut(mess);
3035
se_SaveToScoreFile("$gamestate_newround_log");
3037
//con << ePlayerNetID::Ranking();
3039
se_PauseGameTimer(false);
3041
sr_con.fullscreen=false;
3042
sr_con.autoDisplayAtNewline=false;
3044
// pings count fully now
3045
nPingAverager::SetWeight(1);
3049
sr_con.autoDisplayAtNewline=false;
3052
if ( sg_NumUsers() <= 0 )
3060
// load contents of everytime.cfg for real
3061
if ( tDirectories::Config().Open(s, "everytime.cfg" ) )
3062
tConfItemBase::LoadAll(s);
3066
if ( tDirectories::Var().Open(s, "everytime.cfg" ) )
3067
tConfItemBase::LoadAll(s);
3069
// load contents of everytime.cfg from playback
3070
tConfItemBase::LoadPlayback();
3073
// safe current players in a file
3077
// pings should not count as much in the between-round phase
3078
nPingAverager::SetWeight(.001);
3080
se_UserShowScores(false);
3082
//con.autoDisplayAtNewline=true;
3083
sr_con.fullscreen=true;
3084
SetState(GS_DELETE_OBJECTS,GS_TRANSFER_SETTINGS);
3086
case GS_DELETE_OBJECTS:
3088
winDeathZone_ = NULL;
3090
rViewport::Update(MAX_PLAYERS);
3091
if ( synced_ && sn_GetNetState() != nSERVER )
3092
ePlayerNetID::Update();
3094
sr_con.autoDisplayAtNewline=true;
3096
gHighscoresBase::SaveAll();
3097
con << tOutput("$gamestate_deleting_objects");
3098
exit_game_objects(grid);
3099
SetState(GS_DELETE_GRID,GS_TRANSFER_SETTINGS);
3100
if ( !uMenu::MenuActive() )
3102
se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
3103
eVoter::VotingMenu();
3104
se_ChatState( ePlayerNetID::ChatFlags_Menu, false );
3106
nNetObject::ClearAllDeleted();
3111
if (sn_GetNetState()==nSERVER){
3116
else if (sn_GetNetState()==nCLIENT){ // inform the server of our progress
3118
nMessage *m=new nMessage(client_gs);
3122
// con << "sending gamestate " << state << '\n';
3129
// uncomment to activate respawning
3130
// #define RESPAWN_HACK
3133
// Respawns cycles (crude test)
3134
static void sg_Respawn( REAL time, eGrid *grid, gArena & arena )
3136
for ( int i = se_PlayerNetIDs.Len()-1; i >= 0; --i )
3138
ePlayerNetID *p = se_PlayerNetIDs(i);
3140
if ( !p->CurrentTeam() )
3143
eGameObject *e=p->Object();
3145
if ( ( !e || !e->Alive() && e->DeathTime() < time - .5 ) && sn_GetNetState() != nCLIENT )
3150
dir = e->Direction();
3151
pos = e->Position();
3152
eWallRim::Bound( pos, 1 );
3153
eCoord displacement = pos - e->Position();
3154
if ( displacement.NormSquared() > .01 )
3161
arena.LeastDangerousSpawnPoint()->Spawn( pos, dir );
3163
// std::cout << "spawning player " << pni->name << '\n';
3165
gCycle * cycle = new gCycle(grid, pos, dir, p, 0);
3166
p->ControlObject(cycle);
3172
static REAL sg_timestepMax = .2;
3173
static tSettingItem<REAL> sg_timestepMaxConf( "TIMESTEP_MAX", sg_timestepMax );
3174
static int sg_timestepMaxCount = 10;
3175
static tSettingItem<int> sg_timestepMaxCountConf( "TIMESTEP_MAX_COUNT", sg_timestepMaxCount );
3177
void gGame::Timestep(REAL time,bool cam){
3183
sg_Respawn(time,grid,Arena);
3186
// chop timestep into small, managable bits
3187
REAL dt = time - lastTimeTimestep;
3190
REAL lt = lastTimeTimestep;
3192
// determine the number of bits
3193
int number_of_steps=int(fabs((dt)/sg_timestepMax));
3194
if (number_of_steps<1)
3196
if ( number_of_steps > sg_timestepMaxCount )
3198
number_of_steps = sg_timestepMaxCount;
3202
for(int i=1;i<=number_of_steps;i++)
3204
REAL stepTime = lt + i * dt/number_of_steps;
3205
s_Timestep(grid, stepTime, cam);
3209
// check if team has any enemies currently
3210
static bool sg_EnemyExists( int team )
3212
// check if the win was legitimate: at least one enemy team needs to bo online
3213
for ( int i = eTeam::teams.Len()-1; i>= 0; --i )
3215
if ( i != team && eTeam::Enemies( eTeam::teams[i], eTeam::teams[team] ) )
3222
static REAL sg_winZoneRandomness = .8;
3223
static tSettingItem< REAL > sg_winZoneSpreadConf( "WIN_ZONE_RANDOMNESS", sg_winZoneRandomness );
3225
void gGame::Analysis(REAL time){
3226
if ( nCLIENT == sn_GetNetState() )
3229
static REAL wintimer=0;
3231
// send timeout warnings
3234
if (tSysTimeFloat()-startTime>10){
3235
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<10 && warning<6){
3236
tOutput o("$gamestate_tensecond_warn");
3237
sn_CenterMessage(o);
3243
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<30 && warning<5){
3244
tOutput o("$gamestate_30seconds_warn");
3245
sn_CenterMessage(o);
3251
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<60 && warning<4){
3252
tOutput o("$gamestate_minute_warn");
3253
sn_CenterMessage(o);
3258
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<2*60 && warning<3){
3259
tOutput o("$gamestate_2minutes_warn");
3264
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<5*60 && warning<2){
3265
tOutput o("$gamestate_5minutes_warn");
3270
if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<10*60 && warning<1){
3271
tOutput o("$gamestate_10minutes_warn");
3277
// count active players
3280
for(i=se_PlayerNetIDs.Len()-1;i>=0;i--){
3281
ePlayerNetID *pni=se_PlayerNetIDs(i);
3282
if (pni->IsActive())
3286
// count other statistics
3287
int alive_and_not_disconnected = 0;
3292
int last_team_alive=-1;
3293
int last_alive_and_not_disconnected=-1;
3295
int active_humans = 0;
3299
bool notyetloggedin = true; // are all current users not yet logged in?
3301
for(i=eTeam::teams.Len()-1;i>=0;i--){
3302
eTeam *t = eTeam::teams(i);
3304
humans += t->NumHumanPlayers();
3305
ais += t->NumAIPlayers();
3310
last_team_alive = i;
3313
if ( t->NumHumanPlayers() > 0 )
3315
for (int j=t->NumPlayers()-1; j>=0; --j)
3317
ePlayerNetID* p = t->Player(j);
3321
gCycle *g=dynamic_cast<gCycle *>(p->Object());
3323
notyetloggedin = false;
3333
last_alive_and_not_disconnected=i;
3334
alive_and_not_disconnected++;
3344
REAL dt=g->DeathTime();
3349
else if (p->IsAuth())
3350
notyetloggedin = false;
3355
for (int j=t->NumPlayers()-1; j>=0; --j)
3357
ePlayerNetID* p = t->Player(j);
3359
gCycle *g=dynamic_cast<gCycle *>(p->Object());
3372
if (sg_NumUsers() <= 0)
3377
if (last_alive_and_not_disconnected >= 0)
3378
last_alive = last_alive_and_not_disconnected;
3380
// kill all disconnected players if they are the only reason the round goes on:
3381
if ( alive_and_not_disconnected <= 1 && alive > alive_and_not_disconnected )
3383
for(int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
3385
gCycle *g=dynamic_cast<gCycle *>(se_PlayerNetIDs(i)->Object());
3386
if(g && !se_PlayerNetIDs(i)->IsActive())
3391
// alive = alive_and_not_disconnected;
3395
// keep the game running when there are only login processes running
3396
if (notyetloggedin && humans > 0)
3400
static int all_alive_last=0;
3402
int all_alive = ai_alive+alive;
3403
if (all_alive != all_alive_last)
3405
all_alive_last = ai_alive+alive;
3410
static nVersionFeature winZone(2);
3412
// activate instant win zone
3413
if ( winZone.Supported() && !bool( winDeathZone_ ) && winner == 0 && time - lastdeath > sg_currentSettings->winZoneMinLastDeath && time > sg_currentSettings->winZoneMinRoundTime )
3415
winDeathZone_ = sg_CreateWinDeathZone( grid, Arena.GetRandomPos( sg_winZoneRandomness ) );
3418
bool holdBackNextRound = false;
3421
if ( time-lastdeath < 1.0f )
3423
holdBackNextRound = true;
3425
else if (winner==0 && absolute_winner==0 ){
3426
if(teams_alive <= 1 )
3428
if ( sg_currentSettings->gameType!=gFREESTYLE )
3430
if ( eTeam::teams.Len()>1 && teams_alive<=1 ){
3431
winner=last_team_alive+1;
3437
if ( teams_alive < 1 )
3443
const char* survivor="$player_win_survivor";
3444
const char* messagetype = survivor;
3449
winner = wishWinner;
3451
messagetype = wishWinnerMessage;
3454
if (winner <= 0 && alive <= 0 && ai_alive <= 0 && teams_alive <= 0){
3455
if ( se_mainGameTimer )
3456
se_mainGameTimer->speed = 1;
3464
if ( se_mainGameTimer )
3465
se_mainGameTimer->speed = 1;
3468
if ( last_team_alive >= 0 )
3469
sg_currentSettings->AutoAI( eTeam::teams( last_team_alive )->NumHumanPlayers() > 0 );
3471
if ( sg_currentSettings->gameType!=gFREESTYLE && winner > 0 )
3473
// check if the win was legitimate: at least one enemy team needs to bo online
3474
if ( sg_EnemyExists( winner-1 ) )
3476
#ifdef KRAWALL_SERVER
3477
// send the result to the master server
3478
if (!dynamic_cast<gAIPlayer*>(eTeam::teams(winner-1)))
3480
tArray<tString> players;
3481
for (int i = eTeam::teams.Len()-1; i>=0; i--)
3482
if (i != winner-1 &&
3483
eTeam::teams(i)->Alive() &&
3484
eTeam::teams(i)->IsHuman() )
3486
players[players.Len()] = eTeam::teams(i)->Name();
3489
players[players.Len()] = eTeam::teams(winner-1)->Name();
3490
if (players.Len() > 1)
3491
nKrawall::ServerRoundEnd(&players(0), players.Len());
3496
eTeam::teams[winner-1]->AddScore
3497
(sg_currentSettings->scoreWin,messagetype, tOutput());
3498
if (!sg_singlePlayer &&
3499
eTeam::teams(winner-1)->NumHumanPlayers() >= 1 &&
3500
eTeam::teams(winner-1)->NumPlayers() >= 1 )
3502
highscore_won_rounds.Add(eTeam::teams[winner-1] ,1);
3503
highscore_ladder.winner(eTeam::teams(winner-1));
3506
// print winning message
3508
message << "$gamestate_winner_winner";
3509
message << eTeam::teams[winner-1]->Name();
3510
sn_CenterMessage(message);
3512
se_SaveToScoreFile(message);
3515
ladderLog << "ROUND_WINNER " << ePlayerNetID::FilterName( eTeam::teams[winner-1]->Name() ) << "\n";
3516
se_SaveToLadderLog( ladderLog );
3524
int winnerExtraRound = ( winner != 0 || alive == 0 ) ? 1 : 0;
3526
// analyze the ranking list
3527
if ( time-lastdeath < 2.0f )
3529
holdBackNextRound = true;
3531
else if (absolute_winner==0 &&
3532
sn_GetNetState()!=nCLIENT && se_PlayerNetIDs.Len()){
3533
ePlayerNetID::SortByScore();
3534
eTeam::SortByScore();
3535
if ( eTeam::teams.Len() > 0 )
3536
if (eTeam::teams.Len() <= 1
3537
|| ( eTeam::teams(0)->Score() > eTeam::teams(1)->Score() && sg_EnemyExists(0))){
3539
// only then we can have a true winner:
3540
if (eTeam::teams(0)->Score() >= sg_currentSettings->limitScore || // the score limit must be hit
3541
rounds + winnerExtraRound >= sg_currentSettings->limitRounds || // or the round limit
3542
tSysTimeFloat()>=startTime+sg_currentSettings->limitTime*60 || // or the time limit
3543
(active <= 1 && eTeam::teams.Len() > 1) // or all but one players must have disconnected.
3546
bool declareChampion = true;
3547
if ( winner!=0 && wintimer > time - ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 4.0 ) )
3549
declareChampion = false;
3550
holdBackNextRound= true;
3553
if ( declareChampion )
3555
lastdeath = time + ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 6.0f );
3559
message.SetTemplateParameter(1, eTeam::teams[0]->Name() );
3560
message << "$gamestate_champ_center";
3561
sn_CenterMessage(message);
3565
tColoredString name;
3566
name << eTeam::teams[0]->Name();
3567
name << tColoredString::ColorString(1,1,1);
3570
ladderLog << "MATCH_WINNER " << ePlayerNetID::FilterName( eTeam::teams[0]->Name() ) << "\n";
3571
se_SaveToLadderLog( ladderLog );
3573
message.SetTemplateParameter(1, name);
3574
message << "$gamestate_champ_console";
3576
if (eTeam::teams(0)->Score() >=sg_currentSettings->limitScore)
3578
message.SetTemplateParameter(1, eTeam::teams(0)->Score());
3579
message.SetTemplateParameter(2, sg_currentSettings->limitScore);
3580
message << "$gamestate_champ_scorehit";
3582
else if ( tSysTimeFloat()>=startTime+sg_currentSettings->limitTime*60)
3584
message.SetTemplateParameter(1, sg_currentSettings->limitTime);
3585
message << "$gamestate_champ_timehit";
3589
message.SetTemplateParameter(1, rounds + 1);
3590
message << "$gamestate_champ_default";
3593
se_SaveToScoreFile(message);
3594
se_SaveToScoreFile("$gamestate_champ_finalscores");
3595
se_SaveToScoreFile(eTeam::Ranking( -1, false ));
3596
se_SaveToScoreFile(ePlayerNetID::Ranking( -1, false ));
3597
se_SaveToScoreFile(sg_GetCurrentTime( "Time: %Y/%m/%d %H:%M:%S\n" ));
3598
se_SaveToScoreFile("\n\n");
3600
eTeam* winningTeam = eTeam::teams(0);
3601
if (!sg_singlePlayer && winningTeam->NumHumanPlayers() > 0 )
3603
highscore_won_matches.Add( winningTeam, 1 );
3606
sn_ConsoleOut(message);
3610
if ( se_mainGameTimer )
3611
se_mainGameTimer->speed = 1;
3620
// time to wait after last death til we start a new round
3623
if (sg_currentSettings->finishType==gFINISH_EXPRESS)
3626
if(( ( winner || absolute_winner ) && wintimer+fintime < time)
3627
|| (((alive==0 && eTeam::teams.Len()>=
3633
)) && time-lastdeath >fintime-2
3639
//con << "winner=" << winner << ' ';
3640
//con << "wintimer=" << wintimer << ' ';
3641
//con << "time=" << time << ' ';
3642
//con << "dt=" << deathTime << '\n';
3644
if (!holdBackNextRound &&
3646
( sg_currentSettings->finishType==gFINISH_IMMEDIATELY ||
3647
sg_currentSettings->finishType==gFINISH_EXPRESS ||
3648
absolute_winner || ( teams_alive <= 1 && time-lastdeath>4.0f ) ) ||
3649
( winner && time - wintimer> 4.0f )
3654
SetState(GS_PLAY,GS_DELETE_OBJECTS);
3657
if ( !winner && !absolute_winner && sg_currentSettings->finishType==gFINISH_SPEEDUP && se_mainGameTimer)
3659
se_mainGameTimer->speed*=1.01;
3660
if(se_mainGameTimer->speed>16)
3661
se_mainGameTimer->speed=16;
3666
for(i=se_PlayerNetIDs.Len()-1;i>=0;i--)
3668
gAIPlayer *ai = dynamic_cast<gAIPlayer*>(se_PlayerNetIDs(i));
3675
void gGame::StartNewMatch(){
3681
void gGame::StartNewMatchNow(){
3683
se_SaveToLadderLog(tString("NEW_MATCH\n"));
3687
startTime=tSysTimeFloat()-10;
3689
ePlayerNetID::ThrowOutDisconnected();
3690
ePlayerNetID::ResetScore();
3694
extern bool debug_grid;
3696
bool simplify_grid=1;
3700
static int sg_dedicatedFPS = 200;
3701
static tSettingItem<int> sg_dedicatedFPSConf( "DEDICATED_FPS", sg_dedicatedFPS );
3705
// mouse grab toggling
3706
static uActionGlobal togglemousegrab( "TOGGLE_MOUSEGRAB" );
3707
static bool togglemousegrab_func(REAL x){
3709
su_mouseGrab = !su_mouseGrab;
3714
static uActionGlobalFunc togglemousegrab_action(&togglemousegrab,&togglemousegrab_func, true );
3717
static uActionGlobal pausegame( "PAUSE_GAME" );
3718
static bool pausegame_func(REAL x){
3719
static bool paused=false;
3723
se_PauseGameTimer(paused);
3728
static uActionGlobalFunc pausegame_action(&pausegame,&pausegame_func, true );
3730
// texture reloading
3731
static uActionGlobal reloadtextures( "RELOAD_TEXTURES" );
3732
static bool reloadtextures_func(REAL x){
3734
rITexture::UnloadAll();
3739
static uActionGlobalFunc reloadtextures_action(&reloadtextures,&reloadtextures_func, true );
3742
static uActionGlobal ingamemenu( "INGAME_MENU" );
3743
static bool ingamemenu_func(REAL x){
3745
st_ToDo(&ingame_menu);
3750
static uActionGlobalFunc ingamemenu_action(&ingamemenu,&ingamemenu_func, true );
3753
bool gGame::GameLoop(bool input){
3754
nNetState netstate = sn_GetNetState();
3757
tDelay( 1000000 / sg_dedicatedFPS );
3764
grid->SimplifyAll(10);
3770
//if (std::cin.good() && !std::cin.underflow())
3771
//tConfItemBase::LoadAll(std::cin);
3775
if (state==GS_PLAY){
3777
if ( netstate != sn_GetNetState() )
3782
gtime=se_GameTime();
3785
if (sn_GetNetState()==nSTANDALONE && sg_IngameMenu)
3786
se_PauseGameTimer(true);
3788
static int lastcountdown=0;
3789
int cd=int(floor(-time))+1;
3790
if (cd>=0 && cd<PREPARE_TIME && cd!=lastcountdown && se_mainGameTimer && se_mainGameTimer->IsSynced() ){
3794
con.CenterDisplay(s,0);
3797
//con << sg_netPlayerWalls.Len() << '\n';
3801
su_HandleDelayedEvents();
3805
uInputProcessGuard inputProcessGuard;
3806
while(su_GetSDLInput(tEvent,time)){
3807
if (time>gtime) time=gtime;
3808
if(time>lastTime_gameloop){
3810
lastTime_gameloop=time;
3814
if (!su_HandleEvent(tEvent, false))
3815
switch (tEvent.type){
3816
case SDL_MOUSEBUTTONDOWN:
3819
switch (tEvent.key.keysym.sym){
3823
st_ToDo(&ingame_menu);
3827
debug_grid=!debug_grid;
3831
simplify_grid=!simplify_grid;
3847
fullscreen=(!fullscreen);
3848
con << fullscreen << "x!\n";
3849
XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
3869
if ( netstate != sn_GetNetState() )
3874
if (state==GS_PLAY){
3875
if (gtime<0 && gtime>-PREPARE_TIME+.3)
3876
eCamera::s_Timestep(grid, gtime);
3878
if (gtime>=lastTime_gameloop){
3880
#ifdef CONNECTION_STRESS
3881
if ( sg_ConnectionStress )
3883
tRandomizer & randomizer = tRandomizer::GetInstance();
3884
int random = randomizer.Get( 1000 );
3887
sg_RequestedDisconnection = true;
3888
// sn_SetNetState( nSTANDALONE );
3895
Timestep(gtime,true);
3897
lastTime_gameloop=gtime;
3899
lastTime_gameloop=gtime;
3901
// else if (lastTime_gameloop>gtime+10)
3902
// lastTime_gameloop=gtime;
3906
if (sn_GetNetState()!=nCLIENT)
3910
// wait for chatting players
3911
if ( sn_GetNetState()==nSERVER && gtime < sg_lastChatBreakTime + 1 )
3912
se_PauseGameTimer( gtime < sg_lastChatBreakTime && ePlayerNetID::WaitToLeaveChat() );
3915
bool synced = se_mainGameTimer && se_mainGameTimer->IsSynced();
3919
// see if there is a game object owned by this client, if so, declare emergency sync
3920
for (int pi = MAX_PLAYERS-1; pi >= 0; --pi )
3922
ePlayer * p = ePlayer::PlayerConfig(pi);
3925
ePlayerNetID * np = p->netPlayer;
3935
else if ( !synced_ )
3937
// synced finally. Send our player info over so we can join the game.
3938
ePlayerNetID::Update();
3942
if (sr_glOut && gtime>-PREPARE_TIME+.5 && goon && synced )
3944
Render(grid, gtime, input);
3952
con.CenterDisplay(tString(tOutput("$network_login_sync")),0);
3964
if ( netstate != sn_GetNetState() )
3972
// between rounds, assume we're synced
3973
if ( !synced_ && sn_GetNetState() != nSERVER )
3974
ePlayerNetID::Update();
3991
bool gGame::GridIsReady(int client){
3992
return HasBeenTransmitted(client) &&
3993
(client_gamestate[client]>=GS_TRANSFER_OBJECTS &&
3994
client_gamestate[client]<=GS_DELETE_OBJECTS);
4001
bool GameLoop(bool input=true){
4003
int oldflags = fcntl (fileno(stdin), F_GETFD, 0);
4005
std::cout << errno << '\n';
4007
if (fcntl(fileno(stdin), F_SETFL, oldflags | O_NONBLOCK)<0)
4008
std::cout << errno << '\n';
4010
//if (std::cin && std::cin.good() && !std::cin.eof() && !std::cin.fail() && !std::cin.bad()){
4011
//if (std::cin.rdbuf()->overflow()!=EOF){
4012
//if (std::cin.rdbuf()->in_avail()>0){
4016
in=read (fileno(stdin),c,9);
4017
for (int i=0;i<in;i++)
4021
// see if pings have dramatically changed
4022
if(sn_GetNetState()==nSERVER){
4023
REAL t=tSysTimeFloat();
4024
for(int i=se_PlayerNetIDs.Len()-1;i>=0;i--){
4025
ePlayerNetID *p=se_PlayerNetIDs(i);
4027
// get average and variance (increased a bit) of this player's ping
4028
nPingAverager const & averager = sn_Connections[p->Owner()].ping;
4029
REAL realping = averager.GetPing();
4030
REAL pingvariance = averager.GetSlowAverager().GetDataVariance() + realping * realping * .01;
4032
// deviation of real ping and synced ping
4033
REAL deviation = realping - p->ping;
4035
// measured against the variance, this player's ping deviates this much
4036
// from the communicated value
4037
REAL relativedeviation = deviation * deviation / pingvariance;
4039
if (0 == p->Owner())
4042
if ( ( t - p->lastSync - 5 ) * relativedeviation > 5 ){
4043
// if yes, send a message about it
4045
p->RequestSync(false);
4052
tControlledPTR< nNetObject > keep( sg_currentGame );
4053
sg_currentGame->StateUpdate();
4054
goon=!uMenu::quickexit && bool(sg_currentGame) && sg_currentGame->GameLoop(input);
4059
void gameloop_idle()
4061
se_UserShowScores( false );
4065
static eSoundPlayer introPlayer(intro);
4066
static eSoundPlayer extroPlayer(extro);
4068
static void sg_EnterGameCleanup();
4070
void sg_EnterGameCore( nNetState enter_state ){
4071
sg_RequestedDisconnection = false;
4073
sr_con.SetHeight(7);
4076
introPlayer.MakeGlobal();
4077
introPlayer.Reset();
4079
// exit_game_objects(grid);
4081
// enter single player settings
4082
if ( sn_GetNetState() != nCLIENT )
4084
sg_currentSettings = &singlePlayer;
4088
gHighscoresBase::LoadAll();
4090
uMenu::SetIdle(gameloop_idle);
4091
sr_con.autoDisplayAtSwap=true;
4093
while (bool(sg_currentGame) && goon && sn_GetNetState()==enter_state){
4094
#ifdef DEDICATED // read input
4102
extroPlayer.MakeGlobal();
4103
extroPlayer.Reset();
4105
sg_EnterGameCleanup();
4108
void sg_EnterGameCleanup()
4110
gHighscoresBase::SaveAll();
4112
sn_SetNetState( nSTANDALONE );
4114
// delete all AI players
4115
gAIPlayer::ClearAll();
4116
// gAIPlayer::SetNumberOfAIs(0, 0, 0, -1);
4117
// gAITeam::BalanceWithAIs( false );
4118
// gAIPlayer::ClearAll();
4120
gLogo::SetDisplayed(true);
4121
uMenu::SetIdle(NULL);
4122
sr_con.autoDisplayAtSwap=false;
4123
sr_con.fullscreen=false;
4125
// exit_game_objects(grid);
4126
nNetObject::ClearAll();
4127
ePlayerNetID::ClearAll();
4128
sg_currentGame = NULL;
4129
uMenu::exitToMain = false;
4132
void sg_EnterGame( nNetState enter_state )
4137
sg_EnterGameCore( enter_state );
4139
catch (tException const & e)
4142
sg_EnterGameCleanup();
4144
// inform user of generic errors
4145
tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
4147
// again: VC6 does not catch tGenericException with above statement
4149
#pragma warning ( disable : 4286 )
4150
catch (tGenericException const & e)
4153
sg_EnterGameCleanup();
4155
// inform user of generic errors
4156
tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
4161
for ( int i = eTeam::teams.Len()-1; i>=0; --i )
4163
tJUST_CONTROLLED_PTR< eTeam > t = eTeam::teams(i);
4167
bool GridIsReady(int c){
4168
return bool(sg_currentGame) && sg_currentGame->GridIsReady(c);
4172
// avoid transfer of game objects if the grid is not yes constructed
4173
static bool notrans(){
4174
return !GridIsReady(eTransferInhibitor::User());
4177
static eTransferInhibitor inh(¬rans);
4180
void Activate(bool act){
4186
se_SoundPause(!act);
4188
if (!tRecorder::IsRunning() )
4190
if (sn_GetNetState()==nSTANDALONE)
4192
se_PauseGameTimer(!act);
4195
se_ChatState( ePlayerNetID::ChatFlags_Away, !act);
4199
static void LoginCallback(){
4200
client_gamestate[nCallbackLoginLogout::User()]=0;
4203
static nCallbackLoginLogout lc(LoginCallback);