/*************************************************************************** replay.cpp - description ------------------- begin : Sun Jan 21 2001 copyright : (C) 2001 by Martin Bickel email : bickel@asc-hq.org ***************************************************************************/ /*! \file replay.cpp \brief Everything for recording and playing replays Replays being the moves of other players or the AI, which can be viewed later (especially useful in email games) */ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include "replay.h" #include "typen.h" #include "buildingtype.h" #include "vehicletype.h" #include "spfst.h" #include "controls.h" #include "dialog.h" #include "stack.h" #include "gameoptions.h" #include "sg.h" #include "viewcalculation.h" #include "dashboard.h" #include "itemrepository.h" #include "building_controls.h" #include "resourcenet.h" trunreplay runreplay; int startreplaylate = 0; void runSpecificReplay( int player, int viewingplayer ) { if ( actmap->replayinfo->map[player] && actmap->replayinfo->guidata[player] ) { npush ( lockdisplaymap ); lockdisplaymap = 0; int t; do { t = runreplay.run ( player, viewingplayer ); } while ( t ); /* enddo */ npop ( lockdisplaymap ); } } void checkforreplay ( void ) { if ( !actmap->replayinfo ) return; int rpnum = 0; int s = actmap->actplayer + 1; if ( s >= 8 ) s = 0; while ( s != actmap->actplayer ) { if ( actmap->replayinfo->map[s] && actmap->replayinfo->guidata[s] ) rpnum++; if ( s < 7 ) s++; else s = 0; } if ( actmap->replayinfo && rpnum && actmap->player[ actmap->actplayer ].stat == Player::human ) if (choice_dlg("run replay of last turn ?","~y~es","~n~o") == 1) { int s = actmap->actplayer + 1; if ( s >= 8 ) s = 0; while ( s != actmap->actplayer ) { if ( s >= 8 ) s = 0; runSpecificReplay(s, actmap->actplayer ); if ( s < 7 ) s++; else s = 0; } } } void initReplayLogging() { if ( startreplaylate ) { actmap->replayinfo = new tmap::ReplayInfo; startreplaylate = 0; } if ( actmap->replayinfo && actmap->player[ actmap->actplayer ].stat != Player::off ) { if ( actmap->replayinfo->actmemstream ) displaymessage2( "actmemstream already open at begin of turn ",2 ); if ( actmap->replayinfo->guidata[actmap->actplayer] ) { delete actmap->replayinfo->guidata[actmap->actplayer]; actmap->replayinfo->guidata[actmap->actplayer] = NULL; } savereplay ( actmap->actplayer ); actmap->replayinfo->guidata[actmap->actplayer] = new tmemorystreambuf; actmap->replayinfo->actmemstream = new tmemorystream ( actmap->replayinfo->guidata[actmap->actplayer], tnstream::writing ); } } void closeReplayLogging() { if ( actmap->replayinfo ) if ( actmap->replayinfo->actmemstream ) { delete actmap->replayinfo->actmemstream; actmap->replayinfo->actmemstream = NULL; } } int ReplayMapDisplay :: checkMapPosition ( int x, int y ) { if ( x >= actmap->xsize ) x = actmap->xsize - 1; if ( y >= actmap->ysize ) y = actmap->ysize - 1; int a = actmap->xpos; int b = actmap->ypos; int xss = idisplaymap.getscreenxsize(); int yss = idisplaymap.getscreenysize(); if ((x < a) || (x >= a + xss )) { if (x >= xss / 2) actmap->xpos = (x - xss / 2); else actmap->xpos = 0; } if (y < b || y >= b + yss ) { if (y >= yss / 2) actmap->ypos = (y - yss / 2); else actmap->ypos = 0; if ( actmap->ypos & 1 ) actmap->ypos--; } if (actmap->xpos + xss > actmap->xsize) actmap->xpos = actmap->xsize - xss ; if (actmap->ypos + yss > actmap->ysize) actmap->ypos = actmap->ysize - yss ; if ((actmap->xpos != a) || (actmap->ypos != b)) return 1; else return 0; } int ReplayMapDisplay :: displayMovingUnit ( const MapCoordinate3D& start, const MapCoordinate3D& dest, pvehicle vehicle, int fieldnum, int totalmove, SoundLoopManager* slc ) { if ( actmap->playerView < 0 ) return 0; if ( fieldvisiblenow ( getfield ( start.x, start.y ), actmap->playerView) || fieldvisiblenow ( getfield ( dest.x, dest.y ), actmap->playerView)) { if ( checkMapPosition ( start.x, start.y )) displayMap(); int fc = mapDisplay->displayMovingUnit ( start, dest, vehicle, fieldnum, totalmove, slc ); if ( fc == 1 ) { mapDisplay->resetMovement(); mapDisplay->displayMap(); } return fc; } else return 0; } void ReplayMapDisplay :: displayPosition ( int x, int y ) { if ( fieldvisiblenow ( getfield ( x, y ), actmap->playerView )) { checkMapPosition ( x, y ); mapDisplay->displayPosition ( x, y ); } } void ReplayMapDisplay :: removeActionCursor ( void ) { cursor.hide(); } void ReplayMapDisplay :: displayActionCursor ( int x1, int y1, int x2, int y2, int secondWait ) { if ( x1 >= 0 && y1 >= 0 ) { int i = fieldvisiblenow ( getfield ( x1, y1 ), actmap->playerView ); if( i ) { cursor.gotoxy ( x1, y1, i ); if ( x2 >= 0 && y2 >= 0 ) wait( 30 ); else wait(); } } if ( x2 >= 0 && y2 >= 0 ) { int i = fieldvisiblenow ( getfield ( x2, y2 ), actmap->playerView ); if( i ) { cursor.gotoxy ( x2, y2, i ); if ( secondWait ) wait(); } } } void ReplayMapDisplay :: wait ( int minTime ) { int t = ticker; while ( ticker < t + max ( cursorDelay, minTime ) ) releasetimeslice(); } LockReplayRecording::LockReplayRecording( tmap::ReplayInfo& _ri ) : ri ( _ri ) { ri.stopRecordingActions++; } LockReplayRecording::~LockReplayRecording() { ri.stopRecordingActions--; } Resources getUnitResourceCargo ( Vehicle* veh ) { Resources res = veh->getTank(); for ( int i = 0; i < 32; ++i ) if ( veh->loading[i] ) res += getUnitResourceCargo ( veh->loading[i] ); return res; } void logtoreplayinfo ( trpl_actions _action, ... ) { char action = _action; if ( actmap->replayinfo && actmap->replayinfo->actmemstream && !actmap->replayinfo->stopRecordingActions) { pnstream stream = actmap->replayinfo->actmemstream; va_list paramlist; va_start ( paramlist, _action ); if ( action == rpl_attack || action == rpl_reactionfire ) { int x1 = va_arg ( paramlist, int ); int y1 = va_arg ( paramlist, int ); int x2 = va_arg ( paramlist, int ); int y2 = va_arg ( paramlist, int ); int ad1 = va_arg ( paramlist, int ); int ad2 = va_arg ( paramlist, int ); int dd1 = va_arg ( paramlist, int ); int dd2 = va_arg ( paramlist, int ); int wpnum = va_arg ( paramlist, int ); int size = 9; stream->writeChar ( action ); stream->writeInt ( size ); stream->writeInt ( x1 ); stream->writeInt ( y1 ); stream->writeInt ( x2 ); stream->writeInt ( y2 ); stream->writeInt ( ad1 ); stream->writeInt ( ad2 ); stream->writeInt ( dd1 ); stream->writeInt ( dd2 ); stream->writeInt ( wpnum ); } if ( action == rpl_move ) { int x1 = va_arg ( paramlist, int ); int y1 = va_arg ( paramlist, int ); int x2 = va_arg ( paramlist, int ); int y2 = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( x1 ); stream->writeInt ( y1 ); stream->writeInt ( x2 ); stream->writeInt ( y2 ); stream->writeInt ( nwid ); } if ( action == rpl_move2 || action == rpl_move3 || action == rpl_move4 || action==rpl_move5) { int x1 = va_arg ( paramlist, int ); int y1 = va_arg ( paramlist, int ); int x2 = va_arg ( paramlist, int ); int y2 = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); int height = va_arg ( paramlist, int ); stream->writeChar ( action ); if ( action == rpl_move5 ) { int size = 8; stream->writeInt( size ); } else if ( action == rpl_move2 ) { int size = 6; stream->writeInt ( size ); } else { int size = 7; stream->writeInt ( size ); } stream->writeInt ( x1 ); stream->writeInt ( y1 ); stream->writeInt ( x2 ); stream->writeInt ( y2 ); stream->writeInt ( nwid ); stream->writeInt ( height ); if ( action == rpl_move3 || action == rpl_move4 || action==rpl_move5) { int nointerrupt = va_arg ( paramlist, int ); stream->writeInt ( nointerrupt ); if ( action==rpl_move5 ) { int destDamage = va_arg( paramlist, int ); stream->writeInt( destDamage ); } } } if ( action == rpl_changeheight || action == rpl_changeheight2 ) { int x1 = va_arg ( paramlist, int ); int y1 = va_arg ( paramlist, int ); int x2 = va_arg ( paramlist, int ); int y2 = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); int oldheight = va_arg ( paramlist, int ); int newheight = va_arg ( paramlist, int ); stream->writeChar ( action ); if ( action == rpl_changeheight ) { int size = 7; stream->writeInt ( size ); } else { int size = 8; stream->writeInt ( size ); } stream->writeInt ( x1 ); stream->writeInt ( y1 ); stream->writeInt ( x2 ); stream->writeInt ( y2 ); stream->writeInt ( nwid ); stream->writeInt ( oldheight ); stream->writeInt ( newheight ); if ( action == rpl_changeheight2 ) { int noInterrupt = va_arg ( paramlist, int ); stream->writeInt ( noInterrupt ); } } if ( action == rpl_convert ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int col = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 3; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( col ); } if ( action == rpl_buildobj || action == rpl_remobj ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int id = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 3; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( id ); } if ( action == rpl_buildobj2 || action == rpl_remobj2 ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int id = va_arg ( paramlist, int ); int unit = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( id ); stream->writeInt ( unit ); } if ( action == rpl_buildtnk || action == rpl_buildtnk3 || action == rpl_buildtnk4 ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int id = va_arg ( paramlist, int ); int col = va_arg ( paramlist, int ); stream->writeChar ( action ); int size; if ( action == rpl_buildtnk ) size = 4; else if ( action == rpl_buildtnk4 ) size = 7; else size = 6; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( id ); stream->writeInt ( col ); if ( action == rpl_buildtnk3 || action == rpl_buildtnk4 ) { stream->writeInt ( va_arg ( paramlist, int ) ); // constructor x stream->writeInt ( va_arg ( paramlist, int ) ); // constructor x if ( action == rpl_buildtnk4 ) stream->writeInt ( va_arg ( paramlist, int ) ); // unit height } } if ( action == rpl_buildtnk2 ) { stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( va_arg ( paramlist, int ) ); stream->writeInt ( va_arg ( paramlist, int ) ); stream->writeInt ( va_arg ( paramlist, int ) ); stream->writeInt ( va_arg ( paramlist, int ) ); stream->writeInt ( va_arg ( paramlist, int ) ); } if ( action == rpl_putbuilding || action == rpl_putbuilding2 ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int id = va_arg ( paramlist, int ); int col = va_arg ( paramlist, int ); stream->writeChar ( action ); if ( action == rpl_putbuilding ) stream->writeInt ( 4 ); else stream->writeInt ( 5 ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( id ); stream->writeInt ( col ); if ( action == rpl_putbuilding2 ) stream->writeInt ( va_arg ( paramlist, int )); } if ( action == rpl_putmine ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int col = va_arg ( paramlist, int ); int typ = va_arg ( paramlist, int ); int strength = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( col ); stream->writeInt ( typ ); stream->writeInt ( strength ); } if ( action == rpl_removemine ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); } if ( action == rpl_removebuilding ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); } if ( action == rpl_removebuilding2 || action == rpl_removebuilding3) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); stream->writeChar ( action ); if ( action == rpl_removebuilding2 ) { int size = 3; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt( nwid ); } else { int size = 6; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt( nwid ); int e = va_arg ( paramlist, int ); int m = va_arg ( paramlist, int ); int f = va_arg ( paramlist, int ); stream->writeInt( e ); stream->writeInt( m ); stream->writeInt( f ); } } if ( action == rpl_produceunit ) { int id = va_arg ( paramlist, int ); int col = va_arg ( paramlist, int ); int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int cl = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 6; stream->writeInt ( size ); stream->writeInt ( id ); stream->writeInt ( col ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( cl ); stream->writeInt ( nwid ); } if ( action == rpl_removeunit ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 3; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( nwid ); } if ( action == rpl_trainunit ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int exp = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( exp ); stream->writeInt ( nwid ); } if ( action == rpl_shareviewchange ) { stream->writeChar ( action ); if ( actmap->shareview ) { int size = 8*8/4+1; stream->writeInt ( size ); for ( int a = 0; a < 8; a++ ) for ( int b = 0; b < 8; b++ ) stream->writeChar ( actmap->shareview->mode[a][b] ); stream->writeInt ( actmap->shareview->recalculateview ); } else { int size = 0; stream->writeInt ( size ); } } if ( action == rpl_alliancechange ) { stream->writeChar ( action ); int size = sizeof ( actmap->alliances ) / sizeof ( int ); stream->writeInt ( size ); for ( int a = 0; a < 8; a++ ) for ( int b = 0; b < 8; b++ ) stream->writeChar ( actmap->alliances[a][b] ); } if ( action == rpl_refuel || action == rpl_refuel2 ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int nwid = va_arg ( paramlist, int ); int pos = va_arg ( paramlist, int ); int amnt = va_arg ( paramlist, int ); stream->writeChar ( action ); stream->writeInt ( action==rpl_refuel ? 5 : 6 ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( nwid ); stream->writeInt ( pos ); stream->writeInt ( amnt ); if ( action == rpl_refuel2 ) { int old = va_arg ( paramlist, int ); stream->writeInt( old ); } } if ( action == rpl_refuel3 ) { int id = va_arg ( paramlist, int ); int resource = va_arg ( paramlist, int ); int delta = va_arg ( paramlist, int ); stream->writeChar ( action ); stream->writeInt ( 3 ); stream->writeInt ( id ); stream->writeInt ( resource ); stream->writeInt ( delta ); } if ( action == rpl_bldrefuel ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int pos = va_arg ( paramlist, int ); int amnt = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( pos ); stream->writeInt ( amnt ); } if ( action == rpl_moveUnitUpDown ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int nwid_from = va_arg ( paramlist, int ); int nwid_to = va_arg ( paramlist, int ); int nwid_moving = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( nwid_from ); stream->writeInt ( nwid_to ); stream->writeInt ( nwid_moving ); } if ( action == rpl_productionResourceUsage ) { int en = va_arg ( paramlist, int ); int ma = va_arg ( paramlist, int ); int fu = va_arg ( paramlist, int ); int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( en ); stream->writeInt ( ma ); stream->writeInt ( fu ); stream->writeInt ( x ); stream->writeInt ( y ); } if ( action == rpl_repairUnit ) { int nwid = va_arg ( paramlist, int ); int destnwid = va_arg ( paramlist, int ); int amount = va_arg ( paramlist, int ); int matremain = va_arg ( paramlist, int ); int fuelremain = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( nwid ); stream->writeInt ( destnwid ); stream->writeInt ( amount ); stream->writeInt ( matremain ); stream->writeInt ( fuelremain ); } if ( action == rpl_repairUnit2 ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int destnwid = va_arg ( paramlist, int ); int amount = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( destnwid ); stream->writeInt ( amount ); } if ( action == rpl_produceAmmo ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int type = va_arg ( paramlist, int ); int amount = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( type ); stream->writeInt ( amount ); } if ( action == rpl_buildProdLine || action == rpl_removeProdLine) { int building = va_arg ( paramlist, int ); int id = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( building ); stream->writeInt ( id ); } if ( action == rpl_techResearched ) { int tech = va_arg ( paramlist, int ); int player = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( tech ); stream->writeInt ( player ); } if ( action == rpl_setGeneratorStatus ) { int vehid = va_arg ( paramlist, int ); int status = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( vehid ); stream->writeInt ( status ); } if ( action == rpl_cutFromGame ) { int vehid = va_arg( paramlist, int ); Resources res = getUnitResourceCargo ( actmap->getUnit ( vehid )); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( vehid ); stream->writeInt ( res.energy ); stream->writeInt ( res.material ); stream->writeInt ( res.fuel ); } if ( action == rpl_setResearch ) { int bldid = va_arg ( paramlist, int ); int amount = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 2; stream->writeInt ( size ); stream->writeInt ( bldid ); stream->writeInt ( amount ); } if ( action == rpl_setResourceProcessingAmount ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int e = va_arg ( paramlist, int ); int m = va_arg ( paramlist, int ); int f = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 5; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( e ); stream->writeInt ( m ); stream->writeInt ( f ); } if ( action == rpl_netcontrol ) { int x = va_arg ( paramlist, int ); int y = va_arg ( paramlist, int ); int cat = va_arg ( paramlist, int ); int stat = va_arg ( paramlist, int ); stream->writeChar ( action ); int size = 4; stream->writeInt ( size ); stream->writeInt ( x ); stream->writeInt ( y ); stream->writeInt ( cat ); stream->writeInt ( stat ); } va_end ( paramlist ); } } trunreplay :: trunreplay ( void ) : gui ( replayGuiHost ) { status = -1; movenum = 0; } void trunreplay::error( const char* message, ... ) { // return; va_list paramlist; va_start ( paramlist, message ); if ( message != lastErrorMessage ) { char tempbuf[1000]; int lng = vsprintf( tempbuf, message, paramlist ); if ( lng >= 1000 ) displaymessage ( "trunreplay::error: String to long !\nPlease report this error", 1 ); va_end ( paramlist ); displaymessage(tempbuf, 1 ); lastErrorMessage = message; } } int trunreplay :: removeunit ( pvehicle eht, int nwid ) { if ( !eht ) return 0; for ( int i = 0; i < 32; i++ ) if ( eht->loading[i] ) if ( eht->loading[i]->networkid == nwid ) { delete eht->loading[i]; eht->loading[i] = NULL; return 1; } else { int ld = removeunit ( eht->loading[i], nwid ); if ( ld ) return ld; } return 0; } int trunreplay :: removeunit ( int x, int y, int nwid ) { pfield fld = getfield ( x, y ); if ( !fld->vehicle ) if ( fld->building ) { for ( int i = 0; i < 32; i++ ) { if ( fld->building->loading[i] ) { if ( fld->building->loading[i]->networkid == nwid ) { delete fld->building->loading[i]; fld->building->loading[i] = NULL; return 1; } else { int ld = removeunit ( fld->building->loading[i], nwid ); if ( ld ) return ld; } } } return 0; } else return 0; else if ( fld->vehicle->networkid == nwid ) { delete fld->vehicle ; fld->vehicle = NULL; return 1; } else return removeunit ( fld->vehicle, nwid ); } void trunreplay :: wait ( int t ) { // if ( fieldvisiblenow ( getactfield(), actmap->playerView )) while ( ticker < t + CGameOptions::Instance()->replayspeed && !keypress()) { /* tkey input; while (keypress ()) { input = r_key ( ); if ( input == ct_'+' ) } */ releasetimeslice(); } } void trunreplay :: wait ( MapCoordinate pos, int t ) { if ( fieldvisiblenow ( actmap->getField ( pos ), actmap->playerView )) wait(); } void trunreplay :: wait ( MapCoordinate pos1, MapCoordinate pos2, int t ) { if ( fieldvisiblenow ( actmap->getField ( pos1 ), actmap->playerView ) || fieldvisiblenow ( actmap->getField ( pos2 ), actmap->playerView )) wait(); } /* void trunreplay :: setcursorpos ( int x, int y ) { int i = fieldvisiblenow ( getfield ( x, y ), actmap->playerview ); cursor.gotoxy ( x, y, i ); if( i ) { lastvisiblecursorpos.x = x; lastvisiblecursorpos.y = y; } } */ void trunreplay :: displayActionCursor ( int x1, int y1, int x2, int y2, int secondWait ) { ReplayMapDisplay rmd( &defaultMapDisplay ); rmd.setCursorDelay ( CGameOptions::Instance()->replayspeed ); rmd.displayActionCursor ( x1, y1, x2, y2, secondWait ); } void trunreplay :: removeActionCursor ( void ) { ReplayMapDisplay rmd( &defaultMapDisplay ); rmd.removeActionCursor ( ); } void trunreplay :: execnextreplaymove ( void ) { if ( verbosity >= 8 ) printf("executing replay move %d\n", movenum ); displaymessage2("executing replay move %d\n", movenum ); movenum++; int actaction = nextaction; if ( nextaction != rpl_finished ) { switch ( nextaction ) { case rpl_move: { stream->readInt(); // size int x1 = stream->readInt(); int y1 = stream->readInt(); int x2 = stream->readInt(); int y2 = stream->readInt(); int nwid = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( x1, y1, nwid ); if ( eht ) { ReplayMapDisplay rmd ( &defaultMapDisplay ); VehicleMovement vm ( &rmd, NULL ); vm.execute ( eht, -1, -1, 0 , -1, -1 ); int t = ticker; vm.execute ( NULL, x2, y2, 2, -1, -1 ); wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2), t ); vm.execute ( NULL, x2, y2, 3, -1, -1 ); if ( vm.getStatus() != 1000 ) eht = NULL; } if ( !eht ) error("severe replay inconsistency:\nno vehicle for move1 command !"); } break; case rpl_move5: case rpl_move4: case rpl_move3: case rpl_move2: { stream->readInt(); // size int x1 = stream->readInt(); int y1 = stream->readInt(); int x2 = stream->readInt(); int y2 = stream->readInt(); int nwid = stream->readInt(); int height = stream->readInt(); int noInterrupt; if ( nextaction == rpl_move3 || nextaction == rpl_move4 || nextaction == rpl_move5 ) noInterrupt = stream->readInt(); else noInterrupt = -1; int destDamage; if ( nextaction == rpl_move5 ) destDamage = stream->readInt(); else destDamage = -1; readnextaction(); pvehicle eht = actmap->getUnit ( x1, y1, nwid ); if ( eht ) { ReplayMapDisplay rmd( &defaultMapDisplay ); VehicleMovement vm ( &rmd ); int t = ticker; vm.execute ( eht, x2, y2, 0, -2, 0 ); vm.execute ( eht, x2, y2, 2, height, -1 ); wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2), t ); vm.execute ( NULL, x2, y2, 3, height, noInterrupt > 0 ? VehicleMovement::NoInterrupt : 0 ); if ( vm.getStatus() != 1000 ) eht = NULL; if ( destDamage >= 0 ) { int realDamage; Vehicle* veh = actmap->getUnit( nwid ); if ( veh ) realDamage = veh->damage; else realDamage = 100; if ( destDamage != realDamage ) error( "severe replay inconsistency:\ndamage after movement differs: recorded=%d, actual=%d", destDamage, realDamage ); } } if ( !eht ) error("severe replay inconsistency:\nno vehicle for move2 command !"); } break; case rpl_attack: { stream->readInt(); // size int x1 = stream->readInt(); int y1 = stream->readInt(); int x2 = stream->readInt(); int y2 = stream->readInt(); int ad1 = stream->readInt(); int ad2 = stream->readInt(); int dd1 = stream->readInt(); int dd2 = stream->readInt(); int wpnum = stream->readInt(); readnextaction(); pfield fld = getfield ( x1, y1 ); pfield targ = getfield ( x2, y2 ); int attackvisible = fieldvisiblenow ( fld, actmap->playerView ) || fieldvisiblenow ( targ, actmap->playerView ); if ( fld && targ && fld->vehicle ) { if ( targ->vehicle ) { tunitattacksunit battle ( fld->vehicle, targ->vehicle, 1, wpnum ); battle.av.damage = ad1; battle.dv.damage = dd1; if ( attackvisible ) { displayActionCursor ( x1, y1, x2, y2, 0 ); battle.calcdisplay ( ); removeActionCursor(); } else { battle.calc (); } if ( battle.av.damage < ad2 || battle.dv.damage > dd2 ) error("severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d\n", battle.av.damage,ad2 ,battle.dv.damage, dd2); battle.setresult (); if ( battle.av.damage >= 100 || battle.dv.damage >= 100 ) computeview( actmap ); dashboard.x = 0xffff; } else if ( targ->building ) { tunitattacksbuilding battle ( fld->vehicle, x2, y2 , wpnum ); battle.av.damage = ad1; battle.dv.damage = dd1; if ( attackvisible ) { displayActionCursor ( x1, y1, x2, y2, 0 ); battle.calcdisplay ( ); removeActionCursor(); } else { battle.calc (); /*battle.av.damage = ad2; battle.dv.damage = dd2; */ } if ( battle.av.damage != ad2 || battle.dv.damage != dd2 ) error("severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d\n", battle.av.damage,ad2 ,battle.dv.damage, dd2); battle.setresult (); if ( battle.av.damage >= 100 || battle.dv.damage >= 100 ) computeview( actmap ); dashboard.x = 0xffff; } else if ( !targ->objects.empty() ) { tunitattacksobject battle ( fld->vehicle, x2, y2, wpnum ); if ( attackvisible ) { displayActionCursor ( x1, y1, x2, y2, 0 ); battle.calcdisplay ( ); removeActionCursor(); } else { battle.calc (); //battle.av.damage = ad2; //battle.dv.damage = dd2; } if ( battle.av.damage != ad2 || battle.dv.damage != dd2 ) error("severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d\n", battle.av.damage,ad2 ,battle.dv.damage, dd2); battle.setresult (); if ( battle.av.damage >= 100 || battle.dv.damage >= 100 ) computeview( actmap ); dashboard.x = 0xffff; } displaymap(); } else error("severe replay inconsistency:\nno vehicle for attack command !"); } break; case rpl_changeheight2: case rpl_changeheight: { stream->readInt(); // size int x1 = stream->readInt(); int y1 = stream->readInt(); int x2 = stream->readInt(); int y2 = stream->readInt(); int nwid = stream->readInt(); int oldheight = stream->readInt(); int newheight = stream->readInt(); int noInterrupt = -1; if ( nextaction == rpl_changeheight2 ) noInterrupt = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( x1, y1, nwid ); if ( eht ) { ReplayMapDisplay rmd( &defaultMapDisplay ); VehicleAction* va; if ( newheight > oldheight ) va = new IncreaseVehicleHeight ( &rmd, NULL ); else va = new DecreaseVehicleHeight ( &rmd, NULL ); va->execute ( eht, -1, -1, 0 , newheight, -1 ); int t = ticker; va->execute ( NULL, x2, y2, 2, -1, -1 ); wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2), t ); va->execute ( NULL, x2, y2, 3, -1, noInterrupt ); if ( va->getStatus() != 1000 ) eht = NULL; delete va; } if ( !eht ) error("severe replay inconsistency:\nno vehicle for changeheight command !"); } break; case rpl_convert: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int col = stream->readInt(); readnextaction(); pfield fld = getfield ( x, y ); if ( fld ) { displayActionCursor ( x, y ); if ( fld->vehicle ) fld->vehicle->convert ( col ); else if ( fld->building ) fld->building->convert ( col ); computeview( actmap ); displaymap(); wait( MapCoordinate(x,y) ); removeActionCursor(); } else error("severe replay inconsistency:\nno vehicle for convert command !"); } break; case rpl_remobj: case rpl_buildobj: case rpl_remobj2: case rpl_buildobj2: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int id = stream->readInt(); int unit = -1; if ( actaction == rpl_remobj2 || actaction == rpl_buildobj2 ) unit = stream->readInt(); readnextaction(); pobjecttype obj = objectTypeRepository.getObject_byID ( id ); pfield fld = getfield ( x, y ); if ( obj && fld ) { displayActionCursor ( x, y ); Resources cost; int movecost; if ( actaction == rpl_remobj || actaction == rpl_remobj2 ) { cost = obj->removecost; fld->removeobject ( obj ); movecost = obj->remove_movecost; } else { cost = obj->buildcost; fld->addobject ( obj ); movecost = obj->build_movecost; } if ( unit > 0 ) { Vehicle* veh = actmap->getUnit(unit); if ( veh ) { if ( veh->getMovement() < movecost ) error("not enough movement to construct/remove object !"); veh->decreaseMovement( movecost ); Resources res2 = static_cast(veh)->getResource( cost, 0, 1 ); for ( int r = 0; r < 3; r++ ) if ( res2.resource(r) < cost.resource(r) && cost.resource(r) > 0 ) error("Resource mismatch: not enough resources to construct/remove object !"); } else error("replay inconsistency:\nCannot find Unit to build/remove Object !"); } if ( obj->basicjamming_plus || obj->basicjamming_abs != -1 || obj->viewbonus_plus || obj->viewbonus_abs != -1 ) computeview( actmap ); displaymap(); wait(MapCoordinate(x,y)); removeActionCursor(); } else error("severe replay inconsistency:\nCannot find Object to build/remove !"); } break; case rpl_buildtnk: case rpl_buildtnk2: case rpl_buildtnk3: case rpl_buildtnk4: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int id = stream->readInt(); int col = stream->readInt(); int nwid = -1; int constx = -1; int consty = -1; int height = -1; if ( nextaction == rpl_buildtnk2 ) nwid = stream->readInt(); if ( nextaction == rpl_buildtnk3 || nextaction == rpl_buildtnk4 ) { constx = stream->readInt(); consty = stream->readInt(); if ( nextaction == rpl_buildtnk4 ) height = stream->readInt(); } readnextaction(); pfield fld = getfield ( x, y ); pvehicletype tnk = vehicleTypeRepository.getObject_byID ( id ); if ( fld && tnk && !fld->vehicle ) { displayActionCursor ( x, y ); pvehicle v = new Vehicle ( tnk, actmap, col ); v->xpos = x; v->ypos = y; fld->vehicle = v; if ( height >= 0 ) v->height = height; if ( constx >= 0 && consty >= 0 ) { pfield constructorField = getfield(constx, consty ); if ( constructorField->vehicle ) { Resources r ( 0, tnk->productionCost.material, tnk->productionCost.energy ); Resources rr = constructorField->getContainer()->getResource( r, 0 ); if ( rr < r ) { displayActionCursor ( x, y ); error("severe replay inconsistency: \nNot enough resources to produce unit %s !\nRequired: %d/%d/%d ; Available: %d/%d/%d", v->typ->description.c_str(), r.energy, r.material, r.fuel, rr.energy, rr.material, rr.fuel); } } else error("severe replay inconsistency: could not find constructor !"); } computeview( actmap ); displaymap(); wait(MapCoordinate(x,y) ); removeActionCursor(); } else error("severe replay inconsistency:\nCannot find Vehicle to build !"); } break; case rpl_putbuilding2: case rpl_putbuilding : { int size = stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int id = stream->readInt(); int color = stream->readInt(); int networkid = 0; if ( size == 5 ) networkid = stream->readInt(); readnextaction(); pfield fld = getfield ( x, y ); pbuildingtype bld = buildingTypeRepository.getObject_byID ( id ); if ( bld && fld ) { displayActionCursor ( x, y ); putbuilding2( MapCoordinate(x, y), color, bld ); computeview( actmap ); if ( networkid ) { Vehicle* veh = actmap->getUnit( networkid ); if ( veh ) { int mf = actmap->getgameparameter ( cgp_building_material_factor ); int ff = actmap->getgameparameter ( cgp_building_fuel_factor ); if ( mf <= 0 ) mf = 100; if ( ff <= 0 ) ff = 100; Resources res ( 0, bld->productionCost.material * mf / 100, bld->productionCost.fuel * ff / 100 ); Resources got = static_cast(veh)->getResource( res, 0 ); if ( got < res ) error("severe replay inconsistency:\nnot enough resources to build/remove building !"); } else error("severe replay inconsistency:\nCannot find vehicle to build/remove building !"); } displaymap(); wait(MapCoordinate(x,y)); removeActionCursor(); } else error("severe replay inconsistency:\nCannot find building to build/remove building!" ); } break; case rpl_putmine: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int col = stream->readInt(); int typ = stream->readInt(); int strength = stream->readInt(); readnextaction(); pfield fld = getfield ( x, y ); if ( fld ) { displayActionCursor ( x, y ); fld -> putmine ( col, typ, strength ); computeview( actmap ); if ( fieldvisiblenow ( actmap->getField(x,y), actmap->playerView )) { displaymap(); wait(); } removeActionCursor(); } else error("severe replay inconsistency:\nno field for putmine command !"); } break; case rpl_removemine: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); readnextaction(); pfield fld = getfield ( x, y ); if ( fld ) { displayActionCursor ( x, y ); fld -> removemine ( -1 ); computeview( actmap ); if ( fieldvisiblenow ( actmap->getField(x,y), actmap->playerView )) { displaymap(); wait(); } removeActionCursor ( ); } else error("severe replay inconsistency:\nno field for remove mine command !"); } break; case rpl_removebuilding2: case rpl_removebuilding3: case rpl_removebuilding: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int nwid = -1; if ( nextaction == rpl_removebuilding2 || nextaction == rpl_removebuilding3 ) nwid = stream->readInt(); Resources res; if ( nextaction == rpl_removebuilding3 ) { res.energy = stream->readInt(); res.material = stream->readInt(); res.fuel = stream->readInt(); } readnextaction(); pfield fld = getfield ( x, y ); if ( fld && fld->building ) { displayActionCursor ( x, y ); pbuilding bb = fld->building; if ( nwid >= 0 ) { Vehicle* veh = actmap->getUnit( nwid ); if ( veh ) { Resources r = getDestructionCost ( bb, veh ); if ( !veh || veh->getResource(r,false) != res ) error("severe replay inconsistency:\nfailed to obtain vehicle resources for removebuilding command !"); } else error("severe replay inconsistency:\nfailed to obtain vehicle for removebuilding command !"); } if ( bb->getCompletion() ) { bb->setCompletion( bb->getCompletion()-1); } else { delete bb; } computeview( actmap ); displaymap(); wait(); removeActionCursor(); } else error("severe replay inconsistency:\nno building for removebuilding command !"); } break; case rpl_produceunit : { stream->readInt(); // size int id = stream->readInt(); int col = stream->readInt(); int x = stream->readInt(); int y = stream->readInt(); int cl = stream->readInt(); int nwid = stream->readInt(); readnextaction(); pfield fld = getfield ( x, y ); pvehicletype tnk = vehicleTypeRepository.getObject_byID ( id ); if ( tnk && fld) { #if 0 printf("produced unit: pos %d / %d; nwid %d; typ id %d; typ %s \n", x,y,nwid,id,tnk->description.c_str() ); #endif pvehicle eht = new Vehicle ( tnk, actmap, col / 8 ); eht->xpos = x; eht->ypos = y; eht->networkid = nwid; if ( fld->building ) { Resources r = fld->building->getResource( tnk->productionCost, 0 ); if ( r < tnk->productionCost ) { displayActionCursor ( x, y ); error("severe replay inconsistency: \nNot enough resources to produce unit %s !\nRequired: %d/%d/%d ; Available: %d/%d/%d", eht->typ->description.c_str(), tnk->productionCost.energy, tnk->productionCost.material, tnk->productionCost.fuel, r.energy, r.material, r.fuel); } int i = 0; while ( fld->building->loading[i]) i++; fld->building->loading[i] = eht; } else { displayActionCursor ( x, y ); fld->vehicle = eht; computeview( actmap ); displaymap(); wait( MapCoordinate(x,y) ); removeActionCursor(); } } else error("severe replay inconsistency:\nCannot find vehicle to build/remove !"); } break; case rpl_removeunit : { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int nwid = stream->readInt(); readnextaction(); pfield fld = getfield(x,y); if ( !fld->vehicle || fld->vehicle->networkid != nwid && fld->building ) { cbuildingcontrols bc; bc.init ( fld->building ); pvehicle veh = actmap->getUnit( nwid ); bc.recycling.recycle( veh ); } else if ( !removeunit ( x, y, nwid )) displaymessage ( "severe replay inconsistency:\nCould not remove unit %d!", 1, nwid ); } break; case rpl_trainunit:{ stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int exp = stream->readInt(); int nwid = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( x, y, nwid ); pbuilding bld = actmap->getField ( x, y )->building; if ( eht && bld ) { cbuildingcontrols bc; bc.init( bld ); if ( bc.training.available( eht )) bc.training.trainunit( eht ); else error("severe replay inconsistency:\nno vehicle for trainunit command !"); } else error("severe replay inconsistency:\nno vehicle for trainunit command !"); } break; case rpl_shareviewchange: { int size = stream->readInt(); tmap::Shareview* sv = new tmap::Shareview; if ( size ) { for ( int a = 0; a < 8; a++ ) for ( int b = 0; b < 8; b++) sv->mode[a][b] = stream->readChar(); sv->recalculateview = stream->readInt(); if ( actmap->shareview ) delete actmap->shareview; actmap->shareview = sv; actmap->shareview->recalculateview = 0; } else if ( actmap->shareview ) { delete actmap->shareview; actmap->shareview = NULL; } readnextaction(); computeview( actmap ); displaymap(); } break; case rpl_alliancechange: { stream->readInt(); // size for ( int a = 0; a < 8; a++ ) for ( int b = 0; b < 8; b++ ) actmap->alliances[a][b] = stream->readChar(); readnextaction(); dashboard.x = 0xffff; } break; case rpl_refuel : case rpl_refuel2 : { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int nwid = stream->readInt(); int pos = stream->readInt(); int amnt = stream->readInt(); int old = -2; if ( nextaction == rpl_refuel2 ) old = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( x, y, nwid ); if ( eht ) { if ( pos < 16 ) eht->ammo[pos] = amnt; else { int res = pos - 1000; int avl = eht->getTank().resource(res); if ( avl != old && old >= 0 ) error("severe replay inconsistency:\nthe resources of unit not matching. \nrecorded: %d , expected: %d !", old, avl); eht->getResource ( avl - amnt, res, false ); } } else error("severe replay inconsistency:\nno vehicle for refuel-unit command !"); } break; case rpl_refuel3 : { stream->readInt(); // size int id = stream->readInt(); int type = stream->readInt(); int delta = stream->readInt(); readnextaction(); ContainerBase* cb = actmap->getContainer ( id ); if ( cb ) { int d = cb->getResource(delta, type-1000, false); if ( d != delta ) error("severe replay inconsistency:\nthe resources of container not matching. \nrequired: %d , available: %d !", delta, d); } else error("severe replay inconsistency:\nno vehicle for refuel3 command !"); } break; case rpl_bldrefuel : { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int pos = stream->readInt(); int amnt = stream->readInt(); readnextaction(); pbuilding bld = actmap->getField(x,y)->building; if ( bld ) { if ( pos < 16 ) bld->ammo[pos] = amnt; else bld->getResource ( amnt, pos-1000, 0 ); } else error("severe replay inconsistency:\nno building for refuel-unit command !"); } break; case rpl_moveUnitUpDown: { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int nwid_from = stream->readInt(); int nwid_to = stream->readInt(); int nwid_moving = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( x, y, nwid_moving ); ContainerBase* from; if ( nwid_from >= 0 ) from = actmap->getUnit ( x, y, nwid_from ); else from = actmap->getField ( x, y )->building; ContainerBase* to; if ( nwid_to >= 0 ) to = actmap->getUnit ( x, y, nwid_to ); else to = actmap->getField ( x, y )->building; if ( eht && from && to ) { int i = 0; while ( from->loading[i] != eht ) i++; if ( i >= 32 ) { error("severe replay inconsistency: container for moveUpDown 2 !"); return; } from->loading[i] = NULL; while ( to->loading[i] ) i++; if ( i >= 32 ) { error("severe replay inconsistency: container for moveUpDown 3 !"); return; } to->loading[i] = eht; } else error("severe replay inconsistency: container for moveUpDown !"); } break; case rpl_repairUnit : { stream->readInt(); // size int nwid = stream->readInt(); int destnwid = stream->readInt(); int amount = stream->readInt(); int matremain = stream->readInt(); int fuelremain = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( nwid ); pvehicle dest = actmap->getUnit ( destnwid ); if ( eht && dest ) { eht->repairItem ( dest, amount ); if ( eht->getTank().fuel != fuelremain || eht->getTank().material != matremain ) error("severe replay inconsistency:\nthe resources of unit not matching for repair operation!"); } else error("severe replay inconsistency:\nno vehicle for repair-unit command !"); } break; case rpl_repairUnit2 : { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int destnwid = stream->readInt(); int amount = stream->readInt(); readnextaction(); pbuilding bld = getfield(x,y)->building; pvehicle dest = actmap->getUnit ( destnwid ); if ( bld && dest ) { bld->repairItem ( dest, amount ); } else error("severe replay inconsistency:\nno vehicle for repair-unit command !"); } break; case rpl_produceAmmo : { stream->readInt(); // size int x = stream->readInt(); int y = stream->readInt(); int type = stream->readInt(); int amount = stream->readInt(); readnextaction(); pbuilding bld = getfield(x,y)->building; if ( bld ) { cbuildingcontrols bc; bc.init ( bld ); bc.produceammunition.produce( type, amount ); } else error("severe replay inconsistency:\nno building for produce ammo command !"); } break; case rpl_buildProdLine : { stream->readInt(); // size int building = stream->readInt(); int vehicleid = stream->readInt(); readnextaction(); Building* bld = dynamic_cast( actmap->getContainer(building)); Vehicletype* veh = actmap->getvehicletype_byid ( vehicleid ); if ( bld && veh ) { if ( veh->techDependency.available( actmap->player[ bld->getOwner()].research )) { cbuildingcontrols bc; bc.init ( bld ); int result = bc.buildProductionLine.build( veh ); if ( result < 0) error("severe replay inconsistency:\ncould not build production line!\n%s !", getmessage(result)); } else error("severe replay inconsistency:\ntechnology for building production line not available!"); } else error("severe replay inconsistency:\nno building for build production line command !"); } break; case rpl_removeProdLine : { stream->readInt(); // size int building = stream->readInt(); int vehicleid = stream->readInt(); readnextaction(); Building* bld = dynamic_cast( actmap->getContainer(building)); Vehicletype* veh = actmap->getvehicletype_byid ( vehicleid ); if ( bld && veh ) { cbuildingcontrols bc; bc.init ( bld ); int result = bc.removeProductionLine.remove( veh ); if ( result < 0) error("severe replay inconsistency:\ncould not remove production line!\n%s !", getmessage(result)); } else error("severe replay inconsistency:\nno building for remove production line command !"); } break; case rpl_setResearch : { stream->readInt(); // size int building = stream->readInt(); int amount = stream->readInt(); readnextaction(); Building* bld = dynamic_cast( actmap->getContainer(building)); if ( bld ) bld->researchpoints = amount; else error("severe replay inconsistency:\nno building for set research command !"); } break; case rpl_techResearched: { stream->readInt(); // size int techID = stream->readInt(); int player = stream->readInt(); readnextaction(); Technology* tech = technologyRepository.getObject_byID( techID ); if ( tech ) { actmap->player[player].research.addanytechnology( tech ); actmap->player[player].research.progress -= tech->researchpoints; } else error("severe replay inconsistency:\nno technology for tech researched command !"); } break; case rpl_setGeneratorStatus : { stream->readInt(); int nwid = stream->readInt(); int status = stream->readInt(); readnextaction(); pvehicle eht = actmap->getUnit ( nwid ); if ( eht ) eht->setGeneratorStatus( status ); else error("severe replay inconsistency:\nvehicle for generator switching not found !"); } break; case rpl_cutFromGame: { stream->readInt(); int vehid = stream->readInt(); Vehicle* veh = actmap->getUnit ( vehid ); Resources res; res.energy = stream->readInt(); res.material = stream->readInt(); res.fuel = stream->readInt(); readnextaction(); if ( veh && res == getUnitResourceCargo ( veh )) { veh->prepareForCleanRemove(); delete veh; computeview( actmap ); displaymap(); } else error ( "resource mismatch at cut unit operation! "); } break; case rpl_setResourceProcessingAmount: { stream->readInt(); int x = stream->readInt(); int y = stream->readInt(); Resources p; p.energy = stream->readInt(); p.material = stream->readInt(); p.fuel = stream->readInt(); readnextaction(); Building* bld = actmap->getField(x,y)->building; if ( bld ) { for ( int r = 0; r< 3; ++r ) if ( abs(p.resource(r)) > abs(bld->typ->maxplus.resource(r)) ) error ("Building can not produ "); bld->plus = p; } else error ("Building not found on for rpl_setResourceProcessingAmount "); } break; case rpl_netcontrol: { stream->readInt(); int x = stream->readInt(); int y = stream->readInt(); int cat = stream->readInt(); int stat = stream->readInt(); readnextaction(); Building* bld = actmap->getField(x,y)->building; if ( bld ) { cbuildingcontrols bc; bc.init( bld ); bc.netcontrol.setnetmode( cat, stat ); bld->execnetcontrol(); } else error ("Building not found on for rpl_setResourceProcessingAmount "); } break; default:{ int size = stream->readInt(); for ( int i = 0; i< size; i++ ) stream->readInt(); readnextaction(); } break; } /* endswitch */ } else { status = 10; dashboard.x = -1; } } void trunreplay :: readnextaction ( void ) { if ( stream->dataavail () ) nextaction = stream->readChar(); else nextaction = rpl_finished; } preactionfire_replayinfo trunreplay::getnextreplayinfo ( void ) { if ( nextaction == rpl_reactionfire ) { preactionfire_replayinfo reac = new treactionfire_replayinfo; stream->readInt(); // size reac->x1 = stream->readInt(); reac->y1 = stream->readInt( ); reac->x2 = stream->readInt( ); reac->y2 = stream->readInt( ); reac->ad1 = stream->readInt( ); reac->ad2 = stream->readInt( ); reac->dd1 = stream->readInt( ); reac->dd2 = stream->readInt( ); reac->wpnum = stream->readInt( ); readnextaction(); return reac; } else return NULL; } int trunreplay :: run ( int player, int viewingplayer ) { if ( status < 0 ) firstinit ( ); lastErrorMessage = ""; cursor.hide(); movenum = 0; actplayer = actmap->actplayer; orgmap = actmap; actmap = loadreplay ( orgmap->replayinfo->map[player] ); if ( !actmap ) { displaymessage("error loading replay", 1 ); actmap = orgmap; return 0; } transfer_all_outstanding_tribute(); actmap->playerView = viewingplayer; tmemorystream guidatastream ( orgmap->replayinfo->guidata [ player ], tnstream::reading ); stream = &guidatastream; if ( stream->dataavail () ) nextaction = stream->readChar(); else nextaction = rpl_finished; // orgmap.replayinfo->actmemstream = stream; npush (actgui); actgui = &gui; actgui->restorebackground(); actmap->xpos = orgmap->cursorpos.position[ viewingplayer ].sx; actmap->ypos = orgmap->cursorpos.position[ viewingplayer ].sy; cursor.gotoxy ( orgmap->cursorpos.position[ viewingplayer ].cx, orgmap->cursorpos.position[ viewingplayer ].cy , 0); if ( stream->dataavail () ) status = 1; else status = 11; computeview( actmap ); displaymap (); dashboard.x = 0xffff; mousevisible( true ); // cursor.show(); cursor.checkposition( getxpos(), getypos() ); bool resourcesCompared = false; do { if ( status == 2 ) { execnextreplaymove ( ); /* if ( getxpos () != lastvisiblecursorpos.x || getypos () != lastvisiblecursorpos.y ) setcursorpos ( lastvisiblecursorpos.x, lastvisiblecursorpos.y ); */ } else releasetimeslice(); if (nextaction == rpl_finished || status != 2) { if ( !cursor.an ) cursor.show(); if ( nextaction == rpl_finished && !resourcesCompared ) { displaymessage2("running final comparison" ); actmap->endTurn(); actmap->nextPlayer(); resourcesCompared = true; ASCString resourceComparisonResult; tmap* comparisonMap = NULL; tmap* nextPlayerMap = NULL; if ( actmap->actplayer == orgmap->actplayer ) comparisonMap = orgmap; else comparisonMap = nextPlayerMap = loadreplay ( orgmap->replayinfo->map[actmap->actplayer] ); if ( comparisonMap ) { if ( comparisonMap->compareResources( actmap, player, &resourceComparisonResult)) { tviewanytext vat; vat.init ( "warning", resourceComparisonResult.c_str() ); vat.run(); vat.done(); } } else error("Replay: no map to compare to!"); delete nextPlayerMap; } } else if ( cursor.an ) cursor.hide(); tkey input; while (keypress ()) { mainloopgeneralkeycheck ( input ); } mainloopgeneralmousecheck (); } while ( status > 0 && status < 100 ) ; actgui->restorebackground(); delete actmap; actmap = orgmap; npop ( actgui ); int st = status; status = 0; cursor.gotoxy ( orgmap->cursorpos.position[ actplayer ].cx, orgmap->cursorpos.position[ actplayer ].cy ); dashboard.x = 0xffff; if ( st == 101 ) return 1; else return 0; } void trunreplay :: firstinit ( void ) { gui.init ( hgmp->resolutionx, hgmp->resolutiony ); gui.starticonload(); status = 0; }