// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" #else #include "Font.h" #include "Font Control.h" #include "mapscreen.h" #include "Map Screen Interface.h" #include "Map Screen Interface Map.h" #include "Map Screen Interface Border.h" #include "Overhead.h" #include "Render Dirty.h" #include "sysutil.h" #include "strategic.h" #include "strategicmap.h" #include "Strategic Pathing.h" #include "Text.h" #include "vsurface.h" #include "video.h" #include "vobject_blitters.h" #include "WCheck.h" #include "Assignments.h" #include "Squads.h" #include "Message.h" #include "Soldier Profile.h" #include "Player Command.h" #include "Strategic Movement.h" #include "Queen Command.h" #include "Campaign Types.h" #include "Strategic Town Loyalty.h" #include "Strategic Mines.h" #include "Vehicles.h" #include "Map Screen Helicopter.h" #include "Game Clock.h" #include "finances.h" #include "line.h" #include "english.h" #include "PreBattle Interface.h" #include "Utilities.h" #include "Town Militia.h" #include "Militia Control.h" #include "GameSettings.h" #include "Tactical Save.h" #include "Map Information.h" #include "Air Raid.h" #endif // zoom x and y coords for map scrolling INT32 iZoomX = 0; INT32 iZoomY = 0; // Scroll region width #define SCROLL_REGION 4 // The Map/Mouse Scroll defines #define EAST_DIR 0 #define WEST_DIR 1 #define NORTH_DIR 2 #define SOUTH_DIR 3 #define TOP_NORTH 2 #define TOP_SOUTH 13 #define RIGHT_WEST 250 #define RIGHT_EAST 260 #define LEFT_EAST 640 #define LEFT_WEST 630 #define BOTTOM_NORTH 320 #define BOTTOM_SOUTH 330 // Map Scroll Defines #define SCROLL_EAST 0 #define SCROLL_WEST 1 #define SCROLL_NORTH 2 #define SCROLL_SOUTH 3 #define SCROLL_DELAY 50 #define HORT_SCROLL 14 #define VERT_SCROLL 10 // the pop up for helicopter stuff #define MAP_HELICOPTER_ETA_POPUP_X (400 + iScreenWidthOffset) #define MAP_HELICOPTER_ETA_POPUP_Y (250 + iScreenHeightOffset) #define MAP_HELICOPTER_UPPER_ETA_POPUP_Y (50 + iScreenHeightOffset) #define MAP_HELICOPTER_ETA_POPUP_WIDTH 120 #define MAP_HELICOPTER_ETA_POPUP_HEIGHT 68 // WANNE 2 #define MAP_LEVEL_STRING_X (SCREEN_WIDTH - 208) //432 #define MAP_LEVEL_STRING_Y (SCREEN_HEIGHT - 175) //305 // font #define MAP_FONT BLOCKFONT2 // index color #define MAP_INDEX_COLOR 32*4-9 // max number of sectors viewable #define MAX_VIEW_SECTORS 16 //Map Location index regions // WANNE 2 // WANNE 2 (The numbers above the map) // x start of hort index #define MAP_HORT_INDEX_X (MAP_BORDER_X + MAP_BORDER_X_OFFSET + 31)//(SCREEN_WIDTH - 348) //292 // y position of hort index #define MAP_HORT_INDEX_Y (MAP_BORDER_Y + MAP_BORDER_Y_OFFSET + 8) // height of hort index #define MAP_HORT_HEIGHT GetFontHeight(MAP_FONT) // WANNE 2 (the letters on the left side of the map) // vert index start x #define MAP_VERT_INDEX_X (MAP_BORDER_X + MAP_BORDER_X_OFFSET + 13) //(SCREEN_WIDTH - 367) // 273 // vert index start y #define MAP_VERT_INDEX_Y (MAP_BORDER_Y + MAP_BORDER_Y_OFFSET + 29) // vert width #define MAP_VERT_WIDTH GetFontHeight(MAP_FONT) // "Boxes" Icons #define SMALL_YELLOW_BOX 0 #define BIG_YELLOW_BOX 1 #define SMALL_DULL_YELLOW_BOX 2 #define BIG_DULL_YELLOW_BOX 3 #define SMALL_WHITE_BOX 4 #define BIG_WHITE_BOX 5 #define SMALL_RED_BOX 6 #define BIG_RED_BOX 7 #define SMALL_QUESTION_MARK 8 #define BIG_QUESTION_MARK 9 #define MERC_ICONS_PER_LINE 6 #define ROWS_PER_SECTOR 5 #define MAP_X_ICON_OFFSET 2 #define MAP_Y_ICON_OFFSET 1 // Arrow Offsets #define UP_X 13 #define UP_Y 7 #define DOWN_X 0 #define DOWN_Y -2 #define RIGHT_X -2 #define RIGHT_Y 11 #define LEFT_X 2 #define LEFT_Y 5 // The Path Lines #define NORTH_LINE 1 #define SOUTH_LINE 0 #define WEST_LINE 3 #define EAST_LINE 2 #define N_TO_E_LINE 4 #define E_TO_S_LINE 5 #define W_TO_N_LINE 6 #define S_TO_W_LINE 7 #define W_TO_S_LINE 8 #define N_TO_W_LINE 9 #define S_TO_E_LINE 10 #define E_TO_N_LINE 11 #define W_TO_E_LINE 12 #define N_TO_S_LINE 13 #define E_TO_W_LINE 14 #define S_TO_N_LINE 15 #define W_TO_E_PART1_LINE 16 #define W_TO_E_PART2_LINE 17 #define E_TO_W_PART1_LINE 18 #define E_TO_W_PART2_LINE 19 #define N_TO_S_PART1_LINE 20 #define N_TO_S_PART2_LINE 21 #define S_TO_N_PART1_LINE 22 #define S_TO_N_PART2_LINE 23 #define GREEN_X_WEST 36 #define GREEN_X_EAST 37 #define GREEN_X_NORTH 38 #define GREEN_X_SOUTH 39 #define RED_X_WEST 40 #define RED_X_EAST 41 #define RED_X_NORTH 42 #define RED_X_SOUTH 43 // The arrows #define Y_NORTH_ARROW 24 #define Y_SOUTH_ARROW 25 #define Y_EAST_ARROW 26 #define Y_WEST_ARROW 27 #define W_NORTH_ARROW 28 #define W_SOUTH_ARROW 29 #define W_EAST_ARROW 30 #define W_WEST_ARROW 31 #define NORTH_ARROW 32 #define SOUTH_ARROW 33 #define EAST_ARROW 34 #define WEST_ARROW 35 #define ZOOM_Y_NORTH_ARROW 68 #define ZOOM_Y_SOUTH_ARROW 69 #define ZOOM_Y_EAST_ARROW 70 #define ZOOM_Y_WEST_ARROW 71 #define ZOOM_W_NORTH_ARROW 72 #define ZOOM_W_SOUTH_ARROW 73 #define ZOOM_W_EAST_ARROW 74 #define ZOOM_W_WEST_ARROW 75 #define ZOOM_NORTH_ARROW 76 #define ZOOM_SOUTH_ARROW 77 #define ZOOM_EAST_ARROW 78 #define ZOOM_WEST_ARROW 79 #define ARROW_DELAY 20 #define PAUSE_DELAY 1000 // The zoomed in path lines #define SOUTH_ZOOM_LINE 44 #define NORTH_ZOOM_LINE 45 #define EAST_ZOOM_LINE 46 #define WEST_ZOOM_LINE 47 #define N_TO_E_ZOOM_LINE 48 #define E_TO_S_ZOOM_LINE 49 #define W_TO_N_ZOOM_LINE 50 #define S_TO_W_ZOOM_LINE 51 #define W_TO_S_ZOOM_LINE 52 #define N_TO_W_ZOOM_LINE 53 #define S_TO_E_ZOOM_LINE 54 #define E_TO_N_ZOOM_LINE 55 #define W_TO_E_ZOOM_LINE 56 #define N_TO_S_ZOOM_LINE 57 #define E_TO_W_ZOOM_LINE 58 #define S_TO_N_ZOOM_LINE 59 #define ZOOM_GREEN_X_WEST 80 #define ZOOM_GREEN_X_EAST 81 #define ZOOM_GREEN_X_NORTH 82 #define ZOOM_GREEN_X_SOUTH 83 #define ZOOM_RED_X_WEST 84 #define ZOOM_RED_X_EAST 85 #define ZOOM_RED_X_NORTH 86 #define ZOOM_RED_X_SOUTH 87 #define CHAR_FONT_COLOR 32*4-9 // Arrow Offsets #define EAST_OFFSET_X 11 #define EAST_OFFSET_Y 0 #define NORTH_OFFSET_X 9 #define NORTH_OFFSET_Y -9 #define SOUTH_OFFSET_X -9 #define SOUTH_OFFSET_Y 9 #define WEST_OFFSET_X -11 #define WEST_OFFSET_Y 0 #define WEST_TO_SOUTH_OFFSET_Y 0 #define EAST_TO_NORTH_OFFSET_Y 0 #define RED_WEST_OFF_X -MAP_GRID_X #define RED_EAST_OFF_X MAP_GRID_X #define RED_NORTH_OFF_Y -21 #define RED_SOUTH_OFF_Y 21 // the font use on the mvt icons for mapscreen #define MAP_MVT_ICON_FONT SMALLCOMPFONT // map shading colors enum{ MAP_SHADE_BLACK =0, MAP_SHADE_LT_GREEN, MAP_SHADE_DK_GREEN, MAP_SHADE_LT_RED, MAP_SHADE_DK_RED, }; // the big map .pcx UINT32 guiBIGMAP; // orta .sti icon UINT32 guiORTAICON; UINT32 guiTIXAICON; // boxes for characters on the map UINT32 guiCHARICONS; // the merc arrival sector landing zone icon UINT32 guiBULLSEYE; // the max allowable towns militia in a sector #define MAP_MILITIA_MAP_X 4 #define MAP_MILITIA_MAP_Y 20 #define MAP_MILITIA_LOWER_ROW_Y 142 #define NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW 25 #define MILITIA_BOX_ROWS 3 #define MILITIA_BOX_BOX_HEIGHT 36 #define MILITIA_BOX_BOX_WIDTH 42 #define MAP_MILITIA_BOX_POS_X 400 #define MAP_MILITIA_BOX_POS_Y 125 #define POPUP_MILITIA_ICONS_PER_ROW 5 // max 6 rows gives the limit of 30 militia #define MEDIUM_MILITIA_ICON_SPACING 5 #define LARGE_MILITIA_ICON_SPACING 6 #define MILITIA_BTN_OFFSET_X 26 #define MILITIA_BTN_HEIGHT 11 #define MILITIA_BOX_WIDTH 133 #define MILITIA_BOX_TEXT_OFFSET_Y 4 #define MILITIA_BOX_UNASSIGNED_TEXT_OFFSET_Y 132 #define MILITIA_BOX_TEXT_TITLE_HEIGHT 13 #define MAP_MILITIA_BOX_AUTO_BOX_X 4 #define MAP_MILITIA_BOX_AUTO_BOX_Y 167 #define MAP_MILITIA_BOX_DONE_BOX_X 67 #define HELI_ICON 0 #define HELI_SHADOW_ICON 1 #define HELI_ICON_WIDTH 20 #define HELI_ICON_HEIGHT 10 #define HELI_SHADOW_ICON_WIDTH 19 #define HELI_SHADOW_ICON_HEIGHT 11 // the militia box buttons and images INT32 giMapMilitiaButtonImage[ 5 ]; INT32 giMapMilitiaButton[ 5 ] = { -1, -1, -1, -1, -1 }; INT16 gsMilitiaSectorButtonColors[]={ FONT_LTGREEN, FONT_LTBLUE, 16, }; // track number of townspeople picked up INT16 sGreensOnCursor = 0; INT16 sRegularsOnCursor = 0; INT16 sElitesOnCursor = 0; // the current militia town id INT16 sSelectedMilitiaTown = 0; extern MINE_LOCATION_TYPE gMineLocation[]; extern MINE_STATUS_TYPE gMineStatus[]; // sublevel graphics UINT32 guiSubLevel1, guiSubLevel2, guiSubLevel3; // the between sector icons UINT32 guiCHARBETWEENSECTORICONS; UINT32 guiCHARBETWEENSECTORICONSCLOSE; extern BOOLEAN fMapScreenBottomDirty; // tixa found BOOLEAN fFoundTixa = FALSE; // selected sector UINT16 sSelMapX = 9; UINT16 sSelMapY = 1; // highlighted sector INT16 gsHighlightSectorX=-1; INT16 gsHighlightSectorY=-1; // the current sector Z value of the map being displayed INT32 iCurrentMapSectorZ = 0; // the palettes UINT16 *pMapLTRedPalette; UINT16 *pMapDKRedPalette; UINT16 *pMapLTGreenPalette; UINT16 *pMapDKGreenPalette; // the map border eta pop up UINT32 guiMapBorderEtaPopUp; // heli pop up UINT32 guiMapBorderHeliSectors; // list of map sectors that player isn't allowed to even highlight BOOLEAN sBadSectorsList[ WORLD_MAP_X ][ WORLD_MAP_X ]; INT16 sBaseSectorList[ MAX_TOWNS - 1 ];/*={ // NOTE: These co-ordinates must match the top left corner of the 3x3 town tiles cutouts in Interface/MilitiaMaps.sti! SECTOR( 9, 1 ), // Omerta SECTOR( 13, 2 ), // Drassen SECTOR( 13, 8 ), // Alma SECTOR( 1, 7 ), // Grumm SECTOR( 8, 9 ), // Tixa SECTOR( 8, 6 ), // Cambria SECTOR( 4, 2 ), // San Mona SECTOR( 5, 8 ), // Estoni SECTOR( 3,10 ), // Orta SECTOR( 11,11 ), // Balime SECTOR( 3,14 ), // Meduna SECTOR( 2, 1 ), // Chitzena };*/ // position of town names on the map // these are no longer PIXELS, but 10 * the X,Y position in SECTORS (fractions possible) to the X-CENTER of the town POINT pTownPoints[ MAX_TOWNS ];/*={ { 0 , 0 }, { 90, 10}, // Omerta {125, 40}, // Drassen {130, 90}, // Alma { 15, 80}, // Grumm { 85,100}, // Tixa { 95, 70}, // Cambria { 45, 40}, // San Mona { 55, 90}, // Estoni { 35,110}, // Orta {110,120}, // Balime { 45,150}, // Meduna { 15, 20}, // Chitzena }; */ // coordinates X,Y of sam sites on strategic map INT16 gpSamSectorX[ MAX_NUMBER_OF_SAMS ]; INT16 gpSamSectorY[ MAX_NUMBER_OF_SAMS ]; extern BOOLEAN fSamSiteFoundOrig[ MAX_NUMBER_OF_SAMS ]; // WANNE 2 (reinitialization in "DrawMap()") // map region SGPRect MapScreenRect={ (MAP_VIEW_START_X+MAP_GRID_X - 2), ( MAP_VIEW_START_Y+MAP_GRID_Y - 1), MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X , MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y}; extern SGPRect gOldClipRect; // symbol already declared globally in renderworld.cpp (jonathanl) // screen region SGPRect FullScreenRect;//={ 0, 0, 1024, 768 }; // temp helicopter path PathStPtr pTempHelicopterPath = NULL; // character temp path PathStPtr pTempCharacterPath = NULL; // draw temp path? BOOLEAN fDrawTempHeliPath = FALSE; // the map arrows graphics UINT32 guiMAPCURSORS; // destination plotting character INT8 bSelectedDestChar = -1; // assignment selection character INT8 bSelectedAssignChar=-1; // current contract char INT8 bSelectedContractChar = -1; // has the temp path for character or helicopter been already drawn? BOOLEAN fTempPathAlreadyDrawn = FALSE; // the regions for the mapscreen militia box MOUSE_REGION gMapScreenMilitiaBoxRegions[ 9 ]; MOUSE_REGION gMapScreenMilitiaRegion; // the mine icon UINT32 guiMINEICON; // militia graphics UINT32 guiMilitia; UINT32 guiMilitiaMaps; UINT32 guiMilitiaSectorHighLight; UINT32 guiMilitiaSectorOutline; // the sector that is highlighted on the militia map INT16 sSectorMilitiaMapSector = -1; BOOLEAN fMilitiaMapButtonsCreated = FALSE; INT16 sSectorMilitiaMapSectorOutline = -1; // have any nodes in the current path list been deleted? BOOLEAN fDeletedNode = FALSE; UINT16 gusUndergroundNearBlack; BOOLEAN gfMilitiaPopupCreated = FALSE; INT32 giAnimateRouteBaseTime = 0; INT32 giPotHeliPathBaseTime = 0; INT32 giClickHeliIconBaseTime = 0; // display the level string on the strategic map void DisplayLevelString( void ); void ShowTownText( void ); void DrawTownLabels(STR16 pString, STR16 pStringA,UINT16 usFirstX, UINT16 usFirstY); void ShowTeamAndVehicles(INT32 fShowFlags); BOOLEAN ShadeMapElem( INT16 sMapX, INT16 sMapY, INT32 iColor ); BOOLEAN ShadeMapElemZoomIn(INT16 sMapX, INT16 sMapY, INT32 iColor ); void AdjustXForLeftMapEdge(STR16 wString, INT16 *psX); void BlitTownGridMarkers( void ); void BlitMineGridMarkers( void ); void BlitSAMGridMarkers( void ); void BlitMineIcon( INT16 sMapX, INT16 sMapY ); void BlitMineText( INT16 sMapX, INT16 sMapY ); extern BOOLEAN GetMouseMapXY( INT16 *psMapWorldX, INT16 *psMapWorldY ); INT16 GetBaseSectorForCurrentTown( void ); void RenderIconsPerSectorForSelectedTown( void ); void MilitiaRegionClickCallback( MOUSE_REGION *pRegion, INT32 iReason ); void MilitiaRegionMoveCallback( MOUSE_REGION *pRegion, INT32 iReason ); void CreateDestroyMilitiaSectorButtons( void ); void ShowHighLightedSectorOnMilitiaMap( void ); void SetMilitiaMapButtonsText( void ); void MilitiaButtonCallback(GUI_BUTTON *btn,INT32 reason); void DisplayUnallocatedMilitia( void ); BOOLEAN IsThisMilitiaTownSectorAllowable( INT16 sSectorIndexValue ); void DrawTownMilitiaName( void ); void HandleShutDownOfMilitiaPanelIfPeopleOnTheCursor( INT16 sTownValue ); void HandleEveningOutOfTroopsAmongstSectors( void ); void CreateMilitiaPanelBottomButton( void ); void DeleteMilitiaPanelBottomButton( void ); void MilitiaDoneButtonCallback(GUI_BUTTON *btn,INT32 reason); void MilitiaAutoButtonCallback(GUI_BUTTON *btn,INT32 reason); void RenderShadingForUnControlledSectors( void ); void DrawTownMilitiaForcesOnMap( void ); void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void ); void HandleLowerLevelMapBlit( void ); void ShowSAMSitesOnStrategicMap( void ); //UINT8 NumActiveCharactersInSector( INT16 sSectorX, INT16 sSectorY, INT16 bSectorZ ); //UINT8 NumFriendlyInSector( INT16 sX, INT16 sY, INT8 bZ ); // callbacks void MilitiaBoxMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); // display potential path, yes or no? void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ); void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT8 ubIconPosition ); void ShowUncertainNumberEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubIconPosition ); BOOLEAN CanMilitiaAutoDistribute( void ); void ShowItemsOnMap( void ); void DrawMapBoxIcon( HVOBJECT hIconHandle, UINT16 usVOIndex, INT16 sMapX, INT16 sMapY, UINT8 ubIconPosition ); void DisplayDestinationOfHelicopter( void ); void DrawOrta(); void DrawTixa(); void DrawBullseye(); void HideExistenceOfUndergroundMapSector( UINT8 ubSectorX, UINT8 ubSectorY ); BOOLEAN CanMercsScoutThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ); BOOLEAN TraceCharAnimatedRoute( PathStPtr pPath, BOOLEAN fCheckFlag, BOOLEAN fForceUpDate ); void AnimateRoute( PathStPtr pPath ); extern void EndConfirmMapMoveMode( void ); extern BOOLEAN CanDrawSectorCursor( void ); void DrawMapIndexBigMap( BOOLEAN fSelectedCursorIsYellow ) { // this procedure will draw the coord indexes on the zoomed out map INT16 usX, usY; INT32 iCount=0; BOOLEAN fDrawCursors; SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); //SetFontColors(FONT_FCOLOR_GREEN) SetFont(MAP_FONT); SetFontForeground(MAP_INDEX_COLOR); // Dk Red is 163 SetFontBackground(FONT_MCOLOR_BLACK); fDrawCursors = CanDrawSectorCursor( ); for(iCount=1; iCount <= MAX_VIEW_SECTORS; iCount++) { if( fDrawCursors && ( iCount == sSelMapX ) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); else if( fDrawCursors && ( iCount == gsHighlightSectorX ) ) SetFontForeground(FONT_WHITE); else SetFontForeground(MAP_INDEX_COLOR); FindFontCenterCoordinates(((INT16)(MAP_HORT_INDEX_X+( iCount - 1) *MAP_GRID_X)), MAP_HORT_INDEX_Y, MAP_GRID_X, MAP_HORT_HEIGHT, pMapHortIndex[iCount], MAP_FONT, &usX, &usY); mprintf(usX,usY,pMapHortIndex[iCount]); if( fDrawCursors && ( iCount == sSelMapY) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); else if( fDrawCursors && ( iCount == gsHighlightSectorY ) ) SetFontForeground(FONT_WHITE); else SetFontForeground(MAP_INDEX_COLOR); FindFontCenterCoordinates(MAP_VERT_INDEX_X, ((INT16)(MAP_VERT_INDEX_Y+ ( iCount - 1) *MAP_GRID_Y)), MAP_HORT_HEIGHT, MAP_GRID_Y, pMapVertIndex[iCount], MAP_FONT, &usX, &usY); mprintf(usX,usY,pMapVertIndex[iCount]); } InvalidateRegion(MAP_VERT_INDEX_X, MAP_VERT_INDEX_Y,MAP_VERT_INDEX_X+MAP_HORT_HEIGHT, MAP_VERT_INDEX_Y+( iCount - 1 ) * MAP_GRID_Y ); InvalidateRegion(MAP_HORT_INDEX_X, MAP_HORT_INDEX_Y,MAP_HORT_INDEX_X + ( iCount - 1) * MAP_GRID_X, MAP_HORT_INDEX_Y+ MAP_HORT_HEIGHT); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } /* void DrawMapIndexSmallMap( BOOLEAN fSelectedCursorIsYellow ) { // this procedure will draw the coord indexes on the zoomed in map INT16 usX, usY; INT32 iCount=0; BOOLEAN fDrawCursors; SetFont(MAP_FONT); SetFontDestBuffer( FRAME_BUFFER, MAP_HORT_INDEX_X, MAP_HORT_INDEX_Y, MAP_HORT_INDEX_X+(MAX_VIEW_SECTORS)*MAP_GRID_X, MAP_HORT_INDEX_Y+MAP_GRID_Y, FALSE ); //SetFontColors(FONT_FCOLOR_GREEN) SetFont(MAP_FONT); SetFontForeground(MAP_INDEX_COLOR); SetFontBackground(FONT_MCOLOR_BLACK); fDrawCursors = CanDrawSectorCursor( ); for(iCount=1; iCount <= MAX_VIEW_SECTORS; iCount++) { if( fDrawCursors && ( iCount == sSelMapX ) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); else if( fDrawCursors && ( iCount == gsHighlightSectorX ) ) SetFontForeground(FONT_WHITE); else SetFontForeground(MAP_INDEX_COLOR); FindFontCenterCoordinates(((INT16)(MAP_HORT_INDEX_X+((iCount)*MAP_GRID_X)*2-iZoomX)), MAP_HORT_INDEX_Y, MAP_GRID_X*2, MAP_HORT_HEIGHT, pMapHortIndex[iCount], MAP_FONT, &usX, &usY); mprintf(usX,usY,pMapHortIndex[iCount]); } SetFontDestBuffer( FRAME_BUFFER, MAP_VERT_INDEX_X, MAP_VERT_INDEX_Y, MAP_VERT_INDEX_X+MAP_GRID_X, MAP_VERT_INDEX_Y+(MAX_VIEW_SECTORS)*MAP_GRID_Y, FALSE ); for(iCount=1; iCount <= MAX_VIEW_SECTORS; iCount++) { if( fDrawCursors && ( iCount == sSelMapY) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); else if( fDrawCursors && ( iCount == gsHighlightSectorY ) ) SetFontForeground(FONT_WHITE); else SetFontForeground(MAP_INDEX_COLOR); FindFontCenterCoordinates(MAP_VERT_INDEX_X, ((INT16)(MAP_VERT_INDEX_Y+(iCount*MAP_GRID_Y)*2-iZoomY)), MAP_HORT_HEIGHT, MAP_GRID_Y*2, pMapVertIndex[iCount], MAP_FONT, &usX, &usY); mprintf(usX,usY,pMapVertIndex[iCount]); } InvalidateRegion(MAP_VERT_INDEX_X, MAP_VERT_INDEX_Y,MAP_VERT_INDEX_X+MAP_HORT_HEIGHT, MAP_VERT_INDEX_Y+iCount*MAP_GRID_Y ); InvalidateRegion(MAP_HORT_INDEX_X, MAP_HORT_INDEX_Y,MAP_HORT_INDEX_X+iCount*MAP_GRID_X, MAP_HORT_INDEX_Y+ MAP_HORT_HEIGHT); SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE ); } */ void HandleShowingOfEnemiesWithMilitiaOn( void ) { INT16 sX = 0, sY = 0; // if show militia flag is false, leave if( !fShowMilitia ) { return; } for( sX = 1; sX < ( MAP_WORLD_X - 1 ); sX++ ) { for( sY = 1; sY < ( MAP_WORLD_Y - 1); sY++ ) { HandleShowingOfEnemyForcesInSector( sX, sY, ( INT8 )iCurrentMapSectorZ, CountAllMilitiaInSector( sX, sY ) ); } } return; } UINT32 DrawMap( void ) { HVSURFACE hSrcVSurface; UINT32 uiDestPitchBYTES; UINT32 uiSrcPitchBYTES; UINT16 *pDestBuf; UINT8 *pSrcBuf; SGPRect clip; INT16 cnt, cnt2; INT32 iCounter = 0; // WANNE 2 //MAP_VIEW_START_X = (SCREEN_WIDTH - 370); //MAP_VIEW_START_Y = 10; MapScreenRect.iLeft = MAP_VIEW_START_X+MAP_GRID_X - 2; MapScreenRect.iTop = MAP_VIEW_START_Y+MAP_GRID_Y - 1; MapScreenRect.iRight = MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X; MapScreenRect.iBottom = MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y; //MapScreenRect={ (MAP_VIEW_START_X+MAP_GRID_X - 2), ( MAP_VIEW_START_Y+MAP_GRID_Y - 1), MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X , MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y}; if( !iCurrentMapSectorZ ) { pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); // clip blits to mapscreen region //ClipBlitsToMapViewRegion( ); if (fZoomFlag) { // set up bounds if(iZoomX < WEST_ZOOM_BOUND) iZoomX=WEST_ZOOM_BOUND; if(iZoomX > EAST_ZOOM_BOUND) iZoomX=EAST_ZOOM_BOUND; if(iZoomY < NORTH_ZOOM_BOUND+1) iZoomY=NORTH_ZOOM_BOUND; if(iZoomY > SOUTH_ZOOM_BOUND) iZoomY=SOUTH_ZOOM_BOUND; clip.iLeft=iZoomX - 2; clip.iRight=clip.iLeft + MAP_VIEW_WIDTH + 2; clip.iTop=iZoomY - 3; clip.iBottom=clip.iTop + MAP_VIEW_HEIGHT - 1; /* clip.iLeft=clip.iLeft - 1; clip.iRight=clip.iLeft + MapScreenRect.iRight - MapScreenRect.iLeft; clip.iTop=iZoomY - 1; clip.iBottom=clip.iTop + MapScreenRect.iBottom - MapScreenRect.iTop; */ if( clip.iBottom > hSrcVSurface->usHeight ) { clip.iBottom = hSrcVSurface->usHeight; } if( clip.iRight > hSrcVSurface->usWidth ) { clip.iRight = hSrcVSurface->usWidth; } Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, MAP_VIEW_START_X+MAP_GRID_X, MAP_VIEW_START_Y+MAP_GRID_Y - 2, &clip); } else { Blt8BPPDataTo16BPPBufferHalf( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf, uiSrcPitchBYTES, MAP_VIEW_START_X + 1, MAP_VIEW_START_Y ); } UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); // shade map sectors (must be done after Tixa/Orta/Mine icons have been blitted, but before icons!) for ( cnt = 1; cnt < MAP_WORLD_X - 1; cnt++ ) { for ( cnt2 = 1; cnt2 < MAP_WORLD_Y - 1; cnt2++ ) { // LATE DESIGN CHANGE: darken sectors not yet visited, instead of those under known enemy control if( GetSectorFlagStatus( cnt, cnt2, ( UINT8 ) iCurrentMapSectorZ, SF_ALREADY_VISITED ) == FALSE ) // if ( IsTheSectorPerceivedToBeUnderEnemyControl( cnt, cnt2, ( INT8 )( iCurrentMapSectorZ ) ) ) { if( fShowAircraftFlag && !iCurrentMapSectorZ ) { if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) { // sector not visited, not air controlled ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_GREEN ); } else { // sector not visited, controlled and air not ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_RED ); } } else { // not visited ShadeMapElem( cnt, cnt2, MAP_SHADE_BLACK ); } } else { if( fShowAircraftFlag && !iCurrentMapSectorZ ) { if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) { // sector visited and air controlled ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_GREEN); } else { // sector visited but not air controlled ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_RED ); } } } } } // UNFORTUNATELY, WE CAN'T SHADE THESE ICONS AS PART OF SHADING THE MAP, BECAUSE FOR AIRSPACE, THE SHADE FUNCTION // DOESN'T MERELY SHADE THE EXISTING MAP SURFACE, BUT INSTEAD GRABS THE ORIGINAL GRAPHICS FROM BIGMAP, AND CHANGES // THEIR PALETTE. BLITTING ICONS PRIOR TO SHADING WOULD MEAN THEY DON'T SHOW UP IN AIRSPACE VIEW AT ALL. // if Orta found if( fFoundOrta ) { DrawOrta(); } // if Tixa found if( fFoundTixa ) { DrawTixa(); } // draw SAM sites ShowSAMSitesOnStrategicMap( ); // draw mine icons for( iCounter = 0; iCounter < MAX_NUMBER_OF_MINES; iCounter++ ) { BlitMineIcon( gMineLocation[ iCounter ].sSectorX, gMineLocation[ iCounter ].sSectorY ); } // if mine details filter is set if( fShowMineFlag ) { // show mine name/production text for( iCounter = 0; iCounter < MAX_NUMBER_OF_MINES; iCounter++ ) { BlitMineText( gMineLocation[ iCounter ].sSectorX, gMineLocation[ iCounter ].sSectorY ); } } // draw towns names & loyalty ratings, and grey town limit borders if( fShowTownFlag ) { BlitTownGridMarkers( ); ShowTownText( ); } // draw militia icons if( fShowMilitia ) { DrawTownMilitiaForcesOnMap( ); } if ( fShowAircraftFlag && !gfInChangeArrivalSectorMode ) { DrawBullseye(); } } else { HandleLowerLevelMapBlit( ); } // show mine outlines even when viewing underground sublevels - they indicate where the mine entrances are if( fShowMineFlag ) // draw grey mine sector borders BlitMineGridMarkers( ); // do not show mercs/vehicles when airspace is ON // commented out on a trial basis! // if( !fShowAircraftFlag ) { if( fShowTeamFlag ) ShowTeamAndVehicles( SHOW_TEAMMATES | SHOW_VEHICLES ); else HandleShowingOfEnemiesWithMilitiaOn( ); /* if((fShowTeamFlag)&&(fShowVehicleFlag)) ShowTeamAndVehicles(SHOW_TEAMMATES | SHOW_VEHICLES); else if(fShowTeamFlag) ShowTeamAndVehicles(SHOW_TEAMMATES); else if(fShowVehicleFlag) ShowTeamAndVehicles(SHOW_VEHICLES); else { HandleShowingOfEnemiesWithMilitiaOn( ); } */ } if ( fShowItemsFlag ) { ShowItemsOnMap(); } DisplayLevelString( ); // WANNE 2 RestoreClipRegionToFullScreen( ); return( TRUE ); } void GetScreenXYFromMapXY( INT16 sMapX, INT16 sMapY, INT16 *psX, INT16 *psY ) { INT16 sXTempOff=1; INT16 sYTempOff=1; if (fZoomFlag) { *psX = ( (sMapX/2+sXTempOff) * MAP_GRID_ZOOM_X ) + MAP_VIEW_START_X; *psY = ( (sMapY/2+sYTempOff) * MAP_GRID_ZOOM_Y ) + MAP_VIEW_START_Y; } else { *psX = ( sMapX * MAP_GRID_X ) + MAP_VIEW_START_X; *psY = ( sMapY * MAP_GRID_Y ) + MAP_VIEW_START_Y; } } void GetScreenXYFromMapXYStationary( INT16 sMapX, INT16 sMapY, INT16 *psX, INT16 *psY ) { INT16 sXTempOff=1; INT16 sYTempOff=1; //(MAP_VIEW_START_X+((iCount+1)*MAP_GRID_X)*2-iZoomX)); *psX = ( (sMapX+sXTempOff) * MAP_GRID_X )*2-((INT16)iZoomX)+MAP_VIEW_START_X; *psY = ( (sMapY+sYTempOff) * MAP_GRID_Y )*2-((INT16)iZoomY)+MAP_VIEW_START_Y; } void ShowTownText( void ) { CHAR16 sString[ 32 ]; CHAR16 sStringA[ 32 ]; INT8 bTown = 0; UINT16 usX,usY; BOOLEAN fLoyaltyTooLowToTrainMilitia; INT32 iMinLoyaltyToTrain = gGameExternalOptions.iMinLoyaltyToTrain; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen1"); // this procedure will display the town names on the screen SetFont(MAP_FONT); SetFontBackground(FONT_MCOLOR_BLACK); for( bTown = FIRST_TOWN; bTown < NUM_TOWNS; bTown++) { // skip Orta/Tixa until found if( ( ( fFoundOrta != FALSE ) || ( bTown != ORTA ) ) && ( ( bTown != TIXA ) || ( fFoundTixa != FALSE) ) ) { swprintf( sString, L"%s", pTownNames[ bTown ] ); fLoyaltyTooLowToTrainMilitia = FALSE; // don't show loyalty string until loyalty tracking for that town has been started if( gTownLoyalty[ bTown ].fStarted && gfTownUsesLoyalty[ bTown ]) { swprintf( sStringA, L"%d%%%% %s", gTownLoyalty[ bTown ].ubRating, gsLoyalString[ 0 ]); // if loyalty is too low to train militia, and militia training is allowed here if ( ( gTownLoyalty[ bTown ].ubRating < iMinLoyaltyToTrain ) && MilitiaTrainingAllowedInTown( bTown ) ) { fLoyaltyTooLowToTrainMilitia = TRUE; } } else { wcscpy( sStringA, L""); } if(!fZoomFlag) { usX = (UINT16) (MAP_VIEW_START_X + MAP_GRID_X + (pTownPoints[ bTown ].x * MAP_GRID_X) / 10); usY = (UINT16) (MAP_VIEW_START_Y + MAP_GRID_Y + ((pTownPoints[ bTown ].y * MAP_GRID_Y) / 10) + 1); } else { usX = (UINT16) (MAP_VIEW_START_X + MAP_GRID_X + MAP_GRID_ZOOM_X - iZoomX + (pTownPoints[ bTown ].x * MAP_GRID_ZOOM_X) / 10); usY = (UINT16) (MAP_VIEW_START_Y + MAP_GRID_Y + MAP_GRID_ZOOM_Y - iZoomY + ((pTownPoints[ bTown ].y * MAP_GRID_ZOOM_Y) / 10) + 1); // usX = 2 * pTownPoints[ bTown ].x - iZoomX - MAP_VIEW_START_X + MAP_GRID_X; // usY = 2 * pTownPoints[ bTown ].y - iZoomY - MAP_VIEW_START_Y + MAP_GRID_Y; } // red for low loyalty, green otherwise SetFontForeground( ( UINT8 ) ( fLoyaltyTooLowToTrainMilitia ? FONT_MCOLOR_RED : FONT_MCOLOR_LTGREEN ) ); DrawTownLabels(sString, sStringA, usX, usY); } } } void DrawTownLabels(STR16 pString, STR16 pStringA, UINT16 usFirstX, UINT16 usFirstY) { // this procedure will draw the given strings on the screen centered around the given x and at the given y INT16 sSecondX, sSecondY; INT16 sPastEdge; // if within view region...render, else don't if( ( usFirstX > MAP_VIEW_START_X + MAP_VIEW_WIDTH )||( usFirstX < MAP_VIEW_START_X )|| (usFirstY < MAP_VIEW_START_Y ) || ( usFirstY > MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) ) { return; } SetFontDestBuffer( guiSAVEBUFFER, MapScreenRect.iLeft + 2, MapScreenRect.iTop, MapScreenRect.iRight, MapScreenRect.iBottom , FALSE ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); // we're CENTERING the first string AROUND usFirstX, so calculate the starting X usFirstX -= StringPixLength( pString, MAP_FONT) / 2; // print first string gprintfdirty( usFirstX, usFirstY, pString); mprintf(usFirstX, usFirstY, pString); // calculate starting coordinates for the second string VarFindFontCenterCoordinates(( INT16 )( usFirstX ), ( INT16 )usFirstY, StringPixLength( pString, MAP_FONT), 0, MAP_FONT, &sSecondX, &sSecondY, pStringA); // make sure we don't go past left edge (Grumm) if( !fZoomFlag ) { sPastEdge = (MAP_VIEW_START_X + 23) - sSecondX; if (sPastEdge > 0) sSecondX += sPastEdge; } // print second string beneath first sSecondY = ( INT16 )( usFirstY + GetFontHeight( MAP_FONT ) ); gprintfdirty( sSecondX, sSecondY, pStringA ); mprintf( sSecondX, sSecondY, pStringA ); // restore clip blits RestoreClipRegionToFullScreen( ); } // "on duty" includes mercs inside vehicles INT32 ShowOnDutyTeam( INT16 sMapX, INT16 sMapY ) { UINT8 ubCounter = 0, ubIconPosition = 0; HVOBJECT hIconHandle; SOLDIERTYPE *pSoldier = NULL; GetVideoObject(&hIconHandle, guiCHARICONS); // run through list while(gCharactersList[ubCounter].fValid) { pSoldier = MercPtrs[ gCharactersList[ ubCounter ].usSolID ]; if( !( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) && ( pSoldier->sSectorX == sMapX) && ( pSoldier->sSectorY == sMapY) && ( pSoldier->bSectorZ == iCurrentMapSectorZ ) && ( ( pSoldier->bAssignment < ON_DUTY ) || ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) ) && ( pSoldier->bLife > 0) && ( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) ) { DrawMapBoxIcon( hIconHandle, SMALL_YELLOW_BOX, sMapX, sMapY, ubIconPosition ); ubIconPosition++; } ubCounter++; } return ubIconPosition; } INT32 ShowAssignedTeam(INT16 sMapX, INT16 sMapY, INT32 iCount) { UINT8 ubCounter, ubIconPosition; HVOBJECT hIconHandle; SOLDIERTYPE *pSoldier = NULL; GetVideoObject(&hIconHandle, guiCHARICONS); ubCounter=0; // run through list ubIconPosition = ( UINT8 ) iCount; while(gCharactersList[ubCounter].fValid) { pSoldier = MercPtrs[ gCharactersList[ ubCounter ].usSolID ]; // given number of on duty members, find number of assigned chars // start at beginning of list, look for people who are in sector and assigned if( !( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) && ( pSoldier->sSectorX == sMapX) && ( pSoldier->sSectorY == sMapY) && ( pSoldier->bSectorZ == iCurrentMapSectorZ ) && ( pSoldier->bAssignment >= ON_DUTY ) && ( pSoldier->bAssignment != VEHICLE ) && ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bLife > 0 ) && ( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) ) { // skip mercs inside the helicopter if we're showing airspace level - they show up inside chopper icon instead if ( !fShowAircraftFlag || ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) { DrawMapBoxIcon( hIconHandle, SMALL_DULL_YELLOW_BOX, sMapX, sMapY, ubIconPosition ); ubIconPosition++; } } ubCounter++; } return ubIconPosition; } INT32 ShowVehicles(INT16 sMapX, INT16 sMapY, INT32 iCount) { UINT8 ubCounter, ubIconPosition; HVOBJECT hIconHandle; SOLDIERTYPE *pVehicleSoldier; GetVideoObject(&hIconHandle, guiCHARICONS); ubCounter=0; ubIconPosition = (UINT8) iCount; // run through list of vehicles while( ubCounter < ubNumberOfVehicles ) { // skip the chopper, it has its own icon and displays in airspace mode if ( ubCounter != iHelicopterVehicleId ) { if ( (pVehicleList[ ubCounter ].sSectorX == sMapX) && ( pVehicleList[ ubCounter ].sSectorY == sMapY ) ) { // don't show vehicles between sectors (in motion - they're counted as "people in motion" if( ( pVehicleList[ ubCounter ].sSectorZ == iCurrentMapSectorZ ) && !PlayerIDGroupInMotion( pVehicleList[ ubCounter ].ubMovementGroup ) ) { // ATE: Check if this vehicle has a soldier and it's on our team..... pVehicleSoldier = GetSoldierStructureForVehicle( ubCounter ); // this skips the chopper, which has no soldier if ( pVehicleSoldier ) { if ( pVehicleSoldier->bTeam == gbPlayerNum ) { DrawMapBoxIcon( hIconHandle, SMALL_WHITE_BOX, sMapX, sMapY, ubIconPosition ); ubIconPosition++; } } } } } ubCounter++; } return ubIconPosition; } void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT8 ubIconPosition ) { HVOBJECT hIconHandle; UINT8 ubEnemy = 0; // get the video object GetVideoObject(&hIconHandle, guiCHARICONS); for( ubEnemy = 0; ubEnemy < sNumberOfEnemies; ubEnemy++ ) { DrawMapBoxIcon( hIconHandle, SMALL_RED_BOX, sSectorX, sSectorY, ubIconPosition ); ubIconPosition++; } } void ShowUncertainNumberEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) { INT16 sXPosition = 0, sYPosition = 0; HVOBJECT hIconHandle; // grab the x and y postions sXPosition = sSectorX; sYPosition = sSectorY; // get the video object GetVideoObject(&hIconHandle, guiCHARICONS); // check if we are zoomed in...need to offset in case for scrolling purposes if(!fZoomFlag) { sXPosition = ( INT16 )( MAP_X_ICON_OFFSET + ( MAP_VIEW_START_X + ( sSectorX * MAP_GRID_X + 1 ) ) - 1 ); sYPosition = ( INT16 )( ( ( MAP_VIEW_START_Y + ( sSectorY * MAP_GRID_Y ) + 1 ) ) ); sYPosition -= 2; // small question mark BltVideoObject(guiSAVEBUFFER, hIconHandle, SMALL_QUESTION_MARK, sXPosition, sYPosition, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( sXPosition ,sYPosition, sXPosition + DMAP_GRID_X, sYPosition + DMAP_GRID_Y ); } /* else { INT16 sX = 0, sY = 0; GetScreenXYFromMapXYStationary( sSectorX, sSectorY, &sX, &sY ); sYPosition = sY-MAP_GRID_Y; sXPosition = sX-MAP_GRID_X; // get the x and y position sXPosition = MAP_X_ICON_OFFSET + sXPosition ; sYPosition = sYPosition - 1; // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); // large question mark BltVideoObject(guiSAVEBUFFER, hIconHandle, BIG_QUESTION_MARK, sXPosition, sYPosition, VO_BLT_SRCTRANSPARENCY, NULL ); // restore clip blits RestoreClipRegionToFullScreen( ); InvalidateRegion( sXPosition, sYPosition, sXPosition + DMAP_GRID_ZOOM_X, sYPosition + DMAP_GRID_ZOOM_Y ); } */ } void ShowTeamAndVehicles(INT32 fShowFlags) { // go through each sector, display the on duty, assigned, and vehicles INT16 sMapX = 0; INT16 sMapY = 0; INT32 iIconOffset = 0; BOOLEAN fContemplatingRetreating = FALSE; if( gfDisplayPotentialRetreatPaths && gpBattleGroup ) { fContemplatingRetreating = TRUE; } for(sMapX=1; sMapX ubSectorX ) || ( sMapY != gpBattleGroup->ubSectorY ) ) { if(fShowFlags & SHOW_TEAMMATES) { iIconOffset = ShowOnDutyTeam( sMapX, sMapY ); iIconOffset = ShowAssignedTeam( sMapX, sMapY, iIconOffset ); } if(fShowFlags & SHOW_VEHICLES) iIconOffset = ShowVehicles( sMapX, sMapY, iIconOffset ); } if(fShowFlags & SHOW_TEAMMATES) { HandleShowingOfEnemyForcesInSector( sMapX, sMapY, ( INT8 )iCurrentMapSectorZ, ( UINT8 ) iIconOffset ); ShowPeopleInMotion( sMapX, sMapY ); } } } } BOOLEAN ShadeMapElem( INT16 sMapX, INT16 sMapY, INT32 iColor ) { INT16 sScreenX, sScreenY; HVSURFACE hSrcVSurface; //HVSURFACE hSAMSurface; //HVSURFACE hMineSurface; UINT32 uiDestPitchBYTES; UINT32 uiSrcPitchBYTES; UINT16 *pDestBuf; UINT8 *pSrcBuf; SGPRect clip; UINT16 *pOriginalPallette; // get original video surface palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP ) ); // get original video surface palette //CHECKF( GetVideoSurface( &hSAMSurface, guiSAMICON ) ); // get original video surface palette //CHECKF( GetVideoSurface( &hMineSurface, guiMINEICON ) ); // get original video surface palette pOriginalPallette = hSrcVSurface->p16BPPPalette; if(fZoomFlag) ShadeMapElemZoomIn( sMapX, sMapY, iColor ); else { GetScreenXYFromMapXY( sMapX, sMapY, &sScreenX, &sScreenY ); // compensate for original BIG_MAP blit being done at MAP_VIEW_START_X + 1 sScreenX += 1; // compensate for original BIG_MAP blit being done at MAP_VIEW_START_X + 1 clip.iLeft = 2 * ( sScreenX - ( MAP_VIEW_START_X + 1 ) ); clip.iTop = 2 * ( sScreenY - MAP_VIEW_START_Y ); clip.iRight = clip.iLeft + ( 2 * MAP_GRID_X ); clip.iBottom = clip.iTop + ( 2 * MAP_GRID_Y ); if( iColor != MAP_SHADE_BLACK ) { // airspace /* if( sMapX == 1 ) { clip.iLeft -= 4; clip.iRight += 4; sScreenX -= 2; } else { sScreenX += 1; } */ } else { // non-airspace sScreenY -= 1; } switch( iColor ) { case( MAP_SHADE_BLACK ): // simply shade darker ShadowVideoSurfaceRect( guiSAVEBUFFER, sScreenX, sScreenY, sScreenX + MAP_GRID_X - 1, sScreenY + MAP_GRID_Y - 1 ); break; case( MAP_SHADE_LT_GREEN ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapLTGreenPalette; //hMineSurface->p16BPPPalette = pMapLTGreenPalette; //hSAMSurface->p16BPPPalette = pMapLTGreenPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); Blt8BPPDataTo16BPPBufferHalfRect( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY, &clip ); // now blit //Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY, &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_DK_GREEN ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapDKGreenPalette; //hMineSurface->p16BPPPalette = pMapDKGreenPalette; //hSAMSurface->p16BPPPalette = pMapDKGreenPalette; /// lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); Blt8BPPDataTo16BPPBufferHalfRect( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX , sScreenY, &clip ); // now blit //Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX , sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_LT_RED ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapLTRedPalette; //hMineSurface->p16BPPPalette = pMapLTRedPalette; //hSAMSurface->p16BPPPalette = pMapLTRedPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); Blt8BPPDataTo16BPPBufferHalfRect( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX , sScreenY, &clip ); // now blit //Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX , sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_DK_RED ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapDKRedPalette; //hMineSurface->p16BPPPalette = pMapDKRedPalette; //hSAMSurface->p16BPPPalette = pMapDKRedPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); Blt8BPPDataTo16BPPBufferHalfRect( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY, &clip ); // now blit //Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX , sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; } // restore original palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pOriginalPallette; //hMineSurface->p16BPPPalette = pOriginalPallette; //hSAMSurface->p16BPPPalette = pOriginalPallette; } return ( TRUE ); } BOOLEAN ShadeMapElemZoomIn(INT16 sMapX, INT16 sMapY, INT32 iColor ) { INT16 sScreenX, sScreenY; INT32 iX, iY; HVSURFACE hSrcVSurface; UINT32 uiDestPitchBYTES; UINT32 uiSrcPitchBYTES; UINT16 *pDestBuf; //UINT8 *pDestBuf2; UINT8 *pSrcBuf; SGPRect clip; UINT16 *pOriginalPallette; // get sX and sY iX=(INT32)sMapX; iY=(INT32)sMapY; // trabslate to screen co-ords for zoomed GetScreenXYFromMapXYStationary( ((UINT16)(iX)),((UINT16)(iY)) , &sScreenX, &sScreenY ); // shift left by one sector iY=(INT32)sScreenY-MAP_GRID_Y; iX=(INT32)sScreenX-MAP_GRID_X; // get original video surface palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pOriginalPallette = hSrcVSurface->p16BPPPalette; if((iX >MapScreenRect.iLeft-MAP_GRID_X*2)&&(iX MapScreenRect.iTop-MAP_GRID_Y*2)&&(iY < MapScreenRect.iBottom)) { sScreenX=(INT16)iX; sScreenY=(INT16)iY; if( iColor == MAP_SHADE_BLACK ) { clip.iLeft = sScreenX + 1; clip.iRight = sScreenX + MAP_GRID_X*2 - 1; clip.iTop = sScreenY; clip.iBottom = sScreenY + MAP_GRID_Y*2 - 1; } else { clip.iLeft=iZoomX + sScreenX - MAP_VIEW_START_X - MAP_GRID_X ; clip.iRight=clip.iLeft + MAP_GRID_X*2; clip.iTop=iZoomY + sScreenY - MAP_VIEW_START_Y - MAP_GRID_Y; clip.iBottom=clip.iTop + MAP_GRID_Y*2; if( sScreenY <= MapScreenRect.iTop + 10 ) { clip.iTop -= 5; sScreenY -= 5; } if( sMapX == 1 ) { clip.iLeft -= 5; sScreenX -= 4; } else { sScreenX +=1; } } if( sScreenX >= MapScreenRect.iRight - 2 * MAP_GRID_X ) { clip.iRight++; } if( sScreenY >= MapScreenRect.iBottom - 2 * MAP_GRID_X ) { clip.iBottom++; } sScreenX += 1; sScreenY += 1; if( ( sScreenX > MapScreenRect.iRight ) || ( sScreenY > MapScreenRect.iBottom ) ) { return( FALSE ); } switch( iColor ) { case( MAP_SHADE_BLACK ): // simply shade darker if( iCurrentMapSectorZ > 0 ) { ShadowVideoSurfaceRect( guiSAVEBUFFER, clip.iLeft, clip.iTop, clip.iRight, clip.iBottom ); } ShadowVideoSurfaceRect( guiSAVEBUFFER, clip.iLeft, clip.iTop, clip.iRight, clip.iBottom ); break; case( MAP_SHADE_LT_GREEN ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapLTGreenPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); // now blit Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY, &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_DK_GREEN ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapDKGreenPalette; /// lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); // now blit Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_LT_RED ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapLTRedPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); // now blit Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; case( MAP_SHADE_DK_RED ): // grab video surface and set palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pMapDKRedPalette; // lock source and dest buffers pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); pSrcBuf = LockVideoSurface( guiBIGMAP, &uiSrcPitchBYTES); // now blit Blt8BPPDataSubTo16BPPBuffer( pDestBuf, uiDestPitchBYTES, hSrcVSurface, pSrcBuf,uiSrcPitchBYTES, sScreenX, sScreenY , &clip); // unlock source and dest buffers UnLockVideoSurface( guiBIGMAP ); UnLockVideoSurface( guiSAVEBUFFER ); break; } } // restore original palette CHECKF( GetVideoSurface( &hSrcVSurface, guiBIGMAP) ); hSrcVSurface->p16BPPPalette = pOriginalPallette; return ( TRUE ); } BOOLEAN InitializePalettesForMap( void ) { // init palettes HVSURFACE hSrcVSurface; SGPPaletteEntry pPalette[ 256 ]; VSURFACE_DESC vs_desc; UINT32 uiTempMap; // load image vs_desc.fCreateFlags = VSURFACE_CREATE_FROMFILE | VSURFACE_SYSTEM_MEM_USAGE; strcpy(vs_desc.ImageFile, "INTERFACE\\b_map.pcx"); CHECKF(AddVideoSurface(&vs_desc, &uiTempMap)); // get video surface CHECKF( GetVideoSurface( &hSrcVSurface, uiTempMap) ); GetVSurfacePaletteEntries( hSrcVSurface, pPalette ); // set up various palettes pMapLTRedPalette = Create16BPPPaletteShaded( pPalette, 400, 0, 0, TRUE ); pMapDKRedPalette = Create16BPPPaletteShaded( pPalette, 200, 0, 0, TRUE ); pMapLTGreenPalette = Create16BPPPaletteShaded( pPalette, 0, 400, 0, TRUE ); pMapDKGreenPalette = Create16BPPPaletteShaded( pPalette, 0, 200, 0, TRUE ); // delete image DeleteVideoSurfaceFromIndex(uiTempMap); return ( TRUE ); } void ShutDownPalettesForMap( void ) { MemFree( pMapLTRedPalette ); MemFree( pMapDKRedPalette ); MemFree( pMapLTGreenPalette ); MemFree( pMapDKGreenPalette ); pMapLTRedPalette = NULL; pMapDKRedPalette = NULL; pMapLTGreenPalette = NULL; pMapDKGreenPalette = NULL; return; } void PlotPathForCharacter( SOLDIERTYPE *pCharacter, INT16 sX, INT16 sY, BOOLEAN fTacticalTraversal ) { // will plot a path for this character // is cursor allowed here?..if not..don't build path if( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) { return; } // is the character in transit?..then leave if( pCharacter->bAssignment == IN_TRANSIT ) { // leave return; } if( pCharacter->bSectorZ != 0 ) { if( pCharacter->bAssignment >= ON_DUTY ) { // not on the surface, character won't move until they reach surface..info player of this fact MapScreenMessage( FONT_MCOLOR_DKRED, MSG_INTERFACE, L"%s %s", pCharacter->name, gsUndergroundString[0] ); } else // squad { MapScreenMessage( FONT_MCOLOR_DKRED, MSG_INTERFACE, L"%s %s", pLongAssignmentStrings[ pCharacter->bAssignment ], gsUndergroundString[0] ); } return; } if( ( pCharacter->bAssignment == VEHICLE ) || ( pCharacter->uiStatusFlags & SOLDIER_VEHICLE ) ) { SetUpMvtGroupForVehicle( pCharacter ); } // make sure we are at the beginning pCharacter->pMercPath = MoveToBeginningOfPathList( pCharacter->pMercPath ); // will plot a path from current position to sX, sY // get last sector in characters list, build new path, remove tail section, move to beginning of list, and append onto old list pCharacter->pMercPath = AppendStrategicPath( MoveToBeginningOfPathList ( BuildAStrategicPath( NULL, GetLastSectorIdInCharactersPath( pCharacter ), ( INT16 )( sX + sY*( MAP_WORLD_X ) ), GetSoldierGroupId( pCharacter ), fTacticalTraversal /*, FALSE */ ) ), pCharacter->pMercPath ); // move to beginning of list pCharacter->pMercPath = MoveToBeginningOfPathList( pCharacter->pMercPath ); // check if in vehicle, if so, copy path to vehicle if( ( pCharacter->bAssignment == VEHICLE ) || ( pCharacter->uiStatusFlags & SOLDIER_VEHICLE ) ) { MoveCharactersPathToVehicle( pCharacter ); } else { CopyPathToCharactersSquadIfInOne( pCharacter ); } } void PlotATemporaryPathForCharacter( SOLDIERTYPE *pCharacter, INT16 sX, INT16 sY ) { // make sure we're at the beginning pTempCharacterPath = MoveToBeginningOfPathList( pTempCharacterPath ); // clear old temp path pTempCharacterPath = ClearStrategicPathList( pTempCharacterPath, -1 ); // is cursor allowed here?..if not..don't build temp path if( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) { return; } // build path pTempCharacterPath = BuildAStrategicPath( pTempCharacterPath, GetLastSectorIdInCharactersPath( pCharacter ) , ( INT16 )( sX + sY*( MAP_WORLD_X ) ), GetSoldierGroupId( pCharacter ), FALSE /*, TRUE */ ); return; } // clear out character path list, after and including this sector UINT32 ClearPathAfterThisSectorForCharacter( SOLDIERTYPE *pCharacter, INT16 sX, INT16 sY ) { INT32 iOrigLength = 0; VEHICLETYPE *pVehicle = NULL; iOrigLength = GetLengthOfMercPath( pCharacter ); if( !iOrigLength ) { // no previous path, nothing to do return( ABORT_PLOTTING ); } // if we're clearing everything beyond the current sector, that's quite different. Since we're basically cancelling // his movement completely, we must also make sure his next X,Y are changed and he officially "returns" to his sector if ( ( sX == pCharacter->sSectorX ) && ( sY == pCharacter->sSectorY ) ) { // if we're in confirm map move mode, cancel that (before new UI messages are issued) EndConfirmMapMoveMode( ); CancelPathsOfAllSelectedCharacters(); return( PATH_CLEARED ); } else // click not in the current sector { // if the clicked sector is along current route, this will repath only as far as it. If not, the entire path will // be canceled. // if a vehicle if( pCharacter->uiStatusFlags & SOLDIER_VEHICLE ) { pVehicle = &( pVehicleList[ pCharacter->bVehicleID ] ); } // or in a vehicle else if( pCharacter->bAssignment == VEHICLE ) { pVehicle = &( pVehicleList[ pCharacter->iVehicleId ] ); } else { // foot soldier pCharacter->pMercPath = ClearStrategicPathListAfterThisSector( pCharacter->pMercPath, sX, sY, pCharacter->ubGroupID ); } // if there's an associated vehicle structure if ( pVehicle != NULL ) { // do it for the vehicle, too pVehicle->pMercPath = ClearStrategicPathListAfterThisSector( pVehicle->pMercPath, sX, sY, pVehicle->ubMovementGroup ); } if( GetLengthOfMercPath( pCharacter ) < iOrigLength ) { CopyPathToAllSelectedCharacters( pCharacter->pMercPath ); // path WAS actually shortened return( PATH_SHORTENED ); } else { // same path as before - it's not any shorter return ( ABORT_PLOTTING ); } } } void CancelPathForCharacter( SOLDIERTYPE *pCharacter ) { // clear out character's entire path list, he and his squad will stay/return to his current sector. pCharacter->pMercPath = ClearStrategicPathList( pCharacter->pMercPath, pCharacter->ubGroupID ); // NOTE: This automatically calls RemoveGroupWaypoints() internally for valid movement groups // This causes the group to effectively reverse directions (even if they've never actually left), so handle that. // They are going to return to their current X,Y sector. RebuildWayPointsForGroupPath( pCharacter->pMercPath, pCharacter->ubGroupID ); // GroupReversingDirectionsBetweenSectors( GetGroup( pCharacter->ubGroupID ), ( UINT8 )( pCharacter->sSectorX ), ( UINT8 )( pCharacter->sSectorY ), FALSE ); // if he's in a vehicle, clear out the vehicle, too if( pCharacter->bAssignment == VEHICLE ) { CancelPathForVehicle( &( pVehicleList[ pCharacter->iVehicleId ] ), TRUE ); } else { // display "travel route canceled" message MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 3 ] ); } CopyPathToCharactersSquadIfInOne( pCharacter ); fMapPanelDirty = TRUE; fTeamPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; // to update ETA } void CancelPathForVehicle( VEHICLETYPE *pVehicle, BOOLEAN fAlreadyReversed ) { // we're clearing everything beyond the *current* sector, that's quite different. Since we're basically cancelling // his movement completely, we must also make sure his next X,Y are changed and he officially "returns" to his sector pVehicle->pMercPath = ClearStrategicPathList( pVehicle->pMercPath, pVehicle->ubMovementGroup ); // NOTE: This automatically calls RemoveGroupWaypoints() internally for valid movement groups // if we already reversed one of the passengers, flag will be TRUE, // don't do it again or we're headed back where we came from! if ( !fAlreadyReversed ) { // This causes the group to effectively reverse directions (even if they've never actually left), so handle that. // They are going to return to their current X,Y sector. RebuildWayPointsForGroupPath( pVehicle->pMercPath, pVehicle->ubMovementGroup ); // GroupReversingDirectionsBetweenSectors( GetGroup( pVehicle->ubMovementGroup ), ( UINT8 ) ( pVehicle->sSectorX ), ( UINT8 ) ( pVehicle->sSectorY ), FALSE ); } // display "travel route canceled" message MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 3 ] ); // turn the helicopter flag off here, this prevents the "route aborted" msg from coming up fPlotForHelicopter = FALSE; fTeamPanelDirty = TRUE; fMapPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE; // to update ETA } void CancelPathForGroup( GROUP *pGroup ) { INT32 iVehicleId; // if it's the chopper, but player can't redirect it if ( pGroup->fPlayer && IsGroupTheHelicopterGroup( pGroup ) && ( CanHelicopterFly( ) == FALSE ) ) { // explain & ignore ExplainWhySkyriderCantFly(); return; } // is it a non-vehicle group? if( ( pGroup->fPlayer ) && ( pGroup->fVehicle == FALSE ) ) { if( pGroup->pPlayerList ) { if( pGroup->pPlayerList->pSoldier ) { // clearing one merc should be enough, it copies changes to his squad on its own CancelPathForCharacter( pGroup->pPlayerList->pSoldier ); } } } // is it a vehicle group? else if( pGroup->fVehicle ) { iVehicleId = GivenMvtGroupIdFindVehicleId( pGroup->ubGroupID ); // must be valid! Assert( iVehicleId != -1 ); if ( iVehicleId == -1 ) return; CancelPathForVehicle( &( pVehicleList[ iVehicleId ] ), FALSE ); } } void CopyPathToCharactersSquadIfInOne( SOLDIERTYPE *pCharacter ) { INT8 bSquad = 0; // check if on a squad, if so, do same thing for all characters // what squad is character in? bSquad = SquadCharacterIsIn( pCharacter ); // check to see if character is on a squad, if so, copy path to squad if( bSquad != -1) { // copy path over CopyPathOfCharacterToSquad( pCharacter, bSquad ); } } void DisplaySoldierPath( SOLDIERTYPE *pCharacter ) { PathStPtr pPath = NULL; /* ARM: Hopefully no longer required once using GetSoldierMercPathPtr() ??? // check if in vehicle, if so, copy path to vehicle if( ( pCharacter->bAssignment == VEHICLE )||( pCharacter->uiStatusFlags & SOLDIER_VEHICLE ) ) { // get the real path from vehicle's structure and copy it into this soldier's CopyVehiclePathToSoldier( pCharacter ); } */ pPath = GetSoldierMercPathPtr( pCharacter ); // trace real route TracePathRoute( FALSE, TRUE, pPath ); AnimateRoute( pPath ); return; } void DisplaySoldierTempPath( SOLDIERTYPE *pCharacter ) { // now render temp route TracePathRoute( FALSE, TRUE, pTempCharacterPath ); return; } void DisplayHelicopterPath( void ) { // move to beginning of path list pVehicleList[ iHelicopterVehicleId ].pMercPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); // clip to map ClipBlitsToMapViewRegion( ); // trace both lists..temp is conditional if cursor has sat in same sector grid long enough TracePathRoute( TRUE, TRUE, pVehicleList[ iHelicopterVehicleId ].pMercPath ); AnimateRoute( pVehicleList[ iHelicopterVehicleId ].pMercPath ); // restore RestoreClipRegionToFullScreen( ); return; } void DisplayHelicopterTempPath( void ) { //should we draw temp path? if( fDrawTempHeliPath ) { TracePathRoute( TRUE, TRUE, pTempHelicopterPath ); } return; } void PlotPathForHelicopter( INT16 sX, INT16 sY ) { // will plot the path for the helicopter // no heli...go back if( !fShowAircraftFlag || !fHelicopterAvailable ) { return; } // is cursor allowed here?..if not..don't build path if( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) { return; } // set up mvt group for helicopter SetUpHelicopterForMovement( ); // move to beginning of list //pHelicopterPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); // will plot a path from current position to sX, sY // get last sector in helicopters list, build new path, remove tail section, move to beginning of list, and append onto old list pVehicleList[ iHelicopterVehicleId ].pMercPath = AppendStrategicPath( MoveToBeginningOfPathList( BuildAStrategicPath( NULL, GetLastSectorOfHelicoptersPath( ), ( INT16 )( sX + sY*( MAP_WORLD_X ) ), pVehicleList[ iHelicopterVehicleId ].ubMovementGroup, FALSE /*, FALSE */ ) ), pVehicleList[ iHelicopterVehicleId ].pMercPath ); // move to beginning of list pVehicleList[ iHelicopterVehicleId ].pMercPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); fMapPanelDirty = TRUE; return; } void PlotATemporaryPathForHelicopter( INT16 sX, INT16 sY ) { // clear old temp path pTempHelicopterPath = ClearStrategicPathList( pTempHelicopterPath, 0 ); // is cursor allowed here?..if not..don't build temp path if( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) { return; } // build path pTempHelicopterPath = BuildAStrategicPath( NULL, GetLastSectorOfHelicoptersPath( ), ( INT16 )( sX + sY*( MAP_WORLD_X ) ), pVehicleList[ iHelicopterVehicleId ].ubMovementGroup, FALSE /*, TRUE */ ); return; } // clear out helicopter path list, after and including this sector UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ) { VEHICLETYPE *pVehicle = NULL; INT32 iOrigLength = 0; // clear out helicopter path list, after and including this sector if( iHelicopterVehicleId == -1 || !CanHelicopterFly() ) { // abort plotting, shouldn't even be here return( ABORT_PLOTTING ); } pVehicle = &( pVehicleList[ iHelicopterVehicleId ] ); iOrigLength = GetLengthOfPath( pVehicle->pMercPath ); if( !iOrigLength ) { // no previous path, nothing to do, and we didn't shorten it return( ABORT_PLOTTING ); } // are we clearing everything beyond the helicopter's CURRENT sector? if ( ( sX == pVehicle->sSectorX ) && ( sY == pVehicle->sSectorY ) ) { // if we're in confirm map move mode, cancel that (before new UI messages are issued) EndConfirmMapMoveMode( ); CancelPathForVehicle( pVehicle, FALSE ); return( PATH_CLEARED ); } else // click not in the current sector { // if the clicked sector is along current route, this will repath only as far as it. If not, the entire path will // be canceled. pVehicle->pMercPath = ClearStrategicPathListAfterThisSector( pVehicle->pMercPath, sX, sY, pVehicle->ubMovementGroup ); if( GetLengthOfPath( pVehicle->pMercPath ) < iOrigLength ) { // really shortened! return( PATH_SHORTENED ); } else { // same path as before - it's not any shorter return ( ABORT_PLOTTING ); } } } INT16 GetLastSectorOfHelicoptersPath( void ) { // will return the last sector of the helicopter's current path INT16 sLastSector = pVehicleList[ iHelicopterVehicleId ].sSectorX + pVehicleList[ iHelicopterVehicleId ].sSectorY * MAP_WORLD_X ; PathStPtr pNode = NULL; pNode = pVehicleList[ iHelicopterVehicleId ].pMercPath; while( pNode ) { sLastSector = ( INT16 ) ( pNode->uiSectorId ); pNode = pNode->pNext; } return sLastSector; } BOOLEAN TracePathRoute(BOOLEAN fCheckFlag, BOOLEAN fForceUpDate, PathStPtr pPath ) { PathStPtr pCurrentNode=NULL; BOOLEAN fSpeedFlag=FALSE; BOOLEAN fUpDate=FALSE; INT32 iDifference=0; INT32 iArrow=-1; INT32 iX, iY; INT16 sX, sY; INT32 iArrowX, iArrowY; INT32 iDeltaA, iDeltaB, iDeltaB1; INT32 iDirection = 0; BOOLEAN fUTurnFlag=FALSE; BOOLEAN fNextNode=FALSE; PathStPtr pTempNode=NULL; PathStPtr pNode=NULL; PathStPtr pPastNode=NULL; PathStPtr pNextNode=NULL; UINT ubCounter = 1; HVOBJECT hMapHandle; if ( pPath==NULL ) { return FALSE; } while( pPath->pPrev ) { pPath = pPath->pPrev; } pNode = pPath; iDirection=-1; if (pNode->pNext) pNextNode=pNode->pNext; else pNextNode=NULL; if (pNode->pPrev) pPastNode=pNode->pPrev; else pPastNode=NULL; GetVideoObject(&hMapHandle, guiMAPCURSORS); // go through characters list and display arrows for path while(pNode) { fUTurnFlag=FALSE; if ((pPastNode)&&(pNextNode)) { iDeltaA=(INT16)pNode->uiSectorId-(INT16)pPastNode->uiSectorId; iDeltaB=(INT16)pNode->uiSectorId-(INT16)pNextNode->uiSectorId; if (iDeltaA ==0) return( FALSE ); if(pNode->fSpeed) fSpeedFlag=FALSE; else fSpeedFlag=TRUE; if(!fZoomFlag) { iX=(pNode->uiSectorId%MAP_WORLD_X); iY=(pNode->uiSectorId/MAP_WORLD_X); iX=(iX*MAP_GRID_X)+MAP_VIEW_START_X; iY=(iY*MAP_GRID_Y)+MAP_VIEW_START_Y; } else { GetScreenXYFromMapXYStationary( ((UINT16)(pNode->uiSectorId%MAP_WORLD_X)),((UINT16)(pNode->uiSectorId/MAP_WORLD_X)) , &sX, &sY ); iY=sY-MAP_GRID_Y; iX=sX-MAP_GRID_X; } iArrowX=iX; iArrowY=iY; if ((pPastNode->pPrev)&&(pNextNode->pNext)) { fUTurnFlag=FALSE; // check to see if out-of sector U-turn // for placement of arrows iDeltaB1=pNextNode->uiSectorId-pNextNode->pNext->uiSectorId; if ((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==-1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==WORLD_MAP_X)&&(iDeltaA==WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-1)&&(iDeltaA==-1)&&(iDeltaB==-WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-1)&&(iDeltaA==-1)&&(iDeltaB==WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==1)&&(iDeltaA==1)&&(iDeltaB==-WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==1)&&(iDeltaA==1)&&(iDeltaB==WORLD_MAP_X)) { fUTurnFlag=TRUE; } else fUTurnFlag=FALSE; } if ((pPastNode->uiSectorId==pNextNode->uiSectorId)) { if (pPastNode->uiSectorId+WORLD_MAP_X==pNode->uiSectorId) { if(!(pNode->fSpeed)) fSpeedFlag=TRUE; else fSpeedFlag=FALSE; if(fZoomFlag) { iDirection=S_TO_N_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=S_TO_N_LINE; if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if(pPastNode->uiSectorId-WORLD_MAP_X==pNode->uiSectorId) { if(fZoomFlag) { iDirection=N_TO_S_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=N_TO_S_LINE; if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if (pPastNode->uiSectorId+1==pNode->uiSectorId) { if(fZoomFlag) { iDirection=E_TO_W_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=E_TO_W_LINE; if(fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else { if(fZoomFlag) { iDirection=W_TO_E_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=W_TO_E_LINE; if(fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } } else { if ((iDeltaA==-1)&&(iDeltaB==1)) { /* if( pPastNode == NULL ) { fSpeedFlag = !fSpeedFlag; } */ if(fZoomFlag) { iDirection=WEST_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=WEST_LINE; if(fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if((iDeltaA==1)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=EAST_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=EAST_LINE; if(fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=NORTH_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=NORTH_LINE; if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if((iDeltaA==WORLD_MAP_X)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=SOUTH_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=SOUTH_LINE; if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=N_TO_E_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=N_TO_E_LINE; if(fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if((iDeltaA==WORLD_MAP_X)&&(iDeltaB==1)) { if(fZoomFlag) { iDirection=S_TO_W_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=S_TO_W_LINE; if(fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if((iDeltaA==1)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=E_TO_S_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=E_TO_S_LINE; if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if ((iDeltaA==-1)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=W_TO_N_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=W_TO_N_LINE; if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if ((iDeltaA==-1)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=W_TO_S_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=(SOUTH_OFFSET_Y+WEST_TO_SOUTH_OFFSET_Y)*2; } else { iDirection=W_TO_S_LINE; if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=(SOUTH_OFFSET_Y+WEST_TO_SOUTH_OFFSET_Y); } } else if ((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { if(fZoomFlag) { iDirection=N_TO_W_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=N_TO_W_LINE; if(fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if ((iDeltaA==WORLD_MAP_X)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=S_TO_E_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=S_TO_E_LINE; if(fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if ((iDeltaA==1)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=E_TO_N_ZOOM_LINE; if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=(NORTH_OFFSET_X*2); iArrowY+=(NORTH_OFFSET_Y+EAST_TO_NORTH_OFFSET_Y)*2; } else { iDirection=E_TO_N_LINE; if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y+EAST_TO_NORTH_OFFSET_Y; } } } } else { if(!fZoomFlag) { iX=(pNode->uiSectorId%MAP_WORLD_X); iY=(pNode->uiSectorId/MAP_WORLD_X); iX=(iX*MAP_GRID_X)+MAP_VIEW_START_X; iY=(iY*MAP_GRID_Y)+MAP_VIEW_START_Y; } else { GetScreenXYFromMapXYStationary( ((UINT16)(pNode->uiSectorId%MAP_WORLD_X)),((UINT16)(pNode->uiSectorId/MAP_WORLD_X)) , &sX, &sY ); iY=sY-MAP_GRID_Y; iX=sX-MAP_GRID_X; } iArrowX=iX; iArrowY=iY; if((pNode->fSpeed)) fSpeedFlag=FALSE; else fSpeedFlag=TRUE; // display enter and exit 'X's if (pPastNode) { fUTurnFlag=TRUE; iDeltaA=(INT16)pNode->uiSectorId-(INT16)pPastNode->uiSectorId; if (iDeltaA==-1) { if(fZoomFlag) { iDirection=ZOOM_RED_X_WEST; //iX-=MAP_GRID_X; //iY-=MAP_GRID_Y; } else iDirection=RED_X_WEST; //iX+=RED_WEST_OFF_X; } else if (iDeltaA==1) { if(fZoomFlag) { iDirection=ZOOM_RED_X_EAST; } else iDirection=RED_X_EAST; //iX+=RED_EAST_OFF_X; } else if(iDeltaA==-WORLD_MAP_X) { if(fZoomFlag) { iDirection=ZOOM_RED_X_NORTH; } else iDirection=RED_X_NORTH; //iY+=RED_NORTH_OFF_Y; } else { if(fZoomFlag) { iDirection=ZOOM_RED_X_SOUTH; } else iDirection=RED_X_SOUTH; // iY+=RED_SOUTH_OFF_Y; } } if (pNextNode) { fUTurnFlag=FALSE; iDeltaB=(INT16)pNode->uiSectorId-(INT16)pNextNode->uiSectorId; if((pNode->fSpeed)) fSpeedFlag=FALSE; else fSpeedFlag=TRUE; if (iDeltaB==-1) { if(fZoomFlag) { iDirection=ZOOM_GREEN_X_EAST; if(fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iX-=0;MAP_GRID_X; iY-=0;MAP_GRID_Y; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=GREEN_X_EAST; if(fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } //iX+=RED_EAST_OFF_X; } else if (iDeltaB==1) { if(fZoomFlag) { iDirection=ZOOM_GREEN_X_WEST; if(fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=GREEN_X_WEST; if(fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } //iX+=RED_WEST_OFF_X; } else if(iDeltaB==WORLD_MAP_X) { if(fZoomFlag) { iDirection=ZOOM_GREEN_X_NORTH; if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=GREEN_X_NORTH; if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; //iY+=RED_NORTH_OFF_Y; } } else { if(fZoomFlag) { iDirection=ZOOM_GREEN_X_SOUTH; if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=GREEN_X_SOUTH; if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; //iY+=RED_SOUTH_OFF_Y; } } } } if ((iDirection !=-1)) { if((!fZoomFlag)||((fZoomFlag)&&(iX >MAP_VIEW_START_X)&&(iY >MAP_VIEW_START_Y)&&(iX < 640-MAP_GRID_X*2)&&(iY < MAP_VIEW_START_Y+MAP_VIEW_HEIGHT))) { BltVideoObject(FRAME_BUFFER, hMapHandle, (UINT16)iDirection, iX,iY, VO_BLT_SRCTRANSPARENCY, NULL ); if(!fUTurnFlag) { BltVideoObject(FRAME_BUFFER, hMapHandle, (UINT16)iArrow, iArrowX, iArrowY, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( iArrowX, iArrowY, iArrowX + 2 * MAP_GRID_X, iArrowY + 2 * MAP_GRID_Y ); } InvalidateRegion( iX, iY, iX + 2 * MAP_GRID_X, iY + 2 * MAP_GRID_Y ); fUTurnFlag=FALSE; } } // check to see if there is a turn pPastNode=pNode; pNode=pNode->pNext; if(!pNode) return( FALSE ); if (pNode->pNext) pNextNode=pNode->pNext; else pNextNode=NULL; } return ( TRUE ); } void AnimateRoute( PathStPtr pPath ) { // set buffer SetFontDestBuffer( FRAME_BUFFER, 0,0,SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); // the animated path if( TraceCharAnimatedRoute( pPath, FALSE, FALSE )) { // ARM? Huh? Why the same thing twice more? TraceCharAnimatedRoute( pPath, FALSE, TRUE ); TraceCharAnimatedRoute( pPath, FALSE, TRUE ); } } void RestoreArrowBackgroundsForTrace(INT32 iArrow, INT32 iArrowX, INT32 iArrowY, BOOLEAN fZoom) { INT16 sArrow=0; INT32 iX = -1, iY = -1; // find location of arrow and restore appropriate background if((iArrow==SOUTH_ARROW)||(iArrow==W_SOUTH_ARROW)||(iArrow==ZOOM_W_SOUTH_ARROW)||(ZOOM_SOUTH_ARROW==iArrow)) { sArrow=SOUTH_ARROW; } else if((iArrow==NORTH_ARROW)||(iArrow==W_NORTH_ARROW)||(iArrow==ZOOM_W_NORTH_ARROW)||(ZOOM_NORTH_ARROW==iArrow)) { sArrow=NORTH_ARROW; } else if((iArrow==WEST_ARROW)||(iArrow==W_WEST_ARROW)||(iArrow==ZOOM_W_WEST_ARROW)||(ZOOM_WEST_ARROW==iArrow)) { sArrow=WEST_ARROW; } else if((iArrow==EAST_ARROW)||(iArrow==W_EAST_ARROW)||(iArrow==ZOOM_W_EAST_ARROW)||(ZOOM_EAST_ARROW==iArrow)) { sArrow=EAST_ARROW; } switch(sArrow) { case(SOUTH_ARROW): iX=iArrowX; iY=iArrowY; break; case(NORTH_ARROW): iX=iArrowX; iY=iArrowY; break; case(WEST_ARROW): iX=iArrowX; iY=iArrowY; break; case(EAST_ARROW): iX=iArrowX; iY=iArrowY; break; } // error check if( iX == -1 ) { return; } if(!fZoom) RestoreExternBackgroundRect(((INT16)iX),((INT16)iY),DMAP_GRID_X/2 ,DMAP_GRID_Y/2 ); else RestoreExternBackgroundRect(((INT16)iX), ((INT16)iY),DMAP_GRID_ZOOM_X, DMAP_GRID_ZOOM_Y); return; } BOOLEAN TraceCharAnimatedRoute( PathStPtr pPath, BOOLEAN fCheckFlag, BOOLEAN fForceUpDate ) { static PathStPtr pCurrentNode=NULL; static INT8 bCurrentChar=-1; static BOOLEAN fUpDateFlag=FALSE; static BOOLEAN fPauseFlag=TRUE; static UINT8 ubCounter=1; HVOBJECT hMapHandle; BOOLEAN fSpeedFlag=FALSE; BOOLEAN fUpDate=FALSE; INT32 iDifference=0; INT32 iArrow=-1; INT32 iX = 0, iY = 0; INT32 iPastX, iPastY; INT16 sX = 0, sY = 0; INT32 iArrowX, iArrowY; INT32 iDeltaA, iDeltaB, iDeltaB1; INT32 iDirection = -1; BOOLEAN fUTurnFlag=FALSE; BOOLEAN fNextNode=FALSE; PathStPtr pTempNode=NULL; PathStPtr pNode=NULL; PathStPtr pPastNode=NULL; PathStPtr pNextNode=NULL; // must be plotting movement if ( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) { return FALSE; } // if any nodes have been deleted, reset current node to beginning of the list if( fDeletedNode ) { fDeletedNode = FALSE; pCurrentNode = NULL; } // Valid path? if ( pPath == NULL ) { return FALSE; } else { if(pCurrentNode==NULL) { pCurrentNode = pPath; } } // Check Timer if (giAnimateRouteBaseTime==0) { giAnimateRouteBaseTime=GetJA2Clock(); return FALSE; } // check difference in time iDifference=GetJA2Clock()-giAnimateRouteBaseTime; // if pause flag, check time, if time passed, reset, continue on, else return if(fPauseFlag) { if(iDifference < PAUSE_DELAY) { return FALSE; } else { fPauseFlag=FALSE; giAnimateRouteBaseTime=GetJA2Clock(); } } // if is checkflag and change in status, return TRUE; if(!fForceUpDate) { if(iDifference < ARROW_DELAY) { if (!fUpDateFlag) return FALSE; } else { // sufficient time, update base time giAnimateRouteBaseTime=GetJA2Clock(); fUpDateFlag=!fUpDateFlag; if(fCheckFlag) return TRUE; fNextNode=TRUE; } } // check to see if Current node has not been deleted pTempNode = pPath; while(pTempNode) { if(pTempNode==pCurrentNode) { //not deleted //reset pause flag break; } else pTempNode=pTempNode->pNext; } // if deleted, restart at beginnning if(pTempNode==NULL) { pCurrentNode = pPath; // set pause flag if(!pCurrentNode) return FALSE; } // Grab Video Objects GetVideoObject(&hMapHandle, guiMAPCURSORS); // Handle drawing of arrow pNode=pCurrentNode; if((!pNode->pPrev)&&(ubCounter==1)&&(fForceUpDate)) { ubCounter=0; return FALSE; } else if((ubCounter==1)&&(fForceUpDate)) { pNode=pCurrentNode->pPrev; } if (pNode->pNext) pNextNode=pNode->pNext; else pNextNode=NULL; if (pNode->pPrev) pPastNode=pNode->pPrev; else pPastNode=NULL; // go through characters list and display arrows for path fUTurnFlag=FALSE; if ((pPastNode)&&(pNextNode)) { iDeltaA=(INT16)pNode->uiSectorId-(INT16)pPastNode->uiSectorId; iDeltaB=(INT16)pNode->uiSectorId-(INT16)pNextNode->uiSectorId; if(!pNode->fSpeed) fSpeedFlag=TRUE; else fSpeedFlag=FALSE; if (iDeltaA ==0) return FALSE; if(!fZoomFlag) { iX=(pNode->uiSectorId%MAP_WORLD_X); iY=(pNode->uiSectorId/MAP_WORLD_X); iX=(iX*MAP_GRID_X)+MAP_VIEW_START_X; iY=(iY*MAP_GRID_Y)+MAP_VIEW_START_Y; } else { GetScreenXYFromMapXYStationary( ((UINT16)(pNode->uiSectorId%MAP_WORLD_X)),((UINT16)(pNode->uiSectorId/MAP_WORLD_X)) , &sX, &sY ); iY=sY-MAP_GRID_Y; iX=sX-MAP_GRID_X; } iArrowX=iX; iArrowY=iY; if ((pPastNode->pPrev)&&(pNextNode->pNext)) { fUTurnFlag=FALSE; // check to see if out-of sector U-turn // for placement of arrows iDeltaB1=pNextNode->uiSectorId-pNextNode->pNext->uiSectorId; if ((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==-1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==WORLD_MAP_X)&&(iDeltaA==WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-WORLD_MAP_X)&&(iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-1)&&(iDeltaA==-1)&&(iDeltaB==-WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==-1)&&(iDeltaA==-1)&&(iDeltaB==WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==1)&&(iDeltaA==1)&&(iDeltaB==-WORLD_MAP_X)) { fUTurnFlag=TRUE; } else if((iDeltaB1==1)&&(iDeltaA==1)&&(iDeltaB==WORLD_MAP_X)) { fUTurnFlag=TRUE; } else fUTurnFlag=FALSE; } if ((pPastNode->uiSectorId==pNextNode->uiSectorId)) { if (pPastNode->uiSectorId+WORLD_MAP_X==pNode->uiSectorId) { if(fZoomFlag) { iDirection=S_TO_N_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_NORTH_ARROW; else if(fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=S_TO_N_LINE; if(!ubCounter) iArrow=W_NORTH_ARROW; else if(fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if(pPastNode->uiSectorId-WORLD_MAP_X==pNode->uiSectorId) { if(fZoomFlag) { iDirection=N_TO_S_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_SOUTH_ARROW; else if(fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=N_TO_S_LINE; if(!ubCounter) iArrow=W_SOUTH_ARROW; else if(fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if (pPastNode->uiSectorId+1==pNode->uiSectorId) { if(fZoomFlag) { iDirection=E_TO_W_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_WEST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=E_TO_W_LINE; if(!ubCounter) iArrow=W_WEST_ARROW; else if (fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else { if(fZoomFlag) { iDirection=W_TO_E_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_EAST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=W_TO_E_LINE; if(!ubCounter) iArrow=W_EAST_ARROW; else if (fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } } else { if ((iDeltaA==-1)&&(iDeltaB==1)) { if(fZoomFlag) { iDirection=WEST_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_WEST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=WEST_LINE; if(!ubCounter) iArrow=W_WEST_ARROW; else if (fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if((iDeltaA==1)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=EAST_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=EAST_LINE; if(!ubCounter) iArrow=W_EAST_ARROW; else if (fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=NORTH_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_NORTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=NORTH_LINE; if(!ubCounter) iArrow=W_NORTH_ARROW; else if (fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if((iDeltaA==WORLD_MAP_X)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=SOUTH_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=SOUTH_LINE; if(!ubCounter) iArrow=W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=N_TO_E_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_EAST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=N_TO_E_LINE; if(!ubCounter) iArrow=W_EAST_ARROW; else if (fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if((iDeltaA==WORLD_MAP_X)&&(iDeltaB==1)) { if(fZoomFlag) { iDirection=S_TO_W_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_WEST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=S_TO_W_LINE; if(!ubCounter) iArrow=W_WEST_ARROW; else if (fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if((iDeltaA==1)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=E_TO_S_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=SOUTH_OFFSET_Y*2; } else { iDirection=E_TO_S_LINE; if(!ubCounter) iArrow=W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; } } else if ((iDeltaA==-1)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=W_TO_N_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_NORTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=NORTH_OFFSET_X*2; iArrowY+=NORTH_OFFSET_Y*2; } else { iDirection=W_TO_N_LINE; if(!ubCounter) iArrow=W_NORTH_ARROW; else if (fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; } } else if ((iDeltaA==-1)&&(iDeltaB==-WORLD_MAP_X)) { if(fZoomFlag) { iDirection=W_TO_S_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_SOUTH_ARROW; else iArrow=ZOOM_SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X*2; iArrowY+=(SOUTH_OFFSET_Y+WEST_TO_SOUTH_OFFSET_Y)*2; } else { iDirection=W_TO_S_LINE; if(!ubCounter) iArrow=W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=(SOUTH_OFFSET_Y+WEST_TO_SOUTH_OFFSET_Y); } } else if ((iDeltaA==-WORLD_MAP_X)&&(iDeltaB==1)) { if(fZoomFlag) { iDirection=N_TO_W_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_WEST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_WEST_ARROW; else iArrow=ZOOM_WEST_ARROW; iArrowX+=WEST_OFFSET_X*2; iArrowY+=WEST_OFFSET_Y*2; } else { iDirection=N_TO_W_LINE; if(!ubCounter) iArrow=W_WEST_ARROW; else if (fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; } } else if ((iDeltaA==WORLD_MAP_X)&&(iDeltaB==-1)) { if(fZoomFlag) { iDirection=S_TO_E_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_EAST_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_EAST_ARROW; else iArrow=ZOOM_EAST_ARROW; iArrowX+=EAST_OFFSET_X*2; iArrowY+=EAST_OFFSET_Y*2; } else { iDirection=S_TO_E_LINE; if(!ubCounter) iArrow=W_EAST_ARROW; else if (fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; } } else if ((iDeltaA==1)&&(iDeltaB==WORLD_MAP_X)) { if(fZoomFlag) { iDirection=E_TO_N_ZOOM_LINE; if(!ubCounter) iArrow=ZOOM_W_NORTH_ARROW; else if (fSpeedFlag) iArrow=ZOOM_Y_NORTH_ARROW; else iArrow=ZOOM_NORTH_ARROW; iArrowX+=(NORTH_OFFSET_X*2); iArrowY+=(NORTH_OFFSET_Y+EAST_TO_NORTH_OFFSET_Y)*2; } else { iDirection=E_TO_N_LINE; if(!ubCounter) iArrow=W_NORTH_ARROW; else if (fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y+EAST_TO_NORTH_OFFSET_Y; } } } } else { iX=(pNode->uiSectorId%MAP_WORLD_X); iY=(pNode->uiSectorId/MAP_WORLD_X); iX=(iX*MAP_GRID_X)+MAP_VIEW_START_X; iY=(iY*MAP_GRID_Y)+MAP_VIEW_START_Y; if(pPastNode) { iPastX=(pPastNode->uiSectorId%MAP_WORLD_X); iPastY=(pPastNode->uiSectorId/MAP_WORLD_X); iPastX=(iPastX*MAP_GRID_X)+MAP_VIEW_START_X; iPastY=(iPastY*MAP_GRID_Y)+MAP_VIEW_START_Y; } if(pNode->fSpeed) fSpeedFlag=TRUE; else fSpeedFlag=FALSE; iArrowX=iX; iArrowY=iY; // display enter and exit 'X's if (pPastNode) { // red 'X' fUTurnFlag=TRUE; iDeltaA=(INT16)pNode->uiSectorId-(INT16)pPastNode->uiSectorId; if (iDeltaA==-1) { iDirection=RED_X_WEST; //iX+=RED_WEST_OFF_X; } else if (iDeltaA==1) { iDirection=RED_X_EAST; //iX+=RED_EAST_OFF_X; } else if(iDeltaA==-WORLD_MAP_X) { iDirection=RED_X_NORTH; //iY+=RED_NORTH_OFF_Y; } else { iDirection=RED_X_SOUTH; // iY+=RED_SOUTH_OFF_Y; } } if (pNextNode) { fUTurnFlag=FALSE; iDeltaB=(INT16)pNode->uiSectorId-(INT16)pNextNode->uiSectorId; if (iDeltaB==-1) { iDirection=GREEN_X_EAST; if(!ubCounter) iArrow=W_EAST_ARROW; else if (fSpeedFlag) iArrow=Y_EAST_ARROW; else iArrow=EAST_ARROW; iArrowX+=EAST_OFFSET_X; iArrowY+=EAST_OFFSET_Y; //iX+=RED_EAST_OFF_X; } else if (iDeltaB==1) { iDirection=GREEN_X_WEST; if(!ubCounter) iArrow=W_WEST_ARROW; else if (fSpeedFlag) iArrow=Y_WEST_ARROW; else iArrow=WEST_ARROW; iArrowX+=WEST_OFFSET_X; iArrowY+=WEST_OFFSET_Y; //iX+=RED_WEST_OFF_X; } else if(iDeltaB==WORLD_MAP_X) { iDirection=GREEN_X_NORTH; if(!ubCounter) iArrow=W_NORTH_ARROW; else if (fSpeedFlag) iArrow=Y_NORTH_ARROW; else iArrow=NORTH_ARROW; iArrowX+=NORTH_OFFSET_X; iArrowY+=NORTH_OFFSET_Y; //iY+=RED_NORTH_OFF_Y; } else { iDirection=GREEN_X_SOUTH; if(!ubCounter) iArrow=W_SOUTH_ARROW; else if (fSpeedFlag) iArrow=Y_SOUTH_ARROW; else iArrow=SOUTH_ARROW; iArrowX+=SOUTH_OFFSET_X; iArrowY+=SOUTH_OFFSET_Y; //iY+=RED_SOUTH_OFF_Y; } } } if(fNextNode) { if(!ubCounter) { pCurrentNode=pCurrentNode->pNext; if(!pCurrentNode) fPauseFlag=TRUE; } } if ((iDirection !=-1)&&(iArrow!=-1)) { if(!fUTurnFlag) { if((!fZoomFlag)||((fZoomFlag)&&(iX >MAP_VIEW_START_X)&&(iY >MAP_VIEW_START_Y)&&(iX < 640-MAP_GRID_X*2)&&(iY < MAP_VIEW_START_Y+MAP_VIEW_HEIGHT))) { //if(!fZoomFlag) //RestoreExternBackgroundRect(((INT16)iArrowX),((INT16)iArrowY),DMAP_GRID_X, DMAP_GRID_Y); //else //RestoreExternBackgroundRect(((INT16)iArrowX), ((INT16)iArrowY),DMAP_GRID_ZOOM_X, DMAP_GRID_ZOOM_Y); if( pNode != pPath ) { BltVideoObject(FRAME_BUFFER, hMapHandle, (UINT16)iArrow, iArrowX, iArrowY, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( iArrowX, iArrowY, iArrowX + 2 * MAP_GRID_X, iArrowY + 2 * MAP_GRID_Y ); } } if(ubCounter==1) ubCounter=0; else ubCounter=1; return TRUE; } if(ubCounter==1) ubCounter=0; else ubCounter=1; } // move to next arrow //ARM who knows what it should return here? return FALSE; } void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ) { // simply check if we want to refresh the screen to display path static BOOLEAN fOldShowAirCraft = FALSE; static INT16 sOldMapX, sOldMapY; INT32 iDifference = 0; if( fOldShowAirCraft != fShowAircraftFlag ) { fOldShowAirCraft = fShowAircraftFlag; giPotHeliPathBaseTime = GetJA2Clock( ); sOldMapX = sMapX; sOldMapY = sMapY; fTempPathAlreadyDrawn = FALSE; fDrawTempHeliPath = FALSE; } if( ( sMapX != sOldMapX) || ( sMapY != sOldMapY ) ) { giPotHeliPathBaseTime = GetJA2Clock( ); sOldMapX = sMapX; sOldMapY = sMapY; // path was plotted and we moved, re draw map..to clean up mess if( fTempPathAlreadyDrawn ) { fMapPanelDirty = TRUE; } fTempPathAlreadyDrawn = FALSE; fDrawTempHeliPath = FALSE; } iDifference = GetJA2Clock( ) - giPotHeliPathBaseTime ; if( fTempPathAlreadyDrawn ) { return; } if( iDifference > MIN_WAIT_TIME_FOR_TEMP_PATH ) { fDrawTempHeliPath = TRUE; giPotHeliPathBaseTime = GetJA2Clock( ); fTempPathAlreadyDrawn = TRUE; } return; } BOOLEAN IsTheCursorAllowedToHighLightThisSector( INT16 sSectorX, INT16 sSectorY ) { // check to see if this sector is a blocked out sector? if( sBadSectorsList[ sSectorX ][ sSectorY ] ) { return ( FALSE ); } else { // return cursor is allowed to highlight this sector return ( TRUE ); } } void SetUpBadSectorsList( void ) { // initalizes all sectors to highlighable and then the ones non highlightable are marked as such INT8 bY; memset( &sBadSectorsList, 0, sizeof( sBadSectorsList ) ); // the border regions for( bY = 0; bY < WORLD_MAP_X; bY++ ) { sBadSectorsList[ 0 ][ bY ] = sBadSectorsList[ WORLD_MAP_X - 1 ][ bY ] = sBadSectorsList[ bY ][ 0 ] = sBadSectorsList[ bY ][ WORLD_MAP_X - 1 ] = TRUE; } sBadSectorsList[ 4 ][ 1 ] = TRUE; sBadSectorsList[ 5 ][ 1 ] = TRUE; sBadSectorsList[ 16 ][ 1 ] = TRUE; sBadSectorsList[ 16 ][ 5 ] = TRUE; sBadSectorsList[ 16 ][ 6 ] = TRUE; sBadSectorsList[ 16 ][ 10 ] = TRUE; sBadSectorsList[ 16 ][ 11 ] = TRUE; sBadSectorsList[ 16 ][ 12 ] = TRUE; sBadSectorsList[ 16 ][ 13 ] = TRUE; sBadSectorsList[ 16 ][ 14 ] = TRUE; sBadSectorsList[ 16 ][ 15 ] = TRUE; sBadSectorsList[ 16 ][ 16 ] = TRUE; sBadSectorsList[ 15 ][ 13 ] = TRUE; sBadSectorsList[ 15 ][ 14 ] = TRUE; sBadSectorsList[ 15 ][ 15 ] = TRUE; sBadSectorsList[ 15 ][ 16 ] = TRUE; sBadSectorsList[ 14 ][ 14 ] = TRUE; sBadSectorsList[ 14 ][ 15 ] = TRUE; sBadSectorsList[ 14 ][ 16 ] = TRUE; sBadSectorsList[ 13 ][ 14 ] = TRUE; return; } void RestoreBackgroundForMapGrid( INT16 sMapX, INT16 sMapY ) { INT16 sX, sY; if(!fZoomFlag) { // screen values sX=(sMapX * MAP_GRID_X ) + MAP_VIEW_START_X; sY=(sMapY * MAP_GRID_Y ) + MAP_VIEW_START_Y; // restore background RestoreExternBackgroundRect( sX, sY ,DMAP_GRID_X ,DMAP_GRID_Y ); } else { // get screen coords from map values GetScreenXYFromMapXYStationary( sMapX, sMapY, &sX, &sY ); // is this on the screen? if( ( sX > MapScreenRect.iLeft ) && ( sX < MapScreenRect.iRight ) && ( sY > MapScreenRect.iTop ) && ( sY < MapScreenRect.iBottom ) ) { // offset sY=sY-MAP_GRID_Y; sX=sX-MAP_GRID_X; // restore RestoreExternBackgroundRect( sX, sY ,DMAP_GRID_ZOOM_X ,DMAP_GRID_ZOOM_Y ); } } } void ClipBlitsToMapViewRegion( void ) { // the standard mapscreen rectangle doesn't work for clipping while zoomed... SGPRect ZoomedMapScreenClipRect={ MAP_VIEW_START_X + MAP_GRID_X, MAP_VIEW_START_Y + MAP_GRID_Y - 1, MAP_VIEW_START_X + MAP_VIEW_WIDTH + MAP_GRID_X, MAP_VIEW_START_Y + MAP_VIEW_HEIGHT + MAP_GRID_Y - 10 }; SGPRect *pRectToUse; if (fZoomFlag) pRectToUse = &ZoomedMapScreenClipRect; else pRectToUse = &MapScreenRect; SetClippingRect( pRectToUse ); memcpy( &gOldClipRect, &gDirtyClipRect, sizeof( gOldClipRect ) ); memcpy( &gDirtyClipRect, pRectToUse, sizeof( gDirtyClipRect ) ); } void RestoreClipRegionToFullScreen( void ) { FullScreenRect.iLeft = 0; FullScreenRect.iTop = 0; FullScreenRect.iRight = SCREEN_WIDTH; FullScreenRect.iBottom = SCREEN_HEIGHT; SetClippingRect( &FullScreenRect ); memcpy( &gDirtyClipRect, &gOldClipRect, sizeof( gDirtyClipRect ) ); } void ClipBlitsToMapViewRegionForRectangleAndABit( UINT32 uiDestPitchBYTES ) { // clip blits to map view region // because MC's map coordinates system is so screwy, these had to be hand-tuned to work right... ARM if (fZoomFlag) SetClippingRegionAndImageWidth( uiDestPitchBYTES, MapScreenRect.iLeft + 2, MapScreenRect.iTop, MapScreenRect.iRight - MapScreenRect.iLeft, MapScreenRect.iBottom - MapScreenRect.iTop ); else SetClippingRegionAndImageWidth( uiDestPitchBYTES, MapScreenRect.iLeft - 1, MapScreenRect.iTop - 1, MapScreenRect.iRight - MapScreenRect.iLeft + 3, MapScreenRect.iBottom - MapScreenRect.iTop + 2 ); return; } void RestoreClipRegionToFullScreenForRectangle( UINT32 uiDestPitchBYTES ) { // clip blits to map view region //SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); // WANNE 2 SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); return; } // mvt icon offset defines #define SOUTH_Y_MVT_OFFSET +10 #define SOUTH_X_MVT_OFFSET 0 #define NORTH_Y_MVT_OFFSET -10 #define NORTH_X_MVT_OFFSET +10 #define NORTH_SOUTH_CENTER_OFFSET +5 #define SOUTH_Y_MVT_OFFSET_ZOOM +30 #define SOUTH_X_MVT_OFFSET_ZOOM +5 #define NORTH_Y_MVT_OFFSET_ZOOM -8 #define NORTH_X_MVT_OFFSET_ZOOM +25 #define NORTH_SOUTH_CENTER_OFFSET_ZOOM +15 #define EAST_Y_MVT_OFFSET + 8 #define EAST_X_MVT_OFFSET 15 #define WEST_Y_MVT_OFFSET -2 #define WEST_X_MVT_OFFSET -8 #define EAST_WEST_CENTER_OFFSET +2 #define EAST_Y_MVT_OFFSET_ZOOM +24 #define EAST_X_MVT_OFFSET_ZOOM +36 #define WEST_Y_MVT_OFFSET_ZOOM +5 #define WEST_X_MVT_OFFSET_ZOOM -10 #define EAST_WEST_CENTER_OFFSET_ZOOM +12 #define NORTH_TEXT_X_OFFSET +1 #define NORTH_TEXT_Y_OFFSET +4 #define SOUTH_TEXT_X_OFFSET +1 #define SOUTH_TEXT_Y_OFFSET +2 #define EAST_TEXT_X_OFFSET + 2 #define EAST_TEXT_Y_OFFSET 0 #define WEST_TEXT_X_OFFSET + 4 #define WEST_TEXT_Y_OFFSET 0 #define ICON_WIDTH 8 void ShowPeopleInMotion( INT16 sX, INT16 sY ) { INT32 sExiting = 0; INT32 sEntering = 0; INT16 sDest = 0; INT16 sSource = 0; INT16 sOffsetX = 0, sOffsetY = 0; INT16 iX = sX, iY = sY; INT16 sXPosition = 0, sYPosition = 0; INT32 iCounter = 0; HVOBJECT hIconHandle; BOOLEAN fAboutToEnter = FALSE; CHAR16 sString[ 32 ]; INT16 sTextXOffset = 0; INT16 sTextYOffset = 0; INT16 usX, usY; INT32 iWidth = 0, iHeight = 0; INT32 iDeltaXForError = 0, iDeltaYForError = 0; if( iCurrentMapSectorZ != 0 ) { return; } // show the icons for people in motion from this sector to the next guy over for( iCounter = 0; iCounter < 4; iCounter++ ) { // find how many people are coming and going in this sector sExiting = 0; sEntering = 0; sSource = CALCULATE_STRATEGIC_INDEX( sX, sY ); sOffsetX = 0; sOffsetY = 0; iX = sX; iY = sY; // reset fact about to enter fAboutToEnter = FALSE; sDest = sSource; if( ( iCounter == 0 ) && sY > 1 ) { sDest += NORTH_MOVE; } else if( ( iCounter == 1 ) && ( sX < MAP_WORLD_X - 1 ) ) { sDest += EAST_MOVE; } else if( ( iCounter == 2 ) && ( sY < MAP_WORLD_Y - 1 ) ) { sDest += SOUTH_MOVE; } else if( ( iCounter == 3 ) && ( sX > 1 ) ) { sDest += WEST_MOVE; } // if not at edge of map if ( sDest != sSource ) { if( PlayersBetweenTheseSectors( ( INT16 ) SECTOR( sSource % MAP_WORLD_X, sSource / MAP_WORLD_X ) , ( INT16 ) SECTOR( sDest % MAP_WORLD_X, sDest / MAP_WORLD_X ), &sExiting, &sEntering, &fAboutToEnter ) ) { // someone is leaving // now find position if( !( iCounter % 2 ) ) { // guys going north or south if( sEntering > 0 ) { // more than one coming in, offset from middle sOffsetX = ( !iCounter ? ( !fZoomFlag ? NORTH_X_MVT_OFFSET: NORTH_X_MVT_OFFSET_ZOOM ) : ( !fZoomFlag ? SOUTH_X_MVT_OFFSET: SOUTH_X_MVT_OFFSET_ZOOM ) ); } else { sOffsetX = ( !fZoomFlag ? NORTH_SOUTH_CENTER_OFFSET : NORTH_SOUTH_CENTER_OFFSET_ZOOM ); } if( !iCounter ) { // going north sOffsetY = ( !fZoomFlag ? NORTH_Y_MVT_OFFSET : NORTH_Y_MVT_OFFSET_ZOOM ); } else { // going south sOffsetY = ( !fZoomFlag ? SOUTH_Y_MVT_OFFSET : SOUTH_Y_MVT_OFFSET_ZOOM ); } } else { // going east/west if( sEntering > 0 ) { // people also entering, offset from middle sOffsetY = ( iCounter == 1? ( !fZoomFlag ? EAST_Y_MVT_OFFSET: EAST_Y_MVT_OFFSET_ZOOM ) : ( !fZoomFlag ? WEST_Y_MVT_OFFSET: WEST_Y_MVT_OFFSET_ZOOM ) ); } else { sOffsetY = ( !fZoomFlag ? EAST_WEST_CENTER_OFFSET : EAST_WEST_CENTER_OFFSET_ZOOM ); } if( iCounter == 1 ) { // going east sOffsetX = ( !fZoomFlag ? EAST_X_MVT_OFFSET : EAST_X_MVT_OFFSET_ZOOM ); } else { // going west sOffsetX = ( !fZoomFlag ? WEST_X_MVT_OFFSET : WEST_X_MVT_OFFSET_ZOOM ); } } switch( iCounter ) { case 0: sTextXOffset = NORTH_TEXT_X_OFFSET; sTextYOffset = NORTH_TEXT_Y_OFFSET; break; case 1: sTextXOffset = EAST_TEXT_X_OFFSET; sTextYOffset = EAST_TEXT_Y_OFFSET; break; case 2: sTextXOffset = SOUTH_TEXT_X_OFFSET; sTextYOffset = SOUTH_TEXT_Y_OFFSET; break; case 3: sTextXOffset = WEST_TEXT_X_OFFSET; sTextYOffset = WEST_TEXT_Y_OFFSET; break; } // blit the text SetFont( MAP_MVT_ICON_FONT ); if( !fAboutToEnter ) { SetFontForeground( FONT_WHITE ); } else { SetFontForeground( FONT_BLACK ); } SetFontBackground( FONT_BLACK ); swprintf( sString, L"%d", sExiting ); // about to enter if( !fAboutToEnter ) { // draw blue arrows GetVideoObject(&hIconHandle, guiCHARBETWEENSECTORICONS ); } else { // draw yellow arrows GetVideoObject(&hIconHandle, guiCHARBETWEENSECTORICONSCLOSE ); } // zoomed in or not? if(!fZoomFlag) { iX = MAP_VIEW_START_X+( iX * MAP_GRID_X ) + sOffsetX; iY = MAP_Y_ICON_OFFSET + MAP_VIEW_START_Y + ( iY * MAP_GRID_Y ) + sOffsetY; BltVideoObject(guiSAVEBUFFER, hIconHandle, ( UINT16 )iCounter , ( INT16 ) iX, ( INT16 ) iY , VO_BLT_SRCTRANSPARENCY, NULL ); } else { GetScreenXYFromMapXYStationary( ((UINT16)(iX)),((UINT16)(iY)) , &sXPosition, &sYPosition ); iY=sYPosition-MAP_GRID_Y + sOffsetY; iX=sXPosition-MAP_GRID_X + sOffsetX; // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); BltVideoObject(guiSAVEBUFFER, hIconHandle,( UINT16 )iCounter , iX , iY , VO_BLT_SRCTRANSPARENCY, NULL ); // restore clip blits RestoreClipRegionToFullScreen( ); } FindFontCenterCoordinates(( INT16 )( iX + sTextXOffset ), 0, ICON_WIDTH, 0, sString, MAP_FONT, &usX, &usY); SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); mprintf( usX, iY + sTextYOffset, sString); switch( iCounter % 2 ) { case 0 : // north south iWidth = 10; iHeight = 12; break; case 1 : // east west iWidth = 12; iHeight = 7; break; } // error correction for scrolling with people on the move if( iX < 0 ) { iDeltaXForError = 0 - iX; iWidth -= iDeltaXForError; iX = 0; } if( iY < 0 ) { iDeltaYForError = 0 - iY; iHeight -= iDeltaYForError; iY = 0; } if( ( iWidth > 0 )&&( iHeight > 0 ) ) { RestoreExternBackgroundRect( iX, iY, ( INT16 )iWidth, ( INT16 )iHeight ); } } } } // restore buffer SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } void DisplayDistancesForHelicopter( void ) { // calculate the distance travelled, the proposed distance, and total distance one can go // display these on screen INT16 sDistanceToGo = 0;//, sDistanceSoFar = 0, sTotalCanTravel = 0; INT16 sX = 0, sY = 0; CHAR16 sString[ 32 ]; HVOBJECT hHandle; INT16 sTotalOfTrip = 0; INT32 iTime = 0; INT16 sMapX, sMapY; INT16 sYPosition = 0; static INT16 sOldYPosition = 0; INT16 sNumSafeSectors; INT16 sNumUnSafeSectors; UINT32 uiTripCost; if ( GetMouseMapXY( &sMapX, &sMapY ) && !fZoomFlag && ( sMapY >= 13 ) ) { sYPosition = MAP_HELICOPTER_UPPER_ETA_POPUP_Y; } else { sYPosition = MAP_HELICOPTER_ETA_POPUP_Y; } if( ( sOldYPosition != 0 ) && ( sOldYPosition != sYPosition ) ) { RestoreExternBackgroundRect( MAP_HELICOPTER_ETA_POPUP_X, sOldYPosition, MAP_HELICOPTER_ETA_POPUP_WIDTH + 20, MAP_HELICOPTER_ETA_POPUP_HEIGHT ); } sOldYPosition = sYPosition; // blit in background GetVideoObject( &hHandle, guiMapBorderHeliSectors ); BltVideoObject( FRAME_BUFFER, hHandle, 0, MAP_HELICOPTER_ETA_POPUP_X, sYPosition, VO_BLT_SRCTRANSPARENCY, NULL ); // sTotalCanTravel = ( INT16 )GetTotalDistanceHelicopterCanTravel( ); sDistanceToGo = ( INT16 )DistanceOfIntendedHelicopterPath( ); sTotalOfTrip = sDistanceToGo; // + ( INT16 ) ( DistanceToNearestRefuelPoint( ( INT16 )( LastSectorInHelicoptersPath() % MAP_WORLD_X ), ( INT16 ) ( LastSectorInHelicoptersPath() / MAP_WORLD_X ) ) ); sNumSafeSectors = GetNumSafeSectorsInPath( ); sNumUnSafeSectors = GetNumUnSafeSectorsInPath( ); // sDistanceSoFar = ( INT16 )HowFarHelicopterhasTravelledSinceRefueling( ); // sTotalDistanceOfTrip = ( INT16 )DistanceToNearestRefuelPoint( ) if( sDistanceToGo == 9999) { sDistanceToGo = 0; } // set the font stuff SetFont( MAP_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); swprintf( sString, L"%s", pHelicopterEtaStrings[ 0 ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5, sString ); /* if ( IsSectorOutOfTheWay( sMapX, sMapY ) ) { SetFontForeground( FONT_RED ); } else */ { SetFontForeground( FONT_LTGREEN ); } swprintf( sString, L"%d", sTotalOfTrip ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, MAP_HELICOPTER_ETA_POPUP_Y + 5, MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, sYPosition + 5, sString ); SetFontForeground( FONT_LTGREEN ); swprintf( sString, L"%s", pHelicopterEtaStrings[ 1 ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + GetFontHeight( MAP_FONT ), sString ); swprintf( sString, L"%d", sNumSafeSectors ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, ( INT16 ) ( MAP_HELICOPTER_ETA_POPUP_Y + 5 + 2 * GetFontHeight( MAP_FONT ) ), MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, ( INT16 ) ( sYPosition + 5 + GetFontHeight( MAP_FONT ) ), sString ); swprintf( sString, L"%s", pHelicopterEtaStrings[ 2 ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + 2 * GetFontHeight( MAP_FONT ), sString ); swprintf( sString, L"%d", sNumUnSafeSectors ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, ( INT16 ) ( MAP_HELICOPTER_ETA_POPUP_Y + 5 + 2 * GetFontHeight( MAP_FONT ) ), MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, ( INT16 ) ( sYPosition + 5 + 2 * GetFontHeight( MAP_FONT ) ), sString ); swprintf( sString, L"%s", pHelicopterEtaStrings[ 3 ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + 3 * GetFontHeight( MAP_FONT ), sString ); // calculate the cost of the trip based on the number of safe and unsafe sectors it will pass through uiTripCost = ( sNumSafeSectors * COST_AIRSPACE_SAFE ) + ( sNumUnSafeSectors * COST_AIRSPACE_UNSAFE ); swprintf( sString, L"%d", uiTripCost ); InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, ( INT16 ) ( MAP_HELICOPTER_ETA_POPUP_Y + 5 + 3 * GetFontHeight( MAP_FONT ) ), MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, ( INT16 ) ( sYPosition + 5 + 3 * GetFontHeight( MAP_FONT ) ), sString ); swprintf( sString, L"%s", pHelicopterEtaStrings[ 4 ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + 4 * GetFontHeight( MAP_FONT ), sString ); // get travel time for the last path segment iTime = GetPathTravelTimeDuringPlotting( pTempHelicopterPath ); // add travel time for any prior path segments (stored in the helicopter's mercpath, but waypoints aren't built) iTime += GetPathTravelTimeDuringPlotting( pVehicleList[ iHelicopterVehicleId ].pMercPath ); swprintf( sString, L"%d%s %d%s", iTime / 60, gsTimeStrings[0], iTime % 60, gsTimeStrings[1] ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, ( INT16 ) ( sYPosition + 5 + 4 * GetFontHeight( MAP_FONT ) ), MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, ( INT16 ) ( sYPosition + 5 + 4 * GetFontHeight( MAP_FONT ) ), sString ); // show # of passengers aboard the chopper mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + 5 * GetFontHeight( MAP_FONT ), pHelicopterEtaStrings[ 6 ] ); swprintf( sString, L"%d", GetNumberOfPassengersInHelicopter() ); FindFontRightCoordinates( MAP_HELICOPTER_ETA_POPUP_X + 5, ( INT16 ) ( MAP_HELICOPTER_ETA_POPUP_Y + 5 + 5 * GetFontHeight( MAP_FONT ) ), MAP_HELICOPTER_ETA_POPUP_WIDTH, 0, sString, MAP_FONT, &sX, &sY ); mprintf( sX, ( INT16 ) ( sYPosition + 5 + 5 * GetFontHeight( MAP_FONT ) ), sString ); InvalidateRegion( MAP_HELICOPTER_ETA_POPUP_X, sOldYPosition, MAP_HELICOPTER_ETA_POPUP_X + MAP_HELICOPTER_ETA_POPUP_WIDTH + 20, sOldYPosition + MAP_HELICOPTER_ETA_POPUP_HEIGHT ); return; } // grab position of helicopter and blt to screen void DisplayPositionOfHelicopter( void ) { static INT16 sOldMapX = 0, sOldMapY = 0; // INT16 sX =0, sY = 0; FLOAT flRatio = 0.0; UINT32 x,y; UINT16 minX, minY, maxX, maxY; GROUP *pGroup; HVOBJECT hHandle; INT32 iNumberOfPeopleInHelicopter = 0; CHAR16 sString[ 4 ]; AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < SCREEN_HEIGHT ), String( "DisplayPositionOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); // restore background on map where it is if( sOldMapX != 0 ) { RestoreExternBackgroundRect( sOldMapX, sOldMapY, HELI_ICON_WIDTH, HELI_ICON_HEIGHT ); sOldMapX = 0; } if( iHelicopterVehicleId != -1 ) { // draw the destination icon first, so when they overlap, the real one is on top! DisplayDestinationOfHelicopter( ); // check if mvt group if( pVehicleList[ iHelicopterVehicleId ].ubMovementGroup != 0 ) { pGroup = GetGroup( pVehicleList[ iHelicopterVehicleId ].ubMovementGroup ); // this came up in one bug report! Assert( pGroup->uiTraverseTime != -1 ); if( ( pGroup->uiTraverseTime > 0 ) && ( pGroup->uiTraverseTime != 0xffffffff ) ) { flRatio = ( ( pGroup->uiTraverseTime + GetWorldTotalMin() ) - pGroup->uiArrivalTime ) / ( float ) pGroup->uiTraverseTime; } /* AssertMsg( ( flRatio >= 0 ) && ( flRatio <= 100 ), String( "DisplayPositionOfHelicopter: Invalid flRatio = %6.2f, trav %d, arr %d, time %d", flRatio, pGroup->uiTraverseTime, pGroup->uiArrivalTime, GetWorldTotalMin() ) ); */ if ( flRatio < 0 ) { flRatio = 0; } else if ( flRatio > 100 ) { flRatio = 100; } // if( !fZoomFlag ) { // grab min and max locations to interpolate sub sector position minX = MAP_VIEW_START_X + MAP_GRID_X * ( pGroup->ubSectorX ); maxX = MAP_VIEW_START_X + MAP_GRID_X * ( pGroup->ubNextX ); minY = MAP_VIEW_START_Y + MAP_GRID_Y * ( pGroup->ubSectorY ); maxY = MAP_VIEW_START_Y + MAP_GRID_Y * ( pGroup->ubNextY ); } /* else { // grab coords for nextx,y and current x,y // zoomed in, takes a little more work GetScreenXYFromMapXYStationary( ((UINT16)(pGroup->ubSectorX)),((UINT16)(pGroup->ubSectorY)) , &sX, &sY ); sY=sY-MAP_GRID_Y; sX=sX-MAP_GRID_X; minX = ( sX ); minY = ( sY ); GetScreenXYFromMapXYStationary( ((UINT16)(pGroup->ubNextX)),((UINT16)(pGroup->ubNextY)) , &sX, &sY ); sY=sY-MAP_GRID_Y; sX=sX-MAP_GRID_X; maxX = ( sX ); maxY = ( sY ); } */ // WANNE 2 AssertMsg( ( minX >= 0 ) && ( minX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid minX = %d", minX ) ); AssertMsg( ( maxX >= 0 ) && ( maxX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid maxX = %d", maxX ) ); AssertMsg( ( minY >= 0 ) && ( minY < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid minY = %d", minY ) ); AssertMsg( ( maxY >= 0 ) && ( maxY < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid maxY = %d", maxY ) ); // IMPORTANT: Since min can easily be larger than max, we gotta cast to as signed value x = ( UINT32 )( minX + flRatio * ( ( INT16 ) maxX - ( INT16 ) minX ) ); y = ( UINT32 )( minY + flRatio * ( ( INT16 ) maxY - ( INT16 ) minY ) ); /* if( fZoomFlag ) { x += 13; y += 8; } else */ { x += 1; y += 3; } // WANNE 2 AssertMsg( ( x >= 0 ) && ( x < (UINT32)SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid x = %d. At %d,%d. Next %d,%d. Min/Max X = %d/%d", x, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubNextX, pGroup->ubNextY, minX, maxX ) ); AssertMsg( ( y >= 0 ) && ( y < (UINT32)SCREEN_HEIGHT ), String( "DisplayPositionOfHelicopter: Invalid y = %d. At %d,%d. Next %d,%d. Min/Max Y = %d/%d", y, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubNextX, pGroup->ubNextY, minY, maxY ) ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); GetVideoObject( &hHandle, guiHelicopterIcon ); BltVideoObject( FRAME_BUFFER, hHandle, HELI_ICON, x, y, VO_BLT_SRCTRANSPARENCY, NULL ); // now get number of people and blit that too iNumberOfPeopleInHelicopter = GetNumberOfPassengersInHelicopter( ); swprintf( sString, L"%d", iNumberOfPeopleInHelicopter ); SetFont( MAP_MVT_ICON_FONT ); SetFontForeground( FONT_WHITE ); SetFontBackground( FONT_BLACK ); mprintf( x + 5, y + 1 , sString ); InvalidateRegion( x, y, x + HELI_ICON_WIDTH, y + HELI_ICON_HEIGHT ); RestoreClipRegionToFullScreen( ); // now store the old stuff sOldMapX = ( INT16 ) x; sOldMapY = ( INT16 ) y; } } return; } void DisplayDestinationOfHelicopter( void ) { static INT16 sOldMapX = 0, sOldMapY = 0; INT16 sSector; INT16 sMapX, sMapY; UINT32 x,y; HVOBJECT hHandle; // WANNE 2 AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < SCREEN_WIDTH ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < SCREEN_HEIGHT ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); // restore background on map where it is if( sOldMapX != 0 ) { RestoreExternBackgroundRect( sOldMapX, sOldMapY, HELI_SHADOW_ICON_WIDTH, HELI_SHADOW_ICON_HEIGHT ); sOldMapX = 0; } // if helicopter is going somewhere if ( GetLengthOfPath( pVehicleList[ iHelicopterVehicleId ].pMercPath ) > 1 ) { // get destination sSector = GetLastSectorIdInVehiclePath( iHelicopterVehicleId ); sMapX = sSector % MAP_WORLD_X; sMapY = sSector / MAP_WORLD_X; x = MAP_VIEW_START_X + ( MAP_GRID_X * sMapX ) + 1; y = MAP_VIEW_START_Y + ( MAP_GRID_Y * sMapY ) + 3; // WANNE 2 AssertMsg( ( x >= 0 ) && ( x < (UINT32)SCREEN_WIDTH ), String( "DisplayDestinationOfHelicopter: Invalid x = %d. Dest %d,%d", x, sMapX, sMapY ) ); AssertMsg( ( y >= 0 ) && ( y < (UINT32)SCREEN_HEIGHT ), String( "DisplayDestinationOfHelicopter: Invalid y = %d. Dest %d,%d", y, sMapX, sMapY ) ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); GetVideoObject( &hHandle, guiHelicopterIcon ); BltVideoObject( FRAME_BUFFER, hHandle, HELI_SHADOW_ICON, x, y, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( x, y, x + HELI_SHADOW_ICON_WIDTH, y + HELI_SHADOW_ICON_HEIGHT ); RestoreClipRegionToFullScreen( ); // now store the old stuff sOldMapX = ( INT16 ) x; sOldMapY = ( INT16 ) y; } } BOOLEAN CheckForClickOverHelicopterIcon( INT16 sClickedSectorX, INT16 sClickedSectorY ) { INT32 iDeltaTime = 0; BOOLEAN fIgnoreClick = FALSE; GROUP *pGroup = NULL; BOOLEAN fHelicopterOverNextSector = FALSE; FLOAT flRatio = 0.0; INT16 sSectorX; INT16 sSectorY; iDeltaTime = GetJA2Clock() - giClickHeliIconBaseTime; giClickHeliIconBaseTime = GetJA2Clock(); if( iDeltaTime < 400 ) { fIgnoreClick = TRUE; } if( !fHelicopterAvailable || !fShowAircraftFlag ) { return( FALSE ); } if ( iHelicopterVehicleId == -1 ) { return( FALSE ); } // figure out over which sector the helicopter APPEARS to be to the player (because we slide it smoothly across the // map, unlike groups travelling on the ground, it can appear over its next sector while it's not there yet. pGroup = GetGroup( pVehicleList[ iHelicopterVehicleId ].ubMovementGroup ); Assert( pGroup ); if ( pGroup->fBetweenSectors ) { // this came up in one bug report! Assert( pGroup->uiTraverseTime != -1 ); if( ( pGroup->uiTraverseTime > 0 ) && ( pGroup->uiTraverseTime != 0xffffffff ) ) { flRatio = ( pGroup->uiTraverseTime - pGroup->uiArrivalTime + GetWorldTotalMin() ) / ( float ) pGroup->uiTraverseTime; } // if more than halfway there, the chopper appears more over the next sector, not over its current one(!) if ( flRatio > 0.5 ) { fHelicopterOverNextSector = TRUE; } } if ( fHelicopterOverNextSector ) { // use the next sector's coordinates sSectorX = pGroup->ubNextX; sSectorY = pGroup->ubNextY; } else { // use current sector's coordinates sSectorX = pVehicleList[ iHelicopterVehicleId ].sSectorX; sSectorY = pVehicleList[ iHelicopterVehicleId ].sSectorY; } // check if helicopter appears where he clicked if( ( sSectorX != sClickedSectorX ) || ( sSectorY != sClickedSectorY ) ) { return( FALSE ); } return( TRUE ); } void BlitMineIcon( INT16 sMapX, INT16 sMapY ) { HVOBJECT hHandle; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf2; INT16 sScreenX, sScreenY; GetVideoObject( &hHandle, guiMINEICON ); pDestBuf2 = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, MAP_VIEW_START_X+MAP_GRID_X - 1, MAP_VIEW_START_Y+MAP_GRID_Y - 1, MAP_VIEW_WIDTH+1,MAP_VIEW_HEIGHT-9 ); UnLockVideoSurface(guiSAVEBUFFER); if( fZoomFlag ) { GetScreenXYFromMapXYStationary( ( INT16 )( sMapX ), ( INT16 )( sMapY ) , &sScreenX, &sScreenY ); // when zoomed, the x,y returned is the CENTER of the map square in question BltVideoObject( guiSAVEBUFFER, hHandle, 0, sScreenX - MAP_GRID_ZOOM_X / 4, sScreenY - MAP_GRID_ZOOM_Y / 4, VO_BLT_SRCTRANSPARENCY, NULL ); } else { GetScreenXYFromMapXY( ( INT16 )( sMapX ), ( INT16 )( sMapY ), &sScreenX, &sScreenY ); // when not zoomed, the x,y returned is the top left CORNER of the map square in question BltVideoObject( guiSAVEBUFFER, hHandle, 1, sScreenX + MAP_GRID_X / 4, sScreenY + MAP_GRID_Y / 4, VO_BLT_SRCTRANSPARENCY, NULL ); } } void BlitMineText( INT16 sMapX, INT16 sMapY ) { INT16 sScreenX, sScreenY; CHAR16 wString[ 32 ], wSubString[ 32 ]; UINT8 ubMineIndex; UINT8 ubLineCnt = 0; if( fZoomFlag ) { GetScreenXYFromMapXYStationary( ( INT16 )( sMapX ), ( INT16 )( sMapY ) , &sScreenX, &sScreenY ); // set coordinates for start of mine text sScreenY += MAP_GRID_ZOOM_Y / 2 + 1; // slightly below } else { GetScreenXYFromMapXY( ( INT16 )( sMapX ), ( INT16 )( sMapY ), &sScreenX, &sScreenY ); // set coordinates for start of mine text sScreenX += MAP_GRID_X / 2; // centered around middle of mine square sScreenY += MAP_GRID_Y + 1; // slightly below } // show detailed mine info (name, production rate, daily production) SetFontDestBuffer( guiSAVEBUFFER, MAP_VIEW_START_X, MAP_VIEW_START_Y, MAP_VIEW_START_X+MAP_VIEW_WIDTH+MAP_GRID_X, MAP_VIEW_START_Y+MAP_VIEW_HEIGHT+7, FALSE ); SetFont(MAP_FONT); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); ubMineIndex = GetMineIndexForSector( sMapX, sMapY ); // display associated town name, followed by "mine" swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( GetMineIndexForSector( sMapX, sMapY ) ) ], pwMineStrings[ 0 ] ); AdjustXForLeftMapEdge(wString, &sScreenX); mprintf( ( sScreenX - StringPixLength( wString, MAP_FONT ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MAP_FONT ) , wString ); ubLineCnt++; // check if mine is empty (abandoned) or running out if (gMineStatus[ ubMineIndex ].fEmpty) { swprintf( wString, L"%s", pwMineStrings[ 5 ] ); AdjustXForLeftMapEdge(wString, &sScreenX); mprintf( ( sScreenX - StringPixLength( wString, MAP_FONT ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MAP_FONT ) , wString ); ubLineCnt++; } else if (gMineStatus[ ubMineIndex ].fShutDown) { swprintf( wString, L"%s", pwMineStrings[ 6 ] ); AdjustXForLeftMapEdge(wString, &sScreenX); mprintf( ( sScreenX - StringPixLength( wString, MAP_FONT ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MAP_FONT ) , wString ); ubLineCnt++; } else if (gMineStatus[ ubMineIndex ].fRunningOut) { swprintf( wString, L"%s", pwMineStrings[ 7 ] ); AdjustXForLeftMapEdge(wString, &sScreenX); mprintf( ( sScreenX - StringPixLength( wString, MAP_FONT ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MAP_FONT ) , wString ); ubLineCnt++; } // only show production if player controls it and it's actually producing if (PlayerControlsMine(ubMineIndex) && !gMineStatus[ ubMineIndex ].fEmpty) { // show current production swprintf( wSubString, L"%d", PredictDailyIncomeFromAMine(ubMineIndex) ); InsertCommasForDollarFigure( wSubString ); InsertDollarSignInToString( wSubString ); wcscpy( wString, wSubString ); /* // show maximum potential production swprintf( wSubString, L"%d", GetMaxDailyRemovalFromMine(ubMineIndex) ); InsertCommasForDollarFigure( wSubString ); InsertDollarSignInToString( wSubString ); wcscat( wString, L" / "); wcscat( wString, wSubString ); */ // if potential is not nil, show percentage of the two if (GetMaxPeriodicRemovalFromMine(ubMineIndex) > 0) { swprintf( wSubString, L" (%d%%%%)", (PredictDailyIncomeFromAMine(ubMineIndex) * 100 ) / GetMaxDailyRemovalFromMine(ubMineIndex) ); wcscat( wString, wSubString ); } AdjustXForLeftMapEdge(wString, &sScreenX); mprintf( ( sScreenX - StringPixLengthArg( MAP_FONT, wcslen(wString), wString ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MAP_FONT ), wString ); ubLineCnt++; } SetFontDestBuffer( FRAME_BUFFER, MAP_VIEW_START_X, MAP_VIEW_START_Y, MAP_VIEW_START_X+MAP_VIEW_WIDTH+MAP_GRID_X, MAP_VIEW_START_Y+MAP_VIEW_HEIGHT+7, FALSE ); } void AdjustXForLeftMapEdge(STR16 wString, INT16 *psX) { INT16 sStartingX, sPastEdge; if( fZoomFlag ) // it's ok to cut strings off in zoomed mode return; sStartingX = *psX - (StringPixLengthArg( MAP_FONT, wcslen(wString), wString ) / 2); sPastEdge = (MAP_VIEW_START_X + 23) - sStartingX; if (sPastEdge > 0) *psX += sPastEdge; } void BlitTownGridMarkers( void ) { INT16 sScreenX = 0, sScreenY = 0; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor = 0; INT32 iCounter = 0; INT16 sWidth = 0, sHeight = 0; // get 16 bpp color usColor = Get16BPPColor( FROMRGB( 100, 100, 100) ); // blit in the highlighted sector pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); // go through list of towns and place on screen while( pTownNamesList[ iCounter ] != 0 ) { // skip Orta/Tixa until found if( ( ( fFoundOrta != FALSE ) || ( pTownNamesList[ iCounter ] != ORTA ) ) && ( ( pTownNamesList[ iCounter ] != TIXA ) || ( fFoundTixa != FALSE) ) ) { if( fZoomFlag ) { GetScreenXYFromMapXYStationary( ( INT16 )( pTownLocationsList[ iCounter ] % MAP_WORLD_X ), ( INT16 )( pTownLocationsList[ iCounter ] / MAP_WORLD_X ) , &sScreenX, &sScreenY ); sScreenX -= MAP_GRID_X - 1; sScreenY -= MAP_GRID_Y; sWidth = 2 * MAP_GRID_X; sHeight= 2 * MAP_GRID_Y; } else { // get location on screen GetScreenXYFromMapXY( ( INT16 )( pTownLocationsList[ iCounter ] % MAP_WORLD_X ), ( INT16 )( pTownLocationsList[ iCounter ] / MAP_WORLD_X ), &sScreenX, &sScreenY ); sWidth = MAP_GRID_X - 1; sHeight= MAP_GRID_Y; sScreenX += 2; } if( StrategicMap[ pTownLocationsList[ iCounter ] - MAP_WORLD_X ].bNameId == BLANK_SECTOR ) { LineDraw( TRUE, sScreenX - 1, sScreenY - 1, sScreenX + sWidth - 1, sScreenY - 1, usColor, pDestBuf ); } if( ( StrategicMap[ pTownLocationsList[ iCounter ] + MAP_WORLD_X ].bNameId == BLANK_SECTOR ) /* || ( StrategicMap[ pTownLocationsList[ iCounter ] + MAP_WORLD_X ].bNameId == PALACE ) */ ) { LineDraw( TRUE, sScreenX - 1, sScreenY + sHeight - 1, sScreenX + sWidth - 1, sScreenY + sHeight - 1, usColor, pDestBuf ); } if( StrategicMap[ pTownLocationsList[ iCounter ] - 1 ].bNameId == BLANK_SECTOR ) { LineDraw( TRUE, sScreenX - 2, sScreenY - 1, sScreenX - 2, sScreenY + sHeight - 1, usColor, pDestBuf ); } if( StrategicMap[ pTownLocationsList[ iCounter ] + 1 ].bNameId == BLANK_SECTOR ) { LineDraw( TRUE, sScreenX + sWidth - 1, sScreenY - 1, sScreenX + sWidth - 1, sScreenY + sHeight - 1, usColor, pDestBuf ); } } iCounter++; } // restore clips RestoreClipRegionToFullScreenForRectangle( uiDestPitchBYTES ); // unlock surface UnLockVideoSurface( guiSAVEBUFFER ); return; } void BlitMineGridMarkers( void ) { INT16 sScreenX = 0, sScreenY = 0; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor = 0; INT32 iCounter = 0; INT16 sWidth = 0, sHeight = 0; // get 16 bpp color usColor = Get16BPPColor( FROMRGB( 100, 100, 100) ); // blit in the highlighted sector pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); for( iCounter = 0; iCounter < MAX_NUMBER_OF_MINES; iCounter++ ) { if( fZoomFlag ) { GetScreenXYFromMapXYStationary( ( INT16 )( gMineLocation[ iCounter ].sSectorX), ( INT16 )( gMineLocation[ iCounter ].sSectorY ) , &sScreenX, &sScreenY ); sScreenX -= MAP_GRID_X; sScreenY -= MAP_GRID_Y; sWidth = 2 * MAP_GRID_X; sHeight= 2 * MAP_GRID_Y; } else { // get location on screen GetScreenXYFromMapXY( ( INT16 )( gMineLocation[ iCounter ].sSectorX ), ( INT16 )( gMineLocation[ iCounter ].sSectorY ), &sScreenX, &sScreenY ); sWidth = MAP_GRID_X; sHeight= MAP_GRID_Y; } // draw rectangle RectangleDraw( TRUE, sScreenX, sScreenY - 1, sScreenX + sWidth, sScreenY + sHeight - 1, usColor, pDestBuf ); } // restore clips RestoreClipRegionToFullScreenForRectangle( uiDestPitchBYTES ); // unlock surface UnLockVideoSurface( guiSAVEBUFFER ); return; } /* void CheckIfAnyoneLeftInSector( INT16 sX, INT16 sY, INT16 sNewX, INT16 sNewY, INT8 bZ ) { // if this map sector is currently selected if( ( sX == sSelMapX ) && ( sY == sSelMapY ) && ( bZ == iCurrentMapSectorZ ) ) { // check if anyone left in the old sector if( NumFriendlyInSector( (INT8)sX, (INT8)sY, bZ ) == 0) { ChangeSelectedMapSector( sNewX, sNewY, bZ ); fMapScreenBottomDirty = TRUE; } } return; } UINT8 NumFriendlyInSector( INT16 sX, INT16 sY, INT8 bZ ) { SOLDIERTYPE *pTeamSoldier; INT32 cnt = 0; UINT8 ubNumFriendlies = 0; // Check if the battle is won! // Loop through all mercs and make go for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; pTeamSoldier++, cnt++ ) { if ( pTeamSoldier->bActive && pTeamSoldier->bLife > 0 ) { if ( (pTeamSoldier->bSide == gbPlayerNum ) && ( pTeamSoldier->sSectorX == sX ) && ( pTeamSoldier->sSectorY == sY ) && ( pTeamSoldier->bSectorZ == bZ ) ) { ubNumFriendlies++; } } } return( ubNumFriendlies ); } */ void DisplayLevelString( void ) { CHAR16 sString[ 32 ]; // given the current level being displayed on the map, show a sub level message // at the surface if( !iCurrentMapSectorZ ) { return; } // otherwise we will have to display the string with the level number SetFontDestBuffer( guiSAVEBUFFER, MAP_VIEW_START_X, MAP_VIEW_START_Y, MAP_VIEW_START_X+MAP_VIEW_WIDTH+MAP_GRID_X, MAP_VIEW_START_Y+MAP_VIEW_HEIGHT+7, FALSE ); SetFont( MAP_FONT ); SetFontForeground( MAP_INDEX_COLOR ); SetFontBackground( FONT_BLACK ); swprintf( sString, L"%s %d", sMapLevelString[ 0 ], iCurrentMapSectorZ ); // WANNE 2 mprintf( MAP_LEVEL_STRING_X, MAP_LEVEL_STRING_Y, sString ); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); return; } // function to manipulate the number of towns people on the cursor BOOLEAN PickUpATownPersonFromSector( UINT8 ubType, INT16 sX, INT16 sY ) { // see if there are any militia of this type in this sector if( !SectorInfo[ SECTOR( sX, sY ) ].ubNumberOfCivsAtLevel[ ubType ] ) { // failed, no one here return( FALSE ); } // are they in the same town as they were pickedup from if( GetTownIdForSector( sX, sY ) != sSelectedMilitiaTown ) { return( FALSE ); } if( !SectorOursAndPeaceful( sX, sY, 0 ) ) { return( FALSE ); } if( SECTOR( sX, sY ) == SECTOR( gWorldSectorX, gWorldSectorY ) ) { gfStrategicMilitiaChangesMade = TRUE; } // otherwise pick this guy up switch( ubType ) { case( GREEN_MILITIA ): sGreensOnCursor++; break; case( REGULAR_MILITIA ): sRegularsOnCursor++; break; case( ELITE_MILITIA ): sElitesOnCursor++; break; } // reduce number in this sector SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ubType ]--; fMapPanelDirty = TRUE; return( TRUE ); } BOOLEAN DropAPersonInASector( UINT8 ubType, INT16 sX, INT16 sY ) { INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen2"); // are they in the same town as they were pickedup from if( GetTownIdForSector( sX, sY ) != sSelectedMilitiaTown ) { return( FALSE ); } if( SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] >= iMaxMilitiaPerSector ) { return( FALSE ); } if( !SectorOursAndPeaceful(sX, sY, 0 ) ) { return( FALSE ); } if( SECTOR( sX, sY ) == SECTOR( gWorldSectorX, gWorldSectorY ) ) { gfStrategicMilitiaChangesMade = TRUE; } // drop the guy into this sector switch( ubType ) { case( GREEN_MILITIA ): if( !sGreensOnCursor ) { return( FALSE ); } sGreensOnCursor--; break; case( REGULAR_MILITIA ): if( !sRegularsOnCursor ) { return( FALSE ); } sRegularsOnCursor--; break; case( ELITE_MILITIA ): if( !sElitesOnCursor ) { return( FALSE ); } sElitesOnCursor--; break; } // up the number in this sector of this type of militia SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ubType ]++; fMapPanelDirty = TRUE; return( TRUE ); } BOOLEAN LoadMilitiaPopUpBox( void ) { VOBJECT_DESC VObjectDesc; // load the militia pop up box VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Militia.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMilitia)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\Militiamaps.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMilitiaMaps)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\MilitiamapsectorOutline2.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMilitiaSectorHighLight)); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("INTERFACE\\MilitiamapsectorOutline.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMilitiaSectorOutline )); return( TRUE ); } void RemoveMilitiaPopUpBox( void ) { // delete the militia pop up box graphic DeleteVideoObjectFromIndex( guiMilitia ); DeleteVideoObjectFromIndex( guiMilitiaMaps ); DeleteVideoObjectFromIndex( guiMilitiaSectorHighLight ); DeleteVideoObjectFromIndex( guiMilitiaSectorOutline ); return; } BOOLEAN DrawMilitiaPopUpBox( void ) { HVOBJECT hVObject; ETRLEObject *pTrav; if( !fShowMilitia ) { sSelectedMilitiaTown = 0; } // create buttons CreateDestroyMilitiaSectorButtons( ); // create mouse regions if we need to CreateDestroyMilitiaPopUPRegions( ); if( !sSelectedMilitiaTown ) { return( FALSE ); } // update states of militia selected sector buttons CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( ); // get the properties of the militia object GetVideoObject( &hVObject, guiMilitia ); BltVideoObject( FRAME_BUFFER, hVObject, 0, MAP_MILITIA_BOX_POS_X, MAP_MILITIA_BOX_POS_Y, VO_BLT_SRCTRANSPARENCY, NULL ); GetVideoObject( &hVObject, guiMilitiaMaps ); BltVideoObject( FRAME_BUFFER, hVObject, ( UINT16 )( sSelectedMilitiaTown - 1 ), MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X, MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y, VO_BLT_SRCTRANSPARENCY, NULL ); // set font color for labels and "total militia" counts SetFontForeground(FONT_WHITE); // draw name of town, and the "unassigned" label DrawTownMilitiaName( ); // render the icons for each sector in the town RenderIconsPerSectorForSelectedTown( ); // shade any sectors not under our control RenderShadingForUnControlledSectors( ); // display anyone picked up DisplayUnallocatedMilitia( ); // draw the highlight last ShowHighLightedSectorOnMilitiaMap( ); GetVideoObject( &hVObject, guiMilitia ); pTrav = &(hVObject->pETRLEObject[ 0 ] ); InvalidateRegion( MAP_MILITIA_BOX_POS_X, MAP_MILITIA_BOX_POS_Y, MAP_MILITIA_BOX_POS_X + pTrav->usWidth, MAP_MILITIA_BOX_POS_Y + pTrav->usHeight ); // set the text for the militia map sector info buttons SetMilitiaMapButtonsText( ); // render buttons MarkButtonsDirty( ); return( TRUE ); } void CreateDestroyMilitiaPopUPRegions( void ) { static INT16 sOldTown = 0; INT32 iCounter = 0; // create destroy militia pop up regions for mapscreen militia pop up box if( sSelectedMilitiaTown != 0 ) { sOldTown = sSelectedMilitiaTown; } if( fShowMilitia && sSelectedMilitiaTown && !gfMilitiaPopupCreated ) { for( iCounter = 0; iCounter < 9; iCounter++ ) { MSYS_DefineRegion( &gMapScreenMilitiaBoxRegions[ iCounter ], ( INT16 ) ( MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ), ( INT16 )( MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ), ( INT16 )( MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( ( iCounter ) % MILITIA_BOX_ROWS ) + 1 ) * MILITIA_BOX_BOX_WIDTH ), ( INT16 )( MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( ( iCounter ) / MILITIA_BOX_ROWS ) + 1 ) * MILITIA_BOX_BOX_HEIGHT ), MSYS_PRIORITY_HIGHEST - 3, MSYS_NO_CURSOR, MilitiaRegionMoveCallback, MilitiaRegionClickCallback ); MSYS_SetRegionUserData( &gMapScreenMilitiaBoxRegions[ iCounter ], 0, iCounter ); } // create militia panel buttons CreateMilitiaPanelBottomButton( ); gfMilitiaPopupCreated = TRUE; } else if( gfMilitiaPopupCreated && ( !fShowMilitia || !sSelectedMilitiaTown ) ) { for( iCounter = 0; iCounter < 9; iCounter++ ) { // remove region MSYS_RemoveRegion( &gMapScreenMilitiaBoxRegions[ iCounter ] ); } // handle the shutdown of the panel...there maybe people on the cursor, distribute them evenly over all the sectors HandleShutDownOfMilitiaPanelIfPeopleOnTheCursor( sOldTown ); DeleteMilitiaPanelBottomButton( ); gfMilitiaPopupCreated = FALSE; } return; } void RenderIconsPerSectorForSelectedTown( void ) { INT16 sBaseSectorValue = 0; INT16 sCurrentSectorValue = 0; INT32 iCounter = 0; INT32 iNumberOfGreens = 0; INT32 iNumberOfRegulars = 0; INT32 iNumberOfElites = 0; INT32 iTotalNumberOfTroops = 0; INT32 iCurrentTroopIcon = 0; HVOBJECT hVObject; INT32 iCurrentIcon = 0; INT16 sX, sY; CHAR16 sString[ 32 ]; INT16 sSectorX = 0, sSectorY = 0; // get the sector value for the upper left corner sBaseSectorValue = GetBaseSectorForCurrentTown( ); // get militia video object GetVideoObject( &hVObject, guiMilitia ); // render icons for map for( iCounter = 0; iCounter < 9; iCounter++ ) { // grab current sector value sCurrentSectorValue = sBaseSectorValue + ( ( iCounter % MILITIA_BOX_ROWS ) + ( iCounter / MILITIA_BOX_ROWS ) * ( 16 ) ); sSectorX = SECTORX( sCurrentSectorValue ); sSectorY = SECTORY( sCurrentSectorValue ); // skip sectors not in the selected town (nearby other towns or wilderness SAM Sites) if( GetTownIdForSector( sSectorX, sSectorY ) != sSelectedMilitiaTown ) { continue; } // get number of each iNumberOfGreens = SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberOfRegulars = SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberOfElites = SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; // get total iTotalNumberOfTroops = iNumberOfGreens + iNumberOfRegulars + iNumberOfElites; // printf number of troops SetFont( FONT10ARIAL ); swprintf( sString, L"%d", iTotalNumberOfTroops ); FindFontRightCoordinates( ( INT16 )( MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ) ), ( INT16 ) ( MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ) ), MILITIA_BOX_BOX_WIDTH, 0, sString, FONT10ARIAL, &sX, &sY ); if( StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( sCurrentSectorValue ) ].bNameId != BLANK_SECTOR && !StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( sCurrentSectorValue ) ].fEnemyControlled ) { if( sSectorMilitiaMapSector != iCounter ) { mprintf( sX, ( INT16 )( sY + MILITIA_BOX_BOX_HEIGHT - 5), sString ); } else { mprintf( sX - 15, ( INT16 )( sY + MILITIA_BOX_BOX_HEIGHT - 5), sString ); } } // now display for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfTroops; iCurrentTroopIcon++ ) { // get screen x and y coords if( sSectorMilitiaMapSector == iCounter ) { sX = ( iCurrentTroopIcon % POPUP_MILITIA_ICONS_PER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ) + 2; sY = ( iCurrentTroopIcon / POPUP_MILITIA_ICONS_PER_ROW ) * ( MEDIUM_MILITIA_ICON_SPACING - 1 ) + MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ) + 3; if( iCurrentTroopIcon < iNumberOfGreens ) { iCurrentIcon = 5; } else if( iCurrentTroopIcon < iNumberOfGreens + iNumberOfRegulars ) { iCurrentIcon = 6; } else { iCurrentIcon = 7; } } else { sX = ( iCurrentTroopIcon % POPUP_MILITIA_ICONS_PER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ) + 3; sY = ( iCurrentTroopIcon / POPUP_MILITIA_ICONS_PER_ROW ) * ( MEDIUM_MILITIA_ICON_SPACING ) + MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ) + 3; if( iCurrentTroopIcon < iNumberOfGreens ) { iCurrentIcon = 8; } else if( iCurrentTroopIcon < iNumberOfGreens + iNumberOfRegulars ) { iCurrentIcon = 9; } else { iCurrentIcon = 10; } } BltVideoObject( FRAME_BUFFER, hVObject, ( UINT16 )( iCurrentIcon ), sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } } return; } INT16 GetBaseSectorForCurrentTown( void ) { INT16 sBaseSector = 0; // is the current town if( sSelectedMilitiaTown != 0 ) { sBaseSector = sBaseSectorList[ ( INT16 )( sSelectedMilitiaTown - 1 ) ]; } // return the current sector value return( sBaseSector ); } void ShowHighLightedSectorOnMilitiaMap( void ) { // show the highlighted sector on the militia map HVOBJECT hVObject; INT16 sX = 0, sY = 0; if( sSectorMilitiaMapSector != -1 ) { sX = MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ); sY = MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ); // get the object GetVideoObject( &hVObject, guiMilitiaSectorHighLight ); // blt the object BltVideoObject( FRAME_BUFFER, hVObject, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } if( sSectorMilitiaMapSectorOutline != -1 ) { sX = MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( sSectorMilitiaMapSectorOutline % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ); sY = MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( sSectorMilitiaMapSectorOutline / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ); // get the object GetVideoObject( &hVObject, guiMilitiaSectorOutline ); // blt the object BltVideoObject( FRAME_BUFFER, hVObject, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } return; } void MilitiaRegionClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) { if( IsThisMilitiaTownSectorAllowable( (INT16)iValue ) ) { if( sSectorMilitiaMapSector == (INT16)iValue ) { sSectorMilitiaMapSector = -1; } else { sSectorMilitiaMapSector = ( INT16 )iValue; } } else { sSectorMilitiaMapSector = -1; } } if( ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) ) { sSectorMilitiaMapSector = -1; } } void MilitiaRegionMoveCallback( MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; iValue = MSYS_GetRegionUserData( pRegion, 0 ); if( ( iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) ) { if( IsThisMilitiaTownSectorAllowable( ( INT16 )iValue ) ) { sSectorMilitiaMapSectorOutline = ( INT16 )iValue; } else { sSectorMilitiaMapSectorOutline = -1; } } else if( iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) { sSectorMilitiaMapSectorOutline = -1; } } void CreateDestroyMilitiaSectorButtons( void ) { static BOOLEAN fCreated = FALSE; static INT16 sOldSectorValue = -1; INT16 sX = 0, sY = 0; INT32 iCounter = 0; HVOBJECT hVObject; ETRLEObject *pTrav; if( sOldSectorValue == sSectorMilitiaMapSector && fShowMilitia && sSelectedMilitiaTown && !fCreated && sSectorMilitiaMapSector != -1 ) { fCreated = TRUE; // given sector..place down the 3 buttons for( iCounter = 0; iCounter < 3; iCounter++ ) { // set screen x and y positions sX = MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ); sY = MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ); // adjust offsets sX += MILITIA_BTN_OFFSET_X; sY += ( iCounter * ( MILITIA_BTN_HEIGHT ) + 2 ); // set the button image giMapMilitiaButtonImage[ iCounter ]= LoadButtonImage( "INTERFACE\\militia.sti" ,-1,3,-1,4,-1 ); // set the button value giMapMilitiaButton[ iCounter ] = QuickCreateButton( giMapMilitiaButtonImage[ iCounter ], sX, sY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MilitiaButtonCallback); // set button user data MSYS_SetBtnUserData( giMapMilitiaButton[ iCounter ], 0, iCounter ); SpecifyButtonFont( giMapMilitiaButton[ iCounter ], FONT10ARIAL ); SpecifyButtonUpTextColors( giMapMilitiaButton[ iCounter ], gsMilitiaSectorButtonColors[ iCounter ], FONT_BLACK ); SpecifyButtonDownTextColors( giMapMilitiaButton[ iCounter ], gsMilitiaSectorButtonColors[ iCounter ], FONT_BLACK ); GetVideoObject( &hVObject, guiMilitia ); pTrav = &(hVObject->pETRLEObject[ 0 ] ); SetButtonFastHelpText( giMapMilitiaButton[ iCounter ], pMilitiaButtonsHelpText[ iCounter ] ); } // mark here the militia box left click region //MSYS_DefineRegion( &gMapScreenMilitiaRegion, ( INT16 ) ( MAP_MILITIA_BOX_POS_X ), ( INT16 )( MAP_MILITIA_BOX_POS_Y ), ( INT16 )( MAP_MILITIA_BOX_POS_X + pTrav->usWidth ), ( INT16 )( MAP_MILITIA_BOX_POS_Y + pTrav->usHeight ), MSYS_PRIORITY_HIGHEST - 2, // MSYS_NO_CURSOR, MilitiaRegionMoveCallback, MilitiaBoxMaskBtnCallback ); CreateScreenMaskForMoveBox( ); // ste the fact that the buttons were in fact created fMilitiaMapButtonsCreated = TRUE; } else if( fCreated && ( sOldSectorValue != sSectorMilitiaMapSector || !fShowMilitia || !sSelectedMilitiaTown || sSectorMilitiaMapSector == -1 ) ) { sOldSectorValue = sSectorMilitiaMapSector; fCreated = FALSE; // the militia box left click region // MSYS_RemoveRegion( &gMapScreenMilitiaRegion ); // get rid of the buttons for( iCounter = 0 ; iCounter < 3; iCounter++ ) { RemoveButton( giMapMilitiaButton[ iCounter ] ); UnloadButtonImage( giMapMilitiaButtonImage[ iCounter ] ); } if( !fShowMilitia || !sSelectedMilitiaTown ) { sSectorMilitiaMapSector = -1; sSelectedMilitiaTown = 0; } RemoveScreenMaskForMoveBox( ); // set the fact that the buttons were destroyed fMilitiaMapButtonsCreated = FALSE; } sOldSectorValue = sSectorMilitiaMapSector; } void SetMilitiaMapButtonsText( void ) { // now set the militia map button text CHAR16 sString[ 64 ]; INT32 iNumberOfGreens = 0, iNumberOfRegulars = 0, iNumberOfElites = 0; INT16 sBaseSectorValue = 0, sGlobalMapSector = 0; if( !fMilitiaMapButtonsCreated ) { return; } // grab the appropriate global sector value in the world sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) + ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * ( 16 ) ); iNumberOfGreens = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberOfRegulars = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberOfElites = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; // the greens in this sector swprintf( sString, L"%d", iNumberOfGreens ); SpecifyButtonText( giMapMilitiaButton[ 0 ], sString ); // the regulars in this sector swprintf( sString, L"%d", iNumberOfRegulars ); SpecifyButtonText( giMapMilitiaButton[ 1 ], sString ); // the number of elites in this sector swprintf( sString, L"%d", iNumberOfElites ); SpecifyButtonText( giMapMilitiaButton[ 2 ], sString ); return; } void MilitiaButtonCallback(GUI_BUTTON *btn,INT32 reason) { INT16 sGlobalMapSector = 0; INT16 sBaseSectorValue = 0; INT32 iValue = 0; // is the button enabled if (!(btn->uiFlags & BUTTON_ENABLED)) return; // get the value iValue = MSYS_GetBtnUserData( btn, 0 ); // get the sector value for the upper left corner sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) + ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * ( 16 ) ); if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if(btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags&=~(BUTTON_CLICKED_ON); DropAPersonInASector( ( UINT8 )( iValue ), ( INT16 )( ( sGlobalMapSector % 16 ) + 1 ), ( INT16 )( ( sGlobalMapSector / 16 ) + 1 ) ); } } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_RBUTTON_UP ) { if(btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags&=~(BUTTON_CLICKED_ON); PickUpATownPersonFromSector( ( UINT8 )( iValue ), ( INT16 )( ( sGlobalMapSector % 16 ) + 1 ), ( INT16 )( ( sGlobalMapSector / 16 ) + 1 ) ); } } } void DisplayUnallocatedMilitia( void ) { // show the nunber on the cursor INT32 iTotalNumberOfTroops =0, iNumberOfGreens = 0, iNumberOfRegulars =0, iNumberOfElites = 0, iCurrentTroopIcon = 0; INT32 iCurrentIcon = 0; INT16 sX = 0, sY = 0; HVOBJECT hVObject; // get number of each iNumberOfGreens = sGreensOnCursor; iNumberOfRegulars = sRegularsOnCursor; iNumberOfElites = sElitesOnCursor; // get total iTotalNumberOfTroops = iNumberOfGreens + iNumberOfRegulars + iNumberOfElites; // get militia video object GetVideoObject( &hVObject, guiMilitia ); // now display for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfTroops; iCurrentTroopIcon++ ) { // get screen x and y coords sX = ( iCurrentTroopIcon % NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + 1; sY = ( iCurrentTroopIcon / NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_LOWER_ROW_Y; if( iCurrentTroopIcon < iNumberOfGreens ) { iCurrentIcon = 8; } else if( iCurrentTroopIcon < iNumberOfGreens + iNumberOfRegulars ) { iCurrentIcon = 9; } else { iCurrentIcon = 10; } BltVideoObject( FRAME_BUFFER, hVObject, ( UINT16 )( iCurrentIcon ), sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } } BOOLEAN IsThisMilitiaTownSectorAllowable( INT16 sSectorIndexValue ) { INT16 sBaseSectorValue = 0, sGlobalMapSector = 0; INT16 sSectorX, sSectorY; // is this sector allowed to be clicked on? sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorIndexValue % MILITIA_BOX_ROWS ) + ( sSectorIndexValue / MILITIA_BOX_ROWS ) * 16 ); sSectorX = SECTORX( sGlobalMapSector ); sSectorY = SECTORY( sGlobalMapSector ); // is this in fact part of a town? if( StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].bNameId == BLANK_SECTOR ) { return( FALSE ); } if( !SectorOursAndPeaceful( sSectorX, sSectorY, 0 ) ) { return( FALSE ); } // valid return( TRUE ); } void DrawTownMilitiaName( void ) { CHAR16 sString[ 64 ]; INT16 sX, sY; // get the name for the current militia town swprintf( sString, L"%s %s", pTownNames[ sSelectedMilitiaTown ], pMilitiaString[ 0 ] ); FindFontCenterCoordinates( MAP_MILITIA_BOX_POS_X, MAP_MILITIA_BOX_POS_Y + MILITIA_BOX_TEXT_OFFSET_Y, MILITIA_BOX_WIDTH, MILITIA_BOX_TEXT_TITLE_HEIGHT, sString, FONT10ARIAL, &sX, &sY ); mprintf( sX, sY, sString ); // might as well show the unassigned string swprintf( sString, L"%s %s", pTownNames[ sSelectedMilitiaTown ], pMilitiaString[ 1 ] ); FindFontCenterCoordinates( MAP_MILITIA_BOX_POS_X, MAP_MILITIA_BOX_POS_Y + MILITIA_BOX_UNASSIGNED_TEXT_OFFSET_Y, MILITIA_BOX_WIDTH, GetFontHeight( FONT10ARIAL ), sString, FONT10ARIAL, &sX, &sY ); mprintf( sX, sY, sString ); return; } void HandleShutDownOfMilitiaPanelIfPeopleOnTheCursor( INT16 sTownValue ) { INT32 iCounter = 0, iCounterB = 0, iNumberUnderControl = 0, iNumberThatCanFitInSector= 0, iCount = 0; BOOLEAN fLastOne = FALSE; INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3"); // check if anyone still on the cursor if( !sGreensOnCursor && !sRegularsOnCursor && !sElitesOnCursor ) { return; } // yep someone left iNumberUnderControl = GetTownSectorsUnderControl( ( INT8 ) sTownValue ); // find number of sectors under player's control while( pTownNamesList[ iCounter ] != 0 ) { if( pTownNamesList[ iCounter] == sTownValue ) { if( SectorOursAndPeaceful( ( INT16 )( pTownLocationsList[ iCounter ] % MAP_WORLD_X ) , ( INT16 )( pTownLocationsList[ iCounter ] / MAP_WORLD_X ), 0 ) ) { iCount = 0; iNumberThatCanFitInSector = iMaxMilitiaPerSector; iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; while( ( iCount < iNumberThatCanFitInSector )&&( ( sGreensOnCursor ) || ( sRegularsOnCursor ) || ( sElitesOnCursor ) ) ) { // green if( ( iCount + 1 <= iNumberThatCanFitInSector )&&( sGreensOnCursor ) ) { SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]++; iCount++; sGreensOnCursor--; } // regular if( ( iCount + 1 <= iNumberThatCanFitInSector ) && ( sRegularsOnCursor ) ) { SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]++; iCount++; sRegularsOnCursor--; } // elite if( ( iCount + 1 <= iNumberThatCanFitInSector ) && ( sElitesOnCursor ) ) { SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]++; iCount++; sElitesOnCursor--; } } if( STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) == SECTOR( gWorldSectorX, gWorldSectorY ) ) { gfStrategicMilitiaChangesMade = TRUE; } } fLastOne = TRUE; iCounterB = iCounter + 1; while( pTownNamesList[ iCounterB ] != 0 ) { if( pTownNamesList[ iCounterB ] == sTownValue ) { fLastOne = FALSE; } iCounterB++; } if( fLastOne ) { SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] += ( UINT8 )( sGreensOnCursor % iNumberUnderControl ); SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] += ( UINT8 )( sRegularsOnCursor % iNumberUnderControl ); SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] += ( UINT8 )( sElitesOnCursor % iNumberUnderControl ); } } iCounter++; } // zero out numbers on the cursor sGreensOnCursor = 0; sRegularsOnCursor = 0; sElitesOnCursor = 0; return; } void HandleEveningOutOfTroopsAmongstSectors( void ) { INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4"); // even out troops among the town INT32 iCounter = 0, iNumberUnderControl = 0, iNumberOfGreens = 0, iNumberOfRegulars = 0, iNumberOfElites = 0, iTotalNumberOfTroops = 0; INT32 iNumberLeftOverGreen = 0, iNumberLeftOverRegular = 0, iNumberLeftOverElite = 0; INT16 sBaseSectorValue = 0, sCurrentSectorValue = 0; INT16 sSectorX = 0, sSectorY = 0, sSector = 0; INT16 sTotalSoFar = 0; // how many sectors in the selected town do we control? iNumberUnderControl = GetTownSectorsUnderControl( ( INT8 ) sSelectedMilitiaTown ); // if none, there's nothing to be done! if( !iNumberUnderControl ) { return; } // get the sector value for the upper left corner sBaseSectorValue = GetBaseSectorForCurrentTown( ); // render icons for map for( iCounter = 0; iCounter < 9; iCounter++ ) { // grab current sector value sCurrentSectorValue = sBaseSectorValue + ( ( iCounter % MILITIA_BOX_ROWS ) + ( iCounter / MILITIA_BOX_ROWS ) * ( 16 ) ); sSectorX = SECTORX( sCurrentSectorValue ); sSectorY = SECTORY( sCurrentSectorValue ); // skip sectors not in the selected town (nearby other towns or wilderness SAM Sites) if( GetTownIdForSector( sSectorX, sSectorY ) != sSelectedMilitiaTown ) { continue; } if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { // get number of each iNumberOfGreens += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberOfRegulars += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberOfElites += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; } } // now grab those on the cursor iNumberOfGreens += sGreensOnCursor; iNumberOfRegulars += sRegularsOnCursor; iNumberOfElites += sElitesOnCursor; // now get the left overs iNumberLeftOverGreen = iNumberOfGreens % iNumberUnderControl; iNumberLeftOverRegular = iNumberOfRegulars % iNumberUnderControl; iNumberLeftOverElite = iNumberOfElites % iNumberUnderControl; // get total iTotalNumberOfTroops = iNumberOfGreens + iNumberOfRegulars + iNumberOfElites; if( !iTotalNumberOfTroops ) { return; } iCounter = 0; while( pTownNamesList[ iCounter ] != 0 ) { if( pTownNamesList[ iCounter] == sSelectedMilitiaTown ) { sSectorX = GET_X_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] ); sSectorY = GET_Y_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] ); if( !StrategicMap[ pTownLocationsList[ iCounter ] ].fEnemyControlled && !NumHostilesInSector( sSectorX, sSectorY, 0 ) ) { sSector = SECTOR( sSectorX, sSectorY ); // distribute here SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] = ( UINT8 )( iNumberOfGreens / iNumberUnderControl ); SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] = ( UINT8 )( iNumberOfRegulars / iNumberUnderControl ); SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] = ( UINT8 )( iNumberOfElites / iNumberUnderControl ); sTotalSoFar = ( INT8 )( ( iNumberOfGreens / iNumberUnderControl ) + ( iNumberOfRegulars / iNumberUnderControl ) + ( iNumberOfElites / iNumberUnderControl ) ); // add leftovers that weren't included in the div operation if( ( iNumberLeftOverGreen ) && ( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]++; sTotalSoFar++; iNumberLeftOverGreen--; } if( ( iNumberLeftOverRegular )&&( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]++; sTotalSoFar++; iNumberLeftOverRegular--; } if( ( iNumberLeftOverElite )&&( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]++; sTotalSoFar++; iNumberLeftOverElite--; } // if this sector is currently loaded if( sSector == SECTOR( gWorldSectorX, gWorldSectorY ) && gWorldSectorY != 0 ) { gfStrategicMilitiaChangesMade = TRUE; } } } iCounter++; } // zero out numbers on the cursor sGreensOnCursor = 0; sRegularsOnCursor = 0; sElitesOnCursor = 0; return; } void CreateMilitiaPanelBottomButton( void ) { // set the button image giMapMilitiaButtonImage[ 3 ]= LoadButtonImage( "INTERFACE\\militia.sti" ,-1,1,-1,2,-1 ); giMapMilitiaButtonImage[ 4 ]= LoadButtonImage( "INTERFACE\\militia.sti" ,-1,1,-1,2,-1 ); giMapMilitiaButton[ 3 ] = QuickCreateButton( giMapMilitiaButtonImage[ 3 ], MAP_MILITIA_BOX_POS_X + MAP_MILITIA_BOX_AUTO_BOX_X, MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_BOX_AUTO_BOX_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK) MilitiaAutoButtonCallback ); giMapMilitiaButton[ 4 ] = QuickCreateButton( giMapMilitiaButtonImage[ 4 ], MAP_MILITIA_BOX_POS_X + MAP_MILITIA_BOX_DONE_BOX_X, MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_BOX_AUTO_BOX_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK) MilitiaDoneButtonCallback ); SpecifyButtonFont( giMapMilitiaButton[ 3 ], FONT10ARIAL ); SpecifyButtonUpTextColors( giMapMilitiaButton[ 3 ], FONT_BLACK, FONT_BLACK ); SpecifyButtonDownTextColors( giMapMilitiaButton[ 3 ], FONT_BLACK, FONT_BLACK ); SpecifyButtonFont( giMapMilitiaButton[ 4 ], FONT10ARIAL ); SpecifyButtonUpTextColors( giMapMilitiaButton[ 4 ], FONT_BLACK, FONT_BLACK ); SpecifyButtonDownTextColors( giMapMilitiaButton[ 4 ], FONT_BLACK, FONT_BLACK ); SpecifyButtonText( giMapMilitiaButton[ 3 ], pMilitiaButtonString[ 0 ] ); SpecifyButtonText( giMapMilitiaButton[ 4 ], pMilitiaButtonString[ 1 ] ); // AUTO button help SetButtonFastHelpText( giMapMilitiaButton[ 3 ], pMilitiaButtonsHelpText[ 3 ] ); // if auto-distribution is not possible if ( !CanMilitiaAutoDistribute( ) ) { // disable the AUTO button DisableButton( giMapMilitiaButton[ 3 ] ); } return; } void DeleteMilitiaPanelBottomButton( void ) { // delete militia panel bottom RemoveButton( giMapMilitiaButton[ 3 ] ); RemoveButton( giMapMilitiaButton[ 4 ] ); UnloadButtonImage( giMapMilitiaButtonImage[ 3 ] ); UnloadButtonImage( giMapMilitiaButtonImage[ 4 ] ); if( sSelectedMilitiaTown != 0 ) { HandleShutDownOfMilitiaPanelIfPeopleOnTheCursor( sSelectedMilitiaTown ); } // redraw the map fMapPanelDirty = TRUE; } void MilitiaAutoButtonCallback(GUI_BUTTON *btn,INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if( btn->uiFlags & BUTTON_CLICKED_ON ) { btn->uiFlags &= ~( BUTTON_CLICKED_ON ); // distribute troops over all the sectors under control HandleEveningOutOfTroopsAmongstSectors( ); fMapPanelDirty = TRUE; } } return; } void MilitiaDoneButtonCallback(GUI_BUTTON *btn,INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); } else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if( btn->uiFlags & BUTTON_CLICKED_ON ) { btn->uiFlags &= ~( BUTTON_CLICKED_ON ); // reset fact we are in the box sSelectedMilitiaTown = 0; fMapPanelDirty = TRUE; } } return; } void RenderShadingForUnControlledSectors( void ) { // now render shading over any uncontrolled sectors // get the sector value for the upper left corner INT16 sBaseSectorValue = 0, sCurrentSectorValue = 0, sX = 0, sY = 0; INT32 iCounter = 0; // get the base sector value sBaseSectorValue = GetBaseSectorForCurrentTown( ); // render icons for map for( iCounter = 0; iCounter < 9; iCounter++ ) { // grab current sector value sCurrentSectorValue = sBaseSectorValue + ( ( iCounter % MILITIA_BOX_ROWS ) + ( iCounter / MILITIA_BOX_ROWS ) * ( 16 ) ); if( ( StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( sCurrentSectorValue ) ].bNameId != BLANK_SECTOR ) && ( ( StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( sCurrentSectorValue ) ].fEnemyControlled ) || ( NumHostilesInSector( ( INT16 ) SECTORX( sCurrentSectorValue ), ( INT16 ) SECTORY( sCurrentSectorValue ), 0 ) ) ) ) { // shade this sector, not under our control sX = MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ); sY = MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ); ShadowVideoSurfaceRect( FRAME_BUFFER , sX, sY, sX + MILITIA_BOX_BOX_WIDTH - 1, sY + MILITIA_BOX_BOX_HEIGHT - 1 ); } } return; } void DrawTownMilitiaForcesOnMap( void ) { INT32 iCounter = 0, iCounterB = 0, iTotalNumberOfTroops = 0, iIconValue = 0; INT32 iNumberOfGreens = 0, iNumberOfRegulars = 0, iNumberOfElites = 0; HVOBJECT hVObject; INT16 sSectorX = 0, sSectorY = 0; // get militia video object GetVideoObject( &hVObject, guiMilitia ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); /* while( pTownNamesList[ iCounter ] != 0 ) { // run through each town sector and plot the icons for the militia forces in the town if( !StrategicMap[ pTownLocationsList[ iCounter ] ].fEnemyControlled ) { sSectorX = GET_X_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] ); sSectorY = GET_Y_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] ); // get number of each iNumberOfGreens = SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberOfRegulars = SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberOfElites = SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; // set the total for loop upper bound iTotalNumberOfTroops = iNumberOfGreens + iNumberOfRegulars + iNumberOfElites; for( iCounterB = 0; iCounterB < iTotalNumberOfTroops; iCounterB++ ) { if( fZoomFlag ) { // LARGE icon offset in the .sti iIconValue = 11; } else { // SMALL icon offset in the .sti iIconValue = 5; } // get the offset further into the .sti if( iCounterB < iNumberOfGreens ) { iIconValue += 0; } else if( iCounterB < iNumberOfGreens + iNumberOfRegulars ) { iIconValue += 1; } else { iIconValue += 2; } DrawMapBoxIcon( hVObject, ( UINT16 ) iIconValue, sSectorX, sSectorY, (UINT8) iCounterB ); } } iCounter++; }*/ // now handle militia for sam sectors for( sSectorX = 0; sSectorX < 16 ; ++sSectorX ) for( sSectorY = 0; sSectorY < 16 ; ++sSectorY ) //for( iCounter = 0; iCounter < NUMBER_OF_SAMS; iCounter++ ) { // sSectorX = SECTORX( pSamList[ iCounter ] ); // sSectorY = SECTORY( pSamList[ iCounter ] ); if( 1)// !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { // get number of each iNumberOfGreens = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; iNumberOfRegulars = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; iNumberOfElites = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; // ste the total for loop upper bound iTotalNumberOfTroops = iNumberOfGreens + iNumberOfRegulars + iNumberOfElites; for( iCounterB = 0; iCounterB < iTotalNumberOfTroops; iCounterB++ ) { if( fZoomFlag ) { // LARGE icon offset in the .sti iIconValue = 11; } else { // SMALL icon offset in the .sti iIconValue = 5; } // get the offset further into the .sti if( iCounterB < iNumberOfGreens ) { iIconValue += 0; } else if( iCounterB < iNumberOfGreens + iNumberOfRegulars ) { iIconValue += 1; } else { iIconValue += 2; } DrawMapBoxIcon( hVObject, ( UINT16 ) iIconValue, sSectorX, sSectorY, (UINT8) iCounterB ); } } } // restore clip blits RestoreClipRegionToFullScreen( ); return; } void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void ) { // now set the militia map button text INT32 iNumberOfGreens = 0, iNumberOfRegulars = 0, iNumberOfElites = 0; INT16 sBaseSectorValue = 0, sGlobalMapSector = 0; if( !fMilitiaMapButtonsCreated ) { EnableButton( giMapMilitiaButton[ 4 ] ); return; } // grab the appropriate global sector value in the world sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) + ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * ( 16 ) ); iNumberOfGreens = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + sGreensOnCursor; iNumberOfRegulars = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + sRegularsOnCursor; iNumberOfElites = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] + sElitesOnCursor; if( ( sGreensOnCursor > 0 ) || ( sRegularsOnCursor > 0 ) || ( sElitesOnCursor > 0 ) ) { DisableButton( giMapMilitiaButton[ 4 ] ); // DONE } else { EnableButton( giMapMilitiaButton[ 4 ] ); // DONE } // greens button if( !iNumberOfGreens ) { DisableButton( giMapMilitiaButton[ 0 ] ); } else { EnableButton( giMapMilitiaButton[ 1 ] ); } // regulars button if( !iNumberOfRegulars ) { DisableButton( giMapMilitiaButton[ 1 ] ); } else { EnableButton( giMapMilitiaButton[ 1 ] ); } // elites button if( !iNumberOfElites ) { DisableButton( giMapMilitiaButton[ 2 ] ); } else { EnableButton( giMapMilitiaButton[ 2 ] ); } return; } BOOLEAN ShadeUndergroundMapElem( INT16 sSectorX, INT16 sSectorY ) { INT16 sScreenX, sScreenY; GetScreenXYFromMapXY( sSectorX, sSectorY, &sScreenX, &sScreenY ); sScreenX += 1; ShadowVideoSurfaceRect( guiSAVEBUFFER, sScreenX, sScreenY, sScreenX + MAP_GRID_X - 2, sScreenY + MAP_GRID_Y - 2 ); return( TRUE ); } void ShadeSubLevelsNotVisited( void ) { UNDERGROUND_SECTORINFO *pNode = gpUndergroundSectorInfoHead; // obtain the 16-bit version of the same color used in the mine STIs gusUndergroundNearBlack = Get16BPPColor( FROMRGB( 2, 2, 0 ) ); // run through all (real & possible) underground sectors while( pNode ) { // if the sector is on the currently displayed sublevel, and has never been visited if( pNode->ubSectorZ == (UINT8)iCurrentMapSectorZ && !pNode->fVisited ) { // remove that portion of the "mine" graphics from view HideExistenceOfUndergroundMapSector( pNode->ubSectorX, pNode->ubSectorY ); } pNode = pNode->next; } } void HandleLowerLevelMapBlit( void ) { HVOBJECT hHandle; // blits the sub level maps switch( iCurrentMapSectorZ ) { case( 1 ): GetVideoObject( &hHandle, guiSubLevel1 ); break; case( 2 ): GetVideoObject( &hHandle, guiSubLevel2 ); break; case( 3 ): GetVideoObject( &hHandle, guiSubLevel3 ); break; } // handle the blt of the sublevel BltVideoObject( guiSAVEBUFFER, hHandle, 0,MAP_VIEW_START_X + 21, MAP_VIEW_START_Y + 17, VO_BLT_SRCTRANSPARENCY, NULL ); // handle shading of sublevels ShadeSubLevelsNotVisited( ); return; } void MilitiaBoxMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) { // btn callback handler for assignment screen mask region if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) { sSectorMilitiaMapSector = -1; } else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) { sSectorMilitiaMapSector = -1; } return; } INT32 GetNumberOfMilitiaInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) { INT32 iNumberInSector = 0; if( !bSectorZ ) { iNumberInSector = SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; } return( iNumberInSector ); } //There is a special case flag used when players encounter enemies in a sector, then retreat. The number of enemies //will display on mapscreen until time is compressed. When time is compressed, the flag is cleared, and //a question mark is displayed to reflect that the player no longer knows. This is the function that clears that //flag. void ClearAnySectorsFlashingNumberOfEnemies() { INT32 i; for( i = 0; i < 256; i++ ) { SectorInfo[ i ].uiFlags &= ~SF_PLAYER_KNOWS_ENEMIES_ARE_HERE; } // redraw map fMapPanelDirty = TRUE; } UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) { UINT32 uiSectorFlags = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].uiFlags; // if player has militia close enough to scout this sector out, if there are mercs who can scout here, OR //Special case flag used when players encounter enemies in a sector, then retreat. The number of enemies //will display on mapscreen until time is compressed. When time is compressed, the flag is cleared, and //a question mark is displayed to reflect that the player no longer knows. if ( CanMercsScoutThisSector( sSectorX, sSectorY, 0 ) || CanNearbyMilitiaScoutThisSector( sSectorX, sSectorY ) || ( uiSectorFlags & SF_PLAYER_KNOWS_ENEMIES_ARE_HERE ) ) { // if the enemies are stationary (i.e. mercs attacking a garrison) if ( NumStationaryEnemiesInSector( sSectorX, sSectorY ) > 0 ) { // inside a garrison - hide their # (show question mark) to match what the PBI is showing return KNOWS_THEYRE_THERE; } else { // other situations - show exactly how many there are return KNOWS_HOW_MANY; } } // if the player has visited the sector during this game if( GetSectorFlagStatus( sSectorX, sSectorY, 0, SF_ALREADY_VISITED ) == TRUE ) { // then he always knows about any enemy presence for the remainder of the game, but not exact numbers return KNOWS_THEYRE_THERE; } // if Skyrider noticed the enemis in the sector recently if ( uiSectorFlags & SF_SKYRIDER_NOTICED_ENEMIES_HERE ) { // and Skyrider is still in this sector, flying if( IsSkyriderIsFlyingInSector( sSectorX, sSectorY ) ) { // player remains aware of them as long as Skyrider remains in the sector return KNOWS_THEYRE_THERE; } else { // Skyrider is gone, reset the flag that he noticed enemies here SectorInfo[ SECTOR( sSectorX, sSectorY ) ].uiFlags &= ~SF_SKYRIDER_NOTICED_ENEMIES_HERE; } } // no information available return KNOWS_NOTHING; } BOOLEAN CanMercsScoutThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) { INT32 iFirstId = 0, iLastId = 0; INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; // to speed it up a little? iFirstId = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; iLastId = gTacticalStatus.Team[ OUR_TEAM ].bLastID; for( iCounter = iFirstId; iCounter <= iLastId; iCounter++ ) { // get the soldier pSoldier = &Menptr[ iCounter ]; // is the soldier active if( pSoldier->bActive == FALSE ) { continue; } // vehicles can't scout! if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) { continue; } // POWs, dead guys, guys in transit, sleeping, and really hurt guys can't scout! if ( ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier -> fMercAsleep == TRUE ) || ( pSoldier->bLife < OKLIFE ) ) { continue; } // don't count mercs aboard Skyrider if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == iHelicopterVehicleId ) ) { continue; } // mercs on the move can't scout if ( pSoldier->fBetweenSectors ) { continue; } // is he here? if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == bSectorZ ) ) { return( TRUE ); } } // none here who can scout return( FALSE ); } void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubIconPosition ) { INT16 sNumberOfEnemies = 0; // ATE: If game has just started, don't do it! if ( DidGameJustStart() ) { return; } // never display enemies underground - sector info doesn't have support for it! if( bSectorZ != 0 ) { return; } // get total number of badguys here sNumberOfEnemies = NumEnemiesInSector( sSectorX, sSectorY ); // anyone here? if( !sNumberOfEnemies ) { // nope - display nothing return; } switch ( WhatPlayerKnowsAboutEnemiesInSector( sSectorX, sSectorY ) ) { case KNOWS_NOTHING: // display nothing break; case KNOWS_THEYRE_THERE: // display a question mark ShowUncertainNumberEnemiesInSector( sSectorX, sSectorY ); break; case KNOWS_HOW_MANY: // display individual icons for each enemy, starting at the received icon position index ShowEnemiesInSector( sSectorX, sSectorY, sNumberOfEnemies, ubIconPosition ); break; } } /* UINT8 NumActiveCharactersInSector( INT16 sSectorX, INT16 sSectorY, INT16 bSectorZ ) { INT32 iCounter = 0; SOLDIERTYPE *pSoldier = NULL; UINT8 ubNumberOnTeam = 0; for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) { if( gCharactersList[ iCounter ].fValid ) { pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] ); if( pSoldier->bActive && ( pSoldier->bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != IN_TRANSIT ) ) { if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == bSectorZ ) ) ubNumberOnTeam++; } } } return( ubNumberOnTeam ); } */ void ShowSAMSitesOnStrategicMap( void ) { INT32 iCounter = 0; INT16 sSectorX = 0, sSectorY = 0; INT16 sX = 0, sY = 0; HVOBJECT hHandle; INT8 ubVidObjIndex = 0; UINT8 *pDestBuf2; UINT32 uiDestPitchBYTES; CHAR16 wString[ 40 ]; if( fShowAircraftFlag ) { BlitSAMGridMarkers( ); } for( iCounter = 0; iCounter < NUMBER_OF_SAMS; iCounter++ ) { // has the sam site here been found? if( !fSamSiteFound[ iCounter ] ) { continue; } // get the sector x and y sSectorX = gpSamSectorX[ iCounter ]; sSectorY = gpSamSectorY[ iCounter ]; if( fZoomFlag ) { pDestBuf2 = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, MAP_VIEW_START_X+MAP_GRID_X - 1, MAP_VIEW_START_Y+MAP_GRID_Y - 1, MAP_VIEW_WIDTH+1,MAP_VIEW_HEIGHT-9 ); UnLockVideoSurface(guiSAVEBUFFER); GetScreenXYFromMapXYStationary( sSectorX, sSectorY, &sX, &sY ); sX -= 8; sY -= 10; ubVidObjIndex = 0; } else { GetScreenXYFromMapXY( sSectorX, sSectorY, &sX, &sY ); sX += 5; sY += 3; ubVidObjIndex = 1; } // draw SAM site icon GetVideoObject( &hHandle, guiSAMICON); BltVideoObject( guiSAVEBUFFER, hHandle, ubVidObjIndex, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); if( fShowAircraftFlag ) { // write "SAM Site" centered underneath if( fZoomFlag ) { sX += 9; sY += 19; } else { sX += 6; sY += 16; } wcscpy( wString, pLandTypeStrings[ SAM_SITE ] ); // we're CENTERING the first string AROUND sX, so calculate the starting X value sX -= StringPixLength( wString, MAP_FONT) / 2; // if within view region...render, else don't if( ( sX > MAP_VIEW_START_X + MAP_VIEW_WIDTH ) || ( sX < MAP_VIEW_START_X ) || ( sY > MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) || ( sY < MAP_VIEW_START_Y ) ) { continue; } SetFontDestBuffer( guiSAVEBUFFER, MapScreenRect.iLeft + 2, MapScreenRect.iTop, MapScreenRect.iRight, MapScreenRect.iBottom, FALSE ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); SetFont(MAP_FONT); // Green on green doesn't contrast well, use Yellow SetFontForeground(FONT_MCOLOR_LTYELLOW); SetFontBackground(FONT_MCOLOR_BLACK); // draw the text gprintfdirty( sX, sY, wString ); mprintf( sX, sY, wString); // restore clip blits RestoreClipRegionToFullScreen( ); } } return; } void BlitSAMGridMarkers( void ) { INT16 sScreenX = 0, sScreenY = 0; UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; UINT16 usColor = 0; INT32 iCounter = 0; INT16 sWidth = 0, sHeight = 0; // get 16 bpp color usColor = Get16BPPColor( FROMRGB( 100, 100, 100) ); pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); for( iCounter = 0; iCounter < NUMBER_OF_SAMS; iCounter++ ) { // has the sam site here been found? if( !fSamSiteFound[ iCounter ] ) { continue; } if( fZoomFlag ) { GetScreenXYFromMapXYStationary( gpSamSectorX[ iCounter ], gpSamSectorY[ iCounter ], &sScreenX, &sScreenY ); sScreenX -= MAP_GRID_X; sScreenY -= MAP_GRID_Y; sWidth = 2 * MAP_GRID_X; sHeight= 2 * MAP_GRID_Y; } else { // get location on screen GetScreenXYFromMapXY( gpSamSectorX[ iCounter ], gpSamSectorY[ iCounter ], &sScreenX, &sScreenY ); sWidth = MAP_GRID_X; sHeight= MAP_GRID_Y; } // draw rectangle RectangleDraw( TRUE, sScreenX, sScreenY - 1, sScreenX + sWidth, sScreenY + sHeight - 1, usColor, pDestBuf ); } // restore clips RestoreClipRegionToFullScreenForRectangle( uiDestPitchBYTES ); // unlock surface UnLockVideoSurface( guiSAVEBUFFER ); return; } BOOLEAN CanMilitiaAutoDistribute( void ) { INT32 iTotalTroopsOnCursor = 0; INT32 iCounter = 0; INT16 sBaseSectorValue = 0, sCurrentSectorValue = 0; INT16 sSectorX = 0, sSectorY = 0; INT32 iTotalTroopsInTown = 0; // can't auto-distribute if we don't have a town selected (this excludes SAM sites) if( sSelectedMilitiaTown == BLANK_SECTOR ) return( FALSE ); // can't auto-distribute if we don't control any sectors in the the town if( !GetTownSectorsUnderControl( ( INT8 ) sSelectedMilitiaTown ) ) return( FALSE ); // get the sector value for the upper left corner sBaseSectorValue = GetBaseSectorForCurrentTown( ); // render icons for map for( iCounter = 0; iCounter < 9; iCounter++ ) { // grab current sector value sCurrentSectorValue = sBaseSectorValue + ( ( iCounter % MILITIA_BOX_ROWS ) + ( iCounter / MILITIA_BOX_ROWS ) * ( 16 ) ); sSectorX = SECTORX( sCurrentSectorValue ); sSectorY = SECTORY( sCurrentSectorValue ); // skip sectors not in the selected town (nearby other towns or wilderness SAM Sites) if( GetTownIdForSector( sSectorX, sSectorY ) != sSelectedMilitiaTown ) { continue; } if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { // get number of each iTotalTroopsInTown += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; } } iTotalTroopsOnCursor = sGreensOnCursor + sRegularsOnCursor + sElitesOnCursor; // can't auto-distribute if we don't have any militia in the town if( !iTotalTroopsInTown ) return( FALSE ); // can auto-distribute return( TRUE ); } void ShowItemsOnMap( void ) { INT16 sMapX, sMapY; INT16 sXCorner, sYCorner; INT16 usXPos, usYPos; UINT32 uiItemCnt; CHAR16 sString[ 10 ]; // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); SetFontDestBuffer( guiSAVEBUFFER, MapScreenRect.iLeft + 2, MapScreenRect.iTop, MapScreenRect.iRight, MapScreenRect.iBottom , FALSE ); SetFont(MAP_FONT); SetFontForeground(FONT_MCOLOR_LTGREEN); SetFontBackground(FONT_MCOLOR_BLACK); // run through sectors for( sMapX = 1; sMapX < ( MAP_WORLD_X - 1 ); sMapX++ ) { for( sMapY = 1; sMapY < ( MAP_WORLD_Y - 1 ); sMapY++ ) { // to speed this up, only look at sector that player has visited if( GetSectorFlagStatus( sMapX, sMapY, ( UINT8 ) iCurrentMapSectorZ, SF_ALREADY_VISITED ) ) { // uiItemCnt = GetSizeOfStashInSector( sMapX, sMapY, ( INT16 ) iCurrentMapSectorZ, FALSE ); uiItemCnt = GetNumberOfVisibleWorldItemsFromSectorStructureForSector( sMapX, sMapY, ( UINT8 ) iCurrentMapSectorZ ); if ( uiItemCnt > 0 ) { sXCorner = ( INT16 )( MAP_VIEW_START_X + ( sMapX * MAP_GRID_X ) ); sYCorner = ( INT16 )( MAP_VIEW_START_Y + ( sMapY * MAP_GRID_Y ) ); swprintf( sString, L"%d", uiItemCnt ); FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, MAP_FONT, &usXPos, &usYPos ); // sXPos -= StringPixLength( sString, MAP_FONT ) / 2; gprintfdirty( usXPos, usYPos, sString ); mprintf( usXPos, usYPos, sString ); } } } } // restore clip blits RestoreClipRegionToFullScreen( ); } void DrawMapBoxIcon( HVOBJECT hIconHandle, UINT16 usVOIndex, INT16 sMapX, INT16 sMapY, UINT8 ubIconPosition ) { INT32 iRowNumber, iColumnNumber; INT32 iX, iY; // don't show any more icons than will fit into one sector, to keep them from spilling into sector(s) beneath if ( ubIconPosition >= ( MERC_ICONS_PER_LINE * ROWS_PER_SECTOR ) ) { return; } iColumnNumber = ubIconPosition % MERC_ICONS_PER_LINE; iRowNumber = ubIconPosition / MERC_ICONS_PER_LINE; if ( !fZoomFlag ) { iX = MAP_VIEW_START_X + ( sMapX * MAP_GRID_X ) + MAP_X_ICON_OFFSET + ( 3 * iColumnNumber ); iY = MAP_VIEW_START_Y + ( sMapY * MAP_GRID_Y ) + MAP_Y_ICON_OFFSET + ( 3 * iRowNumber ); BltVideoObject( guiSAVEBUFFER, hIconHandle, usVOIndex , iX, iY, VO_BLT_SRCTRANSPARENCY, NULL ); InvalidateRegion( iX, iY, iX + DMAP_GRID_X, iY + DMAP_GRID_Y ); } /* else { INT sX, sY; GetScreenXYFromMapXYStationary( ( UINT16 ) sX,( UINT16 ) sY, &sX, &sY ); iY = sY-MAP_GRID_Y; iX = sX-MAP_GRID_X; // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); BltVideoObject(guiSAVEBUFFER, hIconHandle,BIG_YELLOW_BOX,MAP_X_ICON_OFFSET+iX+6*iColumnNumber+2,MAP_Y_ICON_OFFSET+iY+6*iRowNumber, VO_BLT_SRCTRANSPARENCY, NULL ); // restore clip blits RestoreClipRegionToFullScreen( ); InvalidateRegion(MAP_X_ICON_OFFSET+iX+6*iColumnNumber+2, MAP_Y_ICON_OFFSET+iY+6*iRowNumber,MAP_X_ICON_OFFSET+iX+6*iColumnNumber+2+ DMAP_GRID_ZOOM_X, MAP_Y_ICON_OFFSET+iY+6*iRowNumber + DMAP_GRID_ZOOM_Y ); } */ } void DrawOrta() { UINT8 *pDestBuf2; UINT32 uiDestPitchBYTES; INT16 sX, sY; UINT8 ubVidObjIndex; HVOBJECT hHandle; if( fZoomFlag ) { pDestBuf2 = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, MAP_VIEW_START_X+MAP_GRID_X - 1, MAP_VIEW_START_Y+MAP_GRID_Y - 1, MAP_VIEW_WIDTH+1,MAP_VIEW_HEIGHT-9 ); UnLockVideoSurface(guiSAVEBUFFER); GetScreenXYFromMapXYStationary( ORTA_SECTOR_X, ORTA_SECTOR_Y, &sX, &sY ); sX += -MAP_GRID_X + 2; sY += -MAP_GRID_Y - 6; ubVidObjIndex = 0; } else { GetScreenXYFromMapXY( ORTA_SECTOR_X, ORTA_SECTOR_Y, &sX, &sY ); sX += +2; sY += -3; ubVidObjIndex = 1; } // draw Orta in its sector GetVideoObject( &hHandle, guiORTAICON); BltVideoObject( guiSAVEBUFFER, hHandle, ubVidObjIndex, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } void DrawTixa() { UINT8 *pDestBuf2; UINT32 uiDestPitchBYTES; INT16 sX, sY; UINT8 ubVidObjIndex; HVOBJECT hHandle; if( fZoomFlag ) { pDestBuf2 = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, MAP_VIEW_START_X+MAP_GRID_X - 1, MAP_VIEW_START_Y+MAP_GRID_Y - 1, MAP_VIEW_WIDTH+1,MAP_VIEW_HEIGHT-9 ); UnLockVideoSurface(guiSAVEBUFFER); GetScreenXYFromMapXYStationary( TIXA_SECTOR_X, TIXA_SECTOR_Y, &sX, &sY ); sX += -MAP_GRID_X + 3; sY += -MAP_GRID_Y + 6; ubVidObjIndex = 0; } else { GetScreenXYFromMapXY( TIXA_SECTOR_X, TIXA_SECTOR_Y, &sX, &sY ); sY += +2; ubVidObjIndex = 1; } // draw Tixa in its sector GetVideoObject( &hHandle, guiTIXAICON); BltVideoObject( guiSAVEBUFFER, hHandle, ubVidObjIndex, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } void DrawBullseye() { INT16 sX, sY; HVOBJECT hHandle; GetScreenXYFromMapXY( gsMercArriveSectorX, gsMercArriveSectorY, &sX, &sY ); sY -= 2; // draw the bullseye in that sector GetVideoObject( &hHandle, guiBULLSEYE); BltVideoObject( guiSAVEBUFFER, hHandle, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } void HideExistenceOfUndergroundMapSector( UINT8 ubSectorX, UINT8 ubSectorY ) { INT16 sScreenX; INT16 sScreenY; GetScreenXYFromMapXY( ubSectorX, ubSectorY, &sScreenX, &sScreenY ); // fill it with near black ColorFillVideoSurfaceArea( guiSAVEBUFFER, sScreenX + 1, sScreenY, sScreenX + MAP_GRID_X, sScreenY + MAP_GRID_Y - 1, gusUndergroundNearBlack ); } void InitMapSecrets( void ) { //UINT8 ubSamIndex; fFoundTixa = FALSE; fFoundOrta = FALSE; //for( ubSamIndex = 0; ubSamIndex < NUMBER_OF_SAMS; ubSamIndex++ ) //{ // fSamSiteFound[ ubSamIndex ] = fSamSiteFoundOrig[ ubSamIndex ]; //} memcpy(fSamSiteFound, fSamSiteFoundOrig, sizeof(fSamSiteFound)); } BOOLEAN CanRedistributeMilitiaInSector( INT16 sClickedSectorX, INT16 sClickedSectorY, INT8 bClickedTownId ) { INT32 iCounter = 0; INT16 sBaseSectorValue = 0, sCurrentSectorValue = 0; INT16 sSectorX = 0, sSectorY = 0; INT32 iTotalTroopsInTown = 0; // if no world is loaded, we can't be in combat (PBI/Auto-resolve locks out normal mapscreen interface for this) if( !gfWorldLoaded ) { // ok to redistribute return( TRUE ); } // if tactically not in combat, hostile sector, or air-raid if( !( gTacticalStatus.uiFlags & INCOMBAT ) && !( gTacticalStatus.fEnemyInSector ) && !InAirRaid( ) ) { // ok to redistribute return( TRUE ); } // if the fight is underground if ( gbWorldSectorZ != 0 ) { // ok to redistribute return( TRUE ); } // currently loaded surface sector IS hostile - so we must check if it's also one of the sectors in this "militia map" // get the sector value for the upper left corner sBaseSectorValue = sBaseSectorList[ bClickedTownId - 1 ]; // render icons for map for( iCounter = 0; iCounter < 9; iCounter++ ) { // grab current sector value sCurrentSectorValue = sBaseSectorValue + ( ( iCounter % MILITIA_BOX_ROWS ) + ( iCounter / MILITIA_BOX_ROWS ) * ( 16 ) ); sSectorX = SECTORX( sCurrentSectorValue ); sSectorY = SECTORY( sCurrentSectorValue ); // not in the same town? if( StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].bNameId != bClickedTownId ) { continue; } // if this is the loaded sector that is currently hostile if ( ( sSectorX == gWorldSectorX ) && ( sSectorY == gWorldSectorY ) ) { // the fight is within this town! Can't redistribute. return( FALSE ); } } // the fight is elsewhere - ok to redistribute return( TRUE ); }