~swag/armagetronad/0.2.9-sty+ct+ap-fork

« back to all changes in this revision

Viewing changes to src/tron/gGame.cpp

  • Committer: luke-jr
  • Date: 2006-05-29 01:55:42 UTC
  • Revision ID: svn-v3-list-QlpoOTFBWSZTWZvbKhsAAAdRgAAQABK6798QIABURMgAAaeoNT1TxT1DQbKaeobXKiyAmlWT7Y5MkdJOtXDtB7w7DOGFBHiOBxaUIu7HQyyQSvxdyRThQkJvbKhs:7d95bf1e-0414-0410-9756-b78462a59f44:armagetronad%2Fbranches%2F0.2.8%2Farmagetronad:4612
Unify tags/branches of modules released together

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
*************************************************************************
 
4
 
 
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
 
6
Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
 
7
 
 
8
**************************************************************************
 
9
 
 
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.
 
14
 
 
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.
 
19
 
 
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.
 
23
  
 
24
***************************************************************************
 
25
 
 
26
*/
 
27
 
 
28
 
 
29
#include "gStuff.h"
 
30
#include "eSound.h"
 
31
#include "eGrid.h"
 
32
#include "eTeam.h"
 
33
#include "tSysTime.h"
 
34
#include "gGame.h"
 
35
#include "rTexture.h"
 
36
#include "gWall.h"
 
37
#include "rConsole.h"
 
38
#include "gCycle.h"
 
39
#include "eCoord.h"
 
40
#include "eTimer.h"
 
41
#include "gAIBase.h"
 
42
#include "rSysdep.h"
 
43
#include "rFont.h"
 
44
#include "uMenu.h"
 
45
#include "nConfig.h"
 
46
#include "rScreen.h"
 
47
#include "rViewport.h"
 
48
#include "uInput.h"
 
49
#include "ePlayer.h"
 
50
#include "gArena.h"
 
51
#include "gSpawn.h"
 
52
#include "uInput.h"
 
53
#include "uInputQueue.h"
 
54
#include "nNetObject.h"
 
55
#include "tToDo.h"
 
56
#include "gMenus.h"
 
57
#include "gCamera.h"
 
58
#include "gServerBrowser.h"
 
59
#include "gServerFavorites.h"
 
60
#include "gLogo.h"
 
61
#include "gLanguageMenu.h"
 
62
#include "nServerInfo.h"
 
63
#include "gAICharacter.h"
 
64
#include "tDirectories.h"
 
65
#include "gTeam.h"
 
66
#include "gWinZone.h"
 
67
#include "eVoter.h"
 
68
#include "tRecorder.h"
 
69
 
 
70
#include "gParser.h"
 
71
#include "tResourceManager.h"
 
72
 
 
73
#include <math.h>
 
74
#include <stdlib.h>
 
75
#include <string>
 
76
#include <fstream>
 
77
#include <ctype.h>
 
78
#include <time.h>
 
79
 
 
80
#include "nSocket.h"
 
81
 
 
82
#ifdef KRAWALL_SERVER
 
83
#include "nKrawall.h"
 
84
#endif
 
85
 
 
86
 
 
87
#ifndef DEDICATED
 
88
#include "rSDL.h"
 
89
#include <SDL_thread.h>
 
90
 
 
91
#ifdef DEBUG
 
92
#ifndef WIN32
 
93
//#include <GL/xmesa>
 
94
 
 
95
//static bool fullscreen=1;
 
96
#endif
 
97
#endif
 
98
#endif
 
99
 
 
100
#ifdef DEBUG
 
101
//#define CONNECTION_STRESS
 
102
#endif
 
103
 
 
104
tCONFIG_ENUM( gGameType );
 
105
tCONFIG_ENUM( gFinishType );
 
106
 
 
107
// extra round pause time
 
108
static REAL sg_extraRoundTime = 0.0f;
 
109
static tSettingItem<REAL> sg_extraRoundTimeConf( "EXTRA_ROUND_TIME", sg_extraRoundTime );
 
110
 
 
111
static REAL sg_lastChatBreakTime = -1.0f;
 
112
static tSettingItem<REAL> sg_lastChatBreakTimeConf( "LAST_CHAT_BREAK_TIME", sg_lastChatBreakTime );
 
113
 
 
114
static tString mapuri("0");
 
115
static nSettingItem<tString> conf_mapuri("MAP_URI",mapuri);
 
116
 
 
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 );
 
120
 
 
121
// bool globalingame=false;
 
122
tString sg_GetCurrentTime( char *szFormat )
 
123
{
 
124
    char szTemp[128];
 
125
    time_t     now;
 
126
    struct tm *pTime;
 
127
    now = time(NULL);
 
128
    pTime = localtime(&now);
 
129
    strftime(szTemp,sizeof(szTemp),szFormat,pTime);
 
130
    return tString(szTemp);
 
131
}
 
132
 
 
133
void sg_PrintCurrentTime( char *szFormat )
 
134
{
 
135
    con << sg_GetCurrentTime(szFormat);
 
136
}
 
137
 
 
138
void sg_PrintCurrentDate()
 
139
{
 
140
    sg_PrintCurrentTime( "%Y%m%d");
 
141
}
 
142
 
 
143
void sg_PrintCurrentTime()
 
144
{
 
145
    sg_PrintCurrentTime( "%H%M%S" );
 
146
}
 
147
 
 
148
void sg_Timestamp()
 
149
{
 
150
#ifdef DEDICATED
 
151
    sg_PrintCurrentTime( "Timestamp: %Y/%m/%d %H:%M:%S\n" );
 
152
    if ( tRecorder::IsRunning() )
 
153
    {
 
154
        con << "Uptime: " << int(tSysTimeFloat()) << " seconds.\n";
 
155
 
 
156
#ifdef DEBUG_X
 
157
        // to set breakpoints at specific round starts
 
158
        static double breakTime = 0;
 
159
        if ( tSysTimeFloat() > breakTime )
 
160
            st_Breakpoint();
 
161
#endif
 
162
    }
 
163
#endif
 
164
}
 
165
 
 
166
static REAL ded_idle=24;
 
167
static tSettingItem<REAL> dedicaded_idle("DEDICATED_IDLE",ded_idle);
 
168
 
 
169
 
 
170
static eWavData intro("moviesounds/intro.wav");
 
171
static eWavData extro("moviesounds/extro.wav");
 
172
 
 
173
 
 
174
#define MAXAI (gAICharacter::s_Characters.Len())
 
175
 
 
176
#define AUTO_AI_MAXFRAC 6
 
177
#define AUTO_AI_WIN     3
 
178
#define AUTO_AI_LOSE    1
 
179
 
 
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,
 
186
                             int a_minTeams,
 
187
                             int a_winZoneMinRoundTime, int a_winZoneMinLastDeath
 
188
                            )
 
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),
 
196
        minTeams(a_minTeams)
 
197
{
 
198
    autoAIFraction = AUTO_AI_MAXFRAC >> 1;
 
199
 
 
200
    maxTeams = 16;
 
201
    minPlayersPerTeam = 1;
 
202
    maxPlayersPerTeam = 10;
 
203
    maxTeamImbalance = 1;
 
204
    balanceTeamsWithAIs = true;
 
205
    enforceTeamRulesOnQuit = false;
 
206
 
 
207
    wallsStayUpDelay = 2.0f;
 
208
    wallsLength      = -1.0f;
 
209
    explosionRadius  = 4.0f;
 
210
}
 
211
 
 
212
void gGameSettings::AutoAI(bool success){
 
213
    if (!autoNum && !autoIQ)
 
214
        return;
 
215
 
 
216
    if (autoNum)
 
217
    {
 
218
        if (success)
 
219
        {
 
220
            autoAIFraction += AUTO_AI_WIN;
 
221
            while (autoAIFraction > AUTO_AI_MAXFRAC)
 
222
            {
 
223
                autoAIFraction -= AUTO_AI_MAXFRAC;
 
224
                if (numAIs < MAXAI) numAIs++;
 
225
            }
 
226
        }
 
227
        else
 
228
        {
 
229
            autoAIFraction -= AUTO_AI_LOSE;
 
230
            while (autoAIFraction < 0)
 
231
            {
 
232
                autoAIFraction += AUTO_AI_MAXFRAC;
 
233
                if (numAIs >= 2) numAIs--;
 
234
            }
 
235
        }
 
236
    }
 
237
 
 
238
 
 
239
    if (autoIQ)
 
240
    {
 
241
        if (!autoNum)
 
242
            AI_IQ += 4 * (success ? AUTO_AI_WIN : -AUTO_AI_LOSE);
 
243
        else
 
244
        {
 
245
            int total = numAIs * numAIs * AI_IQ;
 
246
            // try to keep total around 100: that is either 10 dumb AIs or
 
247
            // one smart AI.
 
248
 
 
249
            if (success)
 
250
                if (total > 100)
 
251
                    AI_IQ += AUTO_AI_WIN * 4;
 
252
                else
 
253
                    AI_IQ += AUTO_AI_WIN;
 
254
            else
 
255
                if (total < 100)
 
256
                    AI_IQ -= AUTO_AI_LOSE * 4;
 
257
                else
 
258
                    AI_IQ -= AUTO_AI_LOSE;
 
259
        }
 
260
    }
 
261
 
 
262
    if (AI_IQ > 100)
 
263
        AI_IQ = 100;
 
264
    if (AI_IQ < 0)
 
265
        AI_IQ = 0;
 
266
}
 
267
 
 
268
 
 
269
void gGameSettings::Menu()
 
270
{
 
271
    uMenu GameSettings("$game_settings_menu_text");
 
272
 
 
273
    uMenuItemInt wzmr
 
274
    (&GameSettings,
 
275
     "$game_menu_wz_mr_text",
 
276
     "$game_menu_wz_mr_help",
 
277
     winZoneMinRoundTime,0,1000,10);
 
278
 
 
279
    uMenuItemInt wzmld
 
280
    (&GameSettings,
 
281
     "$game_menu_wz_ld_text",
 
282
     "$game_menu_wz_ld_help",
 
283
     winZoneMinLastDeath,0,1000,10);
 
284
 
 
285
    uMenuItemToggle team_et
 
286
    (&GameSettings,
 
287
     "$game_menu_balance_quit_text",
 
288
     "$game_menu_balance_quit_help",
 
289
     enforceTeamRulesOnQuit);
 
290
 
 
291
    uMenuItemToggle team_bt
 
292
    (&GameSettings,
 
293
     "$game_menu_balance_ais_text",
 
294
     "$game_menu_balance_ais_help",
 
295
     balanceTeamsWithAIs);
 
296
 
 
297
    uMenuItemInt team_mi
 
298
    (&GameSettings,
 
299
     "$game_menu_imb_text",
 
300
     "$game_menu_imb_help",
 
301
     maxTeamImbalance,2,10);
 
302
 
 
303
    uMenuItemInt team_maxp
 
304
    (&GameSettings,
 
305
     "$game_menu_max_players_text",
 
306
     "$game_menu_max_players_help",
 
307
     maxPlayersPerTeam,1,16);
 
308
 
 
309
    uMenuItemInt team_minp
 
310
    (&GameSettings,
 
311
     "$game_menu_min_players_text",
 
312
     "$game_menu_min_players_help",
 
313
     minPlayersPerTeam,1,16);
 
314
 
 
315
    uMenuItemInt team_max
 
316
    (&GameSettings,
 
317
     "$game_menu_max_teams_text",
 
318
     "$game_menu_max_teams_help",
 
319
     maxTeams,1,16);
 
320
 
 
321
    uMenuItemInt team_min
 
322
    (&GameSettings,
 
323
     "$game_menu_min_teams_text",
 
324
     "$game_menu_min_teams_help",
 
325
     minTeams,1,16);
 
326
 
 
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",
 
332
                      gFINISH_EXPRESS);
 
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",
 
338
                      gFINISH_SPEEDUP);
 
339
    finisht.NewChoice("$game_menu_finish_normal_text",
 
340
                      "$game_menu_finish_normal_help",
 
341
                      gFINISH_NORMAL);
 
342
 
 
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",
 
348
                    gFREESTYLE);
 
349
    gamet.NewChoice("$game_menu_mode_lms_text",
 
350
                    "$game_menu_mode_lms_help",
 
351
                    gDUEL);
 
352
    /*
 
353
        gamet.NewChoice("$game_menu_mode_team_text",
 
354
                                        "$game_menu_mode_team_help",
 
355
                                        gHUMAN_VS_AI);
 
356
    */
 
357
 
 
358
    uMenuItemInt speedconf
 
359
    (&GameSettings,
 
360
     "$game_menu_speed_text",
 
361
     "$game_menu_speed_help",
 
362
     speedFactor,-10,10);
 
363
 
 
364
    uMenuItemInt sizeconf
 
365
    (&GameSettings,
 
366
     "$game_menu_size_text",
 
367
     "$game_menu_size_help",
 
368
     sizeFactor,-10,10);
 
369
 
 
370
    uMenuItemSelection<REAL> wsuconf
 
371
    (&GameSettings,
 
372
     "$game_menu_wallstayup_text",
 
373
     "$game_menu_wallstayup_help",
 
374
     wallsStayUpDelay);
 
375
    wsuconf.NewChoice( "$game_menu_wallstayup_infinite_text",
 
376
                       "$game_menu_wallstayup_infinite_help",
 
377
                       -1.0f );
 
378
    wsuconf.NewChoice( "$game_menu_wallstayup_immediate_text",
 
379
                       "$game_menu_wallstayup_immediate_help",
 
380
                       0.0f );
 
381
    wsuconf.NewChoice( "$game_menu_wallstayup_halfsecond_text",
 
382
                       "$game_menu_wallstayup_halfsecond_help",
 
383
                       0.5f );
 
384
    wsuconf.NewChoice( "$game_menu_wallstayup_second_text",
 
385
                       "$game_menu_wallstayup_second_help",
 
386
                       1.0f );
 
387
    wsuconf.NewChoice( "$game_menu_wallstayup_2second_text",
 
388
                       "$game_menu_wallstayup_2second_help",
 
389
                       2.0f );
 
390
    wsuconf.NewChoice( "$game_menu_wallstayup_4second_text",
 
391
                       "$game_menu_wallstayup_4second_help",
 
392
                       4.0f );
 
393
    wsuconf.NewChoice( "$game_menu_wallstayup_8second_text",
 
394
                       "$game_menu_wallstayup_8second_help",
 
395
                       8.0f );
 
396
    wsuconf.NewChoice( "$game_menu_wallstayup_16second_text",
 
397
                       "$game_menu_wallstayup_16second_help",
 
398
                       16.0f );
 
399
    wsuconf.NewChoice( "$game_menu_wallstayup_32second_text",
 
400
                       "$game_menu_wallstayup_32second_help",
 
401
                       32.0f );
 
402
 
 
403
    uMenuItemSelection<REAL> wlconf
 
404
    (&GameSettings,
 
405
     "$game_menu_wallslength_text",
 
406
     "$game_menu_wallslength_help",
 
407
     wallsLength);
 
408
    wlconf.NewChoice( "$game_menu_wallslength_infinite_text",
 
409
                      "$game_menu_wallslength_infinite_help",
 
410
                      -1.0f );
 
411
    wlconf.NewChoice( "$game_menu_wallslength_25meter_text",
 
412
                      "$game_menu_wallslength_25meter_help",
 
413
                      25.0f );
 
414
    wlconf.NewChoice( "$game_menu_wallslength_50meter_text",
 
415
                      "$game_menu_wallslength_50meter_help",
 
416
                      50.0f );
 
417
    wlconf.NewChoice( "$game_menu_wallslength_100meter_text",
 
418
                      "$game_menu_wallslength_100meter_help",
 
419
                      100.0f );
 
420
    wlconf.NewChoice( "$game_menu_wallslength_200meter_text",
 
421
                      "$game_menu_wallslength_200meter_help",
 
422
                      200.0f );
 
423
    wlconf.NewChoice( "$game_menu_wallslength_300meter_text",
 
424
                      "$game_menu_wallslength_300meter_help",
 
425
                      300.0f );
 
426
    wlconf.NewChoice( "$game_menu_wallslength_400meter_text",
 
427
                      "$game_menu_wallslength_400meter_help",
 
428
                      400.0f );
 
429
    wlconf.NewChoice( "$game_menu_wallslength_600meter_text",
 
430
                      "$game_menu_wallslength_600meter_help",
 
431
                      600.0f );
 
432
    wlconf.NewChoice( "$game_menu_wallslength_800meter_text",
 
433
                      "$game_menu_wallslength_800meter_help",
 
434
                      800.0f );
 
435
    wlconf.NewChoice( "$game_menu_wallslength_1200meter_text",
 
436
                      "$game_menu_wallslength_1200meter_help",
 
437
                      1200.0f );
 
438
    wlconf.NewChoice( "$game_menu_wallslength_1600meter_text",
 
439
                      "$game_menu_wallslength_1600meter_help",
 
440
                      1600.0f );
 
441
 
 
442
    uMenuItemSelection<REAL> erconf
 
443
    (&GameSettings,
 
444
     "$game_menu_exrad_text",
 
445
     "$game_menu_exrad_help",
 
446
     explosionRadius);
 
447
    erconf.NewChoice( "$game_menu_exrad_0_text",
 
448
                      "$game_menu_exrad_0_help",
 
449
                      0.0f );
 
450
    erconf.NewChoice( "$game_menu_exrad_2meters_text",
 
451
                      "$game_menu_exrad_2meters_help",
 
452
                      2.0f );
 
453
    erconf.NewChoice( "$game_menu_exrad_4meters_text",
 
454
                      "$game_menu_exrad_4meters_help",
 
455
                      4.0f );
 
456
    erconf.NewChoice( "$game_menu_exrad_8meters_text",
 
457
                      "$game_menu_exrad_8meters_help",
 
458
                      8.0f );
 
459
    erconf.NewChoice( "$game_menu_exrad_16meters_text",
 
460
                      "$game_menu_exrad_16meters_help",
 
461
                      16.0f );
 
462
    erconf.NewChoice( "$game_menu_exrad_32meters_text",
 
463
                      "$game_menu_exrad_32meters_help",
 
464
                      32.0f );
 
465
    erconf.NewChoice( "$game_menu_exrad_64meters_text",
 
466
                      "$game_menu_exrad_64meters_help",
 
467
                      64.0f );
 
468
    erconf.NewChoice( "$game_menu_exrad_128meters_text",
 
469
                      "$game_menu_exrad_128meters_help",
 
470
                      128.0f );
 
471
 
 
472
    uMenuItemToggle autoiqconf
 
473
    (&GameSettings,
 
474
     "$game_menu_autoiq_text",
 
475
     "$game_menu_autoiq_help",
 
476
     autoIQ);
 
477
 
 
478
    uMenuItemToggle autoaiconf
 
479
    (&GameSettings,
 
480
     "$game_menu_autoai_text",
 
481
     "$game_menu_autoai_help",
 
482
     autoNum);
 
483
 
 
484
 
 
485
    uMenuItemInt iqconf
 
486
    (&GameSettings,
 
487
     "$game_menu_iq_text",
 
488
     "$game_menu_iq_help",
 
489
     AI_IQ, 20, 100, 10);
 
490
 
 
491
    uMenuItemInt mpconf
 
492
    (&GameSettings,
 
493
     "$game_menu_minplayers_text",
 
494
     "$game_menu_minplayers_help",
 
495
     minPlayers,0,MAXAI);
 
496
 
 
497
    uMenuItemInt aiconf
 
498
    (&GameSettings,
 
499
     "$game_menu_ais_text",
 
500
     "$game_menu_ais_help",
 
501
     numAIs,0,MAXAI);
 
502
 
 
503
 
 
504
    GameSettings.Enter();
 
505
}
 
506
 
 
507
gGameSettings singlePlayer(10,
 
508
                           30, 10, 100000,
 
509
                           1,   0, 30,
 
510
                           true, true,
 
511
                           0  ,  -3,
 
512
                           gDUEL, gFINISH_IMMEDIATELY, 1,
 
513
                           100000, 1000000);
 
514
 
 
515
gGameSettings multiPlayer(10,
 
516
                          30, 10, 100,
 
517
                          0,   4, 100,
 
518
                          false, false,
 
519
                          0  ,  -3,
 
520
                          gDUEL, gFINISH_IMMEDIATELY, 2,
 
521
                          60, 30 );
 
522
 
 
523
gGameSettings* sg_currentSettings = &singlePlayer;
 
524
 
 
525
 
 
526
 
 
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);
 
531
 
 
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);
 
535
 
 
536
static tConfItem<bool>   mp_an("AUTO_AIS"    ,multiPlayer.autoNum);
 
537
static tConfItem<bool>   mp_aq("AUTO_IQ"     ,multiPlayer.autoIQ);
 
538
 
 
539
static tConfItem<int>    mp_sf("SPEED_FACTOR",multiPlayer.speedFactor);
 
540
static tConfItem<int>    mp_zf("SIZE_FACTOR" ,multiPlayer.sizeFactor);
 
541
 
 
542
static tConfItem<gGameType>    mp_gt("GAME_TYPE",multiPlayer.gameType);
 
543
static tConfItem<gFinishType>  mp_ft("FINISH_TYPE",multiPlayer.finishType);
 
544
 
 
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);
 
547
 
 
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);
 
555
 
 
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 );
 
559
 
 
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);
 
564
 
 
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);
 
568
 
 
569
static tConfItem<bool>   sp_an("SP_AUTO_AIS"    ,singlePlayer.autoNum);
 
570
static tConfItem<bool>   sp_aq("SP_AUTO_IQ"     ,singlePlayer.autoIQ);
 
571
 
 
572
static tConfItem<int>    sp_sf("SP_SPEED_FACTOR",singlePlayer.speedFactor);
 
573
static tConfItem<int>    sp_zf("SP_SIZE_FACTOR" ,singlePlayer.sizeFactor);
 
574
 
 
575
static tConfItem<gGameType>    sp_gt("SP_GAME_TYPE",singlePlayer.gameType);
 
576
static tConfItem<gFinishType>  sp_ft("SP_FINISH_TYPE",singlePlayer.finishType);
 
577
 
 
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);
 
580
 
 
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);
 
588
 
 
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 );
 
592
 
 
593
static void GameSettingsMP(){
 
594
    multiPlayer.Menu();
 
595
}
 
596
 
 
597
static void GameSettingsSP(){
 
598
    singlePlayer.Menu();
 
599
}
 
600
 
 
601
static void GameSettingsCurrent(){
 
602
    sg_currentSettings->Menu();
 
603
}
 
604
 
 
605
static REAL sg_Timeout = 5.0f;
 
606
static tConfItem<REAL>   sg_ctimeout("GAME_TIMEOUT"             ,               sg_Timeout );
 
607
 
 
608
bool sg_TalkToMaster = true;
 
609
static tSettingItem<bool> sg_ttm("TALK_TO_MASTER",
 
610
                                 sg_TalkToMaster);
 
611
 
 
612
class gHighscoresBase{
 
613
    int id;
 
614
    static tList<gHighscoresBase> highscoreList;
 
615
protected:
 
616
    tArray<tString> highName;
 
617
 
 
618
    char*   highscore_file;
 
619
    tOutput desc;
 
620
    int     maxSize;
 
621
 
 
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);
 
627
 
 
628
        return NULL;
 
629
    }
 
630
 
 
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]);
 
634
 
 
635
        // swap: i is now the passive player
 
636
 
 
637
        // send the poor guy who just dropped a message
 
638
        ePlayerNetID *p=online(i);
 
639
        if (p){
 
640
            tColoredString name;
 
641
            name << *p << tColoredString::ColorString(1,.5,.5);
 
642
 
 
643
            tOutput message;
 
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);
 
648
 
 
649
            if (i<j)
 
650
                message <<  "$league_message_rose" ;
 
651
            else
 
652
                message <<  "$league_message_dropped" ;
 
653
 
 
654
            message << "\n";
 
655
 
 
656
            tString s;
 
657
            s << message;
 
658
            sn_ConsoleOut(s,p->Owner());
 
659
            // con << message;
 
660
        }
 
661
 
 
662
    }
 
663
 
 
664
    void load_Name(std::istream &s,int i){
 
665
        char c=' ';
 
666
        while (s.good() && !s.eof() && isspace(c))
 
667
            s.get(c);
 
668
        s.putback(c);
 
669
 
 
670
        // read and filter name
 
671
        tString name;
 
672
        name.ReadLine( s );
 
673
        ePlayerNetID::FilterName( name, highName[i] );
 
674
    }
 
675
 
 
676
    void save_Name(std::ostream &s,int i){
 
677
        s << highName[i];
 
678
    }
 
679
 
 
680
 
 
681
public:
 
682
 
 
683
    virtual void Save()=0;
 
684
    virtual void Load()=0;
 
685
 
 
686
    // returns if i should stay above j
 
687
    virtual bool inorder(int i,int j)=0;
 
688
 
 
689
    void sort(){
 
690
        // since single score items travel up the
 
691
        // score ladder, this is the most efficient sort algorithm:
 
692
 
 
693
        for(int i=1;i<highName.Len();i++)
 
694
            for(int j=i;j>=1 && !inorder(j-1,j);j--)
 
695
                swap_entries(j,j-1);
 
696
    }
 
697
 
 
698
 
 
699
    int checkPos(int found){
 
700
        // move him up
 
701
        int newpos=found;
 
702
        while(newpos>0 && !inorder(newpos-1,newpos)){
 
703
            swap_entries(newpos,newpos-1);
 
704
            newpos--;
 
705
        }
 
706
 
 
707
        // move him down
 
708
        while(newpos<highName.Len()-1 && !inorder(newpos,newpos+1)){
 
709
            swap_entries(newpos,newpos+1);
 
710
            newpos++;
 
711
        }
 
712
 
 
713
        //Save();
 
714
 
 
715
        return newpos;
 
716
    }
 
717
 
 
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)){
 
722
                found=i;
 
723
            }
 
724
 
 
725
        if (force && highName[found].Len()<=1)
 
726
            highName[found]=name;
 
727
 
 
728
        return found;
 
729
    }
 
730
 
 
731
    gHighscoresBase(char *name,char *sd,int max=0)
 
732
            :id(-1),highscore_file(name),desc(sd),maxSize(max){
 
733
        highscoreList.Add(this,id);
 
734
    }
 
735
 
 
736
    virtual ~gHighscoresBase(){
 
737
        highscoreList.Remove(this,id);
 
738
    }
 
739
 
 
740
    virtual void greet_this(ePlayerNetID *p,tOutput &o){
 
741
        //    tOutput o;
 
742
 
 
743
        int f=Find(p->GetUserName())+1;
 
744
        int l=highName.Len();
 
745
 
 
746
        o.SetTemplateParameter(1, f);
 
747
        o.SetTemplateParameter(2, l);
 
748
        o.SetTemplateParameter(3, desc);
 
749
 
 
750
        if (l>=f)
 
751
            o << "$league_message_greet";
 
752
        else
 
753
            o << "$league_message_greet_new";
 
754
 
 
755
        //    s << o;
 
756
    }
 
757
 
 
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);
 
762
            if (i>1)
 
763
                o << "$league_message_greet_sep" << " ";
 
764
            if (i==1)
 
765
                o << " " << "$league_message_greet_lastsep" << " ";
 
766
        }
 
767
        o << ".\n";
 
768
    }
 
769
 
 
770
    static void SaveAll(){
 
771
        for(int i=highscoreList.Len()-1;i>=0;i--)
 
772
            highscoreList(i)->Save();
 
773
    }
 
774
 
 
775
    static void LoadAll(){
 
776
        for(int i=highscoreList.Len()-1;i>=0;i--)
 
777
            highscoreList(i)->Load();
 
778
    }
 
779
};
 
780
 
 
781
 
 
782
tString GreetHighscores()
 
783
{
 
784
    tOutput o;
 
785
    gHighscoresBase::Greet(eCallbackGreeting::Greeted(),o);
 
786
    tString s;
 
787
    s << o;
 
788
    return s;
 
789
}
 
790
 
 
791
static eCallbackGreeting g(GreetHighscores);
 
792
 
 
793
tList<gHighscoresBase> gHighscoresBase::highscoreList;
 
794
 
 
795
template<class T>class highscores: public gHighscoresBase{
 
796
    protected:
 
797
    tArray<T>    high_score;
 
798
 
 
799
    virtual void swap_entries(int i,int j){
 
800
        Swap(high_score[i],high_score[j]);
 
801
        gHighscoresBase::swap_entries(i,j);
 
802
    }
 
803
 
 
804
    public:
 
805
    virtual void Load(){
 
806
        tTextFileRecorder stream( tDirectories::Var(), highscore_file );
 
807
        int i=0;
 
808
        while ( !stream.EndOfFile() )
 
809
        {
 
810
            std::stringstream s( stream.GetLine() );
 
811
            s >> high_score[i];
 
812
            load_Name(s,i);
 
813
            // con << highName[i] << " " << high_score[i] << '\n';
 
814
            i++;
 
815
        }
 
816
    }
 
817
 
 
818
    // returns if i should stay above j
 
819
    virtual bool inorder(int i,int j)
 
820
    {
 
821
        return (highName[j].Len()<=1 || high_score[i]>=high_score[j]);
 
822
    }
 
823
 
 
824
 
 
825
    virtual void Save(){
 
826
        std::ofstream s;
 
827
 
 
828
        sort();
 
829
 
 
830
        tString filename(highscore_file);
 
831
        if ( tRecorder::IsPlayingBack() )
 
832
        {
 
833
            filename += ".playback";
 
834
        }
 
835
 
 
836
        if ( tDirectories::Var().Open ( s, filename ) )
 
837
        {
 
838
            int i=0;
 
839
            int max=high_score.Len();
 
840
            if (maxSize && max>maxSize)
 
841
                max=maxSize;
 
842
            while (i<max && highName[i].Len()>1){
 
843
                tString mess;
 
844
                mess << high_score[i];
 
845
                mess.SetPos(10, false );
 
846
                s << mess;
 
847
                save_Name(s,i);
 
848
                s << '\n';
 
849
                i++;
 
850
                //std::cout << mess;
 
851
                //save_Name(std::cout,i);
 
852
                //std::cout << '\n';
 
853
            }
 
854
        }
 
855
    }
 
856
 
 
857
    void checkPos(int found,const tString &name,T score){
 
858
        tOutput message;
 
859
        // find the name in the list
 
860
        bool isnew=false;
 
861
 
 
862
        message.SetTemplateParameter(1, name);
 
863
        message.SetTemplateParameter(2, desc);
 
864
        message.SetTemplateParameter(3, score);
 
865
 
 
866
        if (highName[found].Len()<=1){
 
867
            highName[found]=name;
 
868
            message << "$highscore_message_entered";
 
869
            high_score[found]=score;
 
870
            isnew=true;
 
871
        }
 
872
        else if (score>high_score[found]){
 
873
            message << "$highscore_message_improved";
 
874
            high_score[found]=score;
 
875
        }
 
876
        else
 
877
            return;
 
878
 
 
879
        // move him up
 
880
        int newpos=gHighscoresBase::checkPos(found);
 
881
 
 
882
        message.SetTemplateParameter(4, newpos + 1);
 
883
 
 
884
        if (newpos!=found || isnew)
 
885
            if (newpos==0)
 
886
                message << "$highscore_message_move_top";
 
887
            else
 
888
                message << "$highscore_message_move_pos";
 
889
        else
 
890
            if (newpos==0)
 
891
                message << "$highscore_message_stay_top";
 
892
            else
 
893
                message << "$highscore_message_stay_pos";
 
894
 
 
895
        message << "\n";
 
896
 
 
897
        ePlayerNetID *p=online(newpos);
 
898
        //con << message;
 
899
        if (p)
 
900
            sn_ConsoleOut(tString(message),p->Owner());
 
901
        //Save();
 
902
    }
 
903
 
 
904
    void Add( ePlayerNetID* player,T AddScore)
 
905
    {
 
906
        tASSERT( player );
 
907
        tString const & name = player->GetUserName();
 
908
        int f=Find(name,true);
 
909
        checkPos(f,name,AddScore+high_score[f]);
 
910
    }
 
911
 
 
912
    void Add( eTeam* team,T AddScore)
 
913
    {
 
914
        if ( team->NumHumanPlayers() > 0 )
 
915
        {
 
916
            for ( int i = team->NumPlayers() - 1 ; i>=0; --i )
 
917
            {
 
918
                ePlayerNetID* player = team->Player( i );
 
919
                if ( player->IsHuman() )
 
920
                {
 
921
                    this->Add( player, AddScore );
 
922
                }
 
923
            }
 
924
        }
 
925
    }
 
926
 
 
927
    void Check(const ePlayerNetID* player,T score){
 
928
        tASSERT( player );
 
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);
 
935
        }
 
936
    }
 
937
 
 
938
    highscores(char *name,char *sd,int max=0)
 
939
            :gHighscoresBase(name,sd,max){
 
940
        //              Load();
 
941
    }
 
942
 
 
943
    virtual ~highscores(){
 
944
        //              Save();
 
945
    }
 
946
};
 
947
 
 
948
 
 
949
 
 
950
static REAL ladder_min_bet=1;
 
951
static tSettingItem<REAL> ldd_mb("LADDER_MIN_BET",
 
952
                                 ladder_min_bet);
 
953
 
 
954
static REAL ladder_perc_bet=10;
 
955
static tSettingItem<REAL> ldd_pb("LADDER_PERCENT_BET",
 
956
                                 ladder_perc_bet);
 
957
 
 
958
static REAL ladder_tax=1;
 
959
static tSettingItem<REAL> ldd_tex("LADDER_TAX",
 
960
                                  ladder_tax);
 
961
 
 
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);
 
965
 
 
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);
 
969
 
 
970
static REAL ladder_gain_extra=1;
 
971
static tSettingItem<REAL> ldd_ga("LADDER_GAIN_EXTRA",
 
972
                                 ladder_gain_extra);
 
973
 
 
974
 
 
975
class ladder: public highscores<REAL>{
 
976
public:
 
977
    virtual void Load(){
 
978
        highscores<REAL>::Load();
 
979
 
 
980
        sort();
 
981
 
 
982
        int end=highName.Len();
 
983
 
 
984
        for(int i=highName.Len()-1;i>=0;i--){
 
985
 
 
986
            // make them lose some points
 
987
 
 
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;
 
991
            high_score[i]-=loss;
 
992
 
 
993
            if (high_score[i]<0)
 
994
                end=i;
 
995
        }
 
996
 
 
997
        // remove the bugggers with less than 0 points
 
998
        highName.SetLen(end);
 
999
        high_score.SetLen(end);
 
1000
    }
 
1001
 
 
1002
    void checkPos(int found,const tString &name,REAL score){
 
1003
        tOutput message;
 
1004
 
 
1005
        message.SetTemplateParameter(1, name);
 
1006
        message.SetTemplateParameter(2, desc);
 
1007
        message.SetTemplateParameter(3, score);
 
1008
 
 
1009
        // find the name in the list
 
1010
        bool isnew=false;
 
1011
        if (highName[found].Len()<=1){
 
1012
            highName[found]=name;
 
1013
            message << "$ladder_message_entered";
 
1014
            high_score[found]=score;
 
1015
            isnew=true;
 
1016
        }
 
1017
        else{
 
1018
            REAL diff=score-high_score[found];
 
1019
            message.SetTemplateParameter(5, static_cast<float>(fabs(diff)));
 
1020
 
 
1021
            if (diff>0)
 
1022
                message << "$ladder_message_gained";
 
1023
            else
 
1024
                message << "$ladder_message_lost";
 
1025
 
 
1026
            high_score[found]=score;
 
1027
        }
 
1028
 
 
1029
        // move him up
 
1030
        int newpos=gHighscoresBase::checkPos(found);
 
1031
 
 
1032
        message.SetTemplateParameter(4, newpos + 1);
 
1033
 
 
1034
        if (newpos!=found || isnew)
 
1035
            if (newpos==0)
 
1036
                message << "$ladder_message_move_top";
 
1037
            else
 
1038
                message << "$ladder_message_move_pos";
 
1039
        else
 
1040
            if (newpos==0)
 
1041
                message << "$ladder_message_stay_top";
 
1042
            else
 
1043
                message << "$ladder_message_stay_pos";
 
1044
 
 
1045
        message << "\n";
 
1046
 
 
1047
        ePlayerNetID *p=online(newpos);
 
1048
        // con << message;
 
1049
        if (p){
 
1050
            sn_ConsoleOut(tString(message),p->Owner());
 
1051
        }
 
1052
 
 
1053
        // Save();
 
1054
    }
 
1055
 
 
1056
    void Add(const tString &name,REAL AddScore){
 
1057
        int found=Find(name,true);
 
1058
        checkPos(found,name,AddScore+high_score[found]);
 
1059
    }
 
1060
 
 
1061
    // ladder mechanics: what happens if someone wins?
 
1062
    void winner( eTeam *winningTeam ){
 
1063
        tASSERT( winningTeam );
 
1064
 
 
1065
        // AI won? bail out.
 
1066
        if ( winningTeam->NumHumanPlayers() <= 0 )
 
1067
        {
 
1068
            return;
 
1069
        }
 
1070
 
 
1071
        // only do something in multiplayer mode
 
1072
        int i;
 
1073
        int count=0;
 
1074
 
 
1075
        tArray<ePlayerNetID*> active;
 
1076
 
 
1077
        for(i=se_PlayerNetIDs.Len()-1;i>=0;i--)
 
1078
        {
 
1079
            ePlayerNetID* p=se_PlayerNetIDs(i);
 
1080
 
 
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 ) ) )
 
1083
            {
 
1084
                count++;
 
1085
                active[active.Len()] = p;
 
1086
            }
 
1087
        }
 
1088
 
 
1089
        // only one active player? quit.
 
1090
        if ( active.Len() <= 1 )
 
1091
        {
 
1092
            return;
 
1093
        }
 
1094
 
 
1095
        // collect the bets
 
1096
        tArray<int> nums;
 
1097
        tArray<REAL> bet;
 
1098
 
 
1099
        REAL pot=0;
 
1100
 
 
1101
        for(i=active.Len()-1;i>=0;i--){
 
1102
 
 
1103
            nums[i]=Find(active(i)->GetUserName(),true);
 
1104
 
 
1105
            if (high_score[nums[i]]<0)
 
1106
                high_score[nums[i]]=0;
 
1107
 
 
1108
            bet[i]=high_score[nums[i]]*ladder_perc_bet*.01;
 
1109
            if (bet[i]<ladder_min_bet)
 
1110
                bet[i]=ladder_min_bet;
 
1111
            pot+=bet[i];
 
1112
        }
 
1113
 
 
1114
        pot-=pot*ladder_tax*.01; // you have to pay to the bank :-)
 
1115
 
 
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:
 
1119
 
 
1120
        // take the bet from the losers and give it to the winner
 
1121
        for(i=active.Len()-1; i>=0; i--)
 
1122
        {
 
1123
            ePlayerNetID* player = active(i);
 
1124
            if(player->CurrentTeam() == winningTeam )
 
1125
            {
 
1126
                REAL pc=player->ping + player->pingCharity*.001;
 
1127
                if (pc<0)
 
1128
                    pc=0;
 
1129
                if (pc>1) // add sensible bounds
 
1130
                    pc=1;
 
1131
 
 
1132
                REAL potExtra = pc*ladder_gain_extra;
 
1133
 
 
1134
                if ( player->Object() && player->Object()->Alive() )
 
1135
                {
 
1136
                    potExtra *= 2.0f;
 
1137
                }
 
1138
 
 
1139
                Add(player->GetUserName(), ( pot / winningTeam->NumHumanPlayers() + potExtra ) - bet[i] );
 
1140
            }
 
1141
            else
 
1142
            {
 
1143
                Add(player->GetUserName(),-bet[i]);
 
1144
            }
 
1145
        }
 
1146
    }
 
1147
 
 
1148
    ladder(char *name,char *sd,int max=0)
 
1149
            :highscores<REAL>(name,sd,max){
 
1150
        //              Load();
 
1151
    }
 
1152
 
 
1153
    virtual ~ladder(){
 
1154
        //              Save();
 
1155
    }
 
1156
};
 
1157
 
 
1158
 
 
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");
 
1166
 
 
1167
#define PREPARE_TIME 4
 
1168
 
 
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;
 
1175
 
 
1176
static int wishWinner = 0;
 
1177
static char const * wishWinnerMessage = "";
 
1178
 
 
1179
void sg_DeclareWinner( eTeam* team, char const * message )
 
1180
{
 
1181
    if ( team && !winner )
 
1182
    {
 
1183
        wishWinner = team->TeamID() + 1;
 
1184
        wishWinnerMessage = message;
 
1185
    }
 
1186
}
 
1187
 
 
1188
void check_hs(){
 
1189
    if (sg_singlePlayer)
 
1190
        if(se_PlayerNetIDs.Len()>0 && se_PlayerNetIDs(0)->IsHuman())
 
1191
            highscore.Check(se_PlayerNetIDs(0),se_PlayerNetIDs(0)->Score());
 
1192
}
 
1193
 
 
1194
 
 
1195
static tCONTROLLED_PTR(gGame) sg_currentGame;
 
1196
 
 
1197
 
 
1198
 
 
1199
/*
 
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();
 
1205
 
 
1206
  return dynamic_cast<gCycle *>(object);
 
1207
}
 
1208
*/
 
1209
 
 
1210
#ifdef POWERPAK_DEB
 
1211
#include "PowerPak/poweruInput.h"
 
1212
#include "PowerPak/joystick.h"
 
1213
#endif
 
1214
 
 
1215
#include "rRender.h"
 
1216
 
 
1217
gArena Arena;
 
1218
 
 
1219
 
 
1220
 
 
1221
 
 
1222
 
 
1223
void exit_game_grid(eGrid *grid){
 
1224
    grid->Clear();
 
1225
}
 
1226
 
 
1227
void exit_game_objects(eGrid *grid){
 
1228
    sr_con.fullscreen=true;
 
1229
 
 
1230
    su_prefetchInput=false;
 
1231
 
 
1232
    int i;
 
1233
    for(i=ePlayer::Num()-1;i>=0;i--){
 
1234
        if (ePlayer::PlayerConfig(i))
 
1235
            tDESTROY(ePlayer::PlayerConfig(i)->cam);
 
1236
    }
 
1237
 
 
1238
 
 
1239
    gNetPlayerWall::Clear();
 
1240
 
 
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();
 
1245
 
 
1246
    eGameObject::DeleteAll(grid);
 
1247
 
 
1248
    exit_game_grid(grid);
 
1249
}
 
1250
 
 
1251
REAL exponent(int i)
 
1252
{
 
1253
    int abs = i;
 
1254
    if ( abs < 0 )
 
1255
        abs = -abs;
 
1256
 
 
1257
    REAL ret = 1;
 
1258
    REAL fac = sqrtf(2);
 
1259
 
 
1260
    while (abs > 0)
 
1261
    {
 
1262
        if ( 1 == (abs & 1) )
 
1263
            ret *= fac;
 
1264
 
 
1265
        fac *= fac;
 
1266
        abs >>= 1;
 
1267
    }
 
1268
 
 
1269
    if (i < 0)
 
1270
        ret = 1/ret;
 
1271
 
 
1272
    return ret;
 
1273
}
 
1274
 
 
1275
 
 
1276
void init_game_grid(eGrid *grid, gParser *aParser){
 
1277
    se_ResetGameTimer();
 
1278
    se_PauseGameTimer(true);
 
1279
 
 
1280
#ifndef DEDICATED
 
1281
    if (sr_glOut){
 
1282
        sr_ResetRenderState();
 
1283
 
 
1284
        // rSysDep::ClearGL();
 
1285
 
 
1286
        // glViewport (0, 0, static_cast<GLsizei>(sr_screenWidth), static_cast<GLsizei>(sr_screenHeight));
 
1287
 
 
1288
        // rSysDep::SwapGL();
 
1289
    }
 
1290
#endif
 
1291
 
 
1292
    /*
 
1293
      if(!speedup)
 
1294
      SDL_Delay(1000);
 
1295
    */   
 
1296
 
 
1297
    Arena.PrepareGrid(grid, aParser);
 
1298
 
 
1299
    absolute_winner=winner=wishWinner=0;
 
1300
}
 
1301
 
 
1302
int sg_NumHumans()
 
1303
{
 
1304
    int humans = 0;
 
1305
    for (int i = se_PlayerNetIDs.Len()-1; i>=0; i--)
 
1306
    {
 
1307
        ePlayerNetID* p = se_PlayerNetIDs(i);
 
1308
        if (p->IsHuman() && p->IsActive() && ( bool(p->CurrentTeam()) || bool(p->NextTeam()) ) )
 
1309
            humans++;
 
1310
    }
 
1311
 
 
1312
    return humans;
 
1313
}
 
1314
 
 
1315
int sg_NumUsers()
 
1316
{
 
1317
    // return se_PlayerNetIDs.Len() ;
 
1318
#ifdef DEDICATED
 
1319
    return sn_NumUsers();
 
1320
#else
 
1321
    return sn_NumUsers() + 1;
 
1322
#endif
 
1323
}
 
1324
 
 
1325
static void sg_copySettings()
 
1326
{
 
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;
 
1334
 
 
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 ) );
 
1340
}
 
1341
 
 
1342
void update_settings()
 
1343
{
 
1344
    if (sn_GetNetState()!=nCLIENT)
 
1345
    {
 
1346
#ifdef DEDICATED
 
1347
        // wait for players to join
 
1348
        {
 
1349
            bool restarted = false;
 
1350
 
 
1351
            REAL timeout = tSysTimeFloat() + 3.0f;
 
1352
            while ( sg_NumHumans() <= 0 && sg_NumUsers() > 0 )
 
1353
            {
 
1354
                if ( !restarted && bool(sg_currentGame) )
 
1355
                {
 
1356
                    sg_currentGame->StartNewMatch();
 
1357
                    restarted = true;
 
1358
                }
 
1359
 
 
1360
                if ( tSysTimeFloat() > timeout )
 
1361
                {
 
1362
                    tOutput o("$gamestate_wait_players");
 
1363
                    sn_CenterMessage(o);
 
1364
 
 
1365
                    tOutput o2("$gamestate_wait_players_con");
 
1366
                    sn_ConsoleOut(o2);
 
1367
 
 
1368
                    timeout = tSysTimeFloat() + 10.0f;
 
1369
 
 
1370
                    // kick spectators and chatbots
 
1371
                    nMachine::KickSpectators();
 
1372
                    ePlayerNetID::RemoveChatbots();
 
1373
                }
 
1374
 
 
1375
                gGame::NetSyncIdle();
 
1376
            }
 
1377
        }
 
1378
 
 
1379
        if ( sg_NumUsers() <= 0 && bool( sg_currentGame ) )
 
1380
        {
 
1381
            sg_currentGame->NoLongerGoOn();
 
1382
        }
 
1383
 
 
1384
        // count the active players
 
1385
        int humans = sg_NumHumans();
 
1386
 
 
1387
        bool newsg_singlePlayer = (humans<=1);
 
1388
#else
 
1389
        bool newsg_singlePlayer = (sn_GetNetState() == nSTANDALONE);
 
1390
#endif
 
1391
        if (sg_singlePlayer != newsg_singlePlayer && bool( sg_currentGame ) )
 
1392
        {
 
1393
            sg_currentGame->StartNewMatch();
 
1394
        }
 
1395
        sg_singlePlayer=newsg_singlePlayer;
 
1396
 
 
1397
        if (sg_singlePlayer)
 
1398
            sg_currentSettings = &singlePlayer;
 
1399
        else
 
1400
            sg_currentSettings = &multiPlayer;
 
1401
 
 
1402
        sg_copySettings();
 
1403
    }
 
1404
 
 
1405
    // update team properties
 
1406
    for (int i = eTeam::teams.Len() - 1; i>=0; --i)
 
1407
        eTeam::teams(i)->UpdateProperties();
 
1408
}
 
1409
 
 
1410
static int sg_spawnPointGroupSize=0;
 
1411
static tSettingItem< int > sg_spawnPointGroupSizeConf( "SPAWN_POINT_GROUP_SIZE", sg_spawnPointGroupSize );
 
1412
 
 
1413
void init_game_objects(eGrid *grid){
 
1414
    /*
 
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};
 
1418
    */
 
1419
 
 
1420
    if (sn_GetNetState()!=nCLIENT)
 
1421
    {
 
1422
        // update team settings
 
1423
        gAIPlayer::SetNumberOfAIs(sg_currentSettings->numAIs,
 
1424
                                  sg_currentSettings->minPlayers,
 
1425
                                  sg_currentSettings->AI_IQ);
 
1426
 
 
1427
        int spawnPointsUsed = 0;
 
1428
        for(int t=eTeam::teams.Len()-1;t>=0;t--)
 
1429
        {
 
1430
            eTeam *team = eTeam::teams(t);
 
1431
            team->Update();
 
1432
 
 
1433
            gSpawnPoint *spawn = Arena.LeastDangerousSpawnPoint();
 
1434
            spawnPointsUsed++;
 
1435
 
 
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 ) )
 
1439
            {
 
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 ) ) )
 
1444
                {
 
1445
                    eCoord pos, dir;
 
1446
                    spawn->Spawn( pos, dir );
 
1447
                    spawn = Arena.LeastDangerousSpawnPoint();
 
1448
                    spawnPointsUsed++;
 
1449
                }
 
1450
            }
 
1451
 
 
1452
            int numPlayers = team->NumPlayers();
 
1453
            for (int p = 0; p<numPlayers; ++p)
 
1454
            {
 
1455
                ePlayerNetID *pni=team->Player( p );
 
1456
 
 
1457
                if ( !team->IsHuman() )
 
1458
                {
 
1459
                    spawn = Arena.LeastDangerousSpawnPoint();
 
1460
                    spawnPointsUsed++;
 
1461
                }
 
1462
 
 
1463
                //                      bool isHuman = pni->IsHuman();
 
1464
 
 
1465
#ifdef KRAWALL_SERVER
 
1466
                // don't allow unknown players to play
 
1467
                if (!pni->IsAuth())
 
1468
                    continue;
 
1469
#endif
 
1470
 
 
1471
                // don't give inactive players a cycle
 
1472
                if (!pni->IsActive())
 
1473
                    continue;
 
1474
 
 
1475
                eCoord pos,dir;
 
1476
                gCycle *cycle=NULL;
 
1477
                if (sn_GetNetState()!=nCLIENT){
 
1478
#ifdef DEBUG
 
1479
                    //                std::cout << "spawning player " << pni->name << '\n';
 
1480
#endif
 
1481
                    spawn->Spawn(pos,dir);
 
1482
                    pni->Greet();
 
1483
                    cycle = new gCycle(grid, pos, dir, pni, 0);
 
1484
                    pni->ControlObject(cycle);
 
1485
                    nNetObject::SyncAll();
 
1486
                }
 
1487
                //    int i=se_PlayerNetIDs(p)->pID;
 
1488
 
 
1489
                // se_ResetGameTimer();
 
1490
                // se_PauseGameTimer(true);
 
1491
            }
 
1492
        }
 
1493
 
 
1494
 
 
1495
#ifdef ALLOW_NO_TEAM
 
1496
        for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
 
1497
            ePlayerNetID *pni=se_PlayerNetIDs(p);
 
1498
 
 
1499
            gSpawnPoint *spawn=Arena.LeastDangerousSpawnPoint();
 
1500
 
 
1501
            if ( NULL == pni->CurrentTeam() )
 
1502
            {
 
1503
#ifdef KRAWALL_SERVER
 
1504
                // don't allow unknown players to play
 
1505
                if (!pni->IsAuth())
 
1506
                    continue;
 
1507
#endif
 
1508
 
 
1509
                // don't give inactive players a cycle
 
1510
                if (!pni->IsActive())
 
1511
                    continue;
 
1512
 
 
1513
                eCoord pos,dir;
 
1514
                gCycle *cycle=NULL;
 
1515
                if (sn_GetNetState()!=nCLIENT){
 
1516
#ifdef DEBUG
 
1517
                    //con << "spawning player " << se_PlayerNetIDs[p]->name << '\n';
 
1518
#endif
 
1519
                    st_Breakpoint();
 
1520
 
 
1521
                    spawn->Spawn(pos,dir);
 
1522
                    pni->Greet();
 
1523
                    cycle = new gCycle(grid, pos, dir, pni, 0);
 
1524
                    pni->ControlObject(cycle);
 
1525
                    nNetObject::SyncAll();
 
1526
                }
 
1527
                //    int i=se_PlayerNetIDs(p)->pID;
 
1528
 
 
1529
                // se_ResetGameTimer();
 
1530
                // se_PauseGameTimer(true);
 
1531
            }
 
1532
        }
 
1533
#endif
 
1534
    }
 
1535
 
 
1536
    /*
 
1537
    for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
 
1538
        ePlayerNetID *pni=se_PlayerNetIDs(p);
 
1539
 
 
1540
        bool isHuman = pni->IsHuman();
 
1541
 
 
1542
    #ifdef KRAWALL_SERVER
 
1543
        // don't allow unknown players to play
 
1544
        if (!pni->IsAuth())
 
1545
                continue;
 
1546
    #endif
 
1547
 
 
1548
        // don't give inactive players a cycle
 
1549
        if (!pni->IsActive())
 
1550
                continue;
 
1551
       
 
1552
        eCoord pos,dir;
 
1553
        gCycle *cycle=NULL;
 
1554
        if (sn_GetNetState()!=nCLIENT){
 
1555
    #ifdef DEBUG
 
1556
                //con << "spawning player " << se_PlayerNetIDs[p]->name << '\n';
 
1557
    #endif
 
1558
                spawn->Spawn(pos,dir);
 
1559
                pni->Greet();
 
1560
                cycle = new gCycle(grid, pos, dir, pni, 0);
 
1561
                pni->ControlObject(cycle);
 
1562
                nNetObject::SyncAll();
 
1563
        }
 
1564
        //    int i=se_PlayerNetIDs(p)->pID;
 
1565
 
 
1566
        se_ResetGameTimer();
 
1567
        se_PauseGameTimer(true);
 
1568
 
 
1569
        if (sg_currentSettings->gameType==gHUMAN_VS_AI){
 
1570
                //      if (Cycle(p))
 
1571
                //      Cycle(p)->team=1;
 
1572
                if (cycle)
 
1573
                {
 
1574
                        spawn=Arena.LeastDangerousSpawnPoint();
 
1575
                        if (isHuman)
 
1576
                                cycle->team=2;
 
1577
                        else
 
1578
                        {
 
1579
                                cycle->team=1;
 
1580
                        }
 
1581
                }
 
1582
        }
 
1583
        else{
 
1584
    #ifdef DEBUG
 
1585
                //con << "new eSpawnPoint.\n";
 
1586
    #endif
 
1587
                if (cycle)
 
1588
                {
 
1589
                        spawn=Arena.LeastDangerousSpawnPoint();
 
1590
                        if (isHuman)
 
1591
                                cycle->team=p + 2;
 
1592
                        else
 
1593
                                cycle->team=1;
 
1594
                }
 
1595
                //      if (Cycle(p))
 
1596
                //      Cycle(p)->team=p+1;
 
1597
        }
 
1598
    }
 
1599
    */
 
1600
 
 
1601
    //  spawn=Arena.LeastDangerousSpawnPoint();
 
1602
 
 
1603
    /*
 
1604
    static REAL rgb[MAXAI][3]={
 
1605
      {1,1,.2},
 
1606
      {1,.2,1},
 
1607
      {.2,1,1},
 
1608
      {1,.6,.2},      
 
1609
      {.2,1,.6},      
 
1610
      {.6,.2,1},      
 
1611
      {1,.2,.6},      
 
1612
      {.6,1,.2},      
 
1613
      {1,1,1},      
 
1614
      {.2,.2,.2}       
 
1615
    };
 
1616
    */
 
1617
 
 
1618
 
 
1619
    rITexture::LoadAll();
 
1620
    // se_ResetGameTimer();
 
1621
    // se_PauseGameTimer(true);
 
1622
 
 
1623
    su_prefetchInput=true;
 
1624
 
 
1625
    lastTime_gameloop=lastTimeTimestep=0;
 
1626
 
 
1627
    // reset scores, all players that are spawned need to get ladder points
 
1628
    ePlayerNetID::ResetScoreDifferences();
 
1629
}
 
1630
 
 
1631
void init_game_camera(eGrid *grid){
 
1632
#ifndef DEDICATED
 
1633
    for(int i=ePlayer::Num()-1;i>=0;i--)
 
1634
        if (ePlayer::PlayerIsInGame(i)){
 
1635
            ePlayerNetID *p=ePlayer::PlayerConfig(i)->netPlayer;
 
1636
 
 
1637
            if ( sg_currentSettings->finishType == gFINISH_EXPRESS && ( sn_GetNetState() != nCLIENT ) )
 
1638
                se_ResetGameTimer( -PREPARE_TIME/5 - sg_extraRoundTime );
 
1639
            else
 
1640
                se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
 
1641
 
 
1642
            // se_PauseGameTimer(true);
 
1643
 
 
1644
            ePlayer::PlayerConfig(i)->cam=new gCamera(grid,
 
1645
                                          ePlayer::PlayerViewport(i),
 
1646
                                          p,
 
1647
                                          ePlayer::PlayerConfig(i),
 
1648
                                          CAMERA_SMART);
 
1649
 
 
1650
            lastTime_gameloop=lastTimeTimestep=0;
 
1651
        }
 
1652
#else
 
1653
    se_ResetGameTimer( -PREPARE_TIME - sg_extraRoundTime );
 
1654
    se_PauseGameTimer(false);
 
1655
#endif
 
1656
    /*
 
1657
      for(int p=se_PlayerNetIDs.Len()-1;p>=0;p--){
 
1658
      int i=se_PlayerNetIDs(p)->pID;
 
1659
 
 
1660
      se_ResetGameTimer(-PREPARE_TIME);
 
1661
      se_PauseGameTimer(true);
 
1662
 
 
1663
      if (i>=0)
 
1664
         playerConfig[i]->cam=new eCamera(PlayerViewport(i),
 
1665
      se_PlayerNetIDs(p),CAMERA_SMART);
 
1666
      }
 
1667
 
 
1668
    */
 
1669
}
 
1670
 
 
1671
bool think=1;
 
1672
 
 
1673
 
 
1674
void s_Timestep(eGrid *grid, REAL time,bool cam){
 
1675
    gNetPlayerWall::s_CopyIntoGrid();
 
1676
    se_SoundLock();
 
1677
    eGameObject::s_Timestep(grid, time);
 
1678
 
 
1679
    if (cam)
 
1680
        eCamera::s_Timestep(grid, time);
 
1681
    se_SoundUnlock();
 
1682
 
 
1683
    lastTimeTimestep=time;
 
1684
}
 
1685
 
 
1686
#ifndef DEDICATED
 
1687
void RenderAllViewports(eGrid *grid){
 
1688
    rViewportConfiguration *conf=rViewportConfiguration::CurrentViewportConfiguration();
 
1689
 
 
1690
    if(sr_glOut){
 
1691
        sr_ResetRenderState();
 
1692
 
 
1693
        // enable distance based fog
 
1694
        /*
 
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 );
 
1699
        glEnable( GL_FOG );
 
1700
        */
 
1701
 
 
1702
        const tList<eCamera>& cameras = grid->Cameras();
 
1703
 
 
1704
        for(int i=cameras.Len()-1;i>=0;i--){
 
1705
            int p=sr_viewportBelongsToPlayer[i];
 
1706
            conf->Select(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";
 
1711
        }
 
1712
 
 
1713
        // glDisable( GL_FOG );
 
1714
    }
 
1715
 
 
1716
#ifdef POWERPAK_DEB
 
1717
    if (pp_out){
 
1718
        eGameObject::PPDisplayAll();
 
1719
        PD_ShowDoubleBuffer();
 
1720
    }
 
1721
#endif
 
1722
}
 
1723
#endif
 
1724
 
 
1725
 
 
1726
void Render(eGrid *grid, REAL time, bool swap=true){
 
1727
#ifdef DEBUG
 
1728
    //  eFace::UpdateVisAll(10);
 
1729
#endif
 
1730
    //  se_debugExt=0;
 
1731
 
 
1732
#ifndef DEDICATED
 
1733
    if (sr_glOut){
 
1734
        RenderAllViewports(grid);
 
1735
 
 
1736
        sr_ResetRenderState(true);
 
1737
        gLogo::Display();
 
1738
 
 
1739
        if (swap){
 
1740
            rSysDep::SwapGL();
 
1741
 
 
1742
            if(!sr_ZTrick ||
 
1743
                    (!sr_highRim && !sr_lowerSky && !sr_upperSky) ||
 
1744
                    sr_floorDetail<rFLOOR_TEXTURE ||
 
1745
                    sr_floorMirror==rMIRROR_OBJECTS){
 
1746
                rSysDep::ClearGL();
 
1747
            }
 
1748
        }
 
1749
    }
 
1750
    else
 
1751
    {
 
1752
        if ( swap )
 
1753
            rSysDep::SwapGL();
 
1754
 
 
1755
        tDelay( 50000 );
 
1756
    }
 
1757
#endif
 
1758
}
 
1759
 
 
1760
#ifdef DEDICATED
 
1761
static void cp(){
 
1762
    std::ofstream s;
 
1763
 
 
1764
    if ( tDirectories::Var().Open(s, "players.txt") ){
 
1765
        if (se_PlayerNetIDs.Len()>0)
 
1766
            s << tColoredString::RemoveColors(ePlayerNetID::Ranking( -1, false ));
 
1767
        else{
 
1768
            tOutput o;
 
1769
 
 
1770
            int count=0;
 
1771
            for(int i=MAXCLIENTS;i>0;i--)
 
1772
                if (sn_Connections[i].socket)
 
1773
                    count++;
 
1774
            if (count==0)
 
1775
                o << "$online_activity_nobody";
 
1776
            else if (count==1)
 
1777
                o << "$online_activity_onespec";
 
1778
            else
 
1779
            {
 
1780
                o.SetTemplateParameter(1, count);
 
1781
                o << "$online_activity_manyspec";
 
1782
            }
 
1783
            o << "\n";
 
1784
            s << o;
 
1785
        }
 
1786
    }
 
1787
}
 
1788
#endif
 
1789
 
 
1790
 
 
1791
static void own_game( nNetState enter_state ){
 
1792
    tNEW(gGame);
 
1793
    se_MakeGameTimer();
 
1794
    sg_EnterGame( enter_state );
 
1795
 
 
1796
    // write scores one last time
 
1797
    ePlayerNetID::LogScoreDifferences();
 
1798
    se_SaveToLadderLog(tString("GAME_END\n"));
 
1799
 
 
1800
    sg_currentGame=NULL;
 
1801
    se_KillGameTimer();
 
1802
}
 
1803
 
 
1804
static void singlePlayer_game(){
 
1805
    sn_SetNetState(nSTANDALONE);
 
1806
 
 
1807
    update_settings();
 
1808
    ePlayerNetID::CompleteRebuild();
 
1809
 
 
1810
    own_game( nSTANDALONE );
 
1811
}
 
1812
 
 
1813
void sg_HostGame(){
 
1814
    {
 
1815
        // create a game to check map once
 
1816
        tJUST_CONTROLLED_PTR< gGame > game = tNEW(gGame);
 
1817
        game->Verify();
 
1818
    }
 
1819
 
 
1820
    if (sg_TalkToMaster)
 
1821
        nServerInfo::TellMasterAboutMe();
 
1822
 
 
1823
    sn_SetNetState(nSERVER);
 
1824
 
 
1825
    update_settings();
 
1826
    ePlayerNetID::CompleteRebuild();
 
1827
 
 
1828
    tAdvanceFrame();
 
1829
 
 
1830
    //#ifndef DEBUG
 
1831
#ifdef DEDICATED
 
1832
    static double startTime=tSysTimeFloat();
 
1833
 
 
1834
    if ( sg_NumUsers() == 0)
 
1835
    {
 
1836
        cp();
 
1837
        con << tOutput("$online_activity_napping") << "\n";
 
1838
        sg_Timestamp();
 
1839
 
 
1840
        int counter = -1;
 
1841
 
 
1842
        int numPlayers = 0;
 
1843
 
 
1844
        while(numPlayers == 0 &&
 
1845
                (ded_idle<.0001 || tSysTimeFloat()<startTime + ded_idle * 3600 ) && !uMenu::quickexit ){
 
1846
            sr_Read_stdin();
 
1847
            gGame::NetSyncIdle();
 
1848
 
 
1849
            tDelay( 100000 );
 
1850
 
 
1851
            // std::cout the players who are logged in:
 
1852
            numPlayers = sg_NumUsers();
 
1853
            /*
 
1854
                                for (int i = se_PlayerNetIDs.Len()-1; i>=0; i--)
 
1855
                                        if (se_PlayerNetIDs(i)->IsAuth())
 
1856
                                                numPlayers++;
 
1857
            */
 
1858
 
 
1859
            if (counter <= 0)
 
1860
            {
 
1861
                // restart network, just in case we lost the input socket
 
1862
                sn_BasicNetworkSystem.AccessListener().Listen(false);
 
1863
                sn_BasicNetworkSystem.AccessListener().Listen(true);
 
1864
                counter = 50;
 
1865
            }
 
1866
        }
 
1867
 
 
1868
        if (sg_NumUsers() <= 0 && ded_idle>0.0001 &&
 
1869
                tSysTimeFloat()>= startTime + ded_idle * 3600 )
 
1870
        {
 
1871
            uMenu::quickexit = true;
 
1872
        }
 
1873
    }
 
1874
    cp();
 
1875
 
 
1876
    if (!uMenu::quickexit)
 
1877
#endif
 
1878
        //#endif
 
1879
        own_game( nSERVER );
 
1880
 
 
1881
    sn_SetNetState(nSTANDALONE);
 
1882
 
 
1883
    // close listening sockets
 
1884
    sn_BasicNetworkSystem.AccessListener().Listen(false);
 
1885
}
 
1886
 
 
1887
static tString sg_roundCenterMessage("");
 
1888
static tConfItemLine sn_roundCM_ci("ROUND_CENTER_MESSAGE",sg_roundCenterMessage);
 
1889
 
 
1890
static tString sg_roundConsoleMessage("");
 
1891
static tConfItemLine sn_roundCcM1_ci("ROUND_CONSOLE_MESSAGE",sg_roundConsoleMessage);
 
1892
 
 
1893
static bool sg_RequestedDisconnection = false;
 
1894
 
 
1895
static void sg_NetworkError( const tOutput& title, const tOutput& message, REAL timeout )
 
1896
{
 
1897
    if ( sn_DenyReason.Len() > 2 )
 
1898
    {
 
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 );
 
1905
    }
 
1906
    else
 
1907
    {
 
1908
        tConsole::Message( title, message, timeout );
 
1909
    }
 
1910
}
 
1911
 
 
1912
// revert settings to defaults in the current scope
 
1913
class gSettingsReverter
 
1914
{
 
1915
public:
 
1916
    gSettingsReverter()
 
1917
    {
 
1918
        // restore default configuration of network settings, saving your settings
 
1919
        nConfItemBase::s_SaveValues();
 
1920
        nConfItemBase::s_RevertToDefaults();
 
1921
    }
 
1922
 
 
1923
    ~gSettingsReverter()
 
1924
    {
 
1925
        // restore saved values
 
1926
        nConfItemBase::s_RevertToSavedValues();
 
1927
    }
 
1928
};
 
1929
 
 
1930
void ConnectToServer(nServerInfoBase *server)
 
1931
{
 
1932
    tASSERT( server );
 
1933
 
 
1934
    ePlayerNetID::ClearAll();
 
1935
 
 
1936
    // revert to default settings, restore current vlaues on exit
 
1937
    gSettingsReverter reverter;
 
1938
 
 
1939
    sn_bigBrotherString = renderer_identification;
 
1940
 
 
1941
    nNetObject::ClearAll();
 
1942
 
 
1943
    just_connected=true;
 
1944
 
 
1945
    rViewport::Update(MAX_PLAYERS);
 
1946
    // ePlayerNetID::Update();
 
1947
 
 
1948
#ifndef DEDICATED
 
1949
    rSysDep::SwapGL();
 
1950
    rSysDep::ClearGL();
 
1951
    rSysDep::SwapGL();
 
1952
    rSysDep::ClearGL();
 
1953
    se_SoundLock();
 
1954
#endif
 
1955
 
 
1956
    sr_con.autoDisplayAtNewline=true;
 
1957
    sr_con.fullscreen=true;
 
1958
 
 
1959
    bool to=sr_textOut;
 
1960
    sr_textOut=true;
 
1961
 
 
1962
    tOutput o;
 
1963
 
 
1964
    nConnectError error = nOK;
 
1965
 
 
1966
    nNetObject::ClearAll();
 
1967
 
 
1968
    o.SetTemplateParameter(1, server->GetName());
 
1969
    o << "$network_connecting_to_server";
 
1970
    con << o;
 
1971
    error = server->Connect();
 
1972
 
 
1973
    switch (error)
 
1974
    {
 
1975
    case nOK:
 
1976
        break;
 
1977
    case nTIMEOUT:
 
1978
        sg_NetworkError("$network_message_timeout_title", "$network_message_timeout_inter", 20);
 
1979
#ifndef DEDICATED
 
1980
        se_SoundUnlock();
 
1981
#endif
 
1982
        return;
 
1983
        break;
 
1984
 
 
1985
    case nDENIED:
 
1986
        sg_NetworkError("$network_message_denied_title", sn_DenyReason.Len() > 2 ? "$network_message_denied_inter2" : "$network_message_denied_inter", 20);
 
1987
#ifndef DEDICATED
 
1988
        se_SoundUnlock();
 
1989
#endif
 
1990
        return;
 
1991
        break;
 
1992
    }
 
1993
 
 
1994
#ifndef DEDICATED
 
1995
    se_SoundUnlock();
 
1996
#endif
 
1997
 
 
1998
    // ePlayerNetID::CompleteRebuild();
 
1999
 
 
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)){
 
2004
            sn_Receive();
 
2005
            nNetObject::SyncAll();
 
2006
            st_DoToDo();
 
2007
 
 
2008
#ifndef DEDICATED
 
2009
            rSysDep::SwapGL();
 
2010
            rSysDep::ClearGL();
 
2011
#endif
 
2012
 
 
2013
            tAdvanceFrame(sn_defaultDelay);
 
2014
        }
 
2015
        if (sg_currentGame){
 
2016
            sr_con.autoDisplayAtNewline=false;
 
2017
            sr_con.fullscreen=false;
 
2018
 
 
2019
            con << tOutput("$network_syncing_gamestate");
 
2020
            sg_EnterGame( nCLIENT );
 
2021
        }
 
2022
        else{
 
2023
            //con << "Timeout. Try again!\n";
 
2024
            sg_NetworkError("$network_message_lateto_title", "$network_message_lateto_inter", 20);
 
2025
        }
 
2026
    }
 
2027
 
 
2028
 
 
2029
    if (!sg_RequestedDisconnection && !uMenu::quickexit)
 
2030
        switch (sn_GetLastError())
 
2031
        {
 
2032
        case nOK:
 
2033
            sg_NetworkError("$network_message_abortconn_title",
 
2034
                            "$network_message_abortconn_inter", 20);
 
2035
            break;
 
2036
        default:
 
2037
            sg_NetworkError("$network_message_lostconn_title",
 
2038
                            "$network_message_lostconn_inter", 20);
 
2039
            break;
 
2040
        }
 
2041
 
 
2042
    sr_con.autoDisplayAtNewline=false;
 
2043
    sr_con.fullscreen=false;
 
2044
 
 
2045
    sn_SetNetState(nSTANDALONE);
 
2046
 
 
2047
    sg_currentGame = NULL;
 
2048
    nNetObject::ClearAll();
 
2049
    ePlayerNetID::ClearAll();
 
2050
 
 
2051
    sr_textOut=to;
 
2052
}
 
2053
 
 
2054
static tConfItem<int> mor("MAX_OUT_RATE",sn_maxRateOut);
 
2055
static tConfItem<int> mir("MAX_IN_RATE",sn_maxRateIn);
 
2056
 
 
2057
 
 
2058
static tConfItem<int> pc("PING_CHARITY",pingCharity);
 
2059
 
 
2060
 
 
2061
uMenu *sg_IngameMenu=NULL;
 
2062
uMenu *sg_HostMenu  =NULL;
 
2063
 
 
2064
void ret_to_MainMenu(){
 
2065
    sg_RequestedDisconnection = true;
 
2066
 
 
2067
    if (sg_HostMenu)
 
2068
        sg_HostMenu->Exit();
 
2069
 
 
2070
    if (sg_IngameMenu)
 
2071
        sg_IngameMenu->Exit();
 
2072
 
 
2073
    sr_con.fullscreen=true;
 
2074
    sr_con.autoDisplayAtNewline=true;
 
2075
 
 
2076
    if(sg_currentGame)
 
2077
        sg_currentGame->NoLongerGoOn();
 
2078
 
 
2079
    sn_SetNetState(nSTANDALONE);
 
2080
 
 
2081
    uMenu::SetIdle(NULL);
 
2082
}
 
2083
 
 
2084
 
 
2085
 
 
2086
void net_options(){
 
2087
    uMenu net_menu("$network_opts_text");
 
2088
 
 
2089
    uMenuItemInt high_port
 
2090
    (&net_menu,"$network_opts_maxport_text",
 
2091
     "$network_opts_maxport_help",
 
2092
     gServerBrowser::highPort,1024,65536);
 
2093
 
 
2094
    uMenuItemInt low_port
 
2095
    (&net_menu,"$network_opts_minport_text",
 
2096
     "$network_opts_minport_help",
 
2097
     gServerBrowser::lowPort,1024,65536);
 
2098
 
 
2099
    /*
 
2100
        uMenuItemFunction delpw(&net_menu,
 
2101
                                                        "$network_opts_deletepw_text",
 
2102
                                                        "$network_opts_deletepw_help",
 
2103
                                                        &se_DeletePasswords);
 
2104
      
 
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",
 
2111
                                          -1);
 
2112
        storepw.NewChoice("$login_storepw_mem_text",
 
2113
                                          "$login_storepw_mem_help",
 
2114
                                          0);
 
2115
        storepw.NewChoice("$login_storepw_disk_text",
 
2116
                                          "$login_storepw_disk_help",
 
2117
                                          1);
 
2118
    */
 
2119
 
 
2120
    /*
 
2121
      uMenuItemToggle master
 
2122
      (&net_menu,"$network_opts_master_text",
 
2123
      "$network_opts_master_help",
 
2124
      sg_TalkToMaster);
 
2125
    */
 
2126
 
 
2127
 
 
2128
    uMenuItemInt out_rate
 
2129
    (&net_menu,"$network_opts_outrate_text",
 
2130
     "$network_opts_outrate_help",
 
2131
     sn_maxRateOut,1,20);
 
2132
 
 
2133
 
 
2134
    uMenuItemInt in_rate
 
2135
    (&net_menu,"$network_opts_inrate_text",
 
2136
     "$network_opts_inrate_help",
 
2137
     sn_maxRateIn,1,20);
 
2138
 
 
2139
 
 
2140
    uMenuItemToggle po2
 
2141
    (&net_menu,"$network_opts_predict_text",
 
2142
     "$network_opts_predict_help",
 
2143
     sr_predictObjects);
 
2144
 
 
2145
    uMenuItemToggle lm2
 
2146
    (&net_menu,"$network_opts_lagometer_text",
 
2147
     "$network_opts_lagometer_help",
 
2148
     sr_laggometer);
 
2149
 
 
2150
 
 
2151
    uMenuItemInt p_s
 
2152
    (&net_menu,"$network_opts_pingchar_text",
 
2153
     "$network_opts_pingchar_help",
 
2154
     pingCharity,0,300,20);
 
2155
 
 
2156
    net_menu.Enter();
 
2157
 
 
2158
    if (gServerBrowser::lowPort > gServerBrowser::highPort)
 
2159
        gServerBrowser::highPort = gServerBrowser::lowPort;
 
2160
}
 
2161
 
 
2162
void sg_HostGameMenu(){
 
2163
    uMenu net_menu("$network_host_text");
 
2164
 
 
2165
    sg_HostMenu = &net_menu;
 
2166
 
 
2167
    uMenuItemInt port(&net_menu, "$network_host_port_text",
 
2168
                      "$network_host_port_help"
 
2169
                      ,reinterpret_cast<int &>(sn_serverPort), gServerBrowser::lowPort, gServerBrowser::highPort);
 
2170
 
 
2171
    uMenuItemString serverName
 
2172
    (&net_menu,"$network_host_name_text",
 
2173
     "$network_host_name_help",
 
2174
     sn_serverName);
 
2175
 
 
2176
    uMenuItemFunction settings1
 
2177
    (&net_menu,
 
2178
     "$game_settings_menu_text",
 
2179
     "$game_settings_menu_help",
 
2180
     &GameSettingsMP);
 
2181
 
 
2182
    uMenuItemFunction serv
 
2183
    (&net_menu,"$network_host_host_text",
 
2184
     "$network_host_host_help",&sg_HostGame);
 
2185
 
 
2186
    net_menu.ReverseItems();
 
2187
    net_menu.SetSelected(0);
 
2188
    net_menu.Enter();
 
2189
 
 
2190
    sg_HostMenu = NULL;
 
2191
}
 
2192
 
 
2193
 
 
2194
void net_game(){
 
2195
    uMenu net_menu("$network_menu_text");
 
2196
 
 
2197
    uMenuItemFunction cust
 
2198
    (&net_menu,"$network_custjoin_text",
 
2199
     "$network_custjoin_help",&gServerFavorites::CustomConnectMenu);
 
2200
 
 
2201
 
 
2202
    uMenuItemFunction fav
 
2203
    (&net_menu,"$bookmarks_menu",
 
2204
     "$bookmarks_menu_help",&gServerFavorites::FavoritesMenu);
 
2205
 
 
2206
    uMenuItemFunction opt
 
2207
    (&net_menu,"$network_opts_text",
 
2208
     "$network_opts_help",&net_options);
 
2209
 
 
2210
    /*
 
2211
      uMenuItemFunction serv
 
2212
      (&net_menu,"$network_host_text",
 
2213
      "$network_host_help",&sg_HostGameMenu);
 
2214
    */
 
2215
 
 
2216
    uMenuItemFunction inter
 
2217
    (&net_menu,"$network_menu_internet_text",
 
2218
     "$network_menu_internet_help",&gServerBrowser::BrowseMaster);
 
2219
 
 
2220
    uMenuItemFunction lan
 
2221
    (&net_menu,"$network_menu_lan_text",
 
2222
     "$network_menu_lan_help",&gServerBrowser::BrowseLAN);
 
2223
 
 
2224
    net_menu.Enter();
 
2225
}
 
2226
 
 
2227
 
 
2228
 
 
2229
static void StartNewMatch(){
 
2230
    if (sg_currentGame)
 
2231
        sg_currentGame->StartNewMatch();
 
2232
    if (sn_GetNetState()!=nCLIENT){
 
2233
        sn_CenterMessage("$gamestate_reset_center");
 
2234
        sn_ConsoleOut("$gamestate_reset_console");
 
2235
    }
 
2236
}
 
2237
 
 
2238
static void StartNewMatch_conf(std::istream &){
 
2239
    StartNewMatch();
 
2240
}
 
2241
 
 
2242
static tConfItemFunc snm("START_NEW_MATCH",&StartNewMatch_conf);
 
2243
 
 
2244
#ifdef DEDICATED
 
2245
static void Quit_conf(std::istream &){
 
2246
 
 
2247
    if ( sg_currentGame )
 
2248
    {
 
2249
        sg_currentGame->NoLongerGoOn();
 
2250
    }
 
2251
 
 
2252
    // mark end of recording
 
2253
    tRecorder::Playback("END");
 
2254
    tRecorder::Record("END");
 
2255
    uMenu::quickexit = true;
 
2256
}
 
2257
 
 
2258
static tConfItemFunc quit_conf("QUIT",&Quit_conf);
 
2259
static tConfItemFunc exit_conf("EXIT",&Quit_conf);
 
2260
#endif
 
2261
 
 
2262
 
 
2263
void MainMenu(bool ingame){
 
2264
    //  update_settings();
 
2265
 
 
2266
    if (ingame)
 
2267
        sr_con.SetHeight(2);
 
2268
 
 
2269
    gLogo::SetDisplayed(true);
 
2270
 
 
2271
    tOutput gametitle;
 
2272
    if (!ingame)
 
2273
        gametitle << "$game_menu_text";
 
2274
    else
 
2275
        gametitle << "$game_menu_ingame_text";
 
2276
 
 
2277
    uMenu game_menu(gametitle);
 
2278
 
 
2279
    uMenuItemFunction *reset=NULL;
 
2280
 
 
2281
    if(ingame && sn_GetNetState()!=nCLIENT){
 
2282
        reset=new uMenuItemFunction
 
2283
              (&game_menu,"$game_menu_reset_text",
 
2284
               "$game_menu_reset_help",
 
2285
               &StartNewMatch);
 
2286
    }
 
2287
 
 
2288
    uMenuItemFunction *settings1=NULL;
 
2289
 
 
2290
    if (!ingame)
 
2291
        settings1=tNEW(uMenuItemFunction)
 
2292
                  (&game_menu,
 
2293
                   "$game_settings_menu_text",
 
2294
                   "$game_settings_menu_help",
 
2295
                   &GameSettingsSP);
 
2296
    else
 
2297
        settings1=tNEW(uMenuItemFunction)
 
2298
                  (&game_menu,
 
2299
                   "$game_settings_menu_text",
 
2300
                   "$game_settings_menu_help",
 
2301
                   &GameSettingsCurrent);
 
2302
 
 
2303
    uMenuItemFunction *connect=NULL,*start=NULL,*sound=NULL;
 
2304
 
 
2305
    if (!ingame){
 
2306
        connect=new uMenuItemFunction
 
2307
                (&game_menu,
 
2308
                 "$network_menu_text",
 
2309
                 "$network_menu_help",
 
2310
                 &net_game);
 
2311
 
 
2312
        start= new uMenuItemFunction(&game_menu,"$game_menu_start_text",
 
2313
                                     "$game_menu_start_help",&singlePlayer_game);
 
2314
    }
 
2315
 
 
2316
    tOutput title;
 
2317
    title.SetTemplateParameter( 1, sn_programVersion );
 
2318
    if (!ingame)
 
2319
        title << "$main_menu_text";
 
2320
    else
 
2321
        title << "$ingame_menu_text";
 
2322
 
 
2323
    uMenu MainMenu(title,false);
 
2324
 
 
2325
    if (ingame)
 
2326
        sg_IngameMenu = &MainMenu;
 
2327
 
 
2328
    char *extitle,*exhelp;
 
2329
    if (!ingame){
 
2330
        extitle="$main_menu_exit_text";
 
2331
        exhelp="$main_menu_exit_help";
 
2332
    }
 
2333
    else{
 
2334
        extitle="$ingame_menu_exit_text";
 
2335
        exhelp="$ingame_menu_exit_help";
 
2336
    }
 
2337
 
 
2338
    uMenuItemExit exx(&MainMenu,extitle,
 
2339
                      exhelp);
 
2340
 
 
2341
 
 
2342
    uMenuItemFunction *return_to_main=NULL;
 
2343
 
 
2344
    if (ingame){
 
2345
        if (sn_GetNetState()==nSTANDALONE)
 
2346
            return_to_main=new uMenuItemFunction
 
2347
                           (&MainMenu,"$game_menu_exit_text",
 
2348
                            "$game_menu_exit_help",
 
2349
                            &ret_to_MainMenu);
 
2350
        else if (sn_GetNetState()==nCLIENT)
 
2351
            return_to_main=new uMenuItemFunction
 
2352
                           (&MainMenu,"$game_menu_disconnect_text",
 
2353
                            "$game_menu_disconnect_help",
 
2354
                            &ret_to_MainMenu);
 
2355
        else
 
2356
            return_to_main=new uMenuItemFunction
 
2357
                           (&MainMenu,
 
2358
                            "$game_menu_shutdown_text",
 
2359
                            "game_menu_shutdown_help",
 
2360
                            &ret_to_MainMenu);
 
2361
    }
 
2362
 
 
2363
 
 
2364
 
 
2365
    uMenu Settings("$system_settings_menu_text");
 
2366
 
 
2367
    uMenuItemSubmenu subm_settings
 
2368
    (&MainMenu,&Settings,
 
2369
     "$system_settings_menu_help");
 
2370
 
 
2371
 
 
2372
    uMenuItem* team = NULL;
 
2373
    if ( ingame )
 
2374
    {
 
2375
        team = tNEW( uMenuItemFunction) ( &MainMenu,
 
2376
                                          "$team_menu_title",
 
2377
                                          "$team_menu_help",
 
2378
                                          &gTeam::TeamMenu );
 
2379
    }
 
2380
 
 
2381
    uMenuItemFunction *se_PlayerMenu=NULL;
 
2382
 
 
2383
    //   if (!ingame)
 
2384
    se_PlayerMenu= new uMenuItemFunction
 
2385
                   (&MainMenu,"$player_mainmenu_text",
 
2386
                    "$player_mainmenu_help",
 
2387
                    &sg_PlayerMenu);
 
2388
 
 
2389
    uMenuItemFunction *player_police=NULL;
 
2390
    uMenuItemFunction *voting=NULL;
 
2391
    if ( ingame && sn_GetNetState() != nSTANDALONE )
 
2392
    {
 
2393
        player_police = tNEW( uMenuItemFunction )( &MainMenu, "$player_police_text", "$player_police_help", ePlayerNetID::PoliceMenu );
 
2394
 
 
2395
        if ( eVoter::VotingPossible() )
 
2396
            voting = tNEW( uMenuItemFunction )( &MainMenu, "$voting_menu_text", "$voting_menu_help", eVoter::VotingMenu );
 
2397
    }
 
2398
 
 
2399
    uMenu misc("$misc_menu_text");
 
2400
 
 
2401
    //  misc.SetCenter(.25);
 
2402
 
 
2403
    uMenuItemFunction language
 
2404
    (&misc,"$language_menu_title",
 
2405
     "$language_menu_help",
 
2406
     &sg_LanguageMenu);
 
2407
 
 
2408
    uMenuItemFunction global_key
 
2409
    (&misc,"$misc_global_key_text",
 
2410
     "$misc_global_key_help",
 
2411
     &su_InputConfigGlobal);
 
2412
 
 
2413
    uMenuItemToggle wrap
 
2414
    (&misc,"$misc_menuwrap_text",
 
2415
     "$misc_menuwrap_help",
 
2416
     uMenu::wrap);
 
2417
 
 
2418
    uMenuItemToggle to2
 
2419
    (&misc,"$misc_textout_text",
 
2420
     "$misc_textout_help",sr_textOut);
 
2421
 
 
2422
 
 
2423
 
 
2424
    uMenuItemToggle mp
 
2425
    (&misc,"$misc_moviepack_text",
 
2426
     "$misc_moviepack_help",sg_moviepackUse);
 
2427
 
 
2428
 
 
2429
    uMenuItemSubmenu misc_sm
 
2430
    (&Settings,&misc,
 
2431
     "$misc_menu_help");
 
2432
 
 
2433
    sound = new uMenuItemFunction
 
2434
            (&Settings,"$sound_menu_text",
 
2435
             "$sound_menu_help",&se_SoundMenu);
 
2436
 
 
2437
    uMenuItemSubmenu subm
 
2438
    (&Settings,&sg_screenMenu,
 
2439
     "$display_settings_menu_help");
 
2440
 
 
2441
    uMenuItemSubmenu *gamemenuitem = NULL;
 
2442
    if (sn_GetNetState() != nCLIENT)
 
2443
    {
 
2444
        char *gamehelp;
 
2445
        if (!ingame)
 
2446
            gamehelp="$game_menu_main_help";
 
2447
        else
 
2448
            gamehelp="$game_menu_ingame_help";
 
2449
 
 
2450
        gamemenuitem = tNEW(uMenuItemSubmenu) (&MainMenu,
 
2451
                                               &game_menu,
 
2452
                                               gamehelp
 
2453
                                              );
 
2454
    }
 
2455
 
 
2456
    if (!ingame)
 
2457
    {
 
2458
        rViewport::Update(MAX_PLAYERS);
 
2459
        // ePlayerNetID::Update();
 
2460
    }
 
2461
 
 
2462
    MainMenu.Enter();
 
2463
 
 
2464
    if (settings1)
 
2465
        delete settings1;
 
2466
    if (team)
 
2467
        delete team;
 
2468
    if (gamemenuitem)
 
2469
        delete gamemenuitem;
 
2470
    if (sound)
 
2471
        delete sound;
 
2472
    if (connect)
 
2473
        delete connect;
 
2474
    if (start)
 
2475
        delete start;
 
2476
    if (return_to_main)
 
2477
        delete return_to_main;
 
2478
    if (se_PlayerMenu)
 
2479
        delete se_PlayerMenu;
 
2480
    if (reset)
 
2481
        delete reset;
 
2482
    if ( player_police )
 
2483
        delete player_police;
 
2484
    if ( voting )
 
2485
        delete voting;
 
2486
 
 
2487
    if (ingame)
 
2488
        sg_IngameMenu=NULL;
 
2489
 
 
2490
    if (ingame)
 
2491
    {
 
2492
        gLogo::SetDisplayed(false);
 
2493
        sr_con.SetHeight(7);
 
2494
    }
 
2495
}
 
2496
 
 
2497
 
 
2498
 
 
2499
// Game states:
 
2500
 
 
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
 
2510
#define GS_PLAY                                 50
 
2511
#define GS_DELETE_OBJECTS               60
 
2512
#define GS_DELETE_GRID                  70
 
2513
#define GS_STATE_MAX                    80
 
2514
 
 
2515
static bool sg_AbeforeB( int stateA, int stateB )
 
2516
{
 
2517
    return ( ( GS_STATE_MAX + stateA - stateB ) % GS_STATE_MAX > GS_STATE_MAX >> 2 );
 
2518
}
 
2519
 
 
2520
#ifndef DEDICATED
 
2521
static void ingame_menu_cleanup();
 
2522
static void ingame_menu()
 
2523
{
 
2524
    //    globalingame=true;
 
2525
    try
 
2526
    {
 
2527
        se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
 
2528
        if (sn_GetNetState()==nSTANDALONE)
 
2529
            se_PauseGameTimer(true);
 
2530
        MainMenu(true);
 
2531
    }
 
2532
    catch( ... )
 
2533
    {
 
2534
        ingame_menu_cleanup();
 
2535
        ret_to_MainMenu();
 
2536
        sg_IngameMenu=NULL;
 
2537
        sg_HostMenu=NULL;
 
2538
        throw;
 
2539
    }
 
2540
    ingame_menu_cleanup();
 
2541
}
 
2542
 
 
2543
static void ingame_menu_cleanup()
 
2544
{
 
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)
 
2550
    {
 
2551
        rViewport::Update(MAX_PLAYERS);
 
2552
        ePlayerNetID::Update();
 
2553
    }
 
2554
    //    globalingame=false;
 
2555
}
 
2556
#endif
 
2557
 
 
2558
 
 
2559
static nNOInitialisator<gGame> game_init(310,"game");
 
2560
 
 
2561
nDescriptor &gGame::CreatorDescriptor() const{
 
2562
    return game_init;
 
2563
}
 
2564
 
 
2565
 
 
2566
void gGame::Init(){
 
2567
    grid = tNEW(eGrid());
 
2568
    state=GS_CREATED;
 
2569
    stateNext=GS_TRANSFER_SETTINGS;
 
2570
    goon=true;
 
2571
 
 
2572
    sg_currentGame=this;
 
2573
#ifdef DEBUG
 
2574
    // con << "Game created.\n";
 
2575
#endif
 
2576
    aParser = tNEW(gParser)(&Arena, grid);
 
2577
 
 
2578
    rounds = 0;
 
2579
    StartNewMatchNow();
 
2580
}
 
2581
 
 
2582
 
 
2583
void gGame::NoLongerGoOn(){
 
2584
    goon=false;
 
2585
    //  stateNext=GS_DELETE_OBJECTS;
 
2586
    if (sn_GetNetState()==nSERVER)
 
2587
        RequestSync();
 
2588
}
 
2589
 
 
2590
// console with filter for remote admin output redirection
 
2591
class gMapLoadConsoleFilter:public tConsoleFilter{
 
2592
public:
 
2593
    gMapLoadConsoleFilter()
 
2594
    {
 
2595
    }
 
2596
 
 
2597
    ~gMapLoadConsoleFilter()
 
2598
    {
 
2599
    }
 
2600
 
 
2601
    tColoredString message_; // the console log for the error message
 
2602
private:
 
2603
    // we want to come first
 
2604
    virtual int DoGetPriority() const{ return -100; }
 
2605
 
 
2606
    // don't actually filter; take line and add it to the potential error message
 
2607
    virtual void DoFilterLine( tString &line )
 
2608
    {
 
2609
        message_ << line << "\n";
 
2610
    }
 
2611
};
 
2612
 
 
2613
static void sg_ParseMap ( gParser * aParser )
 
2614
{
 
2615
    FILE* mapFD = NULL;
 
2616
 
 
2617
    gMapLoadConsoleFilter consoleLog;
 
2618
#ifdef DEBUG      
 
2619
    /*
 
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;
 
2624
      }
 
2625
    */
 
2626
 
 
2627
    con << "Loading map " << mapfile << "...\n";
 
2628
#endif      
 
2629
    mapFD = tResourceManager::openResource(mapuri, mapfile);
 
2630
 
 
2631
    if (!mapFD || !aParser->LoadAndValidateMapXML("", mapFD, mapfile))
 
2632
    {
 
2633
        tOutput errorMessage( sn_GetNetState() == nCLIENT ? "$map_file_load_failure_server" : "$map_file_load_failure_self", mapfile );
 
2634
 
 
2635
#ifndef DEDICATED
 
2636
        errorMessage << "\nLog:\n" << consoleLog.message_;
 
2637
#endif
 
2638
 
 
2639
        con << errorMessage;
 
2640
 
 
2641
        tOutput errorTitle("$map_file_load_failure_title");
 
2642
 
 
2643
        if ( sn_GetNetState() != nSTANDALONE )
 
2644
        {
 
2645
            throw tGenericException( errorMessage, errorTitle );
 
2646
        }
 
2647
 
 
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 );
 
2652
        }
 
2653
    }
 
2654
 
 
2655
    if (mapFD)
 
2656
        fclose(mapFD);
 
2657
}
 
2658
 
 
2659
void gGame::Verify()
 
2660
{
 
2661
    // test map and load map settings
 
2662
    sg_ParseMap( aParser );
 
2663
    init_game_grid(grid, aParser);
 
2664
    exit_game_grid(grid);
 
2665
}
 
2666
 
 
2667
gGame::gGame(){
 
2668
    synced_ = true;
 
2669
    gLogo::SetDisplayed(false);
 
2670
    if (sn_GetNetState()!=nCLIENT)
 
2671
        RequestSync();
 
2672
    Init();
 
2673
}
 
2674
 
 
2675
gGame::gGame(nMessage &m):nNetObject(m){
 
2676
    synced_ = false;
 
2677
    Init();
 
2678
}
 
2679
 
 
2680
 
 
2681
gGame::~gGame(){
 
2682
#ifdef DEBUG
 
2683
    //con << "deleting game...\n";
 
2684
#endif
 
2685
    //stateNext=GS_CREATE_GRID;
 
2686
    //StateUpdate();
 
2687
 
 
2688
    tASSERT( sg_currentGame != this );
 
2689
 
 
2690
    exit_game_objects(grid);
 
2691
    grid->Clear();
 
2692
    ePlayerNetID::ThrowOutDisconnected();
 
2693
 
 
2694
    delete aParser;
 
2695
}
 
2696
 
 
2697
 
 
2698
void gGame::WriteSync(nMessage &m){
 
2699
    nNetObject::WriteSync(m);
 
2700
    m.Write(stateNext);
 
2701
#ifdef DEBUG
 
2702
    //con << "Wrote game state " << stateNext << ".\n";
 
2703
#endif
 
2704
}
 
2705
 
 
2706
void gGame::ReadSync(nMessage &m){
 
2707
    nNetObject::ReadSync(m);
 
2708
 
 
2709
    unsigned short newState;
 
2710
    m.Read(newState);
 
2711
 
 
2712
#ifdef DEBUG
 
2713
    con << "Read gamestate " << newState << ".\n";
 
2714
#endif
 
2715
 
 
2716
    // only update the state if it does not go back a few steps
 
2717
    if ( sg_AbeforeB( stateNext, newState ) )
 
2718
        stateNext = newState;
 
2719
 
 
2720
#ifdef DEBUG
 
2721
    //con << "Read game state " << stateNext << ".\n";
 
2722
#endif
 
2723
}
 
2724
 
 
2725
 
 
2726
void gGame::NetSync(){
 
2727
    // find end of recording in playback
 
2728
    if ( tRecorder::Playback("END") )
 
2729
    {
 
2730
        tRecorder::Record("END");
 
2731
        uMenu::quickexit=true;
 
2732
    }
 
2733
 
 
2734
#ifdef DEDICATED
 
2735
    if (!sr_glOut && ePlayer::PlayerConfig(0)->cam)
 
2736
        tERR_ERROR_INT("Someone messed with the camera!");
 
2737
#endif
 
2738
    nNetObject::SyncAll();
 
2739
    sn_Receive();
 
2740
}
 
2741
void gGame::NetSyncIdle(){
 
2742
    NetSync();
 
2743
 
 
2744
    tAdvanceFrame( sn_defaultDelay );
 
2745
}
 
2746
 
 
2747
 
 
2748
unsigned short client_gamestate[MAXCLIENTS+2];
 
2749
 
 
2750
static void client_gamestate_handler(nMessage &m){
 
2751
    unsigned short state;
 
2752
    m.Read( state );
 
2753
    client_gamestate[m.SenderID()] = state;
 
2754
        #ifdef DEBUG
 
2755
    //  con << "User " << m.SenderID() << " is in Mode " << state << '\n';
 
2756
        #endif
 
2757
}
 
2758
 
 
2759
static nDescriptor client_gs(311,client_gamestate_handler,"client_gamestate");
 
2760
 
 
2761
 
 
2762
 
 
2763
void gGame::SyncState(unsigned short state){
 
2764
    if (sn_GetNetState()==nSERVER){
 
2765
 
 
2766
        bool firsttime=true;
 
2767
        bool goon=true;
 
2768
        REAL timeout=tSysTimeFloat()+sg_Timeout*.1;
 
2769
 
 
2770
        sn_Sync(sg_Timeout*.1,true);
 
2771
        NetSyncIdle();
 
2772
 
 
2773
        while(goon && tSysTimeFloat()<timeout){
 
2774
            /*
 
2775
              if (sg_currentGame)
 
2776
              sg_currentGame->RequestSync();
 
2777
            */
 
2778
 
 
2779
            sn_Sync(sg_Timeout*.1,true);
 
2780
            NetSyncIdle();
 
2781
 
 
2782
            goon=false;
 
2783
            for(int i=MAXCLIENTS;i>0;i--)
 
2784
                if ( sn_Connections[i].socket )
 
2785
                {
 
2786
                    int clientState = client_gamestate[i];
 
2787
                    if ( sg_AbeforeB( clientState, state ) )
 
2788
                    {
 
2789
                        goon=true;
 
2790
                    }
 
2791
                }
 
2792
            if (goon && firsttime){
 
2793
                firsttime=false;
 
2794
#ifdef DEBUG
 
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";
 
2798
#endif    
 
2799
            }
 
2800
        }
 
2801
    }
 
2802
}
 
2803
 
 
2804
 
 
2805
void gGame::SetState(unsigned short act,unsigned short next){
 
2806
    state=act;
 
2807
#ifdef DEBUG
 
2808
    //con << "Entering gamestate " << state
 
2809
    //<< ", next state: " << next << '\n';
 
2810
#endif
 
2811
 
 
2812
    if (sn_GetNetState()==nSERVER){
 
2813
        RequestSync();
 
2814
        NetSyncIdle();
 
2815
        SyncState(state);
 
2816
    }
 
2817
 
 
2818
    if (stateNext!=next){
 
2819
        if (sn_GetNetState()!=nCLIENT || goon==false){
 
2820
 
 
2821
            stateNext=next;
 
2822
 
 
2823
            if (sn_GetNetState()==nSERVER){
 
2824
                RequestSync();
 
2825
                NetSyncIdle();
 
2826
            }
 
2827
        }
 
2828
    }
 
2829
}
 
2830
 
 
2831
// from nNetwork.C
 
2832
extern REAL planned_rate_control[MAXCLIENTS+2];
 
2833
extern REAL sent_per_messid[100];
 
2834
 
 
2835
static REAL lastdeath=0;
 
2836
 
 
2837
void gGame::StateUpdate(){
 
2838
 
 
2839
    //  if (state==GS_CREATED)
 
2840
    //          stateNext=GS_CREATE_GRID;
 
2841
 
 
2842
    while ( sg_AbeforeB( state, stateNext ) && goon )
 
2843
    {
 
2844
        #ifdef CONNECTION_STRESS
 
2845
        if ( sg_ConnectionStress )
 
2846
        {
 
2847
            tRandomizer & randomizer = tRandomizer::GetInstance();
 
2848
            int random = randomizer.Get( 16 );
 
2849
            if ( random == 0 )
 
2850
            {
 
2851
                sg_RequestedDisconnection = true;
 
2852
                //                                              sn_SetNetState( nSTANDALONE );
 
2853
                goon = false;
 
2854
            }
 
2855
 
 
2856
            se_ChatState( ePlayerNetID::ChatFlags_Away, 1 );
 
2857
        }
 
2858
        #endif
 
2859
 
 
2860
        // unsigned short int mes1 = 1, mes2 = 1, mes3 = 1, mes4 = 1, mes5 = 1;
 
2861
 
 
2862
        switch(state){
 
2863
        case GS_DELETE_GRID:
 
2864
            sr_con.autoDisplayAtNewline=true;
 
2865
 
 
2866
            con << tOutput("$gamestate_deleting_grid");
 
2867
            //                          sn_ConsoleOut(sg_roundCenterMessage + "\n");
 
2868
            sn_CenterMessage(sg_roundCenterMessage);
 
2869
 
 
2870
            //                          for (unsigned short int mycy = 0; mycy > sg_roundConsoleMessage5.Len(); c++)
 
2871
 
 
2872
            exit_game_objects(grid);
 
2873
 
 
2874
            if (goon)
 
2875
                SetState(GS_TRANSFER_SETTINGS,GS_CREATE_GRID);
 
2876
            else
 
2877
                state=GS_CREATE_GRID;
 
2878
            break;
 
2879
        case GS_CREATED:
 
2880
        case GS_TRANSFER_SETTINGS:
 
2881
            sr_con.autoDisplayAtNewline=true;
 
2882
 
 
2883
            // transfer game settings
 
2884
            if ( nCLIENT != sn_GetNetState() )
 
2885
            {
 
2886
                update_settings();
 
2887
                ePlayerNetID::RemoveChatbots();
 
2888
            }
 
2889
 
 
2890
            rViewport::Update(MAX_PLAYERS);
 
2891
 
 
2892
            // log scores before players get renamed
 
2893
            ePlayerNetID::LogScoreDifferences();
 
2894
            se_SaveToLadderLog(tString("NEW_ROUND\n"));
 
2895
 
 
2896
            // kick spectators
 
2897
            nMachine::KickSpectators();
 
2898
 
 
2899
            // rename players as per request
 
2900
            if ( synced_ && sn_GetNetState() != nSERVER )
 
2901
                ePlayerNetID::Update();
 
2902
 
 
2903
            nConfItemBase::s_SendConfig(false);
 
2904
            sn_Sync( sg_Timeout*.1, true );
 
2905
 
 
2906
            SetState(GS_CREATE_GRID,GS_CAMERA);
 
2907
            break;
 
2908
 
 
2909
        case GS_CREATE_GRID:
 
2910
            sr_con.autoDisplayAtNewline=true;
 
2911
 
 
2912
            sg_ParseMap( aParser );
 
2913
 
 
2914
            sn_Statistics();
 
2915
            sg_Timestamp();
 
2916
 
 
2917
            con << tOutput("$gamestate_creating_grid");
 
2918
 
 
2919
            tAdvanceFrame();
 
2920
 
 
2921
            init_game_grid(grid, aParser);
 
2922
 
 
2923
            nNetObject::ClearAllDeleted();
 
2924
 
 
2925
            SetState(GS_CREATE_OBJECTS,GS_CAMERA);
 
2926
            break;
 
2927
        case GS_CREATE_OBJECTS:
 
2928
            // con << "Creating objects...\n";
 
2929
 
 
2930
            lastdeath = -100;
 
2931
 
 
2932
            // rename players as per request
 
2933
            if ( synced_ )
 
2934
                ePlayerNetID::Update();
 
2935
 
 
2936
            init_game_objects(grid);
 
2937
            s_Timestep(grid, se_GameTime(), false);
 
2938
            SetState(GS_TRANSFER_OBJECTS,GS_CAMERA);
 
2939
 
 
2940
            if (sn_GetNetState() == nCLIENT && just_connected){
 
2941
                sn_Sync(sg_Timeout*.1,true);
 
2942
                sn_Sync(sg_Timeout*.1,true);
 
2943
            }
 
2944
            just_connected=false;
 
2945
 
 
2946
            break;
 
2947
        case GS_TRANSFER_OBJECTS:
 
2948
            // con << "Transferring objects...\n";
 
2949
            rITexture::LoadAll();
 
2950
            // se_ResetGameTimer();
 
2951
            // se_PauseGameTimer(true);
 
2952
 
 
2953
 
 
2954
            // push all data
 
2955
            if(sn_GetNetState()==nSERVER){
 
2956
                bool goon=true;
 
2957
                double timeout=tSysTimeFloat()+sg_Timeout*.4;
 
2958
                while(goon && tSysTimeFloat()<timeout){
 
2959
                    NetSyncIdle();
 
2960
                    goon=false;
 
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))
 
2967
                                    goon=true;
 
2968
                }
 
2969
                if (tSysTimeFloat()<timeout)
 
2970
                    con << tOutput("$gamestate_done");
 
2971
                else{
 
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))
 
2977
                                {
 
2978
                                    tOutput o;
 
2979
                                    tString name;
 
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";
 
2985
                                    con << o;
 
2986
                                }
 
2987
                    con << "\n\n\n";
 
2988
                }
 
2989
            }
 
2990
 
 
2991
            // wait for players to ready
 
2992
            if ( sn_GetNetState() == nSERVER )
 
2993
                while ( ePlayerNetID::WaitToLeaveChat() )
 
2994
                {
 
2995
                    NetSyncIdle();
 
2996
                    se_SyncGameTimer();
 
2997
                }
 
2998
 
 
2999
            SetState(GS_CAMERA,GS_SYNCING);
 
3000
            break;
 
3001
        case GS_CAMERA:
 
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);
 
3008
            break;
 
3009
        case GS_SYNCING:
 
3010
            // con << "Syncing timer...\n";
 
3011
            rITexture::LoadAll();
 
3012
            SetState(GS_PLAY,GS_PLAY);
 
3013
            if (sn_GetNetState()!=nCLIENT){
 
3014
                if (rounds<=0){
 
3015
                    sn_ConsoleOut("$gamestate_resetnow_console");
 
3016
                    StartNewMatchNow();
 
3017
                    sn_CenterMessage("$gamestate_resetnow_center");
 
3018
                    se_SaveToScoreFile("$gamestate_resetnow_log");
 
3019
                }
 
3020
 
 
3021
                tOutput mess;
 
3022
                if (rounds < sg_currentSettings->limitRounds)
 
3023
                {
 
3024
                    mess.SetTemplateParameter(1, rounds+1);
 
3025
                    mess.SetTemplateParameter(2, sg_currentSettings->limitRounds);
 
3026
                    mess << "$gamestate_newround_console";
 
3027
 
 
3028
                    if (strlen(sg_roundConsoleMessage) > 2)
 
3029
                        sn_ConsoleOut(sg_roundConsoleMessage + "\n");
 
3030
                }
 
3031
                else
 
3032
                    mess << "$gamestate_newround_goldengoal";
 
3033
                sn_ConsoleOut(mess);
 
3034
 
 
3035
                se_SaveToScoreFile("$gamestate_newround_log");
 
3036
            }
 
3037
            //con << ePlayerNetID::Ranking();
 
3038
 
 
3039
            se_PauseGameTimer(false);
 
3040
            se_SyncGameTimer();
 
3041
            sr_con.fullscreen=false;
 
3042
            sr_con.autoDisplayAtNewline=false;
 
3043
 
 
3044
            // pings count fully now
 
3045
            nPingAverager::SetWeight(1);
 
3046
 
 
3047
            break;
 
3048
        case GS_PLAY:
 
3049
            sr_con.autoDisplayAtNewline=false;
 
3050
#ifdef DEDICATED
 
3051
            {
 
3052
                if ( sg_NumUsers() <= 0 )
 
3053
                    goon = 0;
 
3054
 
 
3055
                Analysis(0);
 
3056
 
 
3057
                {
 
3058
                    std::ifstream s;
 
3059
 
 
3060
                    // load contents of everytime.cfg for real
 
3061
                    if ( tDirectories::Config().Open(s, "everytime.cfg" ) )
 
3062
                        tConfItemBase::LoadAll(s);
 
3063
 
 
3064
                    s.close();
 
3065
 
 
3066
                    if ( tDirectories::Var().Open(s, "everytime.cfg" ) )
 
3067
                        tConfItemBase::LoadAll(s);
 
3068
 
 
3069
                    // load contents of everytime.cfg from playback
 
3070
                    tConfItemBase::LoadPlayback();
 
3071
                }
 
3072
 
 
3073
                // safe current players in a file
 
3074
                cp();
 
3075
            }
 
3076
#endif
 
3077
            // pings should not count as much in the between-round phase
 
3078
            nPingAverager::SetWeight(.001);
 
3079
 
 
3080
            se_UserShowScores(false);
 
3081
 
 
3082
            //con.autoDisplayAtNewline=true;
 
3083
            sr_con.fullscreen=true;
 
3084
            SetState(GS_DELETE_OBJECTS,GS_TRANSFER_SETTINGS);
 
3085
            break;
 
3086
        case GS_DELETE_OBJECTS:
 
3087
 
 
3088
            winDeathZone_ = NULL;
 
3089
 
 
3090
            rViewport::Update(MAX_PLAYERS);
 
3091
            if ( synced_ && sn_GetNetState() != nSERVER )
 
3092
                ePlayerNetID::Update();
 
3093
 
 
3094
            sr_con.autoDisplayAtNewline=true;
 
3095
 
 
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() )
 
3101
            {
 
3102
                se_ChatState( ePlayerNetID::ChatFlags_Menu, true );
 
3103
                eVoter::VotingMenu();
 
3104
                se_ChatState( ePlayerNetID::ChatFlags_Menu, false );
 
3105
            }
 
3106
            nNetObject::ClearAllDeleted();
 
3107
            break;
 
3108
        default:
 
3109
            break;
 
3110
        }
 
3111
        if (sn_GetNetState()==nSERVER){
 
3112
            NetSyncIdle();
 
3113
            RequestSync();
 
3114
            NetSyncIdle();
 
3115
        }
 
3116
        else if (sn_GetNetState()==nCLIENT){ // inform the server of our progress
 
3117
            NetSyncIdle();
 
3118
            nMessage *m=new nMessage(client_gs);
 
3119
            m->Write(state);
 
3120
            m->Send(0);
 
3121
#ifdef DEBUG
 
3122
            //                  con << "sending gamestate " << state << '\n';
 
3123
#endif
 
3124
            NetSyncIdle();
 
3125
        }
 
3126
    }
 
3127
}
 
3128
 
 
3129
// uncomment to activate respawning
 
3130
// #define RESPAWN_HACK
 
3131
 
 
3132
#ifdef RESPAWN_HACK
 
3133
// Respawns cycles (crude test)
 
3134
static void sg_Respawn( REAL time, eGrid *grid, gArena & arena )
 
3135
{
 
3136
    for ( int i = se_PlayerNetIDs.Len()-1; i >= 0; --i )
 
3137
    {
 
3138
        ePlayerNetID *p = se_PlayerNetIDs(i);
 
3139
 
 
3140
        if ( !p->CurrentTeam() )
 
3141
            continue;
 
3142
 
 
3143
        eGameObject *e=p->Object();
 
3144
 
 
3145
        if ( ( !e || !e->Alive() && e->DeathTime() < time - .5 ) && sn_GetNetState() != nCLIENT )
 
3146
        {
 
3147
            eCoord pos,dir;
 
3148
            if ( e )
 
3149
            {
 
3150
                dir = e->Direction();
 
3151
                pos = e->Position();
 
3152
                eWallRim::Bound( pos, 1 );
 
3153
                eCoord displacement = pos - e->Position();
 
3154
                if ( displacement.NormSquared() > .01 )
 
3155
                {
 
3156
                    dir = displacement;
 
3157
                    dir.Normalize();
 
3158
                }
 
3159
            }
 
3160
            else
 
3161
                arena.LeastDangerousSpawnPoint()->Spawn( pos, dir );
 
3162
#ifdef DEBUG
 
3163
            //                std::cout << "spawning player " << pni->name << '\n';
 
3164
#endif
 
3165
            gCycle * cycle = new gCycle(grid, pos, dir, p, 0);
 
3166
            p->ControlObject(cycle);
 
3167
        }
 
3168
    }
 
3169
}
 
3170
#endif
 
3171
 
 
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 );
 
3176
 
 
3177
void gGame::Timestep(REAL time,bool cam){
 
3178
#ifdef DEBUG
 
3179
    tMemMan::Check();
 
3180
#endif
 
3181
 
 
3182
#ifdef RESPAWN_HACK
 
3183
    sg_Respawn(time,grid,Arena);
 
3184
#endif
 
3185
 
 
3186
    // chop timestep into small, managable bits
 
3187
    REAL dt = time - lastTimeTimestep;
 
3188
    if ( dt < 0 )
 
3189
        return;
 
3190
    REAL lt = lastTimeTimestep;
 
3191
 
 
3192
    // determine the number of bits
 
3193
    int number_of_steps=int(fabs((dt)/sg_timestepMax));
 
3194
    if (number_of_steps<1)
 
3195
        number_of_steps=1;
 
3196
    if ( number_of_steps > sg_timestepMaxCount )
 
3197
    {
 
3198
        number_of_steps = sg_timestepMaxCount;
 
3199
    }
 
3200
 
 
3201
    // chop
 
3202
    for(int i=1;i<=number_of_steps;i++)
 
3203
    {
 
3204
        REAL stepTime = lt + i * dt/number_of_steps;
 
3205
        s_Timestep(grid, stepTime, cam);
 
3206
    }
 
3207
}
 
3208
 
 
3209
// check if team has any enemies currently
 
3210
static bool sg_EnemyExists( int team )
 
3211
{
 
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 )
 
3214
    {
 
3215
        if ( i != team && eTeam::Enemies( eTeam::teams[i], eTeam::teams[team] ) )
 
3216
            return true;
 
3217
    }
 
3218
 
 
3219
    return false;
 
3220
}
 
3221
 
 
3222
static REAL sg_winZoneRandomness = .8;
 
3223
static tSettingItem< REAL > sg_winZoneSpreadConf( "WIN_ZONE_RANDOMNESS", sg_winZoneRandomness );
 
3224
 
 
3225
void gGame::Analysis(REAL time){
 
3226
    if ( nCLIENT == sn_GetNetState() )
 
3227
        return;
 
3228
 
 
3229
    static REAL wintimer=0;
 
3230
 
 
3231
    // send timeout warnings
 
3232
 
 
3233
 
 
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);
 
3238
            sn_ConsoleOut(o);
 
3239
            warning=6;
 
3240
        }
 
3241
 
 
3242
 
 
3243
        if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<30 && warning<5){
 
3244
            tOutput o("$gamestate_30seconds_warn");
 
3245
            sn_CenterMessage(o);
 
3246
            sn_ConsoleOut(o);
 
3247
            warning=6;
 
3248
            warning=5;
 
3249
        }
 
3250
 
 
3251
        if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<60 && warning<4){
 
3252
            tOutput o("$gamestate_minute_warn");
 
3253
            sn_CenterMessage(o);
 
3254
            sn_ConsoleOut(o);
 
3255
            warning=4;
 
3256
        }
 
3257
 
 
3258
        if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<2*60 && warning<3){
 
3259
            tOutput o("$gamestate_2minutes_warn");
 
3260
            sn_ConsoleOut(o);
 
3261
            warning=3;
 
3262
        }
 
3263
 
 
3264
        if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<5*60 && warning<2){
 
3265
            tOutput o("$gamestate_5minutes_warn");
 
3266
            sn_ConsoleOut(o);
 
3267
            warning=2;
 
3268
        }
 
3269
 
 
3270
        if ((startTime+sg_currentSettings->limitTime*60)-tSysTimeFloat()<10*60 && warning<1){
 
3271
            tOutput o("$gamestate_10minutes_warn");
 
3272
            sn_ConsoleOut(o);
 
3273
            warning=1;
 
3274
        }
 
3275
    }
 
3276
 
 
3277
    // count active players
 
3278
    int active = 0;
 
3279
    int i;
 
3280
    for(i=se_PlayerNetIDs.Len()-1;i>=0;i--){
 
3281
        ePlayerNetID *pni=se_PlayerNetIDs(i);
 
3282
        if (pni->IsActive())
 
3283
            active ++;
 
3284
    }
 
3285
 
 
3286
    // count other statistics
 
3287
    int alive_and_not_disconnected = 0;
 
3288
    int alive=0;
 
3289
    int ai_alive=0;
 
3290
    int teams_alive=0;
 
3291
    int last_alive=-1;
 
3292
    int last_team_alive=-1;
 
3293
    int last_alive_and_not_disconnected=-1;
 
3294
    int humans = 0;
 
3295
    int active_humans = 0;
 
3296
    int ais    = 0;
 
3297
    REAL deathTime=0;
 
3298
 
 
3299
    bool notyetloggedin = true;  // are all current users not yet logged in?
 
3300
 
 
3301
    for(i=eTeam::teams.Len()-1;i>=0;i--){
 
3302
        eTeam *t = eTeam::teams(i);
 
3303
 
 
3304
        humans += t->NumHumanPlayers();
 
3305
        ais    += t->NumAIPlayers();
 
3306
 
 
3307
        if ( t->Alive() )
 
3308
        {
 
3309
            teams_alive++;
 
3310
            last_team_alive = i;
 
3311
        }
 
3312
 
 
3313
        if ( t->NumHumanPlayers() > 0 )
 
3314
        { // human players
 
3315
            for (int j=t->NumPlayers()-1; j>=0; --j)
 
3316
            {
 
3317
                ePlayerNetID* p = t->Player(j);
 
3318
                if (p->IsActive())
 
3319
                    active_humans++;
 
3320
 
 
3321
                gCycle *g=dynamic_cast<gCycle *>(p->Object());
 
3322
                if(g){
 
3323
                    notyetloggedin = false;
 
3324
 
 
3325
                    if(g->Alive())
 
3326
                    {
 
3327
 
 
3328
                        if ( p->IsHuman() )
 
3329
                        {
 
3330
                            alive++;
 
3331
                            if (p->IsActive())
 
3332
                            {
 
3333
                                last_alive_and_not_disconnected=i;
 
3334
                                alive_and_not_disconnected++;
 
3335
                            }
 
3336
                        }
 
3337
                        else
 
3338
                            ai_alive++;
 
3339
 
 
3340
                        last_alive=i;
 
3341
                    }
 
3342
                    else
 
3343
                    {
 
3344
                        REAL dt=g->DeathTime();
 
3345
                        if (dt>deathTime)
 
3346
                            deathTime=dt;
 
3347
                    }
 
3348
                }
 
3349
                else if (p->IsAuth())
 
3350
                    notyetloggedin = false;
 
3351
            }
 
3352
        }
 
3353
        else
 
3354
        {
 
3355
            for (int j=t->NumPlayers()-1; j>=0; --j)
 
3356
            {
 
3357
                ePlayerNetID* p = t->Player(j);
 
3358
 
 
3359
                gCycle *g=dynamic_cast<gCycle *>(p->Object());
 
3360
                if(g){
 
3361
                    if(g->Alive())
 
3362
                    {
 
3363
                        ai_alive++;
 
3364
                    }
 
3365
                }
 
3366
            }
 
3367
        }
 
3368
    }
 
3369
 
 
3370
#ifdef DEDICATED
 
3371
    //activeHumans
 
3372
    if (sg_NumUsers() <= 0)
 
3373
        goon = false;
 
3374
#endif
 
3375
 
 
3376
 
 
3377
    if (last_alive_and_not_disconnected >= 0)
 
3378
        last_alive = last_alive_and_not_disconnected;
 
3379
 
 
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 )
 
3382
    {
 
3383
        for(int i=se_PlayerNetIDs.Len()-1;i>=0;i--)
 
3384
        {
 
3385
            gCycle *g=dynamic_cast<gCycle *>(se_PlayerNetIDs(i)->Object());
 
3386
            if(g && !se_PlayerNetIDs(i)->IsActive())
 
3387
            {
 
3388
                g->Kill();
 
3389
            }
 
3390
 
 
3391
            //                  alive = alive_and_not_disconnected;
 
3392
        }
 
3393
    }
 
3394
 
 
3395
    // keep the game running when there are only login processes running
 
3396
    if (notyetloggedin && humans > 0)
 
3397
        alive++;
 
3398
 
 
3399
 
 
3400
    static int all_alive_last=0;
 
3401
    {
 
3402
        int all_alive = ai_alive+alive;
 
3403
        if (all_alive != all_alive_last)
 
3404
        {
 
3405
            all_alive_last = ai_alive+alive;
 
3406
            lastdeath = time;
 
3407
        }
 
3408
    }
 
3409
 
 
3410
    static nVersionFeature winZone(2);
 
3411
 
 
3412
    // activate instant win zone
 
3413
    if ( winZone.Supported() && !bool( winDeathZone_ ) && winner == 0 && time - lastdeath > sg_currentSettings->winZoneMinLastDeath && time > sg_currentSettings->winZoneMinRoundTime )
 
3414
    {
 
3415
        winDeathZone_ = sg_CreateWinDeathZone( grid, Arena.GetRandomPos( sg_winZoneRandomness ) );
 
3416
    }
 
3417
 
 
3418
    bool holdBackNextRound = false;
 
3419
 
 
3420
    // who is alive?
 
3421
    if ( time-lastdeath < 1.0f )
 
3422
    {
 
3423
        holdBackNextRound = true;
 
3424
    }
 
3425
    else if (winner==0 && absolute_winner==0 ){
 
3426
        if(teams_alive <= 1 )
 
3427
        {
 
3428
            if ( sg_currentSettings->gameType!=gFREESTYLE )
 
3429
            {
 
3430
                if ( eTeam::teams.Len()>1 && teams_alive<=1 ){
 
3431
                    winner=last_team_alive+1;
 
3432
                    wintimer=time;
 
3433
                }
 
3434
            }
 
3435
            else
 
3436
            {
 
3437
                if ( teams_alive < 1 )
 
3438
                    winner=-1;
 
3439
                wintimer=time;
 
3440
            }
 
3441
        }
 
3442
 
 
3443
        const char* survivor="$player_win_survivor";
 
3444
        const char* messagetype = survivor;
 
3445
 
 
3446
        if ( wishWinner )
 
3447
        {
 
3448
            wintimer=time;
 
3449
            winner = wishWinner;
 
3450
            wishWinner = 0;
 
3451
            messagetype = wishWinnerMessage;
 
3452
        }
 
3453
 
 
3454
        if (winner <= 0 && alive <= 0 && ai_alive <= 0 && teams_alive <= 0){
 
3455
            if ( se_mainGameTimer )
 
3456
                se_mainGameTimer->speed = 1;
 
3457
 
 
3458
            // emergency
 
3459
            winner=-1;
 
3460
            wintimer=time;
 
3461
        }
 
3462
        else
 
3463
            if (winner){
 
3464
                if ( se_mainGameTimer )
 
3465
                    se_mainGameTimer->speed = 1;
 
3466
                lastdeath = time;
 
3467
 
 
3468
                if ( last_team_alive >= 0 )
 
3469
                    sg_currentSettings->AutoAI( eTeam::teams( last_team_alive )->NumHumanPlayers() > 0 );
 
3470
 
 
3471
                if ( sg_currentSettings->gameType!=gFREESTYLE && winner > 0 )
 
3472
                {
 
3473
                    // check if the win was legitimate: at least one enemy team needs to bo online
 
3474
                    if ( sg_EnemyExists( winner-1 ) )
 
3475
                    {
 
3476
#ifdef KRAWALL_SERVER
 
3477
                        // send the result to the master server
 
3478
                        if (!dynamic_cast<gAIPlayer*>(eTeam::teams(winner-1)))
 
3479
                        {
 
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() )
 
3485
                                {
 
3486
                                    players[players.Len()] = eTeam::teams(i)->Name();
 
3487
                                }
 
3488
 
 
3489
                            players[players.Len()] = eTeam::teams(winner-1)->Name();
 
3490
                            if (players.Len() > 1)
 
3491
                                nKrawall::ServerRoundEnd(&players(0), players.Len());
 
3492
                        }
 
3493
#endif
 
3494
 
 
3495
                        // scoring
 
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 )
 
3501
                        {
 
3502
                            highscore_won_rounds.Add(eTeam::teams[winner-1] ,1);
 
3503
                            highscore_ladder.winner(eTeam::teams(winner-1));
 
3504
                        }
 
3505
 
 
3506
                        // print winning message
 
3507
                        tOutput message;
 
3508
                        message << "$gamestate_winner_winner";
 
3509
                        message << eTeam::teams[winner-1]->Name();
 
3510
                        sn_CenterMessage(message);
 
3511
                        message << '\n';
 
3512
                        se_SaveToScoreFile(message);
 
3513
 
 
3514
                        tString ladderLog;
 
3515
                        ladderLog << "ROUND_WINNER " << ePlayerNetID::FilterName( eTeam::teams[winner-1]->Name() ) << "\n";
 
3516
                        se_SaveToLadderLog( ladderLog );
 
3517
                    }
 
3518
                }
 
3519
                check_hs();
 
3520
                winner = -1;
 
3521
            }
 
3522
    }
 
3523
 
 
3524
    int winnerExtraRound = ( winner != 0 || alive == 0 ) ? 1 : 0;
 
3525
 
 
3526
    // analyze the ranking list
 
3527
    if ( time-lastdeath < 2.0f )
 
3528
    {
 
3529
        holdBackNextRound = true;
 
3530
    }
 
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))){
 
3538
 
 
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.
 
3544
                   )
 
3545
                {
 
3546
                    bool declareChampion = true;
 
3547
                    if ( winner!=0 && wintimer > time - ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 4.0 ) )
 
3548
                    {
 
3549
                        declareChampion = false;
 
3550
                        holdBackNextRound= true;
 
3551
                    }
 
3552
 
 
3553
                    if ( declareChampion )
 
3554
                    {
 
3555
                        lastdeath = time + ( sg_currentSettings->finishType==gFINISH_EXPRESS ? 2.0f : 6.0f );
 
3556
 
 
3557
                        {
 
3558
                            tOutput message;
 
3559
                            message.SetTemplateParameter(1, eTeam::teams[0]->Name() );
 
3560
                            message << "$gamestate_champ_center";
 
3561
                            sn_CenterMessage(message);
 
3562
                        }
 
3563
 
 
3564
                        tOutput message;
 
3565
                        tColoredString name;
 
3566
                        name << eTeam::teams[0]->Name();
 
3567
                        name << tColoredString::ColorString(1,1,1);
 
3568
 
 
3569
                        tString ladderLog;
 
3570
                        ladderLog << "MATCH_WINNER " << ePlayerNetID::FilterName( eTeam::teams[0]->Name() ) << "\n";
 
3571
                        se_SaveToLadderLog( ladderLog );
 
3572
 
 
3573
                        message.SetTemplateParameter(1, name);
 
3574
                        message << "$gamestate_champ_console";
 
3575
 
 
3576
                        if (eTeam::teams(0)->Score() >=sg_currentSettings->limitScore)
 
3577
                        {
 
3578
                            message.SetTemplateParameter(1, eTeam::teams(0)->Score());
 
3579
                            message.SetTemplateParameter(2, sg_currentSettings->limitScore);
 
3580
                            message << "$gamestate_champ_scorehit";
 
3581
                        }
 
3582
                        else if ( tSysTimeFloat()>=startTime+sg_currentSettings->limitTime*60)
 
3583
                        {
 
3584
                            message.SetTemplateParameter(1, sg_currentSettings->limitTime);
 
3585
                            message << "$gamestate_champ_timehit";
 
3586
                        }
 
3587
                        else
 
3588
                        {
 
3589
                            message.SetTemplateParameter(1, rounds + 1);
 
3590
                            message << "$gamestate_champ_default";
 
3591
                        }
 
3592
 
 
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");
 
3599
 
 
3600
                        eTeam* winningTeam = eTeam::teams(0);
 
3601
                        if (!sg_singlePlayer && winningTeam->NumHumanPlayers() > 0 )
 
3602
                        {
 
3603
                            highscore_won_matches.Add( winningTeam, 1 );
 
3604
                        }
 
3605
 
 
3606
                        sn_ConsoleOut(message);
 
3607
                        wintimer=time;
 
3608
                        absolute_winner=1;
 
3609
 
 
3610
                        if ( se_mainGameTimer )
 
3611
                            se_mainGameTimer->speed = 1;
 
3612
 
 
3613
                        StartNewMatch();
 
3614
                    }
 
3615
                }
 
3616
            }
 
3617
    }
 
3618
 
 
3619
 
 
3620
    // time to wait after last death til we start a new round
 
3621
    REAL fintime=6;
 
3622
 
 
3623
    if (sg_currentSettings->finishType==gFINISH_EXPRESS)
 
3624
        fintime=2.5;
 
3625
 
 
3626
    if(( ( winner || absolute_winner ) && wintimer+fintime < time)
 
3627
            || (((alive==0 && eTeam::teams.Len()>=
 
3628
#ifndef DEDICATED
 
3629
                  1
 
3630
#else
 
3631
                  0
 
3632
#endif
 
3633
                 )) && time-lastdeath >fintime-2
 
3634
#ifndef DEDICATED
 
3635
                && humans > 0
 
3636
#endif
 
3637
               )){
 
3638
#ifdef DEBUG
 
3639
        //con << "winner=" << winner << ' ';
 
3640
        //con << "wintimer=" << wintimer << ' ';
 
3641
        //con << "time=" << time << ' ';
 
3642
        //con << "dt=" << deathTime << '\n';
 
3643
#endif
 
3644
        if (!holdBackNextRound &&
 
3645
                (
 
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 )
 
3650
                )
 
3651
           )
 
3652
        {
 
3653
            rounds++;
 
3654
            SetState(GS_PLAY,GS_DELETE_OBJECTS);
 
3655
        }
 
3656
 
 
3657
        if ( !winner && !absolute_winner && sg_currentSettings->finishType==gFINISH_SPEEDUP && se_mainGameTimer)
 
3658
        {
 
3659
            se_mainGameTimer->speed*=1.01;
 
3660
            if(se_mainGameTimer->speed>16)
 
3661
                se_mainGameTimer->speed=16;
 
3662
        }
 
3663
 
 
3664
    }
 
3665
 
 
3666
    for(i=se_PlayerNetIDs.Len()-1;i>=0;i--)
 
3667
    {
 
3668
        gAIPlayer *ai = dynamic_cast<gAIPlayer*>(se_PlayerNetIDs(i));
 
3669
        if (ai && think)
 
3670
            ai->Timestep(time);
 
3671
    }
 
3672
}
 
3673
 
 
3674
 
 
3675
void gGame::StartNewMatch(){
 
3676
    check_hs();
 
3677
    rounds=-100;
 
3678
 
 
3679
}
 
3680
 
 
3681
void gGame::StartNewMatchNow(){
 
3682
    if ( rounds != 0 )
 
3683
        se_SaveToLadderLog(tString("NEW_MATCH\n"));
 
3684
 
 
3685
    rounds=0;
 
3686
    warning=0;
 
3687
    startTime=tSysTimeFloat()-10;
 
3688
 
 
3689
    ePlayerNetID::ThrowOutDisconnected();
 
3690
    ePlayerNetID::ResetScore();
 
3691
}
 
3692
 
 
3693
#ifdef DEBUG          
 
3694
extern bool debug_grid;
 
3695
// from display.cpp
 
3696
bool simplify_grid=1;
 
3697
#endif
 
3698
 
 
3699
#ifdef DEDICATED
 
3700
static int sg_dedicatedFPS = 200;
 
3701
static tSettingItem<int> sg_dedicatedFPSConf( "DEDICATED_FPS", sg_dedicatedFPS );
 
3702
#endif
 
3703
 
 
3704
#ifndef DEDICATED
 
3705
// mouse grab toggling
 
3706
static uActionGlobal togglemousegrab( "TOGGLE_MOUSEGRAB" );
 
3707
static bool togglemousegrab_func(REAL x){
 
3708
    if (x>0){
 
3709
        su_mouseGrab = !su_mouseGrab;
 
3710
    }
 
3711
 
 
3712
    return true;
 
3713
}
 
3714
static uActionGlobalFunc togglemousegrab_action(&togglemousegrab,&togglemousegrab_func, true );
 
3715
 
 
3716
// pause game
 
3717
static uActionGlobal pausegame( "PAUSE_GAME" );
 
3718
static bool pausegame_func(REAL x){
 
3719
    static bool paused=false;
 
3720
 
 
3721
    if (x>0){
 
3722
        paused=!paused;
 
3723
        se_PauseGameTimer(paused);
 
3724
    }
 
3725
 
 
3726
    return true;
 
3727
}
 
3728
static uActionGlobalFunc pausegame_action(&pausegame,&pausegame_func, true );
 
3729
 
 
3730
// texture reloading
 
3731
static uActionGlobal reloadtextures( "RELOAD_TEXTURES" );
 
3732
static bool reloadtextures_func(REAL x){
 
3733
    if (x>0){
 
3734
        rITexture::UnloadAll();
 
3735
    }
 
3736
 
 
3737
    return true;
 
3738
}
 
3739
static uActionGlobalFunc reloadtextures_action(&reloadtextures,&reloadtextures_func, true );
 
3740
 
 
3741
// menu
 
3742
static uActionGlobal ingamemenu( "INGAME_MENU" );
 
3743
static bool ingamemenu_func(REAL x){
 
3744
    if (x>0){
 
3745
        st_ToDo(&ingame_menu);
 
3746
    }
 
3747
 
 
3748
    return true;
 
3749
}
 
3750
static uActionGlobalFunc ingamemenu_action(&ingamemenu,&ingamemenu_func, true );
 
3751
#endif // dedicated
 
3752
 
 
3753
bool gGame::GameLoop(bool input){
 
3754
    nNetState netstate = sn_GetNetState();
 
3755
 
 
3756
#ifdef DEDICATED
 
3757
    tDelay( 1000000 / sg_dedicatedFPS );
 
3758
#endif
 
3759
 
 
3760
#ifdef DEBUG
 
3761
    grid->Check();
 
3762
    if (simplify_grid)
 
3763
#endif
 
3764
        grid->SimplifyAll(10);
 
3765
 
 
3766
#ifdef DEBUG
 
3767
    grid->Check();
 
3768
#endif
 
3769
 
 
3770
    //if (std::cin.good() && !std::cin.underflow())
 
3771
    //tConfItemBase::LoadAll(std::cin);
 
3772
    // network syncing
 
3773
    REAL gtime=0;
 
3774
    REAL time=0;
 
3775
    if (state==GS_PLAY){
 
3776
        NetSync();
 
3777
        if ( netstate != sn_GetNetState() )
 
3778
        {
 
3779
            return false;
 
3780
        }
 
3781
        se_SyncGameTimer();
 
3782
        gtime=se_GameTime();
 
3783
        time=gtime;
 
3784
 
 
3785
        if (sn_GetNetState()==nSTANDALONE && sg_IngameMenu)
 
3786
            se_PauseGameTimer(true);
 
3787
 
 
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() ){
 
3791
            lastcountdown=cd;
 
3792
            tString s;
 
3793
            s << cd;
 
3794
            con.CenterDisplay(s,0);
 
3795
        }
 
3796
    }
 
3797
    //con << sg_netPlayerWalls.Len() << '\n';
 
3798
 
 
3799
#ifndef DEDICATED
 
3800
    if (input){
 
3801
        su_HandleDelayedEvents();
 
3802
 
 
3803
        SDL_Event tEvent;
 
3804
 
 
3805
        uInputProcessGuard inputProcessGuard;
 
3806
        while(su_GetSDLInput(tEvent,time)){
 
3807
            if (time>gtime) time=gtime;
 
3808
            if(time>lastTime_gameloop){
 
3809
                Timestep(time);
 
3810
                lastTime_gameloop=time;
 
3811
            }
 
3812
 
 
3813
 
 
3814
            if (!su_HandleEvent(tEvent, false))
 
3815
                switch (tEvent.type){
 
3816
                case SDL_MOUSEBUTTONDOWN:
 
3817
                    break;
 
3818
                case SDL_KEYDOWN:
 
3819
                    switch (tEvent.key.keysym.sym){
 
3820
 
 
3821
                    case(27):
 
3822
                                    //                                case('q'):
 
3823
                                    st_ToDo(&ingame_menu);
 
3824
                        break;
 
3825
#ifdef DEBUG          
 
3826
                    case('d'):
 
3827
                                    debug_grid=!debug_grid;
 
3828
                        break;
 
3829
 
 
3830
                    case('a'):
 
3831
                                    simplify_grid=!simplify_grid;
 
3832
                        break;
 
3833
 
 
3834
                    case('l'):
 
3835
                                    sr_glOut=!sr_glOut;
 
3836
                        break;
 
3837
 
 
3838
                    case('b'):
 
3839
                                    st_Breakpoint();
 
3840
                        break;
 
3841
 
 
3842
                    case('t'):
 
3843
                                    think=!think;
 
3844
                        break;
 
3845
                        /* #ifndef WIN32
 
3846
                           case('f'):
 
3847
                           fullscreen=(!fullscreen);
 
3848
                           con << fullscreen << "x!\n";
 
3849
                           XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
 
3850
                           break;        
 
3851
                           #endif */
 
3852
#endif
 
3853
 
 
3854
                    default:
 
3855
                        break;
 
3856
                    }
 
3857
                    break;
 
3858
 
 
3859
                default:
 
3860
                    break;
 
3861
                }
 
3862
        }
 
3863
 
 
3864
        su_InputSync();
 
3865
    }
 
3866
#endif
 
3867
 
 
3868
    NetSync();
 
3869
    if ( netstate != sn_GetNetState() )
 
3870
{
 
3871
        return false;
 
3872
    }
 
3873
 
 
3874
    if (state==GS_PLAY){
 
3875
        if (gtime<0 && gtime>-PREPARE_TIME+.3)
 
3876
            eCamera::s_Timestep(grid, gtime);
 
3877
        else{
 
3878
            if (gtime>=lastTime_gameloop){
 
3879
 
 
3880
                                #ifdef CONNECTION_STRESS
 
3881
                if ( sg_ConnectionStress )
 
3882
                {
 
3883
                    tRandomizer & randomizer = tRandomizer::GetInstance();
 
3884
                    int random = randomizer.Get( 1000 );
 
3885
                    if ( random == 0 )
 
3886
                    {
 
3887
                        sg_RequestedDisconnection = true;
 
3888
                        //                                              sn_SetNetState( nSTANDALONE );
 
3889
                        goon = false;
 
3890
                    }
 
3891
                }
 
3892
                                #endif
 
3893
 
 
3894
 
 
3895
                Timestep(gtime,true);
 
3896
                NetSync();
 
3897
                lastTime_gameloop=gtime;
 
3898
            }
 
3899
            lastTime_gameloop=gtime;
 
3900
        }
 
3901
        //    else if (lastTime_gameloop>gtime+10)
 
3902
        // lastTime_gameloop=gtime;
 
3903
 
 
3904
 
 
3905
 
 
3906
        if (sn_GetNetState()!=nCLIENT)
 
3907
        {
 
3908
            Analysis(gtime);
 
3909
 
 
3910
            // wait for chatting players
 
3911
            if ( sn_GetNetState()==nSERVER && gtime < sg_lastChatBreakTime + 1 )
 
3912
                se_PauseGameTimer( gtime < sg_lastChatBreakTime && ePlayerNetID::WaitToLeaveChat() );
 
3913
        }
 
3914
 
 
3915
        bool synced = se_mainGameTimer && se_mainGameTimer->IsSynced();
 
3916
 
 
3917
        if  (!synced)
 
3918
        {
 
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 )
 
3921
            {
 
3922
                ePlayer * p = ePlayer::PlayerConfig(pi);
 
3923
                if ( !p )
 
3924
                    break;
 
3925
                ePlayerNetID * np = p->netPlayer;
 
3926
                if ( !np )
 
3927
                    break;
 
3928
                if ( np->Object() )
 
3929
                {
 
3930
                    synced = true;
 
3931
                    break;
 
3932
                }
 
3933
            }
 
3934
        }
 
3935
        else if ( !synced_ )
 
3936
        {
 
3937
            // synced finally. Send our player info over so we can join the game.
 
3938
            ePlayerNetID::Update();
 
3939
            synced_ = true;
 
3940
        }
 
3941
 
 
3942
        if (sr_glOut && gtime>-PREPARE_TIME+.5 && goon && synced )
 
3943
        {
 
3944
            Render(grid, gtime, input);
 
3945
        }
 
3946
        else{
 
3947
#ifndef DEDICATED
 
3948
            if (input)
 
3949
            {
 
3950
                if ( !synced )
 
3951
                {
 
3952
                    con.CenterDisplay(tString(tOutput("$network_login_sync")),0);
 
3953
                }
 
3954
 
 
3955
                if ( sr_glOut )
 
3956
                    rSysDep::ClearGL();
 
3957
                rSysDep::SwapGL();
 
3958
            }
 
3959
 
 
3960
            tDelay(10000);
 
3961
#endif
 
3962
        }
 
3963
 
 
3964
        if ( netstate != sn_GetNetState() )
 
3965
        {
 
3966
            return false;
 
3967
        }
 
3968
 
 
3969
        return goon;
 
3970
    }
 
3971
    else{
 
3972
        // between rounds, assume we're synced
 
3973
        if ( !synced_ && sn_GetNetState() != nSERVER )
 
3974
            ePlayerNetID::Update();
 
3975
        synced_ = true;
 
3976
 
 
3977
#ifndef DEDICATED
 
3978
        if (input)
 
3979
        {
 
3980
            if (sr_glOut)
 
3981
                rSysDep::ClearGL();
 
3982
            rSysDep::SwapGL();
 
3983
        }
 
3984
#endif
 
3985
        tDelay( 10000 );
 
3986
        return goon;
 
3987
    }
 
3988
}
 
3989
 
 
3990
 
 
3991
bool gGame::GridIsReady(int client){
 
3992
    return HasBeenTransmitted(client) &&
 
3993
           (client_gamestate[client]>=GS_TRANSFER_OBJECTS &&
 
3994
            client_gamestate[client]<=GS_DELETE_OBJECTS);
 
3995
}
 
3996
 
 
3997
#include <fcntl.h> 
 
3998
#include <stdio.h> 
 
3999
#include <errno.h> 
 
4000
 
 
4001
bool GameLoop(bool input=true){
 
4002
    /*
 
4003
      int oldflags = fcntl (fileno(stdin), F_GETFD, 0);
 
4004
      if (oldflags<0)
 
4005
      std::cout << errno << '\n';
 
4006
       
 
4007
      if (fcntl(fileno(stdin), F_SETFL, oldflags | O_NONBLOCK)<0)
 
4008
      std::cout << errno << '\n';
 
4009
      
 
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){
 
4013
 
 
4014
    char c[10];
 
4015
    int in=0;
 
4016
    in=read (fileno(stdin),c,9);
 
4017
    for (int i=0;i<in;i++)
 
4018
    std::cout << c;
 
4019
     */
 
4020
 
 
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);
 
4026
 
 
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;
 
4031
 
 
4032
            // deviation of real ping and synced ping
 
4033
            REAL deviation = realping - p->ping;
 
4034
 
 
4035
            // measured against the variance, this player's ping deviates this much
 
4036
            // from the communicated value
 
4037
            REAL relativedeviation = deviation * deviation / pingvariance;
 
4038
 
 
4039
            if (0 == p->Owner())
 
4040
                realping = 0;
 
4041
 
 
4042
            if ( ( t - p->lastSync - 5 ) * relativedeviation > 5 ){
 
4043
                // if yes, send a message about it
 
4044
                p->ping = realping;
 
4045
                p->RequestSync(false);
 
4046
            }
 
4047
        }
 
4048
    }
 
4049
 
 
4050
    bool goon=false;
 
4051
    if(sg_currentGame){
 
4052
        tControlledPTR< nNetObject > keep( sg_currentGame );
 
4053
        sg_currentGame->StateUpdate();
 
4054
        goon=!uMenu::quickexit && bool(sg_currentGame) && sg_currentGame->GameLoop(input);
 
4055
    }
 
4056
    return goon;
 
4057
}
 
4058
 
 
4059
void gameloop_idle()
 
4060
{
 
4061
    se_UserShowScores( false );
 
4062
    GameLoop(false);
 
4063
}
 
4064
 
 
4065
static eSoundPlayer introPlayer(intro);
 
4066
static eSoundPlayer extroPlayer(extro);
 
4067
 
 
4068
static void sg_EnterGameCleanup();
 
4069
 
 
4070
void sg_EnterGameCore( nNetState enter_state ){
 
4071
    sg_RequestedDisconnection = false;
 
4072
 
 
4073
    sr_con.SetHeight(7);
 
4074
 
 
4075
    extroPlayer.End();
 
4076
    introPlayer.MakeGlobal();
 
4077
    introPlayer.Reset();
 
4078
 
 
4079
    //  exit_game_objects(grid);
 
4080
 
 
4081
    // enter single player settings
 
4082
    if ( sn_GetNetState() != nCLIENT )
 
4083
    {
 
4084
        sg_currentSettings = &singlePlayer;
 
4085
        sg_copySettings();
 
4086
    }
 
4087
 
 
4088
    gHighscoresBase::LoadAll();
 
4089
 
 
4090
    uMenu::SetIdle(gameloop_idle);
 
4091
    sr_con.autoDisplayAtSwap=true;
 
4092
    bool goon=true;
 
4093
    while (bool(sg_currentGame) && goon && sn_GetNetState()==enter_state){
 
4094
#ifdef DEDICATED // read input
 
4095
        sr_Read_stdin();
 
4096
#endif
 
4097
        tAdvanceFrame();
 
4098
        goon=GameLoop();
 
4099
        st_DoToDo();
 
4100
    }
 
4101
 
 
4102
    extroPlayer.MakeGlobal();
 
4103
    extroPlayer.Reset();
 
4104
 
 
4105
    sg_EnterGameCleanup();
 
4106
}
 
4107
 
 
4108
void sg_EnterGameCleanup()
 
4109
{
 
4110
    gHighscoresBase::SaveAll();
 
4111
 
 
4112
    sn_SetNetState( nSTANDALONE );
 
4113
 
 
4114
    // delete all AI players
 
4115
    gAIPlayer::ClearAll();
 
4116
    // gAIPlayer::SetNumberOfAIs(0, 0, 0, -1);
 
4117
    // gAITeam::BalanceWithAIs( false );
 
4118
    // gAIPlayer::ClearAll();
 
4119
 
 
4120
    gLogo::SetDisplayed(true);
 
4121
    uMenu::SetIdle(NULL);
 
4122
    sr_con.autoDisplayAtSwap=false;
 
4123
    sr_con.fullscreen=false;
 
4124
 
 
4125
    //  exit_game_objects(grid);
 
4126
    nNetObject::ClearAll();
 
4127
    ePlayerNetID::ClearAll();
 
4128
    sg_currentGame = NULL;
 
4129
    uMenu::exitToMain = false;
 
4130
}
 
4131
 
 
4132
void sg_EnterGame( nNetState enter_state )
 
4133
{
 
4134
    try
 
4135
    {
 
4136
        // enter the game
 
4137
        sg_EnterGameCore( enter_state );
 
4138
    }
 
4139
    catch (tException const & e)
 
4140
    {
 
4141
        // cleanup
 
4142
        sg_EnterGameCleanup();
 
4143
 
 
4144
        // inform user of generic errors
 
4145
        tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
 
4146
    }
 
4147
    // again: VC6 does not catch tGenericException with above statement
 
4148
#ifdef _MSC_VER
 
4149
#pragma warning ( disable : 4286 )
 
4150
    catch (tGenericException const & e)
 
4151
    {
 
4152
        // cleanup
 
4153
        sg_EnterGameCleanup();
 
4154
 
 
4155
        // inform user of generic errors
 
4156
        tConsole::Message( e.GetName(), e.GetDescription(), 120000 );
 
4157
    }
 
4158
#endif
 
4159
 
 
4160
    // bounce teams
 
4161
    for ( int i = eTeam::teams.Len()-1; i>=0; --i )
 
4162
    {
 
4163
        tJUST_CONTROLLED_PTR< eTeam > t = eTeam::teams(i);
 
4164
    }
 
4165
}
 
4166
 
 
4167
bool GridIsReady(int c){
 
4168
    return bool(sg_currentGame) && sg_currentGame->GridIsReady(c);
 
4169
}
 
4170
 
 
4171
 
 
4172
// avoid transfer of game objects if the grid is not yes constructed
 
4173
static bool notrans(){
 
4174
    return !GridIsReady(eTransferInhibitor::User());
 
4175
}
 
4176
 
 
4177
static eTransferInhibitor inh(&notrans);
 
4178
 
 
4179
// are we active?
 
4180
void Activate(bool act){
 
4181
#ifdef DEBUG
 
4182
    return;
 
4183
#endif
 
4184
    sr_Activate( act );
 
4185
 
 
4186
    se_SoundPause(!act);
 
4187
 
 
4188
    if (!tRecorder::IsRunning() )
 
4189
    {
 
4190
        if (sn_GetNetState()==nSTANDALONE)
 
4191
        {
 
4192
            se_PauseGameTimer(!act);
 
4193
        }
 
4194
 
 
4195
        se_ChatState( ePlayerNetID::ChatFlags_Away, !act);
 
4196
    }
 
4197
}
 
4198
 
 
4199
static void LoginCallback(){
 
4200
    client_gamestate[nCallbackLoginLogout::User()]=0;
 
4201
}
 
4202
 
 
4203
static nCallbackLoginLogout lc(LoginCallback);
 
4204