2017-07-13 10:26:03 +02:00
/*
2023-02-01 16:42:03 +02:00
* CAdvMapInt . cpp , part of VCMI engine
2017-07-13 10:26:03 +02:00
*
* 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
*
*/
2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2023-02-01 20:42:06 +02:00
# include "CAdvMapInt.h"
# include "CAdvMapPanel.h"
# include "CAdventureOptions.h"
# include "CInGameConsole.h"
# include "mapHandler.h"
# include "../windows/CKingdomInterface.h"
# include "../windows/CSpellWindow.h"
# include "../windows/CTradeWindow.h"
# include "../windows/GUIClasses.h"
# include "../windows/InfoWindows.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CMusicHandler.h"
# include "../CPlayerInterface.h"
2018-01-05 19:21:07 +02:00
# include "../lobby/CSavingScreen.h"
2023-02-01 20:42:06 +02:00
# include "../render/CAnimation.h"
2023-01-05 19:34:37 +02:00
# include "../gui/CursorHandler.h"
2023-02-01 20:42:06 +02:00
# include "../render/IImage.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/TextControls.h"
# include "../widgets/Buttons.h"
2023-02-02 21:15:13 +02:00
# include "../CMT.h"
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
# include "../../lib/CConfigHandler.h"
# include "../../lib/CGeneralTextHandler.h"
2015-02-02 10:25:26 +02:00
# include "../../lib/spells/CSpellHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/mapObjects/CGHeroInstance.h"
2023-02-01 20:42:06 +02:00
# include "../../lib/mapObjects/CGTownInstance.h"
# include "../../lib/CPathfinder.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/mapping/CMap.h"
# include "../../lib/UnlockGuard.h"
2023-01-09 01:17:37 +02:00
# include "../../lib/TerrainHandler.h"
2008-12-21 21:17:35 +02:00
2023-01-30 19:55:32 +02:00
# include <SDL_surface.h>
2008-11-12 20:26:23 +02:00
# define ADVOPT (conf.go()->ac)
2009-07-30 15:49:45 +03:00
2018-07-25 00:36:48 +02:00
std : : shared_ptr < CAdvMapInt > adventureInt ;
2010-02-20 15:24:38 +02:00
2016-10-17 12:44:47 +02:00
static void setScrollingCursor ( ui8 direction )
{
if ( direction & CAdvMapInt : : RIGHT )
{
if ( direction & CAdvMapInt : : UP )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_NORTHEAST ) ;
2016-10-17 12:44:47 +02:00
else if ( direction & CAdvMapInt : : DOWN )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_SOUTHEAST ) ;
2016-10-17 12:44:47 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_EAST ) ;
2016-10-17 12:44:47 +02:00
}
else if ( direction & CAdvMapInt : : LEFT )
{
if ( direction & CAdvMapInt : : UP )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_NORTHWEST ) ;
2016-10-17 12:44:47 +02:00
else if ( direction & CAdvMapInt : : DOWN )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_SOUTHWEST ) ;
2016-10-17 12:44:47 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_WEST ) ;
2016-10-17 12:44:47 +02:00
}
else if ( direction & CAdvMapInt : : UP )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_NORTH ) ;
2016-10-17 12:44:47 +02:00
else if ( direction & CAdvMapInt : : DOWN )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCROLL_SOUTH ) ;
2016-10-17 12:44:47 +02:00
}
2009-01-12 22:05:56 +02:00
2012-06-13 16:04:06 +03:00
CAdvMapInt : : CAdvMapInt ( ) :
2015-01-13 21:57:41 +02:00
mode ( EAdvMapMode : : NORMAL ) ,
2016-08-17 08:49:43 +02:00
worldViewScale ( 0.0f ) , //actual init later in changeMode
2015-01-13 21:57:41 +02:00
minimap ( Rect ( ADVOPT . minimapX , ADVOPT . minimapY , ADVOPT . minimapW , ADVOPT . minimapH ) ) ,
2018-08-26 18:09:56 +02:00
statusbar ( CGStatusBar : : create ( ADVOPT . statusbarX , ADVOPT . statusbarY , ADVOPT . statusbarG ) ) ,
2015-01-19 22:48:52 +02:00
heroList ( ADVOPT . hlistSize , Point ( ADVOPT . hlistX , ADVOPT . hlistY ) , ADVOPT . hlistAU , ADVOPT . hlistAD ) ,
townList ( ADVOPT . tlistSize , Point ( ADVOPT . tlistX , ADVOPT . tlistY ) , ADVOPT . tlistAU , ADVOPT . tlistAD ) ,
2016-10-22 10:18:57 +02:00
infoBar ( Rect ( ADVOPT . infoboxX , ADVOPT . infoboxY , 192 , 192 ) ) , state ( NA ) ,
2018-04-07 13:34:11 +02:00
spellBeingCasted ( nullptr ) , position ( int3 ( 0 , 0 , 0 ) ) , selection ( nullptr ) ,
updateScreen ( false ) , anim ( 0 ) , animValHitCount ( 0 ) , heroAnim ( 0 ) , heroAnimValHitCount ( 0 ) ,
2017-08-10 18:39:27 +02:00
activeMapPanel ( nullptr ) , duringAITurn ( false ) , scrollingDir ( 0 ) , scrollingState ( false ) ,
2017-06-07 22:42:41 +02:00
swipeEnabled ( settings [ " general " ] [ " swipe " ] . Bool ( ) ) , swipeMovementRequested ( false ) ,
2017-05-25 19:57:20 +02:00
swipeTargetPosition ( int3 ( - 1 , - 1 , - 1 ) )
2007-08-06 07:03:34 +03:00
{
2009-08-18 11:22:56 +03:00
pos . x = pos . y = 0 ;
pos . w = screen - > w ;
pos . h = screen - > h ;
2019-12-26 20:10:39 +02:00
strongInterest = true ; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
2014-08-04 21:33:59 +03:00
townList . onSelect = std : : bind ( & CAdvMapInt : : selectionChanged , this ) ;
2023-01-30 18:25:47 +02:00
bg = IImage : : createFromFile ( ADVOPT . mainGraphic ) ;
2022-11-15 02:20:55 +02:00
if ( ! ADVOPT . worldViewGraphic . empty ( ) )
2016-10-02 22:05:53 +02:00
{
2023-01-30 18:25:47 +02:00
bgWorldView = IImage : : createFromFile ( ADVOPT . worldViewGraphic ) ;
2016-10-02 22:05:53 +02:00
}
else
{
bgWorldView = nullptr ;
2016-10-03 20:32:01 +02:00
logGlobal - > warn ( " ADVOPT.worldViewGraphic is empty => bitmap not loaded " ) ;
2016-10-02 22:05:53 +02:00
}
2015-01-13 21:57:41 +02:00
if ( ! bgWorldView )
{
logGlobal - > warn ( " bgWorldView not defined in resolution config; fallback to VWorld.bmp " ) ;
2023-01-30 18:25:47 +02:00
bgWorldView = IImage : : createFromFile ( " VWorld.bmp " ) ;
2015-01-13 21:57:41 +02:00
}
2016-10-18 04:46:07 +02:00
worldViewIcons = std : : make_shared < CAnimation > ( " VwSymbol " ) ; //todo: customize with ADVOPT
2018-04-07 13:34:11 +02:00
worldViewIcons - > preload ( ) ;
2016-10-18 04:46:07 +02:00
2018-04-07 13:34:11 +02:00
for ( int g = 0 ; g < ADVOPT . gemG . size ( ) ; + + g )
2010-08-04 14:18:13 +03:00
{
2018-04-07 13:34:11 +02:00
gems . push_back ( std : : make_shared < CAnimImage > ( ADVOPT . gemG [ g ] , 0 , 0 , ADVOPT . gemX [ g ] , ADVOPT . gemY [ g ] ) ) ;
2010-08-04 14:18:13 +03:00
}
2010-07-29 01:24:16 +03:00
2018-04-07 13:34:11 +02:00
auto makeButton = [ & ] ( int textID , std : : function < void ( ) > callback , config : : ButtonInfo info , int key ) - > std : : shared_ptr < CButton >
2014-08-03 14:16:19 +03:00
{
2018-04-07 13:34:11 +02:00
auto button = std : : make_shared < CButton > ( Point ( info . x , info . y ) , info . defName , CGI - > generaltexth - > zelp [ textID ] , callback , key , info . playerColoured ) ;
for ( auto image : info . additionalDefs )
2014-08-03 14:16:19 +03:00
button - > addImage ( image ) ;
return button ;
} ;
2014-08-09 15:14:31 +03:00
kingOverview = makeButton ( 293 , std : : bind ( & CAdvMapInt : : fshowOverview , this ) , ADVOPT . kingOverview , SDLK_k ) ;
underground = makeButton ( 294 , std : : bind ( & CAdvMapInt : : fswitchLevel , this ) , ADVOPT . underground , SDLK_u ) ;
questlog = makeButton ( 295 , std : : bind ( & CAdvMapInt : : fshowQuestlog , this ) , ADVOPT . questlog , SDLK_q ) ;
sleepWake = makeButton ( 296 , std : : bind ( & CAdvMapInt : : fsleepWake , this ) , ADVOPT . sleepWake , SDLK_w ) ;
moveHero = makeButton ( 297 , std : : bind ( & CAdvMapInt : : fmoveHero , this ) , ADVOPT . moveHero , SDLK_m ) ;
spellbook = makeButton ( 298 , std : : bind ( & CAdvMapInt : : fshowSpellbok , this ) , ADVOPT . spellbook , SDLK_c ) ;
advOptions = makeButton ( 299 , std : : bind ( & CAdvMapInt : : fadventureOPtions , this ) , ADVOPT . advOptions , SDLK_a ) ;
sysOptions = makeButton ( 300 , std : : bind ( & CAdvMapInt : : fsystemOptions , this ) , ADVOPT . sysOptions , SDLK_o ) ;
nextHero = makeButton ( 301 , std : : bind ( & CAdvMapInt : : fnextHero , this ) , ADVOPT . nextHero , SDLK_h ) ;
endTurn = makeButton ( 302 , std : : bind ( & CAdvMapInt : : fendTurn , this ) , ADVOPT . endTurn , SDLK_e ) ;
2010-07-29 01:24:16 +03:00
2015-01-29 19:39:46 +02:00
int panelSpaceBottom = screen - > h - resdatabar . pos . h - 4 ;
2015-10-31 19:23:13 +02:00
2018-04-07 13:34:11 +02:00
panelMain = std : : make_shared < CAdvMapPanel > ( nullptr , Point ( 0 , 0 ) ) ;
2015-01-29 19:39:46 +02:00
// TODO correct drawing position
2018-04-07 13:34:11 +02:00
panelWorldView = std : : make_shared < CAdvMapWorldViewPanel > ( worldViewIcons , bgWorldView , Point ( heroList . pos . x - 2 , 195 ) , panelSpaceBottom , LOCPLINT - > playerID ) ;
2015-01-15 01:22:20 +02:00
panelMain - > addChildColorableButton ( kingOverview ) ;
panelMain - > addChildColorableButton ( underground ) ;
panelMain - > addChildColorableButton ( questlog ) ;
panelMain - > addChildColorableButton ( sleepWake ) ;
panelMain - > addChildColorableButton ( moveHero ) ;
panelMain - > addChildColorableButton ( spellbook ) ;
panelMain - > addChildColorableButton ( advOptions ) ;
panelMain - > addChildColorableButton ( sysOptions ) ;
panelMain - > addChildColorableButton ( nextHero ) ;
panelMain - > addChildColorableButton ( endTurn ) ;
2015-01-13 21:57:41 +02:00
// TODO move configs to resolutions.json, similarly to previous buttons
config : : ButtonInfo worldViewBackConfig = config : : ButtonInfo ( ) ;
worldViewBackConfig . defName = " IOK6432.DEF " ;
worldViewBackConfig . x = screen - > w - 73 ;
worldViewBackConfig . y = 343 + 195 ;
worldViewBackConfig . playerColoured = false ;
2015-01-15 01:22:20 +02:00
panelWorldView - > addChildToPanel (
makeButton ( 288 , std : : bind ( & CAdvMapInt : : fworldViewBack , this ) , worldViewBackConfig , SDLK_ESCAPE ) , ACTIVATE | DEACTIVATE ) ;
2015-01-13 21:57:41 +02:00
2015-01-19 21:46:03 +02:00
config : : ButtonInfo worldViewPuzzleConfig = config : : ButtonInfo ( ) ;
worldViewPuzzleConfig . defName = " VWPUZ.DEF " ;
worldViewPuzzleConfig . x = screen - > w - 188 ;
worldViewPuzzleConfig . y = 343 + 195 ;
worldViewPuzzleConfig . playerColoured = false ;
panelWorldView - > addChildToPanel ( // no help text for this one
2018-04-07 13:34:11 +02:00
std : : make_shared < CButton > ( Point ( worldViewPuzzleConfig . x , worldViewPuzzleConfig . y ) , worldViewPuzzleConfig . defName , std : : pair < std : : string , std : : string > ( ) ,
2015-01-19 21:46:03 +02:00
std : : bind ( & CPlayerInterface : : showPuzzleMap , LOCPLINT ) , SDLK_p , worldViewPuzzleConfig . playerColoured ) , ACTIVATE | DEACTIVATE ) ;
2015-01-13 21:57:41 +02:00
config : : ButtonInfo worldViewScale1xConfig = config : : ButtonInfo ( ) ;
worldViewScale1xConfig . defName = " VWMAG1.DEF " ;
worldViewScale1xConfig . x = screen - > w - 191 ;
worldViewScale1xConfig . y = 23 + 195 ;
worldViewScale1xConfig . playerColoured = false ;
2015-01-19 21:46:03 +02:00
panelWorldView - > addChildToPanel ( // help text is wrong for this button
2015-01-17 14:41:59 +02:00
makeButton ( 291 , std : : bind ( & CAdvMapInt : : fworldViewScale1x , this ) , worldViewScale1xConfig , SDLK_1 ) , ACTIVATE | DEACTIVATE ) ;
2015-01-13 21:57:41 +02:00
config : : ButtonInfo worldViewScale2xConfig = config : : ButtonInfo ( ) ;
worldViewScale2xConfig . defName = " VWMAG2.DEF " ;
worldViewScale2xConfig . x = screen - > w - 191 + 63 ;
worldViewScale2xConfig . y = 23 + 195 ;
worldViewScale2xConfig . playerColoured = false ;
2015-01-19 21:46:03 +02:00
panelWorldView - > addChildToPanel ( // help text is wrong for this button
2015-01-17 14:41:59 +02:00
makeButton ( 291 , std : : bind ( & CAdvMapInt : : fworldViewScale2x , this ) , worldViewScale2xConfig , SDLK_2 ) , ACTIVATE | DEACTIVATE ) ;
2015-01-13 21:57:41 +02:00
config : : ButtonInfo worldViewScale4xConfig = config : : ButtonInfo ( ) ;
worldViewScale4xConfig . defName = " VWMAG4.DEF " ;
worldViewScale4xConfig . x = screen - > w - 191 + 126 ;
worldViewScale4xConfig . y = 23 + 195 ;
worldViewScale4xConfig . playerColoured = false ;
2015-01-19 21:46:03 +02:00
panelWorldView - > addChildToPanel ( // help text is wrong for this button
2015-01-17 14:41:59 +02:00
makeButton ( 291 , std : : bind ( & CAdvMapInt : : fworldViewScale4x , this ) , worldViewScale4xConfig , SDLK_4 ) , ACTIVATE | DEACTIVATE ) ;
2015-01-13 21:57:41 +02:00
config : : ButtonInfo worldViewUndergroundConfig = config : : ButtonInfo ( ) ;
worldViewUndergroundConfig . defName = " IAM010.DEF " ;
worldViewUndergroundConfig . additionalDefs . push_back ( " IAM003.DEF " ) ;
worldViewUndergroundConfig . x = screen - > w - 115 ;
worldViewUndergroundConfig . y = 343 + 195 ;
worldViewUndergroundConfig . playerColoured = true ;
2015-01-17 12:56:12 +02:00
worldViewUnderground = makeButton ( 294 , std : : bind ( & CAdvMapInt : : fswitchLevel , this ) , worldViewUndergroundConfig , SDLK_u ) ;
2015-01-15 01:22:20 +02:00
panelWorldView - > addChildColorableButton ( worldViewUnderground ) ;
2015-01-13 21:57:41 +02:00
2010-07-29 01:24:16 +03:00
setPlayer ( LOCPLINT - > playerID ) ;
2015-01-13 21:57:41 +02:00
int iconColorMultiplier = player . getNum ( ) * 19 ;
2015-01-15 01:22:20 +02:00
int wvLeft = heroList . pos . x - 2 ; // TODO correct drawing position
2016-10-18 04:46:07 +02:00
//int wvTop = 195;
2015-01-13 21:57:41 +02:00
for ( int i = 0 ; i < 5 ; + + i )
{
2016-10-18 04:46:07 +02:00
panelWorldView - > addChildIcon ( std : : pair < int , Point > ( i , Point ( 5 , 58 + i * 20 ) ) , iconColorMultiplier ) ;
2022-11-26 23:12:20 +02:00
panelWorldView - > addChildToPanel ( std : : make_shared < CLabel > ( wvLeft + 45 , 263 + i * 20 , EFonts : : FONT_SMALL , ETextAlignment : : TOPLEFT ,
2015-01-13 21:57:41 +02:00
Colors : : WHITE , CGI - > generaltexth - > allTexts [ 612 + i ] ) ) ;
}
for ( int i = 0 ; i < 7 ; + + i )
{
2016-10-18 04:46:07 +02:00
panelWorldView - > addChildIcon ( std : : pair < int , Point > ( i + 5 , Point ( 5 , 182 + i * 20 ) ) , iconColorMultiplier ) ;
panelWorldView - > addChildIcon ( std : : pair < int , Point > ( i + 12 , Point ( 160 , 182 + i * 20 ) ) , iconColorMultiplier ) ;
2022-11-26 23:12:20 +02:00
panelWorldView - > addChildToPanel ( std : : make_shared < CLabel > ( wvLeft + 45 , 387 + i * 20 , EFonts : : FONT_SMALL , ETextAlignment : : TOPLEFT ,
2015-01-13 21:57:41 +02:00
Colors : : WHITE , CGI - > generaltexth - > allTexts [ 619 + i ] ) ) ;
}
2022-11-26 23:12:20 +02:00
panelWorldView - > addChildToPanel ( std : : make_shared < CLabel > ( wvLeft + 5 , 367 , EFonts : : FONT_SMALL , ETextAlignment : : TOPLEFT ,
2015-01-13 21:57:41 +02:00
Colors : : WHITE , CGI - > generaltexth - > allTexts [ 617 ] ) ) ;
2022-11-26 23:12:20 +02:00
panelWorldView - > addChildToPanel ( std : : make_shared < CLabel > ( wvLeft + 45 , 367 , EFonts : : FONT_SMALL , ETextAlignment : : TOPLEFT ,
2015-01-13 21:57:41 +02:00
Colors : : WHITE , CGI - > generaltexth - > allTexts [ 618 ] ) ) ;
2015-01-15 01:22:20 +02:00
activeMapPanel = panelMain ;
2015-10-31 19:23:13 +02:00
2015-01-19 22:48:52 +02:00
changeMode ( EAdvMapMode : : NORMAL ) ;
2015-01-13 21:57:41 +02:00
2014-08-03 14:16:19 +03:00
underground - > block ( ! CGI - > mh - > map - > twoLevel ) ;
2015-02-13 23:52:00 +02:00
questlog - > block ( ! CGI - > mh - > map - > quests . size ( ) ) ;
2015-01-13 21:57:41 +02:00
worldViewUnderground - > block ( ! CGI - > mh - > map - > twoLevel ) ;
2015-02-16 22:45:16 +02:00
addUsedEvents ( MOVE ) ;
2007-08-06 07:03:34 +03:00
}
void CAdvMapInt : : fshowOverview ( )
{
2018-07-25 00:36:48 +02:00
GH . pushIntT < CKingdomInterface > ( ) ;
2007-08-06 07:03:34 +03:00
}
2015-01-13 21:57:41 +02:00
void CAdvMapInt : : fworldViewBack ( )
{
changeMode ( EAdvMapMode : : NORMAL ) ;
CGI - > mh - > discardWorldViewCache ( ) ;
2015-01-17 14:41:59 +02:00
auto hero = curHero ( ) ;
if ( hero )
centerOn ( hero ) ;
2015-01-13 21:57:41 +02:00
}
void CAdvMapInt : : fworldViewScale1x ( )
{
// TODO set corresponding scale button to "selected" mode
2015-01-17 12:56:12 +02:00
changeMode ( EAdvMapMode : : WORLD_VIEW , 0.22f ) ;
2015-01-13 21:57:41 +02:00
}
void CAdvMapInt : : fworldViewScale2x ( )
{
2015-01-17 12:56:12 +02:00
changeMode ( EAdvMapMode : : WORLD_VIEW , 0.36f ) ;
2015-01-13 21:57:41 +02:00
}
void CAdvMapInt : : fworldViewScale4x ( )
{
2015-01-17 12:56:12 +02:00
changeMode ( EAdvMapMode : : WORLD_VIEW , 0.5f ) ;
2015-01-13 21:57:41 +02:00
}
2015-01-17 12:56:12 +02:00
void CAdvMapInt : : fswitchLevel ( )
2015-01-13 21:57:41 +02:00
{
2015-01-17 12:56:12 +02:00
// with support for future multi-level maps :)
2022-09-18 16:39:10 +02:00
int maxLevels = CGI - > mh - > map - > levels ( ) ;
2015-01-17 12:56:12 +02:00
if ( maxLevels < 2 )
2015-01-13 21:57:41 +02:00
return ;
2015-01-17 12:56:12 +02:00
position . z = ( position . z + 1 ) % maxLevels ;
underground - > setIndex ( position . z , true ) ;
underground - > redraw ( ) ;
worldViewUnderground - > setIndex ( position . z , true ) ;
worldViewUnderground - > redraw ( ) ;
2015-01-13 21:57:41 +02:00
2007-08-06 07:03:34 +03:00
updateScreen = true ;
2012-06-13 16:04:06 +03:00
minimap . setLevel ( position . z ) ;
2015-01-17 12:56:12 +02:00
if ( mode = = EAdvMapMode : : WORLD_VIEW )
terrain . redraw ( ) ;
2007-08-06 07:03:34 +03:00
}
void CAdvMapInt : : fshowQuestlog ( )
{
2012-07-06 22:12:04 +03:00
LOCPLINT - > showQuestLog ( ) ;
2007-08-06 07:03:34 +03:00
}
void CAdvMapInt : : fsleepWake ( )
{
2011-09-24 19:46:23 +03:00
const CGHeroInstance * h = curHero ( ) ;
if ( ! h )
return ;
bool newSleep = ! isHeroSleeping ( h ) ;
setHeroSleeping ( h , newSleep ) ;
updateSleepWake ( h ) ;
if ( newSleep )
2011-10-04 22:43:49 +03:00
{
2011-09-24 19:46:23 +03:00
fnextHero ( ) ;
2011-10-04 22:43:49 +03:00
2012-01-12 18:23:00 +03:00
//moveHero.block(true);
2011-10-04 22:43:49 +03:00
//uncomment to enable original HoMM3 behaviour:
//move button is disabled for hero going to sleep, even though it's enabled when you reselect him
}
2007-08-06 07:03:34 +03:00
}
2011-09-24 19:46:23 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fmoveHero ( )
2012-01-12 18:23:00 +03:00
{
2010-03-21 00:17:19 +02:00
const CGHeroInstance * h = curHero ( ) ;
2015-02-09 17:03:24 +02:00
if ( ! h | | ! terrain . currentPath | | ! CGI - > mh - > canStartHeroMovement ( ) )
2007-10-14 00:27:03 +03:00
return ;
2009-04-21 01:57:07 +03:00
2010-03-21 00:17:19 +02:00
LOCPLINT - > moveHero ( h , * terrain . currentPath ) ;
2007-08-06 07:03:34 +03:00
}
2009-06-11 20:21:06 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fshowSpellbok ( )
{
2010-03-21 00:17:19 +02:00
if ( ! curHero ( ) ) //checking necessary values
2008-09-10 15:19:48 +03:00
return ;
2010-03-21 00:17:19 +02:00
centerOn ( selection ) ;
2012-01-12 18:23:00 +03:00
2018-07-25 00:36:48 +02:00
GH . pushIntT < CSpellWindow > ( curHero ( ) , LOCPLINT , false ) ;
2007-08-06 07:03:34 +03:00
}
2009-06-11 20:21:06 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fadventureOPtions ( )
{
2018-07-25 00:36:48 +02:00
GH . pushIntT < CAdventureOptions > ( ) ;
2007-08-06 07:03:34 +03:00
}
2009-06-11 20:21:06 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fsystemOptions ( )
{
2018-07-25 00:36:48 +02:00
GH . pushIntT < CSystemOptionsWindow > ( ) ;
2007-08-06 07:03:34 +03:00
}
2009-06-11 20:21:06 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fnextHero ( )
{
2012-06-13 16:04:06 +03:00
auto hero = dynamic_cast < const CGHeroInstance * > ( selection ) ;
int next = getNextHeroIndex ( vstd : : find_pos ( LOCPLINT - > wanderingHeroes , hero ) ) ;
2011-10-04 22:43:49 +03:00
if ( next < 0 )
return ;
2012-06-13 16:04:06 +03:00
select ( LOCPLINT - > wanderingHeroes [ next ] , true ) ;
2007-08-06 07:03:34 +03:00
}
2009-06-11 20:21:06 +03:00
2007-08-06 07:03:34 +03:00
void CAdvMapInt : : fendTurn ( )
{
2011-05-30 02:49:25 +03:00
if ( ! LOCPLINT - > makingTurn )
return ;
2011-09-24 19:46:23 +03:00
2018-02-24 15:49:42 +02:00
if ( settings [ " adventure " ] [ " heroReminder " ] . Bool ( ) )
2012-01-12 18:23:00 +03:00
{
2018-02-24 15:49:42 +02:00
for ( auto hero : LOCPLINT - > wanderingHeroes )
{
if ( ! isHeroSleeping ( hero ) & & hero - > movement > 0 )
2012-01-12 18:23:00 +03:00
{
2018-02-24 15:49:42 +02:00
// Only show hero reminder if conditions met:
// - There still movement points
// - Hero don't have a path or there not points for first step on path
auto path = LOCPLINT - > getAndVerifyPath ( hero ) ;
if ( ! path | | path - > nodes . size ( ) < 2 | | ! path - > nodes [ path - > nodes . size ( ) - 2 ] . turns )
{
2018-04-07 13:34:11 +02:00
LOCPLINT - > showYesNoDialog ( CGI - > generaltexth - > allTexts [ 55 ] , std : : bind ( & CAdvMapInt : : endingTurn , this ) , nullptr ) ;
2018-02-24 15:49:42 +02:00
return ;
}
2012-01-12 18:23:00 +03:00
}
2018-02-24 15:49:42 +02:00
}
2012-01-12 18:23:00 +03:00
}
2011-09-24 19:46:23 +03:00
endingTurn ( ) ;
}
void CAdvMapInt : : updateSleepWake ( const CGHeroInstance * h )
{
2014-08-03 14:16:19 +03:00
sleepWake - > block ( ! h ) ;
2011-09-24 19:46:23 +03:00
if ( ! h )
2012-01-12 18:23:00 +03:00
return ;
2011-09-24 19:46:23 +03:00
bool state = isHeroSleeping ( h ) ;
2014-08-03 14:16:19 +03:00
sleepWake - > setIndex ( state ? 1 : 0 , true ) ;
sleepWake - > assignedKeys . clear ( ) ;
sleepWake - > assignedKeys . insert ( state ? SDLK_w : SDLK_z ) ;
2007-08-06 07:03:34 +03:00
}
2011-10-04 22:43:49 +03:00
void CAdvMapInt : : updateMoveHero ( const CGHeroInstance * h , tribool hasPath )
{
2016-01-15 18:30:43 +02:00
if ( ! h )
2011-10-04 22:43:49 +03:00
{
2014-08-03 14:16:19 +03:00
moveHero - > block ( true ) ;
2011-10-04 22:43:49 +03:00
return ;
}
2016-01-15 18:30:43 +02:00
//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
if ( boost : : logic : : indeterminate ( hasPath ) )
hasPath = LOCPLINT - > paths [ h ] . nodes . size ( ) ? true : false ;
2019-01-24 16:45:40 +02:00
moveHero - > block ( ! ( bool ) hasPath | | ( h - > movement = = 0 ) ) ;
2011-10-04 22:43:49 +03:00
}
2015-12-06 02:12:39 +02:00
void CAdvMapInt : : updateSpellbook ( const CGHeroInstance * h )
{
spellbook - > block ( ! h ) ;
}
2011-10-04 22:43:49 +03:00
int CAdvMapInt : : getNextHeroIndex ( int startIndex )
{
if ( LOCPLINT - > wanderingHeroes . size ( ) = = 0 )
return - 1 ;
if ( startIndex < 0 )
startIndex = 0 ;
int i = startIndex ;
2012-01-12 18:23:00 +03:00
do
2011-10-04 22:43:49 +03:00
{
i + + ;
if ( i > = LOCPLINT - > wanderingHeroes . size ( ) )
i = 0 ;
2012-01-12 18:23:00 +03:00
}
2011-10-04 22:43:49 +03:00
while ( ( ( LOCPLINT - > wanderingHeroes [ i ] - > movement = = 0 ) | | isHeroSleeping ( LOCPLINT - > wanderingHeroes [ i ] ) ) & & ( i ! = startIndex ) ) ;
2011-11-27 21:55:11 +03:00
if ( ( LOCPLINT - > wanderingHeroes [ i ] - > movement ! = 0 ) & & ! isHeroSleeping ( LOCPLINT - > wanderingHeroes [ i ] ) )
2011-10-04 22:43:49 +03:00
return i ;
else
return - 1 ;
}
void CAdvMapInt : : updateNextHero ( const CGHeroInstance * h )
{
2012-06-13 16:04:06 +03:00
int start = vstd : : find_pos ( LOCPLINT - > wanderingHeroes , h ) ;
2011-10-04 22:43:49 +03:00
int next = getNextHeroIndex ( start ) ;
if ( next < 0 )
{
2014-08-03 14:16:19 +03:00
nextHero - > block ( true ) ;
2011-10-04 22:43:49 +03:00
return ;
}
const CGHeroInstance * nextH = LOCPLINT - > wanderingHeroes [ next ] ;
bool noActiveHeroes = ( next = = start ) & & ( ( nextH - > movement = = 0 ) | | isHeroSleeping ( nextH ) ) ;
2014-08-03 14:16:19 +03:00
nextHero - > block ( noActiveHeroes ) ;
2011-10-04 22:43:49 +03:00
}
2008-01-20 14:34:39 +02:00
void CAdvMapInt : : activate ( )
{
2012-06-02 18:16:54 +03:00
CIntObject : : activate ( ) ;
2012-06-17 01:40:28 +03:00
if ( ! ( active & KEYBOARD ) )
2012-10-06 23:35:04 +03:00
CIntObject : : activate ( KEYBOARD ) ;
2012-02-22 16:41:27 +03:00
2009-05-25 02:21:55 +03:00
screenBuf = screen ;
2018-08-26 18:09:56 +02:00
GH . statusbar = statusbar ;
2022-10-05 17:04:51 +02:00
if ( LOCPLINT )
2022-12-21 17:02:53 +02:00
{
2022-10-05 17:04:51 +02:00
LOCPLINT - > cingconsole - > activate ( ) ;
2022-12-21 17:02:53 +02:00
LOCPLINT - > cingconsole - > pos = this - > pos ;
}
2022-10-05 17:04:51 +02:00
2012-02-22 16:41:27 +03:00
if ( ! duringAITurn )
{
2015-01-15 01:22:20 +02:00
activeMapPanel - > activate ( ) ;
2015-01-13 21:57:41 +02:00
if ( mode = = EAdvMapMode : : NORMAL )
{
heroList . activate ( ) ;
townList . activate ( ) ;
infoBar . activate ( ) ;
}
2012-02-22 16:41:27 +03:00
minimap . activate ( ) ;
terrain . activate ( ) ;
2022-11-20 11:53:46 +02:00
statusbar - > activate ( ) ;
2012-02-22 16:41:27 +03:00
GH . fakeMouseMove ( ) ; //to restore the cursor
}
2008-01-20 14:34:39 +02:00
}
2015-01-13 21:57:41 +02:00
2008-01-20 14:34:39 +02:00
void CAdvMapInt : : deactivate ( )
{
2012-06-02 18:16:54 +03:00
CIntObject : : deactivate ( ) ;
2012-02-22 16:41:27 +03:00
if ( ! duringAITurn )
{
scrollingDir = 0 ;
2010-02-24 15:03:36 +02:00
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2015-01-15 01:22:20 +02:00
activeMapPanel - > deactivate ( ) ;
2015-01-13 21:57:41 +02:00
if ( mode = = EAdvMapMode : : NORMAL )
{
heroList . deactivate ( ) ;
townList . deactivate ( ) ;
infoBar . deactivate ( ) ;
}
2012-02-22 16:41:27 +03:00
minimap . deactivate ( ) ;
terrain . deactivate ( ) ;
2022-12-03 21:32:36 +02:00
statusbar - > deactivate ( ) ;
2012-02-22 16:41:27 +03:00
}
2008-01-20 14:34:39 +02:00
}
2015-01-13 21:57:41 +02:00
2011-12-22 16:05:19 +03:00
void CAdvMapInt : : showAll ( SDL_Surface * to )
2007-08-04 22:01:22 +03:00
{
2023-01-30 18:25:47 +02:00
bg - > draw ( to , 0 , 0 ) ;
2009-04-14 15:47:09 +03:00
2010-02-20 15:24:38 +02:00
if ( state ! = INGAME )
return ;
2015-01-13 21:57:41 +02:00
switch ( mode )
{
case EAdvMapMode : : NORMAL :
heroList . showAll ( to ) ;
townList . showAll ( to ) ;
infoBar . showAll ( to ) ;
break ;
case EAdvMapMode : : WORLD_VIEW :
terrain . showAll ( to ) ;
break ;
}
2015-01-15 01:22:20 +02:00
activeMapPanel - > showAll ( to ) ;
2009-04-14 15:47:09 +03:00
2008-08-28 20:36:34 +03:00
updateScreen = true ;
2015-01-13 21:57:41 +02:00
minimap . showAll ( to ) ;
2009-04-14 15:47:09 +03:00
show ( to ) ;
2007-08-20 00:12:55 +03:00
2015-01-13 21:57:41 +02:00
2018-04-07 13:34:11 +02:00
resdatabar . showAll ( to ) ;
2007-09-16 20:21:23 +03:00
2018-08-26 18:09:56 +02:00
statusbar - > show ( to ) ;
2007-08-07 14:54:50 +03:00
2015-11-08 21:16:58 +02:00
LOCPLINT - > cingconsole - > show ( to ) ;
2007-08-04 22:01:22 +03:00
}
2011-09-24 19:46:23 +03:00
bool CAdvMapInt : : isHeroSleeping ( const CGHeroInstance * hero )
{
if ( ! hero )
return false ;
return vstd : : contains ( LOCPLINT - > sleepingHeroes , hero ) ;
}
void CAdvMapInt : : setHeroSleeping ( const CGHeroInstance * hero , bool sleep )
{
if ( sleep )
2014-10-03 23:34:13 +03:00
LOCPLINT - > sleepingHeroes . push_back ( hero ) ; //FIXME: should we check for existence?
2011-09-24 19:46:23 +03:00
else
LOCPLINT - > sleepingHeroes - = hero ;
2013-06-26 14:18:27 +03:00
updateNextHero ( nullptr ) ;
2011-09-24 19:46:23 +03:00
}
2011-12-22 16:05:19 +03:00
void CAdvMapInt : : show ( SDL_Surface * to )
2007-08-04 22:01:22 +03:00
{
2010-02-20 15:24:38 +02:00
if ( state ! = INGAME )
return ;
2008-08-28 20:36:34 +03:00
+ + animValHitCount ; //for animations
2019-05-26 17:11:57 +02:00
if ( animValHitCount % 2 = = 0 )
{
+ + heroAnim ;
}
2023-01-08 18:05:00 +02:00
if ( animValHitCount > = 8 )
2008-08-28 20:36:34 +03:00
{
2008-11-30 16:08:07 +02:00
CGI - > mh - > updateWater ( ) ;
2008-08-28 20:36:34 +03:00
animValHitCount = 0 ;
+ + anim ;
updateScreen = true ;
}
2009-02-11 19:03:30 +02:00
2017-05-25 19:57:20 +02:00
if ( swipeEnabled )
2008-08-28 20:36:34 +03:00
{
2017-05-25 19:57:20 +02:00
handleSwipeUpdate ( ) ;
}
2021-03-13 13:08:13 +02:00
# if defined(VCMI_ANDROID) || defined(VCMI_IOS) // on mobile, map-moving mode is exclusive (TODO technically it might work with both enabled; to be checked)
2017-05-25 19:57:20 +02:00
else
2021-03-13 13:08:13 +02:00
# endif
2017-05-25 19:57:20 +02:00
{
handleMapScrollingUpdate ( ) ;
2008-08-28 20:36:34 +03:00
}
2017-05-25 19:57:20 +02:00
2016-10-18 03:09:52 +02:00
for ( int i = 0 ; i < 4 ; i + + )
2017-06-03 07:25:10 +02:00
{
if ( settings [ " session " ] [ " spectate " ] . Bool ( ) )
gems [ i ] - > setFrame ( PlayerColor ( 1 ) . getNum ( ) ) ;
else
gems [ i ] - > setFrame ( LOCPLINT - > playerID . getNum ( ) ) ;
}
2008-08-28 20:36:34 +03:00
if ( updateScreen )
2008-11-30 16:08:07 +02:00
{
2013-12-20 18:00:48 +03:00
int3 betterPos = LOCPLINT - > repairScreenPos ( position ) ;
if ( betterPos ! = position )
{
2017-08-10 18:39:27 +02:00
logGlobal - > warn ( " Incorrect position for adventure map! " ) ;
2013-12-20 18:00:48 +03:00
position = betterPos ;
}
2009-04-14 15:47:09 +03:00
terrain . show ( to ) ;
2016-10-18 03:09:52 +02:00
for ( int i = 0 ; i < 4 ; i + + )
gems [ i ] - > showAll ( to ) ;
2012-01-12 18:23:00 +03:00
updateScreen = false ;
2015-11-08 21:16:58 +02:00
LOCPLINT - > cingconsole - > show ( to ) ;
2008-08-28 20:36:34 +03:00
}
2015-01-31 00:37:28 +02:00
else if ( terrain . needsAnimUpdate ( ) )
{
terrain . showAnim ( to ) ;
2016-10-18 03:09:52 +02:00
for ( int i = 0 ; i < 4 ; i + + )
gems [ i ] - > showAll ( to ) ;
2015-01-31 00:37:28 +02:00
}
2015-10-31 19:23:13 +02:00
2012-06-13 16:04:06 +03:00
infoBar . show ( to ) ;
2018-08-26 18:09:56 +02:00
statusbar - > showAll ( to ) ;
2007-09-14 16:11:10 +03:00
}
2017-05-25 19:57:20 +02:00
void CAdvMapInt : : handleMapScrollingUpdate ( )
{
2020-10-01 10:38:06 +02:00
int scrollSpeed = static_cast < int > ( settings [ " adventure " ] [ " scrollSpeed " ] . Float ( ) ) ;
2017-05-25 19:57:20 +02:00
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if ( ( animValHitCount % ( 4 / scrollSpeed ) ) = = 0
2023-02-02 18:02:25 +02:00
& & GH . isKeyboardCtrlDown ( ) )
2017-05-25 19:57:20 +02:00
{
if ( ( scrollingDir & LEFT ) & & ( position . x > - CGI - > mh - > frameW ) )
position . x - - ;
if ( ( scrollingDir & RIGHT ) & & ( position . x < CGI - > mh - > map - > width - CGI - > mh - > tilesW + CGI - > mh - > frameW ) )
position . x + + ;
if ( ( scrollingDir & UP ) & & ( position . y > - CGI - > mh - > frameH ) )
position . y - - ;
if ( ( scrollingDir & DOWN ) & & ( position . y < CGI - > mh - > map - > height - CGI - > mh - > tilesH + CGI - > mh - > frameH ) )
position . y + + ;
if ( scrollingDir )
{
setScrollingCursor ( scrollingDir ) ;
scrollingState = true ;
updateScreen = true ;
minimap . redraw ( ) ;
if ( mode = = EAdvMapMode : : WORLD_VIEW )
terrain . redraw ( ) ;
}
else if ( scrollingState )
{
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2017-05-25 19:57:20 +02:00
scrollingState = false ;
}
}
}
void CAdvMapInt : : handleSwipeUpdate ( )
{
if ( swipeMovementRequested )
{
2017-06-07 22:42:41 +02:00
auto fixedPos = LOCPLINT - > repairScreenPos ( swipeTargetPosition ) ;
position . x = fixedPos . x ;
position . y = fixedPos . y ;
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2017-05-25 19:57:20 +02:00
updateScreen = true ;
minimap . redraw ( ) ;
swipeMovementRequested = false ;
}
}
2008-01-31 23:35:30 +02:00
void CAdvMapInt : : selectionChanged ( )
{
2012-06-13 16:04:06 +03:00
const CGTownInstance * to = LOCPLINT - > towns [ townList . getSelectedIndex ( ) ] ;
2012-09-05 15:49:23 +03:00
if ( selection ! = to )
select ( to ) ;
2008-01-31 23:35:30 +02:00
}
2014-09-18 17:53:41 +03:00
2017-07-15 13:08:20 +02:00
void CAdvMapInt : : centerOn ( int3 on , bool fade )
2007-09-14 16:11:10 +03:00
{
2012-06-13 16:04:06 +03:00
bool switchedLevels = on . z ! = position . z ;
2015-10-31 19:23:13 +02:00
2015-02-02 18:42:42 +02:00
if ( fade )
2015-01-31 00:37:28 +02:00
{
terrain . fadeFromCurrentView ( ) ;
}
2012-06-13 16:04:06 +03:00
2015-01-17 14:41:59 +02:00
switch ( mode )
{
default :
case EAdvMapMode : : NORMAL :
on . x - = CGI - > mh - > frameW ; // is this intentional? frame size doesn't really have to correspond to camera size...
on . y - = CGI - > mh - > frameH ;
break ;
case EAdvMapMode : : WORLD_VIEW :
2020-10-01 10:38:06 +02:00
on . x - = static_cast < si32 > ( CGI - > mh - > tilesW / 2 / worldViewScale ) ;
on . y - = static_cast < si32 > ( CGI - > mh - > tilesH / 2 / worldViewScale ) ;
2015-01-17 14:41:59 +02:00
break ;
}
2012-01-12 18:23:00 +03:00
2009-02-02 15:05:19 +02:00
on = LOCPLINT - > repairScreenPos ( on ) ;
2007-09-14 16:11:10 +03:00
2012-06-13 16:04:06 +03:00
position = on ;
updateScreen = true ;
2014-08-03 14:16:19 +03:00
underground - > setIndex ( on . z , true ) ; //change underground switch button image
underground - > redraw ( ) ;
2015-01-17 14:41:59 +02:00
worldViewUnderground - > setIndex ( on . z , true ) ;
worldViewUnderground - > redraw ( ) ;
2012-06-13 16:04:06 +03:00
if ( switchedLevels )
minimap . setLevel ( position . z ) ;
2014-09-18 17:53:41 +03:00
minimap . redraw ( ) ;
2015-01-13 21:57:41 +02:00
if ( mode = = EAdvMapMode : : WORLD_VIEW )
terrain . redraw ( ) ;
2007-09-14 16:11:10 +03:00
}
2010-03-21 00:17:19 +02:00
2017-07-15 13:08:20 +02:00
void CAdvMapInt : : centerOn ( const CGObjectInstance * obj , bool fade )
2010-03-21 00:17:19 +02:00
{
2015-02-02 18:42:42 +02:00
centerOn ( obj - > getSightCenter ( ) , fade ) ;
2010-03-21 00:17:19 +02:00
}
2023-02-02 18:02:25 +02:00
void CAdvMapInt : : keyReleased ( const SDL_Keycode & key )
2008-10-19 16:17:32 +03:00
{
2023-02-02 18:02:25 +02:00
if ( mode = = EAdvMapMode : : WORLD_VIEW )
return ;
switch ( key )
{
case SDLK_s :
if ( isActive ( ) )
GH . pushIntT < CSavingScreen > ( ) ;
return ;
default :
{
auto direction = keyToMoveDirection ( key ) ;
if ( ! direction )
return ;
2015-01-17 14:41:59 +02:00
2023-02-02 18:02:25 +02:00
ui8 Dir = ( direction - > x < 0 ? LEFT : 0 ) |
( direction - > x > 0 ? RIGHT : 0 ) |
( direction - > y < 0 ? UP : 0 ) |
( direction - > y > 0 ? DOWN : 0 ) ;
scrollingDir & = ~ Dir ;
}
}
}
2023-02-02 18:42:44 +02:00
void CAdvMapInt : : keyPressed ( const SDL_Keycode & key )
2023-02-02 18:02:25 +02:00
{
2015-01-17 14:41:59 +02:00
if ( mode = = EAdvMapMode : : WORLD_VIEW )
return ;
2010-03-21 00:17:19 +02:00
const CGHeroInstance * h = curHero ( ) ; //selected hero
const CGTownInstance * t = curTown ( ) ; //selected town
2023-02-02 18:02:25 +02:00
switch ( key )
2008-10-19 16:17:32 +03:00
{
2012-04-08 04:15:18 +03:00
case SDLK_g :
2023-02-02 18:02:25 +02:00
if ( GH . topInt ( ) - > type & BLOCK_ADV_HOTKEYS )
2012-04-08 04:15:18 +03:00
return ;
{
//find first town with tavern
2013-06-26 14:18:27 +03:00
auto itr = range : : find_if ( LOCPLINT - > towns , [ ] ( const CGTownInstance * town )
{
return town - > hasBuilt ( BuildingID : : TAVERN ) ;
} ) ;
2012-04-08 04:15:18 +03:00
if ( itr ! = LOCPLINT - > towns . end ( ) )
LOCPLINT - > showThievesGuildWindow ( * itr ) ;
else
2022-12-27 22:19:05 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > translate ( " vcmi.adventureMap.noTownWithTavern " ) ) ;
2012-04-08 04:15:18 +03:00
}
return ;
2012-01-12 18:23:00 +03:00
case SDLK_i :
2009-12-28 06:08:24 +02:00
if ( isActive ( ) )
2009-08-27 11:04:32 +03:00
CAdventureOptions : : showScenarioInfo ( ) ;
return ;
2012-04-09 05:53:50 +03:00
case SDLK_l :
if ( isActive ( ) )
LOCPLINT - > proposeLoadingGame ( ) ;
return ;
2012-01-12 18:23:00 +03:00
case SDLK_d :
2010-03-01 21:04:07 +02:00
{
2023-02-02 18:02:25 +02:00
if ( h & & isActive ( ) & & LOCPLINT - > makingTurn )
2010-03-01 21:04:07 +02:00
LOCPLINT - > tryDiggging ( h ) ;
return ;
}
2012-01-12 18:23:00 +03:00
case SDLK_p :
2010-03-01 21:04:07 +02:00
if ( isActive ( ) )
LOCPLINT - > showPuzzleMap ( ) ;
return ;
2015-01-31 11:57:13 +02:00
case SDLK_v :
if ( isActive ( ) )
LOCPLINT - > viewWorldMap ( ) ;
return ;
2012-04-08 06:06:27 +03:00
case SDLK_r :
2023-02-02 16:15:39 +02:00
if ( isActive ( ) & & GH . isKeyboardCtrlDown ( ) )
2012-04-08 06:06:27 +03:00
{
2022-12-27 22:19:05 +02:00
LOCPLINT - > showYesNoDialog ( CGI - > generaltexth - > translate ( " vcmi.adventureMap.confirmRestartGame " ) ,
2023-02-02 18:15:05 +02:00
[ ] ( ) { GH . pushUserEvent ( EUserEvent : : RESTART_GAME ) ; } , nullptr ) ;
2012-04-08 06:06:27 +03:00
}
return ;
2009-03-27 01:05:40 +02:00
case SDLK_SPACE : //space - try to revisit current object with selected hero
{
2012-01-12 18:23:00 +03:00
if ( ! isActive ( ) )
2009-05-22 22:20:30 +03:00
return ;
2023-02-02 18:02:25 +02:00
if ( h )
2009-03-27 01:05:40 +02:00
{
2016-11-25 21:12:22 +02:00
auto unlockPim = vstd : : makeUnlockGuard ( * CPlayerInterface : : pim ) ;
2013-05-27 13:53:28 +03:00
//TODO!!!!!!! possible freeze, when GS mutex is locked and network thread can't apply package
2015-01-13 21:57:41 +02:00
//this thread leaves scope and tries to lock pim while holding gs,
2013-05-27 13:53:28 +03:00
//network thread tries to lock gs (appluy cl) while holding pim
//this thread should first lock pim, however gs locking/unlocking is done inside cb
2009-03-27 01:05:40 +02:00
LOCPLINT - > cb - > moveHero ( h , h - > pos ) ;
}
}
return ;
2009-05-30 19:00:26 +03:00
case SDLK_RETURN :
{
2023-02-02 18:02:25 +02:00
if ( ! isActive ( ) | | ! selection )
2009-05-30 19:00:26 +03:00
return ;
2010-03-21 00:17:19 +02:00
if ( h )
LOCPLINT - > openHeroWindow ( h ) ;
else if ( t )
LOCPLINT - > openTownWindow ( t ) ;
2009-05-30 19:00:26 +03:00
return ;
}
2010-06-01 00:14:15 +03:00
case SDLK_ESCAPE :
{
2023-02-02 18:02:25 +02:00
if ( isActive ( ) | | GH . topInt ( ) . get ( ) ! = this | | ! spellBeingCasted )
2010-06-01 00:14:15 +03:00
return ;
leaveCastingMode ( ) ;
return ;
}
2009-07-01 10:04:21 +03:00
case SDLK_t :
{
//act on key down if marketplace windows is not already opened
2023-02-02 18:02:25 +02:00
if ( GH . topInt ( ) - > type & BLOCK_ADV_HOTKEYS )
2012-04-08 04:15:18 +03:00
return ;
2009-07-01 10:04:21 +03:00
2023-02-02 16:15:39 +02:00
if ( GH . isKeyboardCtrlDown ( ) ) //CTRL + T => open marketplace
2010-05-18 10:01:54 +03:00
{
2012-04-08 04:15:18 +03:00
//check if we have any marketplace
2013-06-26 14:18:27 +03:00
const CGTownInstance * townWithMarket = nullptr ;
2013-06-29 16:05:48 +03:00
for ( const CGTownInstance * t : LOCPLINT - > cb - > getTownsInfo ( ) )
2010-05-18 10:01:54 +03:00
{
2013-02-11 02:24:57 +03:00
if ( t - > hasBuilt ( BuildingID : : MARKETPLACE ) )
2012-04-08 04:15:18 +03:00
{
townWithMarket = t ;
break ;
}
2010-05-18 10:01:54 +03:00
}
2009-07-01 10:04:21 +03:00
2012-04-08 04:15:18 +03:00
if ( townWithMarket ) //if any town has marketplace, open window
2018-07-25 00:36:48 +02:00
GH . pushIntT < CMarketplaceWindow > ( townWithMarket ) ;
2012-04-08 04:15:18 +03:00
else //if not - complain
2022-12-27 22:19:05 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > translate ( " vcmi.adventureMap.noTownWithMarket " ) ) ;
2012-04-08 04:15:18 +03:00
}
else if ( isActive ( ) ) //no ctrl, advmapint is on the top => switch to town
{
townList . selectNext ( ) ;
}
2009-07-01 10:04:21 +03:00
return ;
}
2012-01-12 18:23:00 +03:00
default :
2009-09-07 05:29:44 +03:00
{
2023-02-02 18:02:25 +02:00
auto direction = keyToMoveDirection ( key ) ;
2009-09-07 05:29:44 +03:00
2023-02-02 18:02:25 +02:00
if ( ! direction )
return ;
2015-01-13 21:57:41 +02:00
2023-02-02 18:02:25 +02:00
ui8 Dir = ( direction - > x < 0 ? LEFT : 0 ) |
( direction - > x > 0 ? RIGHT : 0 ) |
( direction - > y < 0 ? UP : 0 ) |
( direction - > y > 0 ? DOWN : 0 ) ;
2015-06-21 00:13:45 +02:00
2023-02-02 18:02:25 +02:00
scrollingDir | = Dir ;
2015-06-21 00:13:45 +02:00
2023-02-02 18:02:25 +02:00
//ctrl makes arrow move screen, not hero
if ( GH . isKeyboardCtrlDown ( ) )
2015-02-09 17:03:24 +02:00
return ;
2009-09-07 05:29:44 +03:00
2023-02-02 18:02:25 +02:00
if ( ! h | | ! isActive ( ) )
return ;
2012-05-15 11:47:11 +03:00
2023-02-02 18:02:25 +02:00
if ( ! CGI - > mh - > canStartHeroMovement ( ) )
return ;
2009-09-07 05:29:44 +03:00
2023-02-02 18:02:25 +02:00
if ( * direction = = Point ( 0 , 0 ) )
2009-09-07 05:29:44 +03:00
{
2010-03-21 00:17:19 +02:00
centerOn ( h ) ;
2009-09-07 05:29:44 +03:00
return ;
}
2010-02-20 15:24:38 +02:00
CGPath & path = LOCPLINT - > paths [ h ] ;
2009-09-07 05:29:44 +03:00
terrain . currentPath = & path ;
2023-02-02 18:02:25 +02:00
int3 dst = h - > visitablePos ( ) + int3 ( direction - > x , direction - > y , 0 ) ;
2015-11-02 10:14:32 +02:00
if ( dst ! = verifyPos ( dst ) | | ! LOCPLINT - > cb - > getPathsInfo ( h ) - > getPath ( path , dst ) )
2009-09-07 05:29:44 +03:00
{
2013-06-26 14:18:27 +03:00
terrain . currentPath = nullptr ;
2009-09-07 05:29:44 +03:00
return ;
}
2012-05-15 11:47:11 +03:00
if ( path . nodes . size ( ) > 2 )
updateMoveHero ( h ) ;
else
2009-09-07 05:29:44 +03:00
if ( ! path . nodes [ 0 ] . turns )
LOCPLINT - > moveHero ( h , path ) ;
}
2008-10-19 16:17:32 +03:00
return ;
}
}
2023-02-02 18:02:25 +02:00
boost : : optional < Point > CAdvMapInt : : keyToMoveDirection ( const SDL_Keycode & key )
{
switch ( key ) {
case SDLK_DOWN : return Point ( 0 , + 1 ) ;
case SDLK_LEFT : return Point ( - 1 , 0 ) ;
case SDLK_RIGHT : return Point ( + 1 , 0 ) ;
case SDLK_UP : return Point ( 0 , - 1 ) ;
case SDLK_KP_1 : return Point ( - 1 , + 1 ) ;
case SDLK_KP_2 : return Point ( 0 , + 1 ) ;
case SDLK_KP_3 : return Point ( + 1 , + 1 ) ;
case SDLK_KP_4 : return Point ( - 1 , 0 ) ;
case SDLK_KP_5 : return Point ( 0 , 0 ) ;
case SDLK_KP_6 : return Point ( + 1 , 0 ) ;
case SDLK_KP_7 : return Point ( - 1 , - 1 ) ;
case SDLK_KP_8 : return Point ( 0 , - 1 ) ;
case SDLK_KP_9 : return Point ( + 1 , - 1 ) ;
}
return boost : : none ;
}
2010-03-21 00:17:19 +02:00
void CAdvMapInt : : handleRightClick ( std : : string text , tribool down )
2008-08-02 18:08:03 +03:00
{
2010-03-21 00:17:19 +02:00
if ( down )
2007-10-13 23:31:50 +03:00
{
2010-03-21 00:17:19 +02:00
CRClickPopup : : createAndPush ( text ) ;
2007-10-13 23:31:50 +03:00
}
}
2007-10-07 17:51:09 +03:00
int3 CAdvMapInt : : verifyPos ( int3 ver )
{
if ( ver . x < 0 )
ver . x = 0 ;
if ( ver . y < 0 )
ver . y = 0 ;
if ( ver . z < 0 )
ver . z = 0 ;
if ( ver . x > = CGI - > mh - > sizes . x )
ver . x = CGI - > mh - > sizes . x - 1 ;
if ( ver . y > = CGI - > mh - > sizes . y )
ver . y = CGI - > mh - > sizes . y - 1 ;
if ( ver . z > = CGI - > mh - > sizes . z )
ver . z = CGI - > mh - > sizes . z - 1 ;
return ver ;
2008-08-02 18:08:03 +03:00
}
2008-08-28 20:36:34 +03:00
2017-07-15 13:08:20 +02:00
void CAdvMapInt : : select ( const CArmedInstance * sel , bool centerView )
2008-08-28 20:36:34 +03:00
{
2010-05-08 21:56:38 +03:00
assert ( sel ) ;
2014-09-21 16:42:08 +03:00
LOCPLINT - > setSelection ( sel ) ;
2008-08-28 20:36:34 +03:00
selection = sel ;
2013-06-26 14:18:27 +03:00
if ( LOCPLINT - > battleInt = = nullptr & & LOCPLINT - > makingTurn )
2012-07-15 18:34:00 +03:00
{
auto pos = sel - > visitablePos ( ) ;
auto tile = LOCPLINT - > cb - > getTile ( pos ) ;
if ( tile )
2023-01-01 22:42:28 +02:00
CCS - > musich - > playMusicFromSet ( " terrain " , tile - > terType - > getJsonKey ( ) , true , false ) ;
2012-07-15 18:34:00 +03:00
}
2010-03-21 00:17:19 +02:00
if ( centerView )
centerOn ( sel ) ;
2009-06-11 20:21:06 +03:00
2013-06-26 14:18:27 +03:00
terrain . currentPath = nullptr ;
2012-09-23 21:01:04 +03:00
if ( sel - > ID = = Obj : : TOWN )
2008-08-28 20:36:34 +03:00
{
2012-06-13 16:04:06 +03:00
auto town = dynamic_cast < const CGTownInstance * > ( sel ) ;
2012-06-22 14:40:16 +03:00
infoBar . showTownSelection ( town ) ;
2012-06-13 16:04:06 +03:00
townList . select ( town ) ;
heroList . select ( nullptr ) ;
2013-06-26 14:18:27 +03:00
updateSleepWake ( nullptr ) ;
updateMoveHero ( nullptr ) ;
2015-12-06 02:12:39 +02:00
updateSpellbook ( nullptr ) ;
2008-08-28 20:36:34 +03:00
}
2009-06-11 20:21:06 +03:00
else //hero selected
2009-04-14 17:26:58 +03:00
{
2012-06-13 16:04:06 +03:00
auto hero = dynamic_cast < const CGHeroInstance * > ( sel ) ;
2012-06-22 14:40:16 +03:00
infoBar . showHeroSelection ( hero ) ;
2012-06-13 16:04:06 +03:00
heroList . select ( hero ) ;
townList . select ( nullptr ) ;
2009-06-11 20:21:06 +03:00
2012-06-13 16:04:06 +03:00
terrain . currentPath = LOCPLINT - > getAndVerifyPath ( hero ) ;
2011-10-04 22:43:49 +03:00
2012-06-13 16:04:06 +03:00
updateSleepWake ( hero ) ;
updateMoveHero ( hero ) ;
2015-12-06 02:12:39 +02:00
updateSpellbook ( hero ) ;
2009-04-14 17:26:58 +03:00
}
2012-06-13 16:04:06 +03:00
townList . redraw ( ) ;
heroList . redraw ( ) ;
2009-06-07 01:47:23 +03:00
}
2009-08-07 01:36:51 +03:00
2023-02-02 15:49:23 +02:00
void CAdvMapInt : : mouseMoved ( const Point & cursorPosition )
2009-08-07 01:36:51 +03:00
{
2021-03-13 13:08:13 +02:00
# if defined(VCMI_ANDROID) || defined(VCMI_IOS)
2017-05-25 19:57:20 +02:00
if ( swipeEnabled )
return ;
# endif
2015-01-13 21:57:41 +02:00
// adventure map scrolling with mouse
2015-01-15 01:22:20 +02:00
// currently disabled in world view mode (as it is in OH3), but should work correctly if mode check is removed
2020-01-05 08:45:33 +02:00
// don't scroll if there is no window in focus - these events don't seem to correspond to the actual mouse movement
2023-02-02 16:15:39 +02:00
if ( ! GH . isKeyboardCtrlDown ( ) & & isActive ( ) & & mode = = EAdvMapMode : : NORMAL )
2009-08-07 01:36:51 +03:00
{
2023-02-02 15:49:23 +02:00
if ( cursorPosition . x < 15 )
2009-08-07 01:36:51 +03:00
{
scrollingDir | = LEFT ;
}
else
{
scrollingDir & = ~ LEFT ;
}
2023-02-02 15:49:23 +02:00
if ( cursorPosition . x > screen - > w - 15 )
2009-08-07 01:36:51 +03:00
{
scrollingDir | = RIGHT ;
}
else
{
scrollingDir & = ~ RIGHT ;
}
2023-02-02 15:49:23 +02:00
if ( cursorPosition . y < 15 )
2009-08-07 01:36:51 +03:00
{
scrollingDir | = UP ;
}
else
{
scrollingDir & = ~ UP ;
}
2023-02-02 15:49:23 +02:00
if ( cursorPosition . y > screen - > h - 15 )
2009-08-07 01:36:51 +03:00
{
scrollingDir | = DOWN ;
}
else
{
scrollingDir & = ~ DOWN ;
}
}
2009-08-27 11:04:32 +03:00
}
2009-12-28 06:08:24 +02:00
bool CAdvMapInt : : isActive ( )
{
2009-12-29 03:07:17 +02:00
return active & ~ CIntObject : : KEYBOARD ;
2009-12-28 06:08:24 +02:00
}
2013-03-03 20:06:03 +03:00
void CAdvMapInt : : startHotSeatWait ( PlayerColor Player )
2010-01-02 03:48:44 +02:00
{
2010-02-20 15:24:38 +02:00
state = WAITING ;
}
2010-01-02 03:48:44 +02:00
2013-03-03 20:06:03 +03:00
void CAdvMapInt : : setPlayer ( PlayerColor Player )
2010-02-20 15:24:38 +02:00
{
player = Player ;
2023-01-30 18:25:47 +02:00
bg - > playerColored ( player ) ;
2010-02-20 15:24:38 +02:00
2015-01-15 01:22:20 +02:00
panelMain - > setPlayerColor ( player ) ;
panelWorldView - > setPlayerColor ( player ) ;
2016-10-18 04:46:07 +02:00
panelWorldView - > recolorIcons ( player , player . getNum ( ) * 19 ) ;
2018-04-07 13:34:11 +02:00
resdatabar . background - > colorize ( player ) ;
2010-02-20 15:24:38 +02:00
}
void CAdvMapInt : : startTurn ( )
{
state = INGAME ;
2017-06-03 07:25:10 +02:00
if ( LOCPLINT - > cb - > getCurrentPlayer ( ) = = LOCPLINT - > playerID
| | settings [ " session " ] [ " spectate " ] . Bool ( ) )
2012-02-22 16:41:27 +03:00
{
adjustActiveness ( false ) ;
2012-06-13 16:04:06 +03:00
minimap . setAIRadar ( false ) ;
2012-02-22 16:41:27 +03:00
}
2010-01-02 03:48:44 +02:00
}
2011-09-24 19:46:23 +03:00
void CAdvMapInt : : endingTurn ( )
{
2017-06-03 07:25:10 +02:00
if ( settings [ " session " ] [ " spectate " ] . Bool ( ) )
return ;
2011-09-24 19:46:23 +03:00
LOCPLINT - > makingTurn = false ;
LOCPLINT - > cb - > endTurn ( ) ;
2017-09-13 02:35:58 +02:00
CCS - > soundh - > ambientStopAllChannels ( ) ;
2011-09-24 19:46:23 +03:00
}
2014-07-01 17:19:08 +03:00
const CGObjectInstance * CAdvMapInt : : getActiveObject ( const int3 & mapPos )
2010-03-21 00:17:19 +02:00
{
2012-05-14 19:29:06 +03:00
std : : vector < const CGObjectInstance * > bobjs = LOCPLINT - > cb - > getBlockingObjs ( mapPos ) ; //blocking objects at tile
if ( bobjs . empty ( ) )
return nullptr ;
2011-05-03 06:14:18 +03:00
2014-07-01 17:19:08 +03:00
return * boost : : range : : max_element ( bobjs , & CMapHandler : : compareObjectBlitOrder ) ;
/*
2012-09-23 21:01:04 +03:00
if ( bobjs . back ( ) - > ID = = Obj : : HERO )
2012-05-14 19:29:06 +03:00
return bobjs . back ( ) ;
else
2014-07-01 17:19:08 +03:00
return bobjs . front ( ) ; */
2012-05-14 19:29:06 +03:00
}
void CAdvMapInt : : tileLClicked ( const int3 & mapPos )
{
2015-01-13 21:57:41 +02:00
if ( mode ! = EAdvMapMode : : NORMAL )
return ;
2012-05-14 19:29:06 +03:00
if ( ! LOCPLINT - > cb - > isVisible ( mapPos ) | | ! LOCPLINT - > makingTurn )
return ;
2011-08-18 00:48:12 +03:00
2012-05-14 19:29:06 +03:00
const TerrainTile * tile = LOCPLINT - > cb - > getTile ( mapPos ) ;
2010-03-21 00:17:19 +02:00
2014-07-01 17:19:08 +03:00
const CGObjectInstance * topBlocking = getActiveObject ( mapPos ) ;
2010-03-21 00:17:19 +02:00
int3 selPos = selection - > getSightCenter ( ) ;
2012-05-14 19:29:06 +03:00
if ( spellBeingCasted & & isInScreenRange ( selPos , mapPos ) )
2010-03-21 00:17:19 +02:00
{
2011-05-10 01:20:47 +03:00
const TerrainTile * heroTile = LOCPLINT - > cb - > getTile ( selPos ) ;
2010-03-21 00:17:19 +02:00
switch ( spellBeingCasted - > id )
{
2013-02-11 02:24:57 +03:00
case SpellID : : SCUTTLE_BOAT : //Scuttle Boat
2013-01-31 23:11:25 +03:00
if ( topBlocking & & topBlocking - > ID = = Obj : : BOAT )
2012-05-14 19:29:06 +03:00
leaveCastingMode ( true , mapPos ) ;
2010-03-21 00:17:19 +02:00
break ;
2013-02-11 02:24:57 +03:00
case SpellID : : DIMENSION_DOOR :
2010-03-21 00:17:19 +02:00
if ( ! tile | | tile - > isClear ( heroTile ) )
2012-05-14 19:29:06 +03:00
leaveCastingMode ( true , mapPos ) ;
2010-03-21 00:17:19 +02:00
break ;
}
return ;
}
2010-08-13 13:46:08 +03:00
//check if we can select this object
2012-09-23 21:01:04 +03:00
bool canSelect = topBlocking & & topBlocking - > ID = = Obj : : HERO & & topBlocking - > tempOwner = = LOCPLINT - > playerID ;
canSelect | = topBlocking & & topBlocking - > ID = = Obj : : TOWN & & LOCPLINT - > cb - > getPlayerRelations ( LOCPLINT - > playerID , topBlocking - > tempOwner ) ;
2010-03-21 00:17:19 +02:00
2023-01-25 19:47:33 +02:00
bool isHero = false ;
2016-01-17 06:48:21 +02:00
if ( selection - > ID ! = Obj : : HERO ) //hero is not selected (presumably town)
2010-03-21 00:17:19 +02:00
{
assert ( ! terrain . currentPath ) ; //path can be active only when hero is selected
if ( selection = = topBlocking ) //selected town clicked
LOCPLINT - > openTownWindow ( static_cast < const CGTownInstance * > ( topBlocking ) ) ;
2016-01-17 06:48:21 +02:00
else if ( canSelect )
select ( static_cast < const CArmedInstance * > ( topBlocking ) , false ) ;
2010-03-21 00:17:19 +02:00
}
else if ( const CGHeroInstance * currentHero = curHero ( ) ) //hero is selected
{
2023-01-25 19:47:33 +02:00
isHero = true ;
2014-09-21 16:42:08 +03:00
const CGPathNode * pn = LOCPLINT - > cb - > getPathsInfo ( currentHero ) - > getPathInfo ( mapPos ) ;
2010-03-21 00:17:19 +02:00
if ( currentHero = = topBlocking ) //clicked selected hero
{
LOCPLINT - > openHeroWindow ( currentHero ) ;
2010-07-13 08:25:40 +03:00
return ;
2010-03-21 00:17:19 +02:00
}
2010-08-13 13:46:08 +03:00
else if ( canSelect & & pn - > turns = = 255 ) //selectable object at inaccessible tile
2010-03-21 00:17:19 +02:00
{
select ( static_cast < const CArmedInstance * > ( topBlocking ) , false ) ;
2010-07-13 08:25:40 +03:00
return ;
2010-03-21 00:17:19 +02:00
}
else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
{
2016-01-17 06:48:21 +02:00
if ( terrain . currentPath & & terrain . currentPath - > endPos ( ) = = mapPos ) //we'll be moving
2010-03-21 00:17:19 +02:00
{
2016-01-17 06:48:21 +02:00
if ( CGI - > mh - > canStartHeroMovement ( ) )
LOCPLINT - > moveHero ( currentHero , * terrain . currentPath ) ;
2010-07-13 08:25:40 +03:00
return ;
2010-03-21 00:17:19 +02:00
}
2016-01-17 06:48:21 +02:00
else //remove old path and find a new one if we clicked on accessible tile
2010-03-21 00:17:19 +02:00
{
CGPath & path = LOCPLINT - > paths [ currentHero ] ;
2016-01-17 06:48:21 +02:00
CGPath newpath ;
bool gotPath = LOCPLINT - > cb - > getPathsInfo ( currentHero ) - > getPath ( newpath , mapPos ) ; //try getting path, erase if failed
if ( gotPath & & newpath . nodes . size ( ) )
path = newpath ;
if ( path . nodes . size ( ) )
terrain . currentPath = & path ;
2010-07-13 08:25:40 +03:00
else
2016-01-17 06:48:21 +02:00
LOCPLINT - > eraseCurrentPathOf ( currentHero ) ;
updateMoveHero ( currentHero ) ;
2010-03-21 00:17:19 +02:00
}
}
} //end of hero is selected "case"
else
{
2012-04-22 10:32:45 +03:00
throw std : : runtime_error ( " Nothing is selected... " ) ;
2010-03-21 00:17:19 +02:00
}
2010-07-13 08:25:40 +03:00
2023-01-25 19:47:33 +02:00
const auto shipyard = ourInaccessibleShipyard ( topBlocking ) ;
if ( isHero & & shipyard ! = nullptr )
2010-07-13 08:25:40 +03:00
{
LOCPLINT - > showShipyardDialogOrProblemPopup ( shipyard ) ;
}
2010-03-21 00:17:19 +02:00
}
2012-05-14 19:29:06 +03:00
void CAdvMapInt : : tileHovered ( const int3 & mapPos )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:33:01 +02:00
if ( mode ! = EAdvMapMode : : NORMAL //disable in world view
| | ! selection ) //may occur just at the start of game (fake move before full intiialization)
2015-01-13 21:57:41 +02:00
return ;
2012-05-14 19:29:06 +03:00
if ( ! LOCPLINT - > cb - > isVisible ( mapPos ) )
2011-05-03 06:14:18 +03:00
{
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2018-08-26 18:09:56 +02:00
statusbar - > clear ( ) ;
2011-05-03 06:14:18 +03:00
return ;
}
2015-11-08 02:10:48 +02:00
auto objRelations = PlayerRelations : : ALLIES ;
2015-11-08 02:33:01 +02:00
const CGObjectInstance * objAtTile = getActiveObject ( mapPos ) ;
2015-11-08 02:10:48 +02:00
if ( objAtTile )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:10:48 +02:00
objRelations = LOCPLINT - > cb - > getPlayerRelations ( LOCPLINT - > playerID , objAtTile - > tempOwner ) ;
2014-06-24 20:39:36 +03:00
std : : string text = curHero ( ) ? objAtTile - > getHoverText ( curHero ( ) ) : objAtTile - > getHoverText ( LOCPLINT - > playerID ) ;
2012-05-14 19:29:06 +03:00
boost : : replace_all ( text , " \n " , " " ) ;
2022-12-19 22:04:50 +02:00
statusbar - > write ( text ) ;
2010-03-21 00:17:19 +02:00
}
else
{
std : : string hlp ;
2012-05-14 19:29:06 +03:00
CGI - > mh - > getTerrainDescr ( mapPos , hlp , false ) ;
2022-12-19 22:04:50 +02:00
statusbar - > write ( hlp ) ;
2010-03-21 00:17:19 +02:00
}
if ( spellBeingCasted )
{
switch ( spellBeingCasted - > id )
{
2013-02-11 02:24:57 +03:00
case SpellID : : SCUTTLE_BOAT :
2012-09-23 21:01:04 +03:00
if ( objAtTile & & objAtTile - > ID = = Obj : : BOAT )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : SCUTTLE_BOAT ) ;
2010-03-21 00:17:19 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2010-03-21 00:17:19 +02:00
return ;
2013-02-11 02:24:57 +03:00
case SpellID : : DIMENSION_DOOR :
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:33:01 +02:00
const TerrainTile * t = LOCPLINT - > cb - > getTile ( mapPos , false ) ;
2010-03-21 00:17:19 +02:00
int3 hpos = selection - > getSightCenter ( ) ;
2015-11-08 02:33:01 +02:00
if ( ( ! t | | t - > isClear ( LOCPLINT - > cb - > getTile ( hpos ) ) ) & & isInScreenRange ( hpos , mapPos ) )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : TELEPORT ) ;
2010-03-21 00:17:19 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2010-03-21 00:17:19 +02:00
return ;
}
}
}
2012-09-23 21:01:04 +03:00
if ( selection - > ID = = Obj : : TOWN )
2010-03-21 00:17:19 +02:00
{
2010-08-13 13:46:08 +03:00
if ( objAtTile )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:33:01 +02:00
if ( objAtTile - > ID = = Obj : : TOWN & & objRelations ! = PlayerRelations : : ENEMIES )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : TOWN ) ;
2015-11-08 02:33:01 +02:00
else if ( objAtTile - > ID = = Obj : : HERO & & objRelations = = PlayerRelations : : SAME_PLAYER )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : HERO ) ;
2012-02-28 14:26:08 +03:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2010-03-21 00:17:19 +02:00
}
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2010-03-21 00:17:19 +02:00
}
2023-01-21 16:30:32 +02:00
else if ( const CGHeroInstance * hero = curHero ( ) )
2010-03-21 00:17:19 +02:00
{
2022-12-18 22:32:07 +02:00
std : : array < Cursor : : Map , 4 > cursorMove = { Cursor : : Map : : T1_MOVE , Cursor : : Map : : T2_MOVE , Cursor : : Map : : T3_MOVE , Cursor : : Map : : T4_MOVE , } ;
std : : array < Cursor : : Map , 4 > cursorAttack = { Cursor : : Map : : T1_ATTACK , Cursor : : Map : : T2_ATTACK , Cursor : : Map : : T3_ATTACK , Cursor : : Map : : T4_ATTACK , } ;
std : : array < Cursor : : Map , 4 > cursorSail = { Cursor : : Map : : T1_SAIL , Cursor : : Map : : T2_SAIL , Cursor : : Map : : T3_SAIL , Cursor : : Map : : T4_SAIL , } ;
std : : array < Cursor : : Map , 4 > cursorDisembark = { Cursor : : Map : : T1_DISEMBARK , Cursor : : Map : : T2_DISEMBARK , Cursor : : Map : : T3_DISEMBARK , Cursor : : Map : : T4_DISEMBARK , } ;
std : : array < Cursor : : Map , 4 > cursorExchange = { Cursor : : Map : : T1_EXCHANGE , Cursor : : Map : : T2_EXCHANGE , Cursor : : Map : : T3_EXCHANGE , Cursor : : Map : : T4_EXCHANGE , } ;
std : : array < Cursor : : Map , 4 > cursorVisit = { Cursor : : Map : : T1_VISIT , Cursor : : Map : : T2_VISIT , Cursor : : Map : : T3_VISIT , Cursor : : Map : : T4_VISIT , } ;
std : : array < Cursor : : Map , 4 > cursorSailVisit = { Cursor : : Map : : T1_SAIL_VISIT , Cursor : : Map : : T2_SAIL_VISIT , Cursor : : Map : : T3_SAIL_VISIT , Cursor : : Map : : T4_SAIL_VISIT , } ;
2023-01-21 16:30:32 +02:00
const CGPathNode * pathNode = LOCPLINT - > cb - > getPathsInfo ( hero ) - > getPathInfo ( mapPos ) ;
assert ( pathNode ) ;
2014-09-21 16:42:08 +03:00
2023-02-02 16:15:39 +02:00
if ( GH . isKeyboardAltDown ( ) & & pathNode - > reachable ( ) ) //overwrite status bar text with movement info
2023-01-16 18:29:33 +02:00
{
2023-01-21 16:30:32 +02:00
ShowMoveDetailsInStatusbar ( * hero , * pathNode ) ;
2023-01-16 18:29:33 +02:00
}
2023-01-21 16:30:32 +02:00
int turns = pathNode - > turns ;
2014-09-21 16:42:08 +03:00
vstd : : amin ( turns , 3 ) ;
2023-01-21 16:30:32 +02:00
switch ( pathNode - > action )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:10:48 +02:00
case CGPathNode : : NORMAL :
2015-12-11 08:42:30 +02:00
case CGPathNode : : TELEPORT_NORMAL :
2023-01-21 16:30:32 +02:00
if ( pathNode - > layer = = EPathfindingLayer : : LAND )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorMove [ turns ] ) ;
2015-11-08 02:10:48 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorSailVisit [ turns ] ) ;
2015-11-08 02:10:48 +02:00
break ;
2010-03-21 00:17:19 +02:00
2015-11-08 02:10:48 +02:00
case CGPathNode : : VISIT :
case CGPathNode : : BLOCKING_VISIT :
2015-12-11 08:42:30 +02:00
case CGPathNode : : TELEPORT_BLOCKING_VISIT :
2015-11-17 06:09:01 +02:00
if ( objAtTile & & objAtTile - > ID = = Obj : : HERO )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:10:48 +02:00
if ( selection = = objAtTile )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : HERO ) ;
2012-01-12 18:23:00 +03:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorExchange [ turns ] ) ;
2010-05-06 15:13:31 +03:00
}
2023-01-21 16:30:32 +02:00
else if ( pathNode - > layer = = EPathfindingLayer : : LAND )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorVisit [ turns ] ) ;
2010-03-21 00:17:19 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorSailVisit [ turns ] ) ;
2015-11-08 02:10:48 +02:00
break ;
case CGPathNode : : BATTLE :
2015-12-11 08:42:30 +02:00
case CGPathNode : : TELEPORT_BATTLE :
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorAttack [ turns ] ) ;
2015-11-08 02:10:48 +02:00
break ;
case CGPathNode : : EMBARK :
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorSail [ turns ] ) ;
2015-11-08 02:10:48 +02:00
break ;
case CGPathNode : : DISEMBARK :
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( cursorDisembark [ turns ] ) ;
2015-11-08 02:10:48 +02:00
break ;
default :
if ( objAtTile & & objRelations ! = PlayerRelations : : ENEMIES )
2010-03-21 00:17:19 +02:00
{
2015-11-08 02:10:48 +02:00
if ( objAtTile - > ID = = Obj : : TOWN )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : TOWN ) ;
2015-11-08 02:10:48 +02:00
else if ( objAtTile - > ID = = Obj : : HERO & & objRelations = = PlayerRelations : : SAME_PLAYER )
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : HERO ) ;
2019-05-03 07:20:32 +02:00
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2010-03-21 00:17:19 +02:00
}
else
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2015-11-08 02:10:48 +02:00
break ;
2010-03-21 00:17:19 +02:00
}
}
2010-07-13 08:25:40 +03:00
2011-02-20 11:24:53 +02:00
if ( ourInaccessibleShipyard ( objAtTile ) )
2010-07-13 08:25:40 +03:00
{
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : T1_SAIL ) ;
2010-07-13 08:25:40 +03:00
}
2010-03-21 00:17:19 +02:00
}
2023-01-21 16:30:32 +02:00
void CAdvMapInt : : ShowMoveDetailsInStatusbar ( const CGHeroInstance & hero , const CGPathNode & pathNode )
{
const int maxMovementPointsAtStartOfLastTurn = pathNode . turns > 0 ? hero . maxMovePoints ( pathNode . layer = = EPathfindingLayer : : LAND ) : hero . movement ;
const int movementPointsLastTurnCost = maxMovementPointsAtStartOfLastTurn - pathNode . moveRemains ;
const int remainingPointsAfterMove = pathNode . turns = = 0 ? pathNode . moveRemains : 0 ;
std : : string result = VLC - > generaltexth - > translate ( " vcmi.adventureMap " , pathNode . turns > 0 ? " moveCostDetails " : " moveCostDetailsNoTurns " ) ;
boost : : replace_first ( result , " %TURNS " , std : : to_string ( pathNode . turns ) ) ;
boost : : replace_first ( result , " %POINTS " , std : : to_string ( movementPointsLastTurnCost ) ) ;
boost : : replace_first ( result , " %REMAINING " , std : : to_string ( remainingPointsAfterMove ) ) ;
statusbar - > write ( result ) ;
}
2012-05-14 19:29:06 +03:00
void CAdvMapInt : : tileRClicked ( const int3 & mapPos )
2010-03-21 00:17:19 +02:00
{
2015-01-13 21:57:41 +02:00
if ( mode ! = EAdvMapMode : : NORMAL )
return ;
2010-03-21 00:17:19 +02:00
if ( spellBeingCasted )
{
leaveCastingMode ( ) ;
return ;
}
2012-05-14 19:29:06 +03:00
if ( ! LOCPLINT - > cb - > isVisible ( mapPos ) )
2011-05-03 06:14:18 +03:00
{
CRClickPopup : : createAndPush ( VLC - > generaltexth - > allTexts [ 61 ] ) ; //Uncharted Territory
return ;
}
2010-03-21 00:17:19 +02:00
2014-07-01 17:19:08 +03:00
const CGObjectInstance * obj = getActiveObject ( mapPos ) ;
2012-05-14 19:29:06 +03:00
if ( ! obj )
2010-03-21 00:17:19 +02:00
{
// Bare or undiscovered terrain
2012-05-14 19:29:06 +03:00
const TerrainTile * tile = LOCPLINT - > cb - > getTile ( mapPos ) ;
2012-01-12 18:23:00 +03:00
if ( tile )
2010-03-21 00:17:19 +02:00
{
std : : string hlp ;
2012-05-14 19:29:06 +03:00
CGI - > mh - > getTerrainDescr ( mapPos , hlp , true ) ;
2010-03-21 00:17:19 +02:00
CRClickPopup : : createAndPush ( hlp ) ;
}
return ;
}
2023-01-27 00:27:06 +02:00
CRClickPopup : : createAndPush ( obj , GH . getCursorPosition ( ) , ETextAlignment : : CENTER ) ;
2010-03-21 00:17:19 +02:00
}
void CAdvMapInt : : enterCastingMode ( const CSpell * sp )
{
2013-02-11 02:24:57 +03:00
assert ( sp - > id = = SpellID : : SCUTTLE_BOAT | | sp - > id = = SpellID : : DIMENSION_DOOR ) ;
2010-03-21 00:17:19 +02:00
spellBeingCasted = sp ;
deactivate ( ) ;
terrain . activate ( ) ;
GH . fakeMouseMove ( ) ;
}
2017-07-15 13:08:20 +02:00
void CAdvMapInt : : leaveCastingMode ( bool cast , int3 dest )
2010-03-21 00:17:19 +02:00
{
assert ( spellBeingCasted ) ;
2013-02-11 02:24:57 +03:00
SpellID id = spellBeingCasted - > id ;
2013-06-26 14:18:27 +03:00
spellBeingCasted = nullptr ;
2010-03-21 00:17:19 +02:00
terrain . deactivate ( ) ;
activate ( ) ;
2010-06-01 00:14:15 +03:00
if ( cast )
LOCPLINT - > cb - > castSpell ( curHero ( ) , id , dest ) ;
2012-01-12 18:23:00 +03:00
else
2010-06-01 00:14:15 +03:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 731 ] ) ; //Spell cancelled
2010-03-21 00:17:19 +02:00
}
const CGHeroInstance * CAdvMapInt : : curHero ( ) const
{
2012-09-23 21:01:04 +03:00
if ( selection & & selection - > ID = = Obj : : HERO )
2010-03-21 00:17:19 +02:00
return static_cast < const CGHeroInstance * > ( selection ) ;
else
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-03-21 00:17:19 +02:00
}
const CGTownInstance * CAdvMapInt : : curTown ( ) const
{
2012-09-23 21:01:04 +03:00
if ( selection & & selection - > ID = = Obj : : TOWN )
2010-03-21 00:17:19 +02:00
return static_cast < const CGTownInstance * > ( selection ) ;
else
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-03-21 00:17:19 +02:00
}
2010-07-13 08:25:40 +03:00
const IShipyard * CAdvMapInt : : ourInaccessibleShipyard ( const CGObjectInstance * obj ) const
{
const IShipyard * ret = IShipyard : : castFrom ( obj ) ;
2022-12-18 22:32:07 +02:00
if ( ! ret | |
obj - > tempOwner ! = player | |
( CCS - > curh - > get < Cursor : : Map > ( ) ! = Cursor : : Map : : T1_SAIL & & CCS - > curh - > get < Cursor : : Map > ( ) ! = Cursor : : Map : : POINTER ) )
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-07-13 08:25:40 +03:00
return ret ;
}
2012-02-22 16:41:27 +03:00
void CAdvMapInt : : aiTurnStarted ( )
{
2017-06-03 07:25:10 +02:00
if ( settings [ " session " ] [ " spectate " ] . Bool ( ) )
return ;
2012-02-22 16:41:27 +03:00
adjustActiveness ( true ) ;
2022-11-13 14:24:15 +02:00
CCS - > musich - > playMusicFromSet ( " enemy-turn " , true , false ) ;
2012-06-13 16:04:06 +03:00
adventureInt - > minimap . setAIRadar ( true ) ;
adventureInt - > infoBar . startEnemyTurn ( LOCPLINT - > cb - > getCurrentPlayer ( ) ) ;
adventureInt - > infoBar . showAll ( screen ) ; //force refresh on inactive object
2012-02-22 16:41:27 +03:00
}
void CAdvMapInt : : adjustActiveness ( bool aiTurnStart )
{
bool wasActive = isActive ( ) ;
2015-01-13 21:57:41 +02:00
if ( wasActive )
2012-02-22 16:41:27 +03:00
deactivate ( ) ;
adventureInt - > duringAITurn = aiTurnStart ;
2015-01-13 21:57:41 +02:00
if ( wasActive )
2012-02-22 16:41:27 +03:00
activate ( ) ;
}
2012-04-08 04:15:18 +03:00
2016-01-10 17:00:24 +02:00
void CAdvMapInt : : quickCombatLock ( )
{
if ( ! duringAITurn )
deactivate ( ) ;
}
void CAdvMapInt : : quickCombatUnlock ( )
{
if ( ! duringAITurn )
activate ( ) ;
}
2017-07-15 13:08:20 +02:00
void CAdvMapInt : : changeMode ( EAdvMapMode newMode , float newScale )
2015-01-13 21:57:41 +02:00
{
if ( mode ! = newMode )
{
mode = newMode ;
switch ( mode )
{
case EAdvMapMode : : NORMAL :
2015-01-15 01:22:20 +02:00
panelMain - > activate ( ) ;
panelWorldView - > deactivate ( ) ;
activeMapPanel = panelMain ;
2015-01-13 21:57:41 +02:00
townList . activate ( ) ;
heroList . activate ( ) ;
infoBar . activate ( ) ;
2015-10-31 19:23:13 +02:00
2015-02-02 14:02:27 +02:00
worldViewOptions . clear ( ) ;
2015-10-31 19:23:13 +02:00
2015-01-13 21:57:41 +02:00
break ;
case EAdvMapMode : : WORLD_VIEW :
2015-01-15 01:22:20 +02:00
panelMain - > deactivate ( ) ;
panelWorldView - > activate ( ) ;
activeMapPanel = panelWorldView ;
2015-01-13 21:57:41 +02:00
townList . deactivate ( ) ;
heroList . deactivate ( ) ;
infoBar . showSelection ( ) ; // to prevent new day animation interfering world view mode
infoBar . deactivate ( ) ;
break ;
}
worldViewScale = newScale ;
redraw ( ) ;
}
else if ( worldViewScale ! = newScale ) // still in world view mode, but the scale changed
{
worldViewScale = newScale ;
2015-01-31 11:57:13 +02:00
redraw ( ) ;
2015-01-13 21:57:41 +02:00
}
}
2015-02-02 14:02:27 +02:00
CAdvMapInt : : WorldViewOptions : : WorldViewOptions ( )
{
clear ( ) ;
}
void CAdvMapInt : : WorldViewOptions : : clear ( )
{
2015-02-26 16:15:17 +02:00
showAllTerrain = false ;
2015-10-31 19:23:13 +02:00
2015-02-26 16:15:17 +02:00
iconPositions . clear ( ) ;
2015-02-02 14:02:27 +02:00
}
void CAdvMapInt : : WorldViewOptions : : adjustDrawingInfo ( MapDrawingInfo & info )
{
2015-02-26 16:15:17 +02:00
info . showAllTerrain = showAllTerrain ;
2015-02-02 14:02:27 +02:00
2015-10-31 19:23:13 +02:00
info . additionalIcons = & iconPositions ;
}
2023-02-01 15:24:43 +02:00