#include "Map_Screen_Interface_Border.h" #include "Assignments.h" #include "Campaign_Types.h" #include "Debug.h" #include "Directories.h" #include "Interface.h" #include "Map_Screen_Helicopter.h" #include "Map_Screen_Interface.h" #include "Map_Screen_Interface_Map.h" #include "Map_Screen_Interface_Map_Inventory.h" #include "MapScreen.h" #include "MouseSystem.h" #include "SysUtil.h" #include "Text.h" #include "UILayout.h" #include "Video.h" #include "VObject.h" #include "VSurface.h" #include struct BUTTON_PICS; #define MAP_BORDER_FILE INTERFACEDIR "/mbs.sti" #define BTN_TOWN_X (STD_SCREEN_X + 299) #define BTN_MINE_X (STD_SCREEN_X + 342) #define BTN_TEAMS_X (STD_SCREEN_X + 385) #define BTN_MILITIA_X (STD_SCREEN_X + 428) #define BTN_AIR_X (STD_SCREEN_X + 471) #define BTN_ITEM_X (STD_SCREEN_X + 514) #define MAP_LEVEL_MARKER_X (STD_SCREEN_X + 565) #define MAP_LEVEL_MARKER_Y (STD_SCREEN_Y + 323) #define MAP_LEVEL_MARKER_DELTA 8 #define MAP_LEVEL_MARKER_WIDTH 55 #define MAP_BORDER_X (STD_SCREEN_X + 261) #define MAP_BORDER_Y (STD_SCREEN_Y + 0) #define MAP_BORDER_CORNER_X (STD_SCREEN_X + 584) #define MAP_BORDER_CORNER_Y (STD_SCREEN_Y + 279) // mouse levels static MOUSE_REGION LevelMouseRegions[4]; // graphics static SGPVObject* guiLEVELMARKER; // the white rectangle highlighting the current level on the map border static SGPVObject* guiMapBorder; static SGPVObject* guiMapBorderEtaPopUp; // the map border eta pop up //static SGPVObject* guiMapBorderCorner; // scroll direction INT32 giScrollButtonState = -1; // flags BOOLEAN fShowTownFlag = FALSE; BOOLEAN fShowMineFlag = FALSE; BOOLEAN fShowTeamFlag = FALSE; BOOLEAN fShowMilitia = FALSE; BOOLEAN fShowAircraftFlag = FALSE; BOOLEAN fShowItemsFlag = FALSE; // buttons & button images GUIButtonRef giMapBorderButtons[6]; static BUTTON_PICS* giMapBorderButtonsImage[6]; extern void CancelMapUIMessage( void ); void LoadMapBorderGraphics(void) { // this procedure will load the graphics needed for the map border guiLEVELMARKER = AddVideoObjectFromFile(INTERFACEDIR "/greenarr.sti"); guiMapBorder = AddVideoObjectFromFile(MAP_BORDER_FILE); guiMapBorderEtaPopUp = AddVideoObjectFromFile(INTERFACEDIR "/eta_pop_up.sti"); } void DeleteMapBorderGraphics( void ) { // procedure will delete graphics loaded for map border DeleteVideoObject(guiLEVELMARKER); DeleteVideoObject(guiMapBorder); DeleteVideoObject(guiMapBorderEtaPopUp); } static void DisplayCurrentLevelMarker(void); void RenderMapBorder( void ) { if( fShowMapInventoryPool ) { // render background, then leave BlitInventoryPoolGraphic( ); return; } BltVideoObject(guiSAVEBUFFER, guiMapBorder, 0, MAP_BORDER_X, MAP_BORDER_Y); // show the level marker DisplayCurrentLevelMarker( ); } void RenderMapBorderEtaPopUp( void ) { if( fShowMapInventoryPool ) { return; } if (fPlotForHelicopter) { DisplayDistancesForHelicopter( ); return; } BltVideoObject(FRAME_BUFFER, guiMapBorderEtaPopUp, 0, MAP_BORDER_X + 215, STD_SCREEN_Y + 291); InvalidateRegion( MAP_BORDER_X + 215, (STD_SCREEN_Y + 291), MAP_BORDER_X + 215 + 100 , (STD_SCREEN_Y + 310)); } static void MakeButton(UINT idx, UINT gfx, INT16 x, GUI_CALLBACK click, const ST::string& help) { BUTTON_PICS* const img = LoadButtonImage(INTERFACEDIR "/map_border_buttons.sti", gfx, gfx + 9); giMapBorderButtonsImage[idx] = img; GUIButtonRef const btn = QuickCreateButtonNoMove(img, x, (STD_SCREEN_Y + 323), MSYS_PRIORITY_HIGH, click); giMapBorderButtons[idx] = btn; btn->SetFastHelpText(help); btn->SetCursor(MSYS_NO_CURSOR); } static void BtnAircraftCallback(GUI_BUTTON* btn, INT32 reason); static void BtnItemCallback(GUI_BUTTON* btn, INT32 reason); static void BtnMilitiaCallback(GUI_BUTTON* btn, INT32 reason); static void BtnMineCallback(GUI_BUTTON* btn, INT32 reason); static void BtnTeamCallback(GUI_BUTTON* btn, INT32 reason); static void BtnTownCallback(GUI_BUTTON* btn, INT32 reason); static void InitializeMapBorderButtonStates(void); void CreateButtonsForMapBorder(void) { // will create the buttons needed for the map screen border region MakeButton(MAP_BORDER_TOWN_BTN, 5, BTN_TOWN_X, BtnTownCallback, pMapScreenBorderButtonHelpText[0]); // towns MakeButton(MAP_BORDER_MINE_BTN, 4, BTN_MINE_X, BtnMineCallback, pMapScreenBorderButtonHelpText[1]); // mines MakeButton(MAP_BORDER_TEAMS_BTN, 3, BTN_TEAMS_X, BtnTeamCallback, pMapScreenBorderButtonHelpText[2]); // people MakeButton(MAP_BORDER_MILITIA_BTN, 8, BTN_MILITIA_X, BtnMilitiaCallback, pMapScreenBorderButtonHelpText[5]); // militia MakeButton(MAP_BORDER_AIRSPACE_BTN, 2, BTN_AIR_X, BtnAircraftCallback, pMapScreenBorderButtonHelpText[3]); // airspace MakeButton(MAP_BORDER_ITEM_BTN, 1, BTN_ITEM_X, BtnItemCallback, pMapScreenBorderButtonHelpText[4]); // items InitializeMapBorderButtonStates( ); } void DeleteMapBorderButtons( void ) { UINT8 ubCnt; RemoveButton( giMapBorderButtons[ 0 ]); RemoveButton( giMapBorderButtons[ 1 ]); RemoveButton( giMapBorderButtons[ 2 ]); RemoveButton( giMapBorderButtons[ 3 ]); RemoveButton( giMapBorderButtons[ 4 ]); RemoveButton( giMapBorderButtons[ 5 ]); // images UnloadButtonImage( giMapBorderButtonsImage[ 0 ] ); UnloadButtonImage( giMapBorderButtonsImage[ 1 ] ); UnloadButtonImage( giMapBorderButtonsImage[ 2 ] ); UnloadButtonImage( giMapBorderButtonsImage[ 3 ] ); UnloadButtonImage( giMapBorderButtonsImage[ 4 ] ); UnloadButtonImage( giMapBorderButtonsImage[ 5 ] ); for ( ubCnt = 0; ubCnt < 6; ubCnt++ ) { giMapBorderButtonsImage[ubCnt] = NULL; } } // callbacks static void CommonBtnCallbackBtnDownChecks(void); static void BtnMilitiaCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleShowMilitiaMode( ); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void BtnTeamCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleShowTeamsMode(); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void BtnTownCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleShowTownsMode(); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void BtnMineCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleShowMinesMode(); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void BtnAircraftCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleAirspaceMode(); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void BtnItemCallback(GUI_BUTTON* btn, INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); ToggleItemsFilter(); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { CommonBtnCallbackBtnDownChecks(); } } static void MapBorderButtonOff(UINT8 ubBorderButtonIndex); static void MapBorderButtonOn(UINT8 ubBorderButtonIndex); void ToggleShowTownsMode( void ) { if (fShowTownFlag) { fShowTownFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); } else { fShowTownFlag = TRUE; MapBorderButtonOn( MAP_BORDER_TOWN_BTN ); if (fShowMineFlag) { fShowMineFlag = FALSE; MapBorderButtonOff( MAP_BORDER_MINE_BTN ); } if (fShowAircraftFlag) { fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } if (fShowItemsFlag) { fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } } fMapPanelDirty = TRUE; } void ToggleShowMinesMode( void ) { if (fShowMineFlag) { fShowMineFlag = FALSE; MapBorderButtonOff( MAP_BORDER_MINE_BTN ); } else { fShowMineFlag = TRUE; MapBorderButtonOn( MAP_BORDER_MINE_BTN ); if (fShowTownFlag) { fShowTownFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); } if (fShowAircraftFlag) { fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } if (fShowItemsFlag) { fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } } fMapPanelDirty = TRUE; } static bool DoesPlayerHaveAnyMilitia(); void ToggleShowMilitiaMode( void ) { if (fShowMilitia) { fShowMilitia = FALSE; MapBorderButtonOff( MAP_BORDER_MILITIA_BTN ); } else { // toggle militia ON fShowMilitia = TRUE; MapBorderButtonOn( MAP_BORDER_MILITIA_BTN ); // if Team is ON, turn it OFF if (fShowTeamFlag) { fShowTeamFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TEAMS_BTN ); } /* // if Airspace is ON, turn it OFF if (fShowAircraftFlag) { fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } */ if (fShowItemsFlag) { fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } // check if player has any militia if (!DoesPlayerHaveAnyMilitia()) { ST::string pwString; // no - so put up a message explaining how it works // if he's already training some if( IsAnyOneOnPlayersTeamOnThisAssignment( TRAIN_TOWN ) ) { // say they'll show up when training is completed pwString = pMapErrorString[ 28 ]; } else { // say you need to train them first pwString = zMarksMapScreenText[ 1 ]; } BeginMapUIMessage(0, pwString); } } fMapPanelDirty = TRUE; } void ToggleShowTeamsMode( void ) { if (fShowTeamFlag) { // turn show teams OFF fShowTeamFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TEAMS_BTN ); // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } else { // turn show teams ON TurnOnShowTeamsMode(); } } void ToggleAirspaceMode( void ) { if (fShowAircraftFlag) { // turn airspace OFF fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); if (fPlotForHelicopter) { AbortMovementPlottingMode( ); } // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } else { // turn airspace ON TurnOnAirSpaceMode(); } } static void TurnOnItemFilterMode(void); void ToggleItemsFilter( void ) { if (fShowItemsFlag) { // turn items OFF fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } else { // turn items ON TurnOnItemFilterMode(); } } static void DisplayCurrentLevelMarker(void) { // display the current level marker on the map border /* if( fDisabledMapBorder ) { return; } */ // it's actually a white rectangle, not a green arrow! BltVideoObject(guiSAVEBUFFER, guiLEVELMARKER, 0, MAP_LEVEL_MARKER_X, MAP_LEVEL_MARKER_Y + MAP_LEVEL_MARKER_DELTA * iCurrentMapSectorZ); } static void LevelMarkerBtnCallback(MOUSE_REGION* pRegion, INT32 iReason); void CreateMouseRegionsForLevelMarkers(void) { for (UINT sCounter = 0; sCounter < 4 ; ++sCounter) { MOUSE_REGION* const r = &LevelMouseRegions[sCounter]; const UINT16 x = MAP_LEVEL_MARKER_X; const UINT16 y = MAP_LEVEL_MARKER_Y + MAP_LEVEL_MARKER_DELTA * sCounter; const UINT16 w = MAP_LEVEL_MARKER_WIDTH; const UINT16 h = MAP_LEVEL_MARKER_DELTA; MSYS_DefineRegion(r, x, y, x + w, y + h, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, LevelMarkerBtnCallback); MSYS_SetRegionUserData(r, 0, sCounter); ST::string sString = ST::format("{} {}", zMarksMapScreenText[0], sCounter + 1); r->SetFastHelpText(sString); } } void DeleteMouseRegionsForLevelMarkers() { FOR_EACH(MOUSE_REGION, i, LevelMouseRegions) MSYS_RemoveRegion(&*i); } static void LevelMarkerBtnCallback(MOUSE_REGION* pRegion, INT32 iReason) { // btn callback handler for assignment screen mask region INT32 iCounter = 0; iCounter = MSYS_GetRegionUserData( pRegion, 0 ); if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) { JumpToLevel( iCounter ); } } /* void DisableMapBorderRegion( void ) { // will shutdown map border region if( fDisabledMapBorder ) { // checked, failed return; } // get rid of graphics and mouse regions DeleteMapBorderGraphics( ); fDisabledMapBorder = TRUE; } void EnableMapBorderRegion( void ) { // will re-enable mapborder region if (!fDisabledMapBorder) { // checked, failed return; } // re load graphics and buttons LoadMapBorderGraphics( ); fDisabledMapBorder = FALSE; } */ void TurnOnShowTeamsMode( void ) { // if mode already on, leave, else set and redraw if (!fShowTeamFlag) { fShowTeamFlag = TRUE; MapBorderButtonOn( MAP_BORDER_TEAMS_BTN ); if (fShowMilitia) { fShowMilitia = FALSE; MapBorderButtonOff( MAP_BORDER_MILITIA_BTN ); } /* if (fShowAircraftFlag) { fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } */ if (fShowItemsFlag) { fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } } void TurnOnAirSpaceMode( void ) { // if mode already on, leave, else set and redraw if (!fShowAircraftFlag) { fShowAircraftFlag = TRUE; MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN ); // Turn off towns & mines (mostly because town/mine names overlap SAM site names) if (fShowTownFlag) { fShowTownFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); } if (fShowMineFlag) { fShowMineFlag = FALSE; MapBorderButtonOff( MAP_BORDER_MINE_BTN ); } /* // Turn off teams and militia if (fShowTeamFlag) { fShowTeamFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TEAMS_BTN ); } if (fShowMilitia) { fShowMilitia = FALSE; MapBorderButtonOff( MAP_BORDER_MILITIA_BTN ); } */ // Turn off items if (fShowItemsFlag) { fShowItemsFlag = FALSE; MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } if ( bSelectedDestChar != -1 ) { AbortMovementPlottingMode( ); } // if showing underground if ( iCurrentMapSectorZ != 0 ) { // switch to the surface JumpToLevel( 0 ); } // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } } static void TurnOnItemFilterMode(void) { // if mode already on, leave, else set and redraw if (!fShowItemsFlag) { fShowItemsFlag = TRUE; MapBorderButtonOn( MAP_BORDER_ITEM_BTN ); // Turn off towns, mines, teams, militia & airspace if any are on if (fShowTownFlag) { fShowTownFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); } if (fShowMineFlag) { fShowMineFlag = FALSE; MapBorderButtonOff( MAP_BORDER_MINE_BTN ); } if (fShowTeamFlag) { fShowTeamFlag = FALSE; MapBorderButtonOff( MAP_BORDER_TEAMS_BTN ); } if (fShowMilitia) { fShowMilitia = FALSE; MapBorderButtonOff( MAP_BORDER_MILITIA_BTN ); } if (fShowAircraftFlag) { fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } if (bSelectedDestChar != -1 || fPlotForHelicopter) { AbortMovementPlottingMode( ); } // dirty regions fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; } } // set button states to match map flags static void InitializeMapBorderButtonStates(void) { if( fShowItemsFlag ) { MapBorderButtonOn( MAP_BORDER_ITEM_BTN ); } else { MapBorderButtonOff( MAP_BORDER_ITEM_BTN ); } if( fShowTownFlag ) { MapBorderButtonOn( MAP_BORDER_TOWN_BTN ); } else { MapBorderButtonOff( MAP_BORDER_TOWN_BTN ); } if( fShowMineFlag ) { MapBorderButtonOn( MAP_BORDER_MINE_BTN ); } else { MapBorderButtonOff( MAP_BORDER_MINE_BTN ); } if( fShowTeamFlag ) { MapBorderButtonOn( MAP_BORDER_TEAMS_BTN ); } else { MapBorderButtonOff( MAP_BORDER_TEAMS_BTN ); } if( fShowAircraftFlag ) { MapBorderButtonOn( MAP_BORDER_AIRSPACE_BTN ); } else { MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } if( fShowMilitia ) { MapBorderButtonOn( MAP_BORDER_MILITIA_BTN ); } else { MapBorderButtonOff( MAP_BORDER_MILITIA_BTN ); } } static bool DoesPlayerHaveAnyMilitia() { FOR_EACH(SECTORINFO const, i, SectorInfo) { UINT8 const (&n)[MAX_MILITIA_LEVELS] = i->ubNumberOfCivsAtLevel; if (n[GREEN_MILITIA] + n[REGULAR_MILITIA] + n[ELITE_MILITIA] != 0) return true; } return false; } static void CommonBtnCallbackBtnDownChecks(void) { // any click cancels MAP UI messages, unless we're in confirm map move mode if (g_ui_message_overlay != NULL && !gfInConfirmMapMoveMode) { CancelMapUIMessage( ); } } void InitMapScreenFlags( void ) { fShowTownFlag = TRUE; fShowMineFlag = FALSE; fShowTeamFlag = TRUE; fShowMilitia = FALSE; fShowAircraftFlag = FALSE; fShowItemsFlag = FALSE; } static void MapBorderButtonOff(UINT8 ubBorderButtonIndex) { Assert( ubBorderButtonIndex < 6 ); if( fShowMapInventoryPool ) { return; } // if button doesn't exist, return GUIButtonRef const b = giMapBorderButtons[ubBorderButtonIndex]; if (b) b->uiFlags &= ~BUTTON_CLICKED_ON; } static void MapBorderButtonOn(UINT8 ubBorderButtonIndex) { Assert( ubBorderButtonIndex < 6 ); if( fShowMapInventoryPool ) { return; } GUIButtonRef const b = giMapBorderButtons[ubBorderButtonIndex]; if (b) b->uiFlags |= BUTTON_CLICKED_ON; }