2007-06-06 22:29:40 +03:00
// CMT.cpp : Defines the entry point for the console application.
//
2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2009-05-20 13:08:56 +03:00
# include <boost/filesystem/operations.hpp>
2008-12-21 21:17:35 +02:00
# include <SDL_mixer.h>
2011-12-22 16:05:19 +03:00
# include "UIFramework/SDL_Extensions.h"
2008-08-04 18:56:36 +03:00
# include "CGameInfo.h"
2010-04-06 11:59:24 +03:00
# include "mapHandler.h"
2011-12-14 00:23:17 +03:00
2008-08-04 18:56:36 +03:00
# include "CPreGame.h"
2008-09-17 13:18:22 +03:00
# include "CCastleInterface.h"
2011-12-14 00:23:17 +03:00
# include "../lib/CConsoleHandler.h"
2011-12-22 16:05:19 +03:00
# include "UIFramework/CCursorHandler.h"
2009-05-20 13:08:56 +03:00
# include "../lib/CGameState.h"
# include "../CCallback.h"
2007-11-19 00:58:28 +02:00
# include "CPlayerInterface.h"
2007-12-06 20:55:58 +02:00
# include "CAdvmapInterface.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CBuildingHandler.h"
# include "CVideoHandler.h"
# include "../lib/CHeroHandler.h"
# include "../lib/CCreatureHandler.h"
# include "../lib/CSpellHandler.h"
# include "CMusicHandler.h"
# include "CVideoHandler.h"
# include "../lib/CLodHandler.h"
# include "CDefHandler.h"
# include "../lib/CGeneralTextHandler.h"
2009-05-20 13:08:56 +03:00
# include "Graphics.h"
# include "Client.h"
# include "CConfigHandler.h"
# include "../lib/Connection.h"
# include "../lib/VCMI_Lib.h"
2009-10-10 08:47:59 +03:00
# include "../lib/VCMIDirs.h"
2009-05-20 13:08:56 +03:00
# include "../lib/NetPacks.h"
2010-02-08 16:38:06 +02:00
# include "CMessage.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CObjectHandler.h"
2011-01-15 04:17:56 +02:00
# include "../lib/CArtHandler.h"
2011-06-20 14:41:04 +03:00
# include "../lib/CScriptingModule.h"
2011-12-14 00:23:17 +03:00
# include "../lib/GameConstants.h"
2011-12-17 21:59:59 +03:00
# include "UIFramework/CGuiHandler.h"
2009-12-03 06:01:14 +02:00
# ifdef _WIN32
2009-11-28 19:21:54 +02:00
# include "SDL_syswm.h"
2009-12-03 06:01:14 +02:00
# endif
2010-12-20 23:22:53 +02:00
# include "../lib/CDefObjInfoHandler.h"
2012-02-20 00:03:43 +03:00
# include "../lib/UnlockGuard.h"
2008-12-21 21:17:35 +02:00
2009-02-08 17:39:26 +02:00
# if __MINGW32__
# undef main
# endif
2009-04-15 17:03:31 +03:00
2010-12-22 22:14:40 +02:00
namespace po = boost : : program_options ;
2009-04-15 17:03:31 +03:00
/*
* CMT . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2009-07-31 23:10:22 +03:00
std : : string NAME_AFFIX = " client " ;
2011-12-14 00:23:17 +03:00
std : : string NAME = GameConstants : : VCMI_VERSION + std : : string ( " ( " ) + NAME_AFFIX + ' ) ' ; //application name
2009-08-07 01:36:51 +03:00
CGuiHandler GH ;
2012-02-16 20:10:58 +03:00
static CClient * client = NULL ;
2012-01-12 18:23:00 +03:00
SDL_Surface * screen = NULL , //main screen surface
* screen2 = NULL , //and hlp surface (used to store not-active interfaces layer)
2009-05-25 02:21:55 +03:00
* screenBuf = screen ; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
2009-12-28 06:08:24 +02:00
static boost : : thread * mainGUIThread ;
2009-04-11 04:32:50 +03:00
2009-10-10 08:47:59 +03:00
VCMIDirs GVCMIDirs ;
2009-03-12 20:50:36 +02:00
std : : queue < SDL_Event * > events ;
2008-08-04 18:56:36 +03:00
boost : : mutex eventsM ;
2009-04-11 04:32:50 +03:00
2009-08-08 02:17:12 +03:00
static bool gOnlyAI = false ;
2010-03-21 00:17:19 +02:00
static bool setResolution = false ; //set by event handling thread after resolution is adjusted
2009-04-11 04:32:50 +03:00
2011-06-11 02:50:32 +03:00
static bool ermInteractiveMode = false ; //structurize when time is right
2009-08-17 11:50:31 +03:00
void processCommand ( const std : : string & message ) ;
2012-02-24 23:41:14 +03:00
static void setScreenRes ( int w , int h , int bpp , bool fullscreen , bool resetVideo = true ) ;
2009-06-23 11:14:49 +03:00
void dispose ( ) ;
2009-06-24 09:56:36 +03:00
void playIntro ( ) ;
2009-11-01 03:15:16 +02:00
static void listenForEvents ( ) ;
2010-07-14 04:08:27 +03:00
void requestChangingResolution ( ) ;
2010-12-22 22:14:40 +02:00
void startGame ( StartInfo * options , CConnection * serv = NULL ) ;
2009-06-24 09:56:36 +03:00
2010-04-04 01:06:50 +03:00
# ifndef _WIN32
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include <getopt.h>
# endif
2012-01-03 04:55:26 +03:00
void startGameFromFile ( const std : : string & fname )
{
if ( fname . size ( ) & & boost : : filesystem : : exists ( fname ) )
{
StartInfo si ;
CLoadFile out ( fname ) ;
out > > si ;
while ( GH . topInt ( ) )
GH . popIntTotally ( GH . topInt ( ) ) ;
startGame ( & si ) ;
}
}
2009-06-24 09:56:36 +03:00
void init ( )
{
2011-12-17 21:59:59 +03:00
CStopWatch tmh , pomtime ;
2009-06-24 09:56:36 +03:00
# if SDL_BYTEORDER == SDL_BIG_ENDIAN
int rmask = 0xff000000 ; int gmask = 0x00ff0000 ; int bmask = 0x0000ff00 ; int amask = 0x000000ff ;
# else
int rmask = 0x000000ff ; int gmask = 0x0000ff00 ; int bmask = 0x00ff0000 ; int amask = 0xff000000 ;
# endif
CSDL_Ext : : std32bppSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE , 1 , 1 , 32 , rmask , gmask , bmask , amask ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " \t Initializing minors: " < < pomtime . getDiff ( ) < < std : : endl ;
2009-07-18 06:13:13 +03:00
2009-06-24 09:56:36 +03:00
//initializing audio
// Note: because of interface button range, volume can only be a
// multiple of 11, from 0 to 99.
2010-12-19 16:39:56 +02:00
CCS - > soundh = new CSoundHandler ;
CCS - > soundh - > init ( ) ;
2012-01-12 18:23:00 +03:00
CCS - > soundh - > setVolume ( settings [ " general " ] [ " sound " ] . Float ( ) ) ;
2010-12-19 16:39:56 +02:00
CCS - > musich = new CMusicHandler ;
2011-08-17 23:44:14 +03:00
CCS - > musich - > init ( ) ;
2012-01-12 18:23:00 +03:00
CCS - > musich - > setVolume ( settings [ " general " ] [ " music " ] . Float ( ) ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " \t Initializing sound: " < < pomtime . getDiff ( ) < < std : : endl ;
tlog0 < < " Initializing screen and sound handling: " < < tmh . getDiff ( ) < < std : : endl ;
2009-06-24 09:56:36 +03:00
initDLL ( : : console , logfile ) ;
2010-12-19 00:11:28 +02:00
const_cast < CGameInfo * > ( CGI ) - > setFromLib ( ) ;
2010-12-19 16:39:56 +02:00
CCS - > soundh - > initCreaturesSounds ( CGI - > creh - > creatures ) ;
CCS - > soundh - > initSpellsSounds ( CGI - > spellh - > spells ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Initializing VCMI_Lib: " < < tmh . getDiff ( ) < < std : : endl ;
2009-06-24 09:56:36 +03:00
2011-12-14 00:23:17 +03:00
pomtime . getDiff ( ) ;
2010-12-19 16:39:56 +02:00
CCS - > curh = new CCursorHandler ;
CCS - > curh - > initCursor ( ) ;
CCS - > curh - > show ( ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Screen handler: " < < pomtime . getDiff ( ) < < std : : endl ;
pomtime . getDiff ( ) ;
2009-06-24 09:56:36 +03:00
graphics = new Graphics ( ) ;
2009-07-06 22:41:27 +03:00
graphics - > loadHeroAnims ( ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " \t Main graphics: " < < tmh . getDiff ( ) < < std : : endl ;
tlog0 < < " Initializing game graphics: " < < tmh . getDiff ( ) < < std : : endl ;
2009-06-24 09:56:36 +03:00
CMessage : : init ( ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Message handler: " < < tmh . getDiff ( ) < < std : : endl ;
2009-08-17 11:50:31 +03:00
//CPG = new CPreGame(); //main menu and submenus
//tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
2009-06-24 09:56:36 +03:00
}
2009-04-14 15:47:09 +03:00
2010-04-04 01:06:50 +03:00
static void prog_version ( void )
{
2011-12-14 00:23:17 +03:00
printf ( " %s \n " , GameConstants : : VCMI_VERSION . c_str ( ) ) ;
printf ( " data directory: %s \n " , GameConstants : : DATA_DIR . c_str ( ) ) ;
printf ( " library directory: %s \n " , GameConstants : : LIB_DIR . c_str ( ) ) ;
printf ( " binary directory: %s \n " , GameConstants : : BIN_DIR . c_str ( ) ) ;
2010-04-04 01:06:50 +03:00
}
2012-01-03 04:55:26 +03:00
static void prog_help ( const po : : options_description & opts )
2010-04-04 01:06:50 +03:00
{
2011-12-14 00:23:17 +03:00
printf ( " %s - A Heroes of Might and Magic 3 clone \n " , GameConstants : : VCMI_VERSION . c_str ( ) ) ;
2012-01-03 04:55:26 +03:00
printf ( " Copyright (C) 2007-2012 VCMI dev team - see AUTHORS file \n " ) ;
2010-04-04 01:06:50 +03:00
printf ( " This is free software; see the source for copying conditions. There is NO \n " ) ;
printf ( " warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \n " ) ;
printf ( " \n " ) ;
printf ( " Usage: \n " ) ;
2012-01-03 04:55:26 +03:00
std : : cout < < opts ;
// printf(" -h, --help display this help and exit\n");
// printf(" -v, --version display version information and exit\n");
2010-04-04 01:06:50 +03:00
}
# ifdef _WIN32
2008-06-30 03:06:41 +03:00
int _tmain ( int argc , _TCHAR * argv [ ] )
2008-08-04 18:56:36 +03:00
# else
2008-09-10 00:10:24 +03:00
int main ( int argc , char * * argv )
2008-08-04 18:56:36 +03:00
# endif
2009-02-08 17:39:26 +02:00
{
2010-12-22 22:14:40 +02:00
tlog0 < < " Starting... " < < std : : endl ;
po : : options_description opts ( " Allowed options " ) ;
opts . add_options ( )
( " help,h " , " display help and exit " )
( " version,v " , " display version information and exit " )
2011-03-20 00:27:05 +02:00
( " battle,b " , po : : value < std : : string > ( ) , " runs game in duel mode (battle-only " )
2012-01-03 04:55:26 +03:00
( " start " , po : : value < std : : string > ( ) , " starts game from saved StartInfo file " )
( " onlyAI " , " runs without GUI, all players will be default AI " )
2012-02-29 04:31:48 +03:00
( " oneGoodAI " , " puts one default AI and the rest will be EmptyAI " )
2012-01-03 04:55:26 +03:00
( " autoSkip " , " automatically skip turns in GUI " )
2011-03-20 00:27:05 +02:00
( " nointro,i " , " skips intro movies " ) ;
2010-12-22 22:14:40 +02:00
po : : variables_map vm ;
if ( argc > 1 )
{
try
{
po : : store ( po : : parse_command_line ( argc , argv , opts ) , vm ) ;
}
catch ( std : : exception & e )
{
tlog1 < < " Failure during parsing command-line options: \n " < < e . what ( ) < < std : : endl ;
2010-04-04 01:06:50 +03:00
}
}
2010-12-22 22:14:40 +02:00
po : : notify ( vm ) ;
if ( vm . count ( " help " ) )
{
2012-01-03 04:55:26 +03:00
prog_help ( opts ) ;
2010-12-22 22:14:40 +02:00
return 0 ;
}
if ( vm . count ( " version " ) )
{
prog_version ( ) ;
return 0 ;
2010-04-04 01:06:50 +03:00
}
2010-01-29 22:52:45 +02:00
//Set environment vars to make window centered. Sometimes work, sometimes not. :/
2011-03-22 15:19:07 +02:00
putenv ( ( char * ) " SDL_VIDEO_WINDOW_POS " ) ;
putenv ( ( char * ) " SDL_VIDEO_CENTERED=1 " ) ;
2009-09-07 05:29:44 +03:00
2011-12-17 21:59:59 +03:00
CStopWatch total , pomtime ;
2008-11-15 15:44:32 +02:00
std : : cout . flags ( std : : ios : : unitbuf ) ;
2011-11-01 15:58:01 +03:00
logfile = new std : : ofstream ( ( GVCMIDirs . UserPath + " /VCMI_Client_log.txt " ) . c_str ( ) ) ;
2009-06-23 11:14:49 +03:00
console = new CConsoleHandler ;
2009-08-17 11:50:31 +03:00
* console - > cb = boost : : bind ( & processCommand , _1 ) ;
2009-06-23 11:14:49 +03:00
console - > start ( ) ;
atexit ( dispose ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Creating console and logfile: " < < pomtime . getDiff ( ) < < std : : endl ;
2008-11-09 00:29:19 +02:00
2012-01-12 18:23:00 +03:00
settings . init ( ) ;
2008-11-09 00:29:19 +02:00
conf . init ( ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Loading settings: " < < pomtime . getDiff ( ) < < std : : endl ;
2008-09-19 11:16:19 +03:00
tlog0 < < NAME < < std : : endl ;
2008-11-09 00:29:19 +02:00
2008-06-16 13:51:14 +03:00
srand ( time ( NULL ) ) ;
2012-01-12 18:23:00 +03:00
2010-12-19 16:39:56 +02:00
CCS = new CClientState ;
CGI = new CGameInfo ; //contains all global informations about game (texts, lodHandlers, map handler etc.)
2010-08-16 12:54:09 +03:00
2009-08-17 11:50:31 +03:00
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO ) )
2007-06-06 22:29:40 +03:00
{
2009-08-17 11:50:31 +03:00
tlog1 < < " Something was wrong: " < < SDL_GetError ( ) < < std : : endl ;
exit ( - 1 ) ;
2007-06-06 22:29:40 +03:00
}
2009-10-26 07:39:30 +02:00
atexit ( SDL_Quit ) ;
2009-08-17 11:50:31 +03:00
2012-01-12 18:23:00 +03:00
const JsonNode & video = settings [ " video " ] ;
const JsonNode & res = video [ " menuRes " ] ;
setScreenRes ( res [ " width " ] . Float ( ) , res [ " height " ] . Float ( ) , video [ " bitsPerPixel " ] . Float ( ) , video [ " fullscreen " ] . Bool ( ) ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " \t Initializing screen: " < < pomtime . getDiff ( ) < < std : : endl ;
2009-08-17 11:50:31 +03:00
// Initialize video
2011-08-08 10:12:18 +03:00
# if defined _M_X64 && defined _WIN32 //Win64 -> cannot load 32-bit DLLs for video handling
CCS - > videoh = new CEmptyVideoPlayer ;
# else
2010-12-19 16:39:56 +02:00
CCS - > videoh = new CVideoPlayer ;
2011-08-08 10:12:18 +03:00
# endif
2011-12-14 00:23:17 +03:00
tlog0 < < " \t Initializing video: " < < pomtime . getDiff ( ) < < std : : endl ;
2009-08-17 11:50:31 +03:00
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
boost : : thread loading ( init ) ;
2010-12-22 22:14:40 +02:00
2011-03-20 00:27:05 +02:00
if ( ! vm . count ( " battle " ) & & ! vm . count ( " nointro " ) )
2010-12-22 22:14:40 +02:00
playIntro ( ) ;
2009-08-17 11:50:31 +03:00
SDL_FillRect ( screen , NULL , 0 ) ;
2011-04-05 20:38:24 +03:00
CSDL_Ext : : update ( screen ) ;
2009-08-17 11:50:31 +03:00
loading . join ( ) ;
2011-12-14 00:23:17 +03:00
tlog0 < < " Initialization of VCMI (together): " < < total . getDiff ( ) < < std : : endl ;
2009-08-17 11:50:31 +03:00
2010-12-22 22:14:40 +02:00
if ( ! vm . count ( " battle " ) )
{
2012-01-03 04:55:26 +03:00
gOnlyAI = vm . count ( " onlyAI " ) ;
2012-01-12 18:23:00 +03:00
Settings session = settings . write [ " session " ] ;
session [ " autoSkip " ] . Bool ( ) = vm . count ( " autoSkip " ) ;
session [ " oneGoodAI " ] . Bool ( ) = vm . count ( " oneGoodAI " ) ;
2012-01-03 04:55:26 +03:00
if ( ! vm . count ( " start " ) )
GH . curInt = new CGPreGame ; //will set CGP pointer to itself
else
startGameFromFile ( vm [ " start " ] . as < std : : string > ( ) ) ;
2010-12-22 22:14:40 +02:00
}
else
{
StartInfo * si = new StartInfo ( ) ;
si - > mode = StartInfo : : DUEL ;
2011-01-21 04:36:30 +02:00
si - > mapname = vm [ " battle " ] . as < std : : string > ( ) ;
2010-12-25 03:43:40 +02:00
si - > playerInfos [ 0 ] . color = 0 ;
si - > playerInfos [ 1 ] . color = 1 ;
2010-12-22 22:14:40 +02:00
startGame ( si ) ;
}
2009-12-28 06:08:24 +02:00
mainGUIThread = new boost : : thread ( & CGuiHandler : : run , boost : : ref ( GH ) ) ;
2009-08-17 11:50:31 +03:00
listenForEvents ( ) ;
2009-10-26 07:39:30 +02:00
return 0 ;
2007-06-07 20:45:56 +03:00
}
2008-09-17 13:18:22 +03:00
2010-10-24 14:35:14 +03:00
void printInfoAboutIntObject ( const CIntObject * obj , int level )
{
int tabs = level ;
while ( tabs - - ) tlog4 < < ' \t ' ;
2012-01-12 18:23:00 +03:00
tlog4 < < typeid ( * obj ) . name ( ) < < " *** " < < ( obj - > active ? " " : " not " ) < < " active " ;
tlog4 < < " at " < < obj - > pos . x < < " x " < < obj - > pos . y < < " \n " ;
2010-10-24 14:35:14 +03:00
BOOST_FOREACH ( const CIntObject * child , obj - > children )
printInfoAboutIntObject ( child , level + 1 ) ;
}
2009-08-17 11:50:31 +03:00
void processCommand ( const std : : string & message )
2008-09-17 13:18:22 +03:00
{
std : : istringstream readed ;
readed . str ( message ) ;
std : : string cn ; //command name
readed > > cn ;
2009-04-04 22:26:41 +03:00
if ( LOCPLINT & & LOCPLINT - > cingconsole )
LOCPLINT - > cingconsole - > print ( message ) ;
2011-06-11 02:50:32 +03:00
if ( ermInteractiveMode )
{
if ( cn = = " exit " )
{
ermInteractiveMode = false ;
return ;
}
else
{
if ( client & & client - > erm )
client - > erm - > executeUserCommand ( message ) ;
tlog0 < < " erm> " ;
}
}
2011-06-24 00:42:30 +03:00
else if ( message = = std : : string ( " die, fool " ) )
2011-06-11 02:50:32 +03:00
{
2008-12-21 21:17:35 +02:00
exit ( EXIT_SUCCESS ) ;
2011-06-11 02:50:32 +03:00
}
else if ( cn = = " erm " )
{
ermInteractiveMode = true ;
tlog0 < < " erm> " ;
}
2008-09-17 13:18:22 +03:00
else if ( cn = = std : : string ( " activate " ) )
{
int what ;
readed > > what ;
switch ( what )
{
case 0 :
2009-08-07 01:36:51 +03:00
GH . topInt ( ) - > activate ( ) ;
2008-09-17 13:18:22 +03:00
break ;
case 1 :
2010-02-20 15:24:38 +02:00
adventureInt - > activate ( ) ;
2008-09-17 13:18:22 +03:00
break ;
case 2 :
LOCPLINT - > castleInt - > activate ( ) ;
break ;
}
}
2009-08-22 16:59:15 +03:00
else if ( cn = = " redraw " )
{
GH . totalRedraw ( ) ;
}
2009-08-17 11:50:31 +03:00
else if ( cn = = " screen " )
{
tlog0 < < " Screenbuf points to " ;
if ( screenBuf = = screen )
tlog1 < < " screen " ;
else if ( screenBuf = = screen2 )
tlog1 < < " screen2 " ;
else
tlog1 < < " ?!? " ;
tlog1 < < std : : endl ;
SDL_SaveBMP ( screen , " Screen_c.bmp " ) ;
SDL_SaveBMP ( screen2 , " Screen2_c.bmp " ) ;
}
2008-11-16 03:06:15 +02:00
else if ( cn = = " save " )
{
std : : string fname ;
readed > > fname ;
client - > save ( fname ) ;
}
2009-08-17 11:50:31 +03:00
//else if(cn=="list")
//{
// if(CPG)
// for(int i = 0; i < CPG->ourScenSel->mapsel.ourGames.size(); i++)
// tlog0 << i << ".\t" << CPG->ourScenSel->mapsel.ourGames[i]->filename << std::endl;
//}
2009-01-11 00:08:18 +02:00
else if ( cn = = " load " )
{
2009-11-01 03:15:16 +02:00
// TODO: this code should end the running game and manage to call startGame instead
2009-01-11 00:08:18 +02:00
std : : string fname ;
readed > > fname ;
2009-11-01 03:15:16 +02:00
client - > loadGame ( fname ) ;
2009-01-11 00:08:18 +02:00
}
2009-08-17 11:50:31 +03:00
//else if(cn=="ln")
//{
// int num;
// readed >> num;
// std::string &name = CPG->ourScenSel->mapsel.ourGames[num]->filename;
// client->load(name.substr(0, name.size()-6));
//}
2009-08-27 11:04:32 +03:00
else if ( cn = = " resolution " | | cn = = " r " )
2009-02-01 22:31:41 +02:00
{
2009-08-01 22:25:12 +03:00
if ( LOCPLINT )
{
tlog1 < < " Resolution can be set only before starting the game. \n " ;
return ;
}
2009-02-01 22:31:41 +02:00
std : : map < std : : pair < int , int > , config : : GUIOptions > : : iterator j ;
2012-03-01 16:36:58 +03:00
int i = 1 ;
2009-02-01 22:31:41 +02:00
tlog4 < < " Available screen resolutions: \n " ;
for ( j = conf . guiOptions . begin ( ) ; j ! = conf . guiOptions . end ( ) ; j + + )
tlog4 < < i + + < < " . " < < j - > first . first < < " x " < < j - > first . second < < std : : endl ;
tlog4 < < " Type number from 1 to " < < i - 1 < < " to set appropriate resolution or 0 to cancel. \n " ;
std : : cin > > i ;
2009-06-02 01:31:11 +03:00
if ( i < 0 | | i > conf . guiOptions . size ( ) | | std : : cin . bad ( ) | | std : : cin . fail ( ) )
2009-02-09 18:18:48 +02:00
{
2009-06-02 01:31:11 +03:00
std : : cin . clear ( ) ;
2009-02-09 18:18:48 +02:00
tlog1 < < " Invalid resolution ID! Not a number between 0 and " < < conf . guiOptions . size ( ) < < " . No settings changed. \n " ;
}
2009-06-02 01:31:11 +03:00
else if ( ! i )
{
return ;
}
2009-02-01 22:31:41 +02:00
else
{
2012-03-01 16:36:58 +03:00
auto j = conf . guiOptions . begin ( ) ;
std : : advance ( j , i - 1 ) ; //move j to the i-th resolution info
const int w = j - > first . first , h = j - > first . second ;
2012-01-12 18:23:00 +03:00
Settings res = settings . write [ " video " ] [ " gameRes " ] ;
Settings screen = settings . write [ " video " ] [ " screenRes " ] ;
2012-03-01 16:36:58 +03:00
res [ " width " ] . Float ( ) = screen [ " width " ] . Float ( ) = w ;
res [ " height " ] . Float ( ) = screen [ " height " ] . Float ( ) = h ;
2012-01-12 18:23:00 +03:00
conf . SetResolution ( screen [ " width " ] . Float ( ) , screen [ " height " ] . Float ( ) ) ;
tlog0 < < " Screen resolution set to " < < ( int ) screen [ " width " ] . Float ( ) < < " x "
< < ( int ) screen [ " height " ] . Float ( ) < < " . It will be applied when the game starts. \n " ;
2009-02-01 22:31:41 +02:00
}
}
2008-09-17 13:18:22 +03:00
else if ( message = = " get txt " )
{
boost : : filesystem : : create_directory ( " Extracted_txts " ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " Command accepted. Opening .lod file... \t " ;
2008-09-17 13:18:22 +03:00
CLodHandler * txth = new CLodHandler ;
2011-12-14 00:23:17 +03:00
txth - > init ( GameConstants : : DATA_DIR + " /Data/H3bitmap.lod " , " " ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " done. \n Scanning .lod file \n " ;
2012-01-12 18:23:00 +03:00
2010-11-09 13:27:58 +02:00
BOOST_FOREACH ( Entry e , txth - > entries )
if ( e . type = = FILE_TEXT )
2011-11-01 15:58:01 +03:00
txth - > extractFile ( std : : string ( GVCMIDirs . UserPath + " /Extracted_txts/ " ) + e . name , e . name , FILE_TEXT ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " \r Extracting done :) \n " ;
2008-09-17 13:18:22 +03:00
}
2009-07-31 23:10:22 +03:00
else if ( cn = = " crash " )
{
int * ptr = NULL ;
* ptr = 666 ;
//disaster!
}
2009-08-08 02:17:12 +03:00
else if ( cn = = " onlyai " )
{
gOnlyAI = true ;
}
2010-11-28 18:39:13 +02:00
else if ( cn = = " ai " )
{
VLC - > IS_AI_ENABLED = ! VLC - > IS_AI_ENABLED ;
tlog4 < < " Current AI status: " < < ( VLC - > IS_AI_ENABLED ? " enabled " : " disabled " ) < < std : : endl ;
}
2010-05-31 23:38:14 +03:00
else if ( cn = = " mp " & & adventureInt )
{
if ( const CGHeroInstance * h = dynamic_cast < const CGHeroInstance * > ( adventureInt - > selection ) )
tlog0 < < h - > movement < < " ; max: " < < h - > maxMovePoints ( true ) < < " / " < < h - > maxMovePoints ( false ) < < std : : endl ;
}
2010-07-12 13:20:25 +03:00
else if ( cn = = " bonuses " )
{
tlog0 < < " Bonuses of " < < adventureInt - > selection - > getHoverText ( ) < < std : : endl
2011-07-13 21:39:02 +03:00
< < adventureInt - > selection - > getBonusList ( ) < < std : : endl ;
2010-07-12 13:20:25 +03:00
tlog0 < < " \n Inherited bonuses: \n " ;
TCNodes parents ;
adventureInt - > selection - > getParents ( parents ) ;
BOOST_FOREACH ( const CBonusSystemNode * parent , parents )
{
2011-07-13 21:39:02 +03:00
tlog0 < < " \n Bonuses from " < < typeid ( * parent ) . name ( ) < < std : : endl < < parent - > getBonusList ( ) < < std : : endl ;
2010-07-12 13:20:25 +03:00
}
}
2010-07-24 14:46:04 +03:00
else if ( cn = = " not dialog " )
{
LOCPLINT - > showingDialog - > setn ( false ) ;
}
2010-10-24 14:35:14 +03:00
else if ( cn = = " gui " )
{
2011-12-17 21:59:59 +03:00
BOOST_FOREACH ( const IShowActivatable * child , GH . listInt )
2010-10-24 14:35:14 +03:00
{
if ( const CIntObject * obj = dynamic_cast < const CIntObject * > ( child ) )
printInfoAboutIntObject ( obj , 0 ) ;
else
tlog4 < < typeid ( * obj ) . name ( ) < < std : : endl ;
}
}
2011-01-15 04:17:56 +02:00
else if ( cn = = " tell " )
{
std : : string what ;
int id1 , id2 ;
readed > > what > > id1 > > id2 ;
if ( what = = " hs " )
{
BOOST_FOREACH ( const CGHeroInstance * h , LOCPLINT - > cb - > getHeroesInfo ( ) )
if ( h - > type - > ID = = id1 )
if ( const CArtifactInstance * a = h - > getArt ( id2 ) )
tlog4 < < a - > nodeName ( ) ;
}
2011-03-22 15:19:07 +02:00
else if ( what = = " anim " )
{
CAnimation : : getAnimInfo ( ) ;
}
2011-01-15 04:17:56 +02:00
}
2011-05-25 16:11:03 +03:00
else if ( cn = = " switchCreWin " )
{
2012-01-12 18:23:00 +03:00
Settings window = settings . write [ " general " ] [ " classicCreatureWindow " ] ;
window - > Bool ( ) = ! window - > Bool ( ) ;
2011-05-25 16:11:03 +03:00
}
2012-01-03 04:55:26 +03:00
else if ( cn = = " sinfo " )
{
std : : string fname ;
readed > > fname ;
if ( fname . size ( ) & & SEL )
{
CSaveFile out ( fname ) ;
out < < SEL - > sInfo ;
}
}
else if ( cn = = " start " )
{
std : : string fname ;
readed > > fname ;
startGameFromFile ( fname ) ;
}
2012-02-20 00:03:43 +03:00
else if ( cn = = " unlock " )
{
std : : string mxname ;
readed > > mxname ;
if ( mxname = = " pim " & & LOCPLINT )
LOCPLINT - > pim - > unlock ( ) ;
}
2012-02-17 00:46:28 +03:00
else if ( client & & client - > serv & & client - > serv - > connected & & LOCPLINT ) //send to server
2008-10-19 02:20:48 +03:00
{
2012-02-17 00:46:28 +03:00
boost : : unique_lock < boost : : recursive_mutex > un ( * LOCPLINT - > pim ) ;
LOCPLINT - > cb - > sendMessage ( message ) ;
2008-10-19 02:20:48 +03:00
}
2009-04-14 15:47:09 +03:00
}
2009-06-24 09:56:36 +03:00
//plays intro, ends when intro is over or button has been pressed (handles events)
void playIntro ( )
{
2010-12-19 16:39:56 +02:00
if ( CCS - > videoh - > openAndPlayVideo ( " 3DOLOGO.SMK " , 60 , 40 , screen , true ) )
2009-06-24 09:56:36 +03:00
{
2010-12-19 16:39:56 +02:00
CCS - > videoh - > openAndPlayVideo ( " AZVS.SMK " , 60 , 80 , screen , true ) ;
2009-06-24 09:56:36 +03:00
}
}
2009-06-23 11:14:49 +03:00
void dispose ( )
{
2009-10-26 07:39:30 +02:00
if ( console )
delete console ;
2011-01-08 21:38:42 +02:00
delete logfile ;
2009-06-23 11:14:49 +03:00
}
2012-02-24 23:41:14 +03:00
static void setScreenRes ( int w , int h , int bpp , bool fullscreen , bool resetVideo )
2012-01-12 18:23:00 +03:00
{
2010-08-05 14:02:18 +03:00
// VCMI will only work with 2, 3 or 4 bytes per pixel
2011-12-14 00:23:17 +03:00
vstd : : amax ( bpp , 16 ) ;
vstd : : amin ( bpp , 32 ) ;
2009-05-17 07:14:30 +03:00
// Try to use the best screen depth for the display
2009-07-16 02:58:47 +03:00
int suggestedBpp = SDL_VideoModeOK ( w , h , bpp , SDL_SWSURFACE | ( fullscreen ? SDL_FULLSCREEN : 0 ) ) ;
if ( suggestedBpp = = 0 )
{
2009-08-11 19:05:33 +03:00
tlog1 < < " Error: SDL says that " < < w < < " x " < < h < < " resolution is not available! \n " ;
return ;
2009-07-16 02:58:47 +03:00
}
2009-08-22 16:59:15 +03:00
bool bufOnScreen = ( screenBuf = = screen ) ;
2009-08-11 19:05:33 +03:00
if ( suggestedBpp ! = bpp )
2009-07-16 02:58:47 +03:00
{
tlog2 < < " Warning: SDL says that " < < bpp < < " bpp is wrong and suggests " < < suggestedBpp < < std : : endl ;
}
2012-02-24 23:41:14 +03:00
//For some reason changing fullscreen via config window checkbox result in SDL_Quit event
if ( resetVideo )
{
if ( screen ) //screen has been already initialized
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
SDL_InitSubSystem ( SDL_INIT_VIDEO ) ;
}
2009-07-16 02:58:47 +03:00
if ( ( screen = SDL_SetVideoMode ( w , h , suggestedBpp , SDL_SWSURFACE | ( fullscreen ? SDL_FULLSCREEN : 0 ) ) ) = = NULL )
{
tlog1 < < " Requested screen resolution is not available ( " < < w < < " x " < < h < < " x " < < suggestedBpp < < " bpp) \n " ;
2009-05-17 07:14:30 +03:00
throw " Requested screen resolution is not available \n " ;
}
2009-08-22 16:59:15 +03:00
tlog0 < < " New screen flags: " < < screen - > flags < < std : : endl ;
2009-04-14 15:47:09 +03:00
if ( screen2 )
SDL_FreeSurface ( screen2 ) ;
screen2 = CSDL_Ext : : copySurface ( screen ) ;
SDL_EnableUNICODE ( 1 ) ;
SDL_WM_SetCaption ( NAME . c_str ( ) , " " ) ; //set window title
SDL_ShowCursor ( SDL_DISABLE ) ;
2010-02-20 15:24:38 +02:00
SDL_EnableKeyRepeat ( SDL_DEFAULT_REPEAT_DELAY , SDL_DEFAULT_REPEAT_INTERVAL ) ;
2009-08-22 16:59:15 +03:00
2009-11-28 19:21:54 +02:00
# ifdef _WIN32
SDL_SysWMinfo wm ;
SDL_VERSION ( & wm . version ) ;
int getwm = SDL_GetWMInfo ( & wm ) ;
if ( getwm = = 1 )
{
int sw = GetSystemMetrics ( SM_CXSCREEN ) ,
sh = GetSystemMetrics ( SM_CYSCREEN ) ;
RECT curpos ;
GetWindowRect ( wm . window , & curpos ) ;
int ourw = curpos . right - curpos . left ,
ourh = curpos . bottom - curpos . top ;
SetWindowPos ( wm . window , 0 , ( sw - ourw ) / 2 , ( sh - ourh ) / 2 , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE ) ;
}
else
{
tlog3 < < " Something went wrong, getwm= " < < getwm < < std : : endl ;
tlog3 < < " SDL says: " < < SDL_GetError ( ) < < std : : endl ;
tlog3 < < " Window won't be centered. \n " ;
}
# endif
//TODO: centering game window on other platforms (or does the environment do their job correctly there?)
2009-08-22 16:59:15 +03:00
screenBuf = bufOnScreen ? screen : screen2 ;
2010-07-14 04:08:27 +03:00
setResolution = true ;
2009-05-06 05:32:36 +03:00
}
2009-08-17 11:50:31 +03:00
2012-02-24 23:41:14 +03:00
static void fullScreenChanged ( const JsonNode & newState )
{
boost : : unique_lock < boost : : recursive_mutex > lock ( * LOCPLINT - > pim ) ;
const JsonNode & video = settings [ " video " ] ;
const JsonNode & res = video [ " screenRes " ] ;
setScreenRes ( res [ " width " ] . Float ( ) , res [ " height " ] . Float ( ) , video [ " bitsPerPixel " ] . Float ( ) , newState . Bool ( ) , false ) ;
GH . totalRedraw ( ) ;
}
2009-11-01 03:15:16 +02:00
static void listenForEvents ( )
2009-08-17 13:47:08 +03:00
{
2012-02-24 23:41:14 +03:00
SettingsListener resChanged = settings . listen [ " video " ] [ " fullscreen " ] ;
resChanged ( fullScreenChanged ) ;
2009-08-17 13:47:08 +03:00
while ( 1 ) //main SDL events loop
{
2009-11-01 03:15:16 +02:00
SDL_Event * ev = new SDL_Event ( ) ;
2009-08-17 13:47:08 +03:00
2009-08-22 16:59:15 +03:00
//tlog0 << "Waiting... ";
2009-08-17 13:47:08 +03:00
int ret = SDL_WaitEvent ( ev ) ;
2009-08-22 16:59:15 +03:00
//tlog0 << "got " << (int)ev->type;
2009-11-01 03:15:16 +02:00
if ( ret = = 0 | | ( ev - > type = = SDL_QUIT ) | |
( ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 & & ( ev - > key . keysym . mod & KMOD_ALT ) ) )
2009-08-17 13:47:08 +03:00
{
2009-10-26 07:39:30 +02:00
if ( client )
2010-08-20 16:34:39 +03:00
client - > endGame ( ) ;
2009-12-28 06:08:24 +02:00
if ( mainGUIThread )
{
GH . terminate = true ;
mainGUIThread - > join ( ) ;
delete mainGUIThread ;
mainGUIThread = NULL ;
2009-10-26 07:39:30 +02:00
}
delete console ;
console = NULL ;
2009-08-17 13:47:08 +03:00
SDL_Delay ( 750 ) ;
2009-10-26 07:39:30 +02:00
SDL_Quit ( ) ;
2009-08-17 13:47:08 +03:00
tlog0 < < " Ending... \n " ;
2009-10-26 07:39:30 +02:00
break ;
2009-08-17 13:47:08 +03:00
}
2009-08-22 16:59:15 +03:00
else if ( LOCPLINT & & ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 )
2009-08-17 13:47:08 +03:00
{
2012-02-24 23:41:14 +03:00
Settings full = settings . write [ " video " ] [ " fullscreen " ] ;
full - > Bool ( ) = ! full - > Bool ( ) ;
2009-11-01 03:15:16 +02:00
delete ev ;
continue ;
2009-08-17 13:47:08 +03:00
}
2010-08-20 16:34:39 +03:00
else if ( ev - > type = = SDL_USEREVENT )
2009-08-22 16:59:15 +03:00
{
2010-08-20 16:34:39 +03:00
switch ( ev - > user . code )
{
case 1 :
2012-01-12 18:23:00 +03:00
{
2010-08-20 16:34:39 +03:00
tlog0 < < " Changing resolution has been requested \n " ;
2012-01-12 18:23:00 +03:00
const JsonNode & video = settings [ " video " ] ;
const JsonNode & res = video [ " gameRes " ] ;
setScreenRes ( res [ " width " ] . Float ( ) , res [ " height " ] . Float ( ) , video [ " bitsPerPixel " ] . Float ( ) , video [ " fullscreen " ] . Bool ( ) ) ;
2010-08-20 16:34:39 +03:00
break ;
2012-01-12 18:23:00 +03:00
}
2010-08-20 16:34:39 +03:00
case 2 :
client - > endGame ( ) ;
delete client ;
client = NULL ;
2011-02-06 19:26:27 +02:00
delete CGI - > dobjinfo . get ( ) ;
2010-12-19 00:11:28 +02:00
const_cast < CGameInfo * > ( CGI ) - > dobjinfo = new CDefObjInfoHandler ;
2010-12-19 16:39:56 +02:00
const_cast < CGameInfo * > ( CGI ) - > dobjinfo - > load ( ) ;
2010-08-20 16:34:39 +03:00
GH . curInt = CGP ;
GH . defActionsDef = 63 ;
break ;
case 3 :
client - > endGame ( false ) ;
break ;
}
2010-01-29 22:52:45 +02:00
2009-11-01 03:15:16 +02:00
delete ev ;
continue ;
2010-08-26 18:33:55 +03:00
}
2009-11-01 03:15:16 +02:00
2009-08-22 16:59:15 +03:00
//tlog0 << " pushing ";
2012-02-20 00:03:43 +03:00
{
boost : : unique_lock < boost : : mutex > lock ( eventsM ) ;
events . push ( ev ) ;
}
2009-08-22 16:59:15 +03:00
//tlog0 << " done\n";
2009-08-17 13:47:08 +03:00
}
}
2012-01-12 18:23:00 +03:00
void startGame ( StartInfo * options , CConnection * serv /* = NULL*/ )
2009-08-17 13:47:08 +03:00
{
2009-12-28 06:08:24 +02:00
GH . curInt = NULL ;
2011-04-17 21:02:13 +03:00
SDL_FillRect ( screen , 0 , 0 ) ;
2009-08-17 13:47:08 +03:00
if ( gOnlyAI )
{
2012-01-12 18:23:00 +03:00
for ( std : : map < int , PlayerSettings > : : iterator it = options - > playerInfos . begin ( ) ;
2010-08-03 14:36:52 +03:00
it ! = options - > playerInfos . end ( ) ; + + it )
2009-08-17 13:47:08 +03:00
{
2010-08-03 14:36:52 +03:00
it - > second . human = false ;
2009-08-17 13:47:08 +03:00
}
}
2012-01-12 18:23:00 +03:00
const JsonNode & res = settings [ " video " ] [ " screenRes " ] ;
2009-08-17 13:47:08 +03:00
2012-01-12 18:23:00 +03:00
if ( screen - > w ! = res [ " width " ] . Float ( ) | | screen - > h ! = res [ " height " ] . Float ( ) )
2009-08-17 13:47:08 +03:00
{
2010-07-14 04:08:27 +03:00
requestChangingResolution ( ) ;
//allow event handling thread change resolution
2012-02-20 00:03:43 +03:00
auto unlock = vstd : : makeUnlockGuard ( eventsM ) ;
2010-07-14 04:08:27 +03:00
while ( ! setResolution ) boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 50 ) ) ;
2009-08-17 13:47:08 +03:00
}
2010-04-02 05:07:40 +03:00
else
setResolution = true ;
2009-08-17 13:47:08 +03:00
2012-02-16 20:10:58 +03:00
client = new CClient ;
2010-07-14 04:08:27 +03:00
2010-08-01 17:46:19 +03:00
CPlayerInterface : : howManyPeople = 0 ;
2010-05-08 21:56:38 +03:00
switch ( options - > mode ) //new game
2009-08-17 13:47:08 +03:00
{
2010-08-18 12:50:25 +03:00
case StartInfo : : NEW_GAME :
case StartInfo : : CAMPAIGN :
2010-12-22 22:14:40 +02:00
case StartInfo : : DUEL :
2010-10-24 14:35:14 +03:00
client - > newGame ( serv , options ) ;
2010-05-08 21:56:38 +03:00
break ;
2010-08-18 12:50:25 +03:00
case StartInfo : : LOAD_GAME :
2009-08-17 13:47:08 +03:00
std : : string fname = options - > mapname ;
boost : : algorithm : : erase_last ( fname , " .vlgm1 " ) ;
2009-12-28 06:08:24 +02:00
client - > loadGame ( fname ) ;
2010-05-08 21:56:38 +03:00
break ;
2009-08-17 13:47:08 +03:00
}
2009-11-01 03:15:16 +02:00
2012-02-16 20:10:58 +03:00
client - > connectionHandler = new boost : : thread ( & CClient : : run , client ) ;
2009-10-04 05:02:45 +03:00
}
2010-07-14 04:08:27 +03:00
void requestChangingResolution ( )
{
//mark that we are going to change resolution
setResolution = false ;
//push special event to order event reading thread to change resolution
SDL_Event ev ;
ev . type = SDL_USEREVENT ;
ev . user . code = 1 ;
SDL_PushEvent ( & ev ) ;
2011-02-06 19:26:27 +02:00
}