00001
00002
00003
00004
00005
00006
00007
00008
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdarg.h>
00026 #include "replay.h"
00027 #include "typen.h"
00028 #include "buildingtype.h"
00029 #include "vehicletype.h"
00030 #include "spfst.h"
00031 #include "controls.h"
00032 #include "dialog.h"
00033 #include "gameoptions.h"
00034 #include "viewcalculation.h"
00035 #include "itemrepository.h"
00036 #include "containercontrols.h"
00037 #include "resourcenet.h"
00038 #include "guiiconhandler.h"
00039 #include "guifunctions.h"
00040 #include "cannedmessages.h"
00041 #include "unitctrl.h"
00042 #include "replaymapdisplay.h"
00043 #include "asc-mainscreen.h"
00044 #include "loaders.h"
00045 #include "turncontrol.h"
00046 #include "widgets/textrenderer.h"
00047 #include "actions/jumpdrive.h"
00048 #include "actions/selfdestruct.h"
00049 #include "reactionfire.h"
00050 #include "gameeventsystem.h"
00051 #include "sdl/graphicsqueue.h"
00052 #include "video/videorecorder.h"
00053 #include "iconrepository.h"
00054 #include "dialogs/replayrecorder.h"
00055
00056 trunreplay runreplay;
00057
00058 int startreplaylate = 0;
00059
00060
00061 class ReplayRecorder;
00062
00063 class ReplayRecorderWatcherGlobal {
00064 ReplayRecorder* recorder;
00065 public:
00066 ReplayRecorderWatcherGlobal() : recorder( NULL ) {};
00067 void set( ReplayRecorder* rec ) {
00068 recorder = rec;
00069 }
00070
00071 ~ReplayRecorderWatcherGlobal() ;
00072 } replayRecorderWatcherGlobal;
00073
00074
00075 class ReplayRecorder : public SigC::Object {
00076
00077 VideoRecorder* rec;
00078 SigC::Connection connection;
00079 bool movieModeStorage;
00080 ASCString lastFilename;
00081
00082 public:
00083 ReplayRecorder() : rec (NULL)
00084 {
00085 movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00086 replayRecorderWatcherGlobal.set( this );
00087 }
00088
00089 void start( const ASCString& filename, bool append, int framerate, int quality )
00090 {
00091 lastFilename = filename;
00092 movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00093 CGameOptions::Instance()->replayMovieMode = true;
00094 ASCString newFilename = constructFileName( 0, "", filename );
00095 if ( !rec || !append || newFilename != rec->getFilename() ) {
00096 delete rec;
00097 rec = new VideoRecorder( newFilename, PG_Application::GetScreen(), framerate, quality );
00098 }
00099
00100 if ( !connection.connected() )
00101 connection = postScreenUpdate.connect( SigC::slot( *this, &ReplayRecorder::screenUpdate ));
00102 }
00103
00104 void pause()
00105 {
00106 if ( connection.connected() )
00107 connection.disconnect();
00108 CGameOptions::Instance()->replayMovieMode = movieModeStorage;
00109 }
00110
00111 void close()
00112 {
00113 pause();
00114 delete rec;
00115 rec = NULL;
00116 }
00117
00118 bool isRunning()
00119 {
00120 return connection.connected() && rec;
00121 }
00122
00123 bool isOpen()
00124 {
00125 return rec != NULL;
00126 }
00127
00128 ASCString getLastFilename()
00129 {
00130 return lastFilename;
00131 }
00132
00133 private:
00134 void screenUpdate( const SDL_Surface* surf )
00135 {
00136 if ( rec )
00137 rec->storeFrame( surf );
00138 }
00139 };
00140
00141 class ReplayRecorderWatcherLocal {
00142 ReplayRecorder* recorder;
00143 public:
00144 ReplayRecorderWatcherLocal( ReplayRecorder* rec ) : recorder( rec ) {};
00145 ~ReplayRecorderWatcherLocal()
00146 {
00147 if ( recorder )
00148 recorder->pause();
00149 }
00150 };
00151
00152
00153 ReplayRecorderWatcherGlobal::~ReplayRecorderWatcherGlobal()
00154 {
00155 if ( recorder )
00156 recorder->pause();
00157 }
00158
00159
00160 ReplayRecorder* replayRecorder = NULL;
00161
00162
00163
00164 namespace ReplayGuiFunctions {
00165
00166 class ReplayPlay : public GuiFunction
00167 {
00168 public:
00169 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00170 {
00171 if ( runreplay.status == 1 )
00172 return true;
00173
00174 return false;
00175 };
00176
00177 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00178 {
00179 runreplay.status = 2;
00180 updateFieldInfo();
00181 }
00182
00183 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00184 {
00185 return IconRepository::getIcon("replay-play.png");
00186 };
00187
00188 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00189 {
00190 return "start re~p~lay";
00191 };
00192
00193 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00194 {
00195 return ( key->keysym.unicode == 'p' );
00196 };
00197
00198 };
00199
00200
00201 class ReplayPause : public GuiFunction
00202 {
00203 public:
00204 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00205 {
00206 if ( runreplay.status == 2 )
00207 return true;
00208
00209 return false;
00210 };
00211
00212 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00213 {
00214 runreplay.status = 1;
00215 updateFieldInfo();
00216 }
00217
00218 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00219 {
00220 return IconRepository::getIcon("replay-pause.png");
00221 };
00222
00223 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00224 {
00225 return "~p~ause replay";
00226 };
00227
00228 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00229 {
00230 return ( key->keysym.unicode == 'p' );
00231 };
00232
00233 };
00234
00235
00236
00237 class ReplayFaster : public GuiFunction
00238 {
00239 public:
00240 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00241 {
00242 if ( runreplay.status == 2 )
00243 if ( CGameOptions::Instance()->replayspeed > 0 )
00244 return true;
00245
00246 return false;
00247 };
00248
00249 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00250 {
00251 if ( CGameOptions::Instance()->replayspeed > 20 )
00252 CGameOptions::Instance()->replayspeed -= 20;
00253 else
00254 CGameOptions::Instance()->replayspeed = 0;
00255
00256 CGameOptions::Instance()->setChanged ( 1 );
00257 displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00258 updateFieldInfo();
00259 }
00260
00261 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00262 {
00263 return IconRepository::getIcon("replay-faster.png");
00264 };
00265
00266 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00267 {
00268 return "increase replay speed (~+~)";
00269 };
00270
00271 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00272 {
00273 return ( key->keysym.unicode == '+' || key->keysym.sym == SDLK_KP_PLUS);
00274 };
00275
00276 };
00277
00278
00279 class ReplaySlower : public GuiFunction
00280 {
00281 public:
00282 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00283 {
00284 if ( runreplay.status == 2 )
00285 return true;
00286
00287 return false;
00288 };
00289
00290 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00291 {
00292 CGameOptions::Instance()->replayspeed += 20;
00293 CGameOptions::Instance()->setChanged ( 1 );
00294 displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00295 updateFieldInfo();
00296 }
00297
00298 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00299 {
00300 return IconRepository::getIcon("replay-slow.png");
00301 };
00302
00303 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00304 {
00305 return "decrease replay speed (~-~)";
00306 };
00307
00308 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00309 {
00310 return ( key->keysym.unicode == '-' || key->keysym.sym == SDLK_KP_MINUS);
00311 };
00312
00313 };
00314
00315
00316 class ReplayRewind : public GuiFunction
00317 {
00318 public:
00319 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00320 {
00321 if ( runreplay.status == 1 || runreplay.status == 10 )
00322 return true;
00323
00324 return false;
00325 };
00326
00327 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00328 {
00329 runreplay.status = 101;
00330 updateFieldInfo();
00331 }
00332
00333 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00334 {
00335 return IconRepository::getIcon("replay-back.png");
00336 };
00337
00338 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00339 {
00340 return "~r~estart replay";
00341 };
00342
00343 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00344 {
00345 return ( key->keysym.unicode == 'r' );
00346 };
00347
00348 };
00349
00350
00351 class ReplayExit : public GuiFunction
00352 {
00353 public:
00354 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00355 {
00356 if ( runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11 )
00357 return true;
00358
00359 return false;
00360 };
00361
00362 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00363 {
00364 runreplay.status = 100;
00365 updateFieldInfo();
00366 }
00367
00368 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00369 {
00370 return IconRepository::getIcon("replay-exit.png");
00371 };
00372
00373 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00374 {
00375 return "e~x~it replay";
00376 };
00377
00378 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00379 {
00380 return ( key->keysym.unicode == 'x' );
00381 };
00382
00383 };
00384
00385 class ReplayRecord : public GuiFunction
00386 {
00387 public:
00388 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00389 {
00390 if ( runreplay.status == 1 )
00391 return true;
00392
00393 return false;
00394 };
00395
00396 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00397 {
00398 ASCString filename;
00399 bool open = false;
00400 if ( replayRecorder ) {
00401 filename = replayRecorder->getLastFilename();
00402 open = replayRecorder->isOpen();
00403 }
00404
00405 ReplayRecorderDialog rrd( filename, open );
00406 rrd.Show();
00407 rrd.RunModal();
00408 rrd.Hide();
00409
00410 if ( !replayRecorder )
00411 replayRecorder = new ReplayRecorder();
00412 replayRecorder->start( rrd.getFilename(), rrd.getAppend(), rrd.getFramerate(), rrd.getQuality() );
00413
00414 runreplay.status = 2;
00415 updateFieldInfo();
00416 }
00417
00418 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00419 {
00420 return IconRepository::getIcon("replay-record.png");
00421 };
00422
00423 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00424 {
00425 return "record to ~v~ideo";
00426 };
00427
00428 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00429 {
00430 return ( key->keysym.unicode == 'v' );
00431 };
00432
00433 };
00434
00435 class ReplayRecordExit : public GuiFunction
00436 {
00437 public:
00438 bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00439 {
00440 if ( replayRecorder && replayRecorder->isOpen() && (runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11) )
00441 return true;
00442
00443 return false;
00444 };
00445
00446 void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00447 {
00448 replayRecorder->close();
00449 runreplay.status = 100;
00450 updateFieldInfo();
00451 }
00452
00453 Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00454 {
00455 return IconRepository::getIcon("replay-record-stop.png");
00456 };
00457
00458 ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00459 {
00460 return "exit replay and ~c~lose recording";
00461 };
00462
00463 bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00464 {
00465 return ( key->keysym.unicode == 'c' );
00466 };
00467
00468 };
00469
00470
00471 }
00472
00473 void registerReplayGuiFunctions( GuiIconHandler& handler )
00474 {
00475 handler.registerUserFunction( new ReplayGuiFunctions::ReplayPlay() );
00476 #ifdef XVIDEXPORT
00477 handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecord() );
00478 #endif
00479 handler.registerUserFunction( new ReplayGuiFunctions::ReplayPause() );
00480 handler.registerUserFunction( new ReplayGuiFunctions::ReplayFaster() );
00481 handler.registerUserFunction( new ReplayGuiFunctions::ReplaySlower() );
00482 handler.registerUserFunction( new ReplayGuiFunctions::ReplayRewind() );
00483 #ifdef XVIDEXPORT
00484 handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecordExit() );
00485 #endif
00486 handler.registerUserFunction( new ReplayGuiFunctions::ReplayExit() );
00487 }
00488
00489
00490
00491 class ReplayGuiIconHandleHandler {
00492 static GuiIconHandler* replayIconHandler;
00493 bool active;
00494 public:
00495 ReplayGuiIconHandleHandler()
00496 {
00497 if ( !replayIconHandler ) {
00498 replayIconHandler = new GuiIconHandler();
00499 registerReplayGuiFunctions( *replayIconHandler );
00500 }
00501
00502 if ( NewGuiHost::getIconHandler() != replayIconHandler ) {
00503 active = true;
00504 NewGuiHost::pushIconHandler( replayIconHandler );
00505 } else
00506 active = false;
00507 };
00508
00509 ~ReplayGuiIconHandleHandler()
00510 {
00511 if ( active )
00512 NewGuiHost::popIconHandler();
00513 };
00514 };
00515 GuiIconHandler* ReplayGuiIconHandleHandler::replayIconHandler = NULL;
00516
00517
00518
00519
00520
00521 void runSpecificReplay( int player, int viewingplayer, bool performEndTurnOperations )
00522 {
00523 if ( actmap->replayinfo->map[player] && actmap->replayinfo->guidata[player] ) {
00524 try {
00525 int t;
00526 do {
00527 t = runreplay.run ( player, viewingplayer, performEndTurnOperations );
00528 } while ( t );
00529 }
00530
00531 #ifndef _DEBUG
00532 catch ( ... ) {
00533 #else
00534 catch ( GameMap ) {
00535 #endif
00536 errorMessage("An unrecognized error occured during the replay");
00537 delete actmap;
00538 actmap = NULL;
00539 throw NoMapLoaded();
00540 }
00541 }
00542 }
00543
00544 void viewOwnReplay( Player& player )
00545 {
00546 if ( player.stat == Player::human || player.stat == Player::supervisor )
00547 if ( CGameOptions::Instance()->debugReplay && player.getParentMap()->replayinfo )
00548 if (choice_dlg("run replay of your turn ?","~y~es","~n~o") == 1) {
00549
00550 runSpecificReplay ( player.getPosition(), player.getPosition(), false );
00551 }
00552 }
00553
00554
00555 void checkforreplay ( void )
00556 {
00557 if ( !actmap->replayinfo )
00558 return;
00559
00560 int rpnum = 0;
00561 int s = actmap->actplayer + 1;
00562 if ( s >= 8 )
00563 s = 0;
00564 while ( s != actmap->actplayer ) {
00565 if ( actmap->replayinfo->map[s] && actmap->replayinfo->guidata[s] )
00566 rpnum++;
00567
00568 if ( s < 7 )
00569 s++;
00570 else
00571 s = 0;
00572 }
00573
00574
00575 if ( actmap->replayinfo && rpnum && (actmap->player[ actmap->actplayer ].stat == Player::human || actmap->player[ actmap->actplayer ].stat == Player::supervisor) )
00576 if (choice_dlg("run replay of last turn ?","~y~es","~n~o") == 1) {
00577
00578 MainScreenWidget::StandardActionLocker locker( mainScreenWidget, MainScreenWidget::LockOptions::Menu );
00579 ReplayGuiIconHandleHandler guiIconHandler;
00580
00581 int s = actmap->actplayer + 1;
00582 if ( s >= 8 )
00583 s = 0;
00584 while ( s != actmap->actplayer ) {
00585 if ( s >= 8 )
00586 s = 0;
00587
00588 runSpecificReplay(s, actmap->actplayer );
00589
00590 if ( s < 7 )
00591 s++;
00592 else
00593 s = 0;
00594 }
00595
00596
00597 }
00598 }
00599
00600
00601 void initReplayLogging( Player& player )
00602 {
00603 GameMap* gamemap = player.getParentMap();
00604
00605 if ( startreplaylate ) {
00606 gamemap->replayinfo = new GameMap::ReplayInfo;
00607 startreplaylate = 0;
00608 }
00609
00610 if ( gamemap->replayinfo && player.stat != Player::off ) {
00611 if ( gamemap->replayinfo->actmemstream )
00612 fatalError( "actmemstream already open at begin of turn " );
00613
00614 if ( gamemap->replayinfo->guidata[ player.getPosition() ] ) {
00615 delete gamemap->replayinfo->guidata[ player.getPosition() ];
00616 gamemap->replayinfo->guidata[ player.getPosition() ] = NULL;
00617 }
00618
00619 savereplay ( gamemap, player.getPosition() );
00620
00621 gamemap->replayinfo->guidata[ player.getPosition() ] = new tmemorystreambuf;
00622 gamemap->replayinfo->actmemstream = new tmemorystream ( gamemap->replayinfo->guidata[ player.getPosition() ], tnstream::writing );
00623 }
00624 }
00625
00626
00627 LockReplayRecording::LockReplayRecording( GameMap::ReplayInfo& _ri )
00628 : ri ( _ri )
00629 {
00630 ri.stopRecordingActions++;
00631 }
00632
00633 LockReplayRecording::~LockReplayRecording()
00634 {
00635 ri.stopRecordingActions--;
00636 }
00637
00638
00639 Resources getUnitResourceCargo ( Vehicle* veh )
00640 {
00641 Resources res = veh->getTank();
00642 for ( ContainerBase::Cargo::const_iterator i = veh->getCargo().begin(); i != veh->getCargo().end(); ++i )
00643 if ( *i )
00644 res += getUnitResourceCargo ( *i );
00645 return res;
00646 }
00647
00648 void logtoreplayinfo ( trpl_actions _action, ... )
00649 {
00650 char action = _action;
00651 if ( actmap->replayinfo && actmap->replayinfo->actmemstream && !actmap->replayinfo->stopRecordingActions) {
00652 pnstream stream = actmap->replayinfo->actmemstream;
00653
00654 va_list paramlist;
00655 va_start ( paramlist, _action );
00656
00657 if ( action == rpl_attack || action == rpl_reactionfire ) {
00658 int x1 = va_arg ( paramlist, int );
00659 int y1 = va_arg ( paramlist, int );
00660 int x2 = va_arg ( paramlist, int );
00661 int y2 = va_arg ( paramlist, int );
00662 int ad1 = va_arg ( paramlist, int );
00663 int ad2 = va_arg ( paramlist, int );
00664 int dd1 = va_arg ( paramlist, int );
00665 int dd2 = va_arg ( paramlist, int );
00666 int wpnum = va_arg ( paramlist, int );
00667 int size = 9;
00668 stream->writeChar ( action );
00669 stream->writeInt ( size );
00670 stream->writeInt ( x1 );
00671 stream->writeInt ( y1 );
00672 stream->writeInt ( x2 );
00673 stream->writeInt ( y2 );
00674 stream->writeInt ( ad1 );
00675 stream->writeInt ( ad2 );
00676 stream->writeInt ( dd1 );
00677 stream->writeInt ( dd2 );
00678 stream->writeInt ( wpnum );
00679 }
00680
00681 if ( action == rpl_move ) {
00682 int x1 = va_arg ( paramlist, int );
00683 int y1 = va_arg ( paramlist, int );
00684 int x2 = va_arg ( paramlist, int );
00685 int y2 = va_arg ( paramlist, int );
00686 int nwid = va_arg ( paramlist, int );
00687 stream->writeChar ( action );
00688 int size = 5;
00689 stream->writeInt ( size );
00690 stream->writeInt ( x1 );
00691 stream->writeInt ( y1 );
00692 stream->writeInt ( x2 );
00693 stream->writeInt ( y2 );
00694 stream->writeInt ( nwid );
00695 }
00696 if ( action == rpl_move2 || action == rpl_move3 || action == rpl_move4 || action==rpl_move5) {
00697 int x1 = va_arg ( paramlist, int );
00698 int y1 = va_arg ( paramlist, int );
00699 int x2 = va_arg ( paramlist, int );
00700 int y2 = va_arg ( paramlist, int );
00701 int nwid = va_arg ( paramlist, int );
00702 int height = va_arg ( paramlist, int );
00703
00704 stream->writeChar ( action );
00705 if ( action == rpl_move5 ) {
00706 int size = 8;
00707 stream->writeInt( size );
00708 } else
00709 if ( action == rpl_move2 ) {
00710 int size = 6;
00711 stream->writeInt ( size );
00712 } else {
00713 int size = 7;
00714 stream->writeInt ( size );
00715 }
00716 stream->writeInt ( x1 );
00717 stream->writeInt ( y1 );
00718 stream->writeInt ( x2 );
00719 stream->writeInt ( y2 );
00720 stream->writeInt ( nwid );
00721 stream->writeInt ( height );
00722 if ( action == rpl_move3 || action == rpl_move4 || action==rpl_move5) {
00723 int nointerrupt = va_arg ( paramlist, int );
00724 stream->writeInt ( nointerrupt );
00725 if ( action==rpl_move5 ) {
00726 int destDamage = va_arg( paramlist, int );
00727 stream->writeInt( destDamage );
00728 }
00729 }
00730 }
00731
00732 if ( action == rpl_changeheight || action == rpl_changeheight2 ) {
00733 int x1 = va_arg ( paramlist, int );
00734 int y1 = va_arg ( paramlist, int );
00735 int x2 = va_arg ( paramlist, int );
00736 int y2 = va_arg ( paramlist, int );
00737 int nwid = va_arg ( paramlist, int );
00738 int oldheight = va_arg ( paramlist, int );
00739 int newheight = va_arg ( paramlist, int );
00740 stream->writeChar ( action );
00741 if ( action == rpl_changeheight ) {
00742 int size = 7;
00743 stream->writeInt ( size );
00744 } else {
00745 int size = 8;
00746 stream->writeInt ( size );
00747 }
00748 stream->writeInt ( x1 );
00749 stream->writeInt ( y1 );
00750 stream->writeInt ( x2 );
00751 stream->writeInt ( y2 );
00752 stream->writeInt ( nwid );
00753 stream->writeInt ( oldheight );
00754 stream->writeInt ( newheight );
00755 if ( action == rpl_changeheight2 ) {
00756 int noInterrupt = va_arg ( paramlist, int );
00757 stream->writeInt ( noInterrupt );
00758 }
00759 }
00760 if ( action == rpl_convert ) {
00761 int x = va_arg ( paramlist, int );
00762 int y = va_arg ( paramlist, int );
00763 int col = va_arg ( paramlist, int );
00764 stream->writeChar ( action );
00765 int size = 3;
00766 stream->writeInt ( size );
00767 stream->writeInt ( x );
00768 stream->writeInt ( y );
00769 stream->writeInt ( col );
00770 }
00771 if ( action == rpl_convert2 ) {
00772 int x = va_arg ( paramlist, int );
00773 int y = va_arg ( paramlist, int );
00774 int col = va_arg ( paramlist, int );
00775 int nwid = va_arg ( paramlist, int );
00776 stream->writeChar ( action );
00777 int size = 4;
00778 stream->writeInt ( size );
00779 stream->writeInt ( x );
00780 stream->writeInt ( y );
00781 stream->writeInt ( col );
00782 stream->writeInt ( nwid );
00783 }
00784 if ( action == rpl_buildobj || action == rpl_remobj ) {
00785 int x = va_arg ( paramlist, int );
00786 int y = va_arg ( paramlist, int );
00787 int id = va_arg ( paramlist, int );
00788 stream->writeChar ( action );
00789 int size = 3;
00790 stream->writeInt ( size );
00791 stream->writeInt ( x );
00792 stream->writeInt ( y );
00793 stream->writeInt ( id );
00794 }
00795 if ( action == rpl_buildobj2 || action == rpl_remobj2 ) {
00796 int x = va_arg ( paramlist, int );
00797 int y = va_arg ( paramlist, int );
00798 int id = va_arg ( paramlist, int );
00799 int unit = va_arg ( paramlist, int );
00800 stream->writeChar ( action );
00801 int size = 4;
00802 stream->writeInt ( size );
00803 stream->writeInt ( x );
00804 stream->writeInt ( y );
00805 stream->writeInt ( id );
00806 stream->writeInt ( unit );
00807 }
00808 if ( action == rpl_buildtnk || action == rpl_buildtnk3 || action == rpl_buildtnk4 ) {
00809 int x = va_arg ( paramlist, int );
00810 int y = va_arg ( paramlist, int );
00811 int id = va_arg ( paramlist, int );
00812 int col = va_arg ( paramlist, int );
00813 stream->writeChar ( action );
00814 int size;
00815 if ( action == rpl_buildtnk )
00816 size = 4;
00817 else
00818 if ( action == rpl_buildtnk4 )
00819 size = 7;
00820 else
00821 size = 6;
00822
00823 stream->writeInt ( size );
00824 stream->writeInt ( x );
00825 stream->writeInt ( y );
00826 stream->writeInt ( id );
00827 stream->writeInt ( col );
00828 if ( action == rpl_buildtnk3 || action == rpl_buildtnk4 ) {
00829 stream->writeInt ( va_arg ( paramlist, int ) );
00830 stream->writeInt ( va_arg ( paramlist, int ) );
00831 if ( action == rpl_buildtnk4 )
00832 stream->writeInt ( va_arg ( paramlist, int ) );
00833 }
00834 }
00835 if ( action == rpl_buildtnk2 ) {
00836 stream->writeChar ( action );
00837 int size = 5;
00838 stream->writeInt ( size );
00839 stream->writeInt ( va_arg ( paramlist, int ) );
00840 stream->writeInt ( va_arg ( paramlist, int ) );
00841 stream->writeInt ( va_arg ( paramlist, int ) );
00842 stream->writeInt ( va_arg ( paramlist, int ) );
00843 stream->writeInt ( va_arg ( paramlist, int ) );
00844 }
00845 if ( action == rpl_putbuilding || action == rpl_putbuilding2 ) {
00846 int x = va_arg ( paramlist, int );
00847 int y = va_arg ( paramlist, int );
00848 int id = va_arg ( paramlist, int );
00849 int col = va_arg ( paramlist, int );
00850 stream->writeChar ( action );
00851 if ( action == rpl_putbuilding )
00852 stream->writeInt ( 4 );
00853 else
00854 stream->writeInt ( 5 );
00855
00856 stream->writeInt ( x );
00857 stream->writeInt ( y );
00858 stream->writeInt ( id );
00859 stream->writeInt ( col );
00860 if ( action == rpl_putbuilding2 )
00861 stream->writeInt ( va_arg ( paramlist, int ));
00862 }
00863 if ( action == rpl_putmine || action == rpl_putmine2 ) {
00864 int x = va_arg ( paramlist, int );
00865 int y = va_arg ( paramlist, int );
00866 int col = va_arg ( paramlist, int );
00867 int typ = va_arg ( paramlist, int );
00868 int strength = va_arg ( paramlist, int );
00869 int nwid = -1;
00870
00871 stream->writeChar ( action );
00872 int size;
00873 if ( action == rpl_putmine ) {
00874 size = 5;
00875 } else {
00876 nwid = va_arg ( paramlist, int );
00877 size = 6;
00878 }
00879 stream->writeInt ( size );
00880 stream->writeInt ( x );
00881 stream->writeInt ( y );
00882 stream->writeInt ( col );
00883 stream->writeInt ( typ );
00884 stream->writeInt ( strength );
00885
00886 if ( action == rpl_putmine2 )
00887 stream->writeInt ( nwid );
00888
00889 }
00890 if ( action == rpl_removemine ) {
00891 int x = va_arg ( paramlist, int );
00892 int y = va_arg ( paramlist, int );
00893 stream->writeChar ( action );
00894 int size = 2;
00895 stream->writeInt ( size );
00896 stream->writeInt ( x );
00897 stream->writeInt ( y );
00898 }
00899 if ( action == rpl_removebuilding ) {
00900 int x = va_arg ( paramlist, int );
00901 int y = va_arg ( paramlist, int );
00902 stream->writeChar ( action );
00903 int size = 2;
00904 stream->writeInt ( size );
00905 stream->writeInt ( x );
00906 stream->writeInt ( y );
00907 }
00908 if ( action == rpl_removebuilding2 || action == rpl_removebuilding3) {
00909 int x = va_arg ( paramlist, int );
00910 int y = va_arg ( paramlist, int );
00911 int nwid = va_arg ( paramlist, int );
00912 stream->writeChar ( action );
00913 if ( action == rpl_removebuilding2 ) {
00914 int size = 3;
00915 stream->writeInt ( size );
00916 stream->writeInt ( x );
00917 stream->writeInt ( y );
00918 stream->writeInt( nwid );
00919 } else {
00920 int size = 6;
00921 stream->writeInt ( size );
00922 stream->writeInt ( x );
00923 stream->writeInt ( y );
00924 stream->writeInt( nwid );
00925 int e = va_arg ( paramlist, int );
00926 int m = va_arg ( paramlist, int );
00927 int f = va_arg ( paramlist, int );
00928 stream->writeInt( e );
00929 stream->writeInt( m );
00930 stream->writeInt( f );
00931 }
00932 }
00933
00934 if ( action == rpl_produceunit ) {
00935 int id = va_arg ( paramlist, int );
00936 int col = va_arg ( paramlist, int );
00937 int x = va_arg ( paramlist, int );
00938 int y = va_arg ( paramlist, int );
00939 int cl = va_arg ( paramlist, int );
00940 int nwid = va_arg ( paramlist, int );
00941 stream->writeChar ( action );
00942 int size = 6;
00943 stream->writeInt ( size );
00944 stream->writeInt ( id );
00945 stream->writeInt ( col );
00946 stream->writeInt ( x );
00947 stream->writeInt ( y );
00948 stream->writeInt ( cl );
00949 stream->writeInt ( nwid );
00950 }
00951 if ( action == rpl_removeunit ) {
00952 int x = va_arg ( paramlist, int );
00953 int y = va_arg ( paramlist, int );
00954 int nwid = va_arg ( paramlist, int );
00955 stream->writeChar ( action );
00956 int size = 3;
00957 stream->writeInt ( size );
00958 stream->writeInt ( x );
00959 stream->writeInt ( y );
00960 stream->writeInt ( nwid );
00961 }
00962 if ( action == rpl_trainunit ) {
00963 int x = va_arg ( paramlist, int );
00964 int y = va_arg ( paramlist, int );
00965 int exp = va_arg ( paramlist, int );
00966 int nwid = va_arg ( paramlist, int );
00967 stream->writeChar ( action );
00968 int size = 4;
00969 stream->writeInt ( size );
00970 stream->writeInt ( x );
00971 stream->writeInt ( y );
00972 stream->writeInt ( exp );
00973 stream->writeInt ( nwid );
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 if ( action == rpl_alliancechange2 ) {
00993 stream->writeChar ( action );
00994 stream->writeInt( 3 );
00995
00996 int actingPlayer = va_arg ( paramlist, int );
00997 int targetPlayer = va_arg ( paramlist, int );
00998 int state = va_arg ( paramlist, int );
00999 stream->writeInt( actingPlayer );
01000 stream->writeInt( targetPlayer );
01001 stream->writeInt( state );
01002 }
01003 if ( action == rpl_refuel || action == rpl_refuel2 ) {
01004 int x = va_arg ( paramlist, int );
01005 int y = va_arg ( paramlist, int );
01006 int nwid = va_arg ( paramlist, int );
01007 int pos = va_arg ( paramlist, int );
01008 int amnt = va_arg ( paramlist, int );
01009 stream->writeChar ( action );
01010 stream->writeInt ( action==rpl_refuel ? 5 : 6 );
01011 stream->writeInt ( x );
01012 stream->writeInt ( y );
01013 stream->writeInt ( nwid );
01014 stream->writeInt ( pos );
01015 stream->writeInt ( amnt );
01016 if ( action == rpl_refuel2 ) {
01017 int old = va_arg ( paramlist, int );
01018 stream->writeInt( old );
01019 }
01020 }
01021 if ( action == rpl_refuel3 ) {
01022 int id = va_arg ( paramlist, int );
01023 int resource = va_arg ( paramlist, int );
01024 int delta = va_arg ( paramlist, int );
01025 stream->writeChar ( action );
01026 stream->writeInt ( 3 );
01027 stream->writeInt ( id );
01028 stream->writeInt ( resource );
01029 stream->writeInt ( delta );
01030 }
01031 if ( action == rpl_bldrefuel ) {
01032 int x = va_arg ( paramlist, int );
01033 int y = va_arg ( paramlist, int );
01034 int pos = va_arg ( paramlist, int );
01035 int amnt = va_arg ( paramlist, int );
01036 stream->writeChar ( action );
01037 int size = 4;
01038 stream->writeInt ( size );
01039 stream->writeInt ( x );
01040 stream->writeInt ( y );
01041 stream->writeInt ( pos );
01042 stream->writeInt ( amnt );
01043 }
01044 if ( action == rpl_moveUnitUpDown ) {
01045 int x = va_arg ( paramlist, int );
01046 int y = va_arg ( paramlist, int );
01047 int nwid_from = va_arg ( paramlist, int );
01048 int nwid_to = va_arg ( paramlist, int );
01049 int nwid_moving = va_arg ( paramlist, int );
01050 stream->writeChar ( action );
01051 int size = 5;
01052 stream->writeInt ( size );
01053 stream->writeInt ( x );
01054 stream->writeInt ( y );
01055 stream->writeInt ( nwid_from );
01056 stream->writeInt ( nwid_to );
01057 stream->writeInt ( nwid_moving );
01058 }
01059 if ( action == rpl_moveUnitUp ) {
01060 int x = va_arg ( paramlist, int );
01061 int y = va_arg ( paramlist, int );
01062 int nwid = va_arg ( paramlist, int );
01063 stream->writeChar ( action );
01064 int size = 3;
01065 stream->writeInt ( size );
01066 stream->writeInt ( x );
01067 stream->writeInt ( y );
01068 stream->writeInt ( nwid );
01069 }
01070 if ( action == rpl_productionResourceUsage ) {
01071 int en = va_arg ( paramlist, int );
01072 int ma = va_arg ( paramlist, int );
01073 int fu = va_arg ( paramlist, int );
01074 int x = va_arg ( paramlist, int );
01075 int y = va_arg ( paramlist, int );
01076 stream->writeChar ( action );
01077 int size = 5;
01078 stream->writeInt ( size );
01079 stream->writeInt ( en );
01080 stream->writeInt ( ma );
01081 stream->writeInt ( fu );
01082 stream->writeInt ( x );
01083 stream->writeInt ( y );
01084 }
01085 if ( action == rpl_repairUnit ) {
01086 int nwid = va_arg ( paramlist, int );
01087 int destnwid = va_arg ( paramlist, int );
01088 int amount = va_arg ( paramlist, int );
01089 int matremain = va_arg ( paramlist, int );
01090 int fuelremain = va_arg ( paramlist, int );
01091
01092 stream->writeChar ( action );
01093 int size = 5;
01094 stream->writeInt ( size );
01095 stream->writeInt ( nwid );
01096 stream->writeInt ( destnwid );
01097 stream->writeInt ( amount );
01098 stream->writeInt ( matremain );
01099 stream->writeInt ( fuelremain );
01100 }
01101 if ( action == rpl_repairUnit2 || action == rpl_repairBuilding ) {
01102 int x = va_arg ( paramlist, int );
01103 int y = va_arg ( paramlist, int );
01104 int destnwid = va_arg ( paramlist, int );
01105 int amount = va_arg ( paramlist, int );
01106
01107 stream->writeChar ( action );
01108 int size = 4;
01109 stream->writeInt ( size );
01110 stream->writeInt ( x );
01111 stream->writeInt ( y );
01112 stream->writeInt ( destnwid );
01113 stream->writeInt ( amount );
01114 }
01115 if ( action == rpl_repairUnit3 ) {
01116 int serviceNWID = va_arg ( paramlist, int );
01117 int destnwid = va_arg ( paramlist, int );
01118 int amount = va_arg ( paramlist, int );
01119
01120 stream->writeChar ( action );
01121 int size = 3;
01122 stream->writeInt ( size );
01123 stream->writeInt ( serviceNWID );
01124 stream->writeInt ( destnwid );
01125 stream->writeInt ( amount );
01126 }
01127 if ( action == rpl_produceAmmo ) {
01128 int x = va_arg ( paramlist, int );
01129 int y = va_arg ( paramlist, int );
01130 int type = va_arg ( paramlist, int );
01131 int amount = va_arg ( paramlist, int );
01132 stream->writeChar ( action );
01133 int size = 4;
01134 stream->writeInt ( size );
01135 stream->writeInt ( x );
01136 stream->writeInt ( y );
01137 stream->writeInt ( type );
01138 stream->writeInt ( amount );
01139 }
01140 if ( action == rpl_buildProdLine || action == rpl_removeProdLine) {
01141 int building = va_arg ( paramlist, int );
01142 int id = va_arg ( paramlist, int );
01143 stream->writeChar ( action );
01144 int size = 2;
01145 stream->writeInt ( size );
01146 stream->writeInt ( building );
01147 stream->writeInt ( id );
01148 }
01149
01150 if ( action == rpl_recycleUnit ) {
01151 int building = va_arg ( paramlist, int );
01152 int id = va_arg ( paramlist, int );
01153 stream->writeChar ( action );
01154 int size = 2;
01155 stream->writeInt ( size );
01156 stream->writeInt ( building );
01157 stream->writeInt ( id );
01158 }
01159
01160 if ( action == rpl_techResearched ) {
01161 int tech = va_arg ( paramlist, int );
01162 int player = va_arg ( paramlist, int );
01163 stream->writeChar ( action );
01164 int size = 2;
01165 stream->writeInt ( size );
01166 stream->writeInt ( tech );
01167 stream->writeInt ( player );
01168 }
01169 if ( action == rpl_setGeneratorStatus ) {
01170 int vehid = va_arg ( paramlist, int );
01171 int status = va_arg ( paramlist, int );
01172 stream->writeChar ( action );
01173 int size = 2;
01174 stream->writeInt ( size );
01175 stream->writeInt ( vehid );
01176 stream->writeInt ( status );
01177 }
01178 if ( action == rpl_cutFromGame ) {
01179 int vehid = va_arg( paramlist, int );
01180 Resources res = getUnitResourceCargo ( actmap->getUnit ( vehid ));
01181 stream->writeChar ( action );
01182 int size = 4;
01183 stream->writeInt ( size );
01184 stream->writeInt ( vehid );
01185 stream->writeInt ( res.energy );
01186 stream->writeInt ( res.material );
01187 stream->writeInt ( res.fuel );
01188 }
01189 if ( action == rpl_setResearch ) {
01190 int bldid = va_arg ( paramlist, int );
01191 int amount = va_arg ( paramlist, int );
01192 stream->writeChar ( action );
01193 int size = 2;
01194 stream->writeInt ( size );
01195 stream->writeInt ( bldid );
01196 stream->writeInt ( amount );
01197 }
01198 if ( action == rpl_setResourceProcessingAmount ) {
01199 int x = va_arg ( paramlist, int );
01200 int y = va_arg ( paramlist, int );
01201 int e = va_arg ( paramlist, int );
01202 int m = va_arg ( paramlist, int );
01203 int f = va_arg ( paramlist, int );
01204 stream->writeChar ( action );
01205 int size = 5;
01206 stream->writeInt ( size );
01207 stream->writeInt ( x );
01208 stream->writeInt ( y );
01209 stream->writeInt ( e );
01210 stream->writeInt ( m );
01211 stream->writeInt ( f );
01212 }
01213 if ( action == rpl_netcontrol ) {
01214 int x = va_arg ( paramlist, int );
01215 int y = va_arg ( paramlist, int );
01216 int cat = va_arg ( paramlist, int );
01217 int stat = va_arg ( paramlist, int );
01218 stream->writeChar ( action );
01219 int size = 4;
01220 stream->writeInt ( size );
01221 stream->writeInt ( x );
01222 stream->writeInt ( y );
01223 stream->writeInt ( cat );
01224 stream->writeInt ( stat );
01225 }
01226 if ( action == rpl_jump ) {
01227 int nwid = va_arg ( paramlist, int );
01228 int x = va_arg ( paramlist, int );
01229 int y = va_arg ( paramlist, int );
01230 stream->writeChar ( action );
01231 int size = 3;
01232 stream->writeInt ( size );
01233 stream->writeInt ( nwid );
01234 stream->writeInt ( x );
01235 stream->writeInt ( y );
01236 }
01237 if ( action == rpl_transferTribute ) {
01238 stream->writeChar( action );
01239 stream->writeInt( 1 );
01240 int player = va_arg( paramlist, int );
01241 stream->writeInt( player );
01242 }
01243
01244 if ( action == rpl_reactionFireOn || action == rpl_reactionFireOff ) {
01245 stream->writeChar( action );
01246 stream->writeInt( 1 );
01247 int nwid = va_arg( paramlist, int );
01248 stream->writeInt( nwid );
01249 }
01250
01251 if ( action == rpl_selfdestruct ) {
01252 stream->writeChar( action );
01253 stream->writeInt( 1 );
01254 int nwid = va_arg( paramlist, int );
01255 stream->writeInt( nwid );
01256 }
01257
01258 if ( action == rpl_cancelResearch ) {
01259 stream->writeChar( action );
01260 stream->writeInt( 0 );
01261 }
01262
01263
01264 va_end ( paramlist );
01265 }
01266 }
01267
01268
01269 trunreplay :: trunreplay ( void )
01270 {
01271 status = -1;
01272 movenum = 0;
01273 }
01274
01275 void trunreplay::error( const MapCoordinate& pos, const ASCString& message )
01276 {
01277 error( message );
01278 }
01279
01280
01281 void trunreplay::error( const MapCoordinate& pos, const char* message, ... )
01282 {
01283 va_list paramlist;
01284 va_start ( paramlist, message );
01285 char tempbuf[1000];
01286 int lng = vsprintf( tempbuf, message, paramlist );
01287
01288 assert(lng < 1000);
01289 error( tempbuf );
01290
01291 }
01292
01293 void trunreplay::error( const char* message, ... )
01294 {
01295 if ( message != lastErrorMessage ) {
01296 va_list paramlist;
01297 va_start ( paramlist, message );
01298
01299 char tempbuf[1000];
01300
01301 int lng = vsprintf( tempbuf, message, paramlist );
01302 if ( lng >= 1000 )
01303 displaymessage ( "trunreplay::error: String to long !\nPlease report this error", 1 );
01304
01305 va_end ( paramlist );
01306
01307 displaymessage(tempbuf, 1 );
01308 lastErrorMessage = message;
01309 }
01310 }
01311
01312 void trunreplay::error( const ASCString& message )
01313 {
01314 if ( CGameOptions::Instance()->replayMovieMode )
01315 return;
01316
01317 if ( message != lastErrorMessage ) {
01318 displaymessage(message.c_str(), 1 );
01319 lastErrorMessage = message;
01320 }
01321 }
01322
01323
01324
01325
01326 void trunreplay :: wait ( int t )
01327 {
01328
01329 while ( ticker < t + CGameOptions::Instance()->replayspeed && !keypress()) {
01330
01331
01332
01333
01334
01335
01336
01337 releasetimeslice();
01338 }
01339 }
01340
01341 void trunreplay :: wait ( MapCoordinate pos, int t )
01342 {
01343