From 2060022e944e6171abd8937cc60ee19cf184af2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Sun, 20 Aug 2023 19:52:34 +0200 Subject: [PATCH 01/10] Battle Panel Multi Resolution (#203) * Battle panel interface with support for multiple resolutions and scrollable list * Support for localized versions of battle panel * Removed commented out code * Fixed wrong copypasta in German version --- Strategic/Auto Resolve.cpp | 4 +- Strategic/Map Screen Interface Bottom.cpp | 2 +- Strategic/PreBattle Interface.cpp | 324 +++++++++++++--------- Strategic/PreBattle Interface.h | 1 + Strategic/mapscreen.cpp | 38 ++- Utils/Multi Language Graphic Utils.cpp | 36 +++ Utils/Multi Language Graphic Utils.h | 3 + 7 files changed, 268 insertions(+), 140 deletions(-) diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 04fa2d56..2029541e 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -681,7 +681,7 @@ UINT32 AutoResolveScreenHandle() SGPRect ClipRect; gpAR->fEnteringAutoResolve = FALSE; //Take the framebuffer, shade it, and save it to the SAVEBUFFER. - ClipRect.iLeft = 0 + xResOffset; + ClipRect.iLeft = 0; ClipRect.iTop = 0; /*ClipRect.iRight = 640; ClipRect.iBottom = 480;*/ @@ -692,7 +692,7 @@ UINT32 AutoResolveScreenHandle() Blt16BPPBufferShadowRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect ); UnLockVideoSurface( FRAME_BUFFER ); //BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 640, 480 ); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0 + xResOffset, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); + BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); KillPreBattleInterface(); CalculateAutoResolveInfo(); CalculateSoldierCells( FALSE ); diff --git a/Strategic/Map Screen Interface Bottom.cpp b/Strategic/Map Screen Interface Bottom.cpp index 0c5530ab..1cb96593 100644 --- a/Strategic/Map Screen Interface Bottom.cpp +++ b/Strategic/Map Screen Interface Bottom.cpp @@ -1936,7 +1936,7 @@ BOOLEAN AllowedToExitFromMapscreenTo( INT8 bExitToWhere ) } // battle about to occur? - if( ( fDisableDueToBattleRoster ) || ( fDisableMapInterfaceDueToBattle ) ) + if( ( fDisableDueToBattleRoster ) || ( fDisableMapInterfaceDueToBattle ) || ( gfPreBattleInterfaceActive )) { return( FALSE ); } diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index f05cf42e..a26c7ab8 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -48,6 +48,7 @@ #include "militiasquads.h" // added by Flugente #include "SkillCheck.h" // added by Flugente #include "Strategic Transport Groups.h" + #include "Utilities.h" #ifdef JA2UB #include "ub_config.h" @@ -99,13 +100,23 @@ enum //GraphicIDs for the panel #define ROW_HEIGHT 10 //The start of the black space #define TOP_Y 113 +#define TOP_Y_TEXT_BUFFER 1 //The end of the black space -//#define BOTTOM_Y (349+(OUR_TEAM_SIZE_NO_VEHICLE-18)*ROW_HEIGHT) -#define BOTTOM_Y 349 +#define BOTTOM_HEIGHT 8 //The internal height of the uninvolved panel -#define INTERNAL_HEIGHT 27 -//The actual height of the uninvolved panel -#define ACTUAL_HEIGHT 24 +#define UNINVOLVED_RELEVANT_HEIGHT 28 +#define UNINVOLVED_OFFSET_HEIGHT 7 + +#define PREBATTLE_INTERFACE_WIDTH 261 +INT32 iPrebattleInterfaceHeight = 360; +UINT16 xOffset; +UINT16 yOffset; +UINT16 blanketStartX; +UINT16 blanketStartY; + +INT16 bListOffset = 0; +UINT16 ubDesiredListHeight = 0; +UINT16 ubAllowedListHeight = 0; BOOLEAN gfDisplayPotentialRetreatPaths = FALSE; UINT16 gusRetreatButtonLeft, gusRetreatButtonTop, gusRetreatButtonRight, gusRetreatButtonBottom; @@ -300,6 +311,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) gAmbushRadiusModifier = 0.0f; + bListOffset = 0; + // ARM: Feb01/98 - Cancel out of mapscreen movement plotting if PBI subscreen is coming up if ( ( GetSelectedDestChar() != -1) || fPlotForHelicopter || fPlotForMilitia ) { @@ -481,32 +494,69 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) fMapScreenBottomDirty = TRUE; ChangeSelectedMapSector( gubPBSectorX, gubPBSectorY, gubPBSectorZ ); - // Headrock: Added FALSE argument, We might need TRUE but not sure. Will need to initiate battle :) - RenderMapScreenInterfaceBottom( FALSE ); if( !fShowTeamFlag ) { ToggleShowTeamsMode(); } - //Define the blanket region to cover all of the other regions used underneath the panel. - MSYS_DefineRegion( &PBInterfaceBlanket, 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset, MSYS_PRIORITY_HIGHEST - 5, 0, 0, 0 ); - //Create the panel VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; - GetMLGFilename( VObjectDesc.ImageFile, MLG_PREBATTLEPANEL ); + + // anv: prebattle interface per vertical resolution + if (isWidescreenUI()) + { + GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_1280x720); + iPrebattleInterfaceHeight = 600; + xOffset = xResOffset + 15; + yOffset = 0; + blanketStartX = 0; + blanketStartY = 0; + } + else if (iResolution >= _640x480 && iResolution < _800x600) + { + GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL); + iPrebattleInterfaceHeight = 360; + xOffset = xResOffset; + yOffset = yResOffset; + blanketStartX = yOffset; + blanketStartY = yOffset; + } + else if (iResolution < _1024x768) + { + GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_800x600); + iPrebattleInterfaceHeight = 478; + xOffset = xResOffset; + yOffset = yResOffset; + blanketStartX = yOffset; + blanketStartY = yOffset; + } + else + { + GetMLGFilename(VObjectDesc.ImageFile, MLG_PREBATTLEPANEL_1024x768); + iPrebattleInterfaceHeight = 647; + xOffset = xResOffset; + yOffset = yResOffset; + blanketStartX = yOffset; + blanketStartY = yOffset; + } + ubAllowedListHeight = iPrebattleInterfaceHeight - TOP_Y - BOTTOM_HEIGHT; + if( !AddVideoObject( &VObjectDesc, &uiInterfaceImages ) ) AssertMsg( 0, "Failed to load interface\\PreBattlePanel.sti" ); + //Define the blanket region to cover all of the other regions used underneath the panel. + MSYS_DefineRegion( &PBInterfaceBlanket, blanketStartX, blanketStartY, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset, MSYS_PRIORITY_HIGHEST, 0, 0, 0 ); + //Create the 3 buttons iPBButtonImage[0] = LoadButtonImage( "INTERFACE\\PreBattleButton.sti", -1, 0, -1, 1, -1 ); if( iPBButtonImage[ 0 ] == -1 ) AssertMsg( 0, "Failed to load interface\\PreBattleButton.sti" ); iPBButtonImage[1] = UseLoadedButtonImage( iPBButtonImage[ 0 ], -1, 0, -1, 1, -1 ); iPBButtonImage[2] = UseLoadedButtonImage( iPBButtonImage[ 0 ], -1, 0, -1, 1, -1 ); - iPBButton[0] = QuickCreateButton( iPBButtonImage[0], 27 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, AutoResolveBattleCallback ); - iPBButton[1] = QuickCreateButton( iPBButtonImage[1], 98 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, GoToSectorCallback ); - iPBButton[2] = QuickCreateButton( iPBButtonImage[2], 169 + xResOffset, 54 + yResOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, DEFAULT_MOVE_CALLBACK, RetreatMercsCallback ); + iPBButton[0] = QuickCreateButton( iPBButtonImage[0], 27 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, AutoResolveBattleCallback ); + iPBButton[1] = QuickCreateButton( iPBButtonImage[1], 98 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, GoToSectorCallback ); + iPBButton[2] = QuickCreateButton( iPBButtonImage[2], 169 + xOffset, 54 + yOffset, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST, DEFAULT_MOVE_CALLBACK, RetreatMercsCallback ); SpecifyGeneralButtonTextAttributes( iPBButton[0], gpStrategicString[ STR_PB_AUTORESOLVE_BTN ], BLOCKFONT, FONT_BEIGE, 141 ); SpecifyGeneralButtonTextAttributes( iPBButton[1], gpStrategicString[ STR_PB_GOTOSECTOR_BTN ], BLOCKFONT, FONT_BEIGE, 141 ); @@ -1050,7 +1100,7 @@ void DoTransitionFromMapscreenToPreBattleInterface() INT32 iPercentage, iFactor; UINT32 uiTimeRange; INT16 sStartLeft, sEndLeft, sStartTop, sEndTop; - INT32 iLeft, iTop, iWidth, iHeight; + INT32 iLeft, iTop, iWidth; BOOLEAN fEnterAutoResolveMode = FALSE; if( !gfExtraBuffer ) @@ -1058,12 +1108,11 @@ void DoTransitionFromMapscreenToPreBattleInterface() PauseTime( FALSE ); - PBIRect.iLeft = 0 + xResOffset; - PBIRect.iTop = 0 + yResOffset; - PBIRect.iRight = 261 + xResOffset; - PBIRect.iBottom = 359 + yResOffset; - iWidth = 261; - iHeight = 359; + PBIRect.iLeft = 0 + xOffset; + PBIRect.iTop = 0 + yOffset; + PBIRect.iRight = PREBATTLE_INTERFACE_WIDTH + xOffset; + PBIRect.iBottom = iPrebattleInterfaceHeight + yOffset; + iWidth = PREBATTLE_INTERFACE_WIDTH; uiTimeRange = 1000; iPercentage = 0; @@ -1072,8 +1121,8 @@ void DoTransitionFromMapscreenToPreBattleInterface() GetScreenXYFromMapXY( gubPBSectorX, gubPBSectorY, &sStartLeft, &sStartTop ); sStartLeft += UI_MAP.GridSize.iX / 2; sStartTop += UI_MAP.GridSize.iY / 2; - sEndLeft = 131 + xResOffset; - sEndTop = 180 + yResOffset; + sEndLeft = PBIRect.iLeft; + sEndTop = PBIRect.iTop; //save the mapscreen buffer BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); @@ -1095,17 +1144,23 @@ void DoTransitionFromMapscreenToPreBattleInterface() gfEnterAutoResolveMode = TRUE; } - BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 27 + xResOffset, 54 + yResOffset, 209, 32 ); + BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 27 + xOffset, 54 + yOffset, 209, 32 ); RenderButtons(); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 27 + xResOffset, 54 + yResOffset, 209, 32 ); + BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 27 + xOffset, 54 + yOffset, 209, 32 ); gfRenderPBInterface = TRUE; //hide the prebattle interface - BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset ); + BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, 0 + xOffset, 0 + yOffset, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset ); PlayJA2SampleFromFile( "SOUNDS\\Laptop power up (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); InvalidateScreen(); RefreshScreen( NULL ); + SGPRect PrevRect; + PrevRect.iLeft = sStartLeft; + PrevRect.iRight = sStartLeft + 1; + PrevRect.iTop = sStartTop; + PrevRect.iBottom = sStartTop + 1; + while( iPercentage < 100 ) { uiCurrTime = GetJA2Clock(); @@ -1117,19 +1172,12 @@ void DoTransitionFromMapscreenToPreBattleInterface() if( iPercentage < 50 ) iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5); else - iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.05); + iPercentage = (UINT32)(iPercentage + (100 - iPercentage) * iFactor * 0.01 + 0.05); - //Calculate the center point. - iLeft = sStartLeft - (sStartLeft-sEndLeft+1) * iPercentage / 100; - if( sStartTop > sEndTop ) - iTop = sStartTop - (sStartTop-sEndTop+1) * iPercentage / 100; - else - iTop = sStartTop + (sEndTop-sStartTop+1) * iPercentage / 100; - - DstRect.iLeft = iLeft - iWidth * iPercentage / 200; + DstRect.iLeft = sStartLeft + (sEndLeft - sStartLeft) * iPercentage / 100; DstRect.iRight = DstRect.iLeft + max( iWidth * iPercentage / 100, 1 ); - DstRect.iTop = iTop - iHeight * iPercentage / 200; - DstRect.iBottom = DstRect.iTop + max( iHeight * iPercentage / 100, 1 ); + DstRect.iTop = sStartTop + (sEndTop - sStartTop) * iPercentage / 100; + DstRect.iBottom = DstRect.iTop + max(iPrebattleInterfaceHeight * iPercentage / 100, 1); BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 0, &PBIRect, &DstRect ); @@ -1137,14 +1185,35 @@ void DoTransitionFromMapscreenToPreBattleInterface() RefreshScreen( NULL ); //Restore the previous rect. - BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, (UINT16)DstRect.iLeft, (UINT16)DstRect.iTop, - (UINT16)(DstRect.iRight-DstRect.iLeft+1), (UINT16)(DstRect.iBottom-DstRect.iTop+1) ); + BlitBufferToBuffer(guiEXTRABUFFER, FRAME_BUFFER, (UINT16)PrevRect.iLeft, (UINT16)PrevRect.iTop, + (UINT16)PrevRect.iRight, (UINT16)PrevRect.iBottom); + + PrevRect.iLeft = DstRect.iLeft; + PrevRect.iRight = DstRect.iRight; + PrevRect.iTop = DstRect.iTop; + PrevRect.iBottom = DstRect.iBottom; } BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); gfZoomDone = TRUE; } +void ScrollPreBattleInterface( BOOLEAN fUp ) +{ + if ( ubDesiredListHeight <= ubAllowedListHeight ) + return; + + if ( fUp ) + { + bListOffset = max( 0, bListOffset - ubAllowedListHeight ); + } + else + { + bListOffset = min( bListOffset + ubAllowedListHeight, ubDesiredListHeight - ubAllowedListHeight ); + } + gfRenderPBInterface = TRUE; +} + void KillPreBattleInterface() { if( !gfPreBattleInterfaceActive ) @@ -1184,7 +1253,7 @@ void KillPreBattleInterface() //Enable the options button when the auto resolve screen comes up EnableDisAbleMapScreenOptionsButton( TRUE ); - ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xResOffset, 359 + yResOffset, 0 ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, PREBATTLE_INTERFACE_WIDTH + xOffset, iPrebattleInterfaceHeight + yOffset, 0 ); EnableTeamInfoPanels(); if( ButtonList[ giMapContractButton ] ) @@ -1277,8 +1346,8 @@ void RenderPBHeader( INT32 *piX, INT32 *piWidth) } width = StringPixLength( str, FONT10ARIALBOLD ); x = 130 - width / 2; - mprintf( x + xResOffset, 4 + yResOffset, str ); - InvalidateRegion( 0, 0, 231 + xResOffset, 12 + yResOffset ); + mprintf( x + xOffset, 4 + yOffset, str ); + InvalidateRegion( 0, 0, 231 + xOffset, 12 + yOffset ); *piX = x; *piWidth = width; } @@ -1293,10 +1362,15 @@ void RenderPreBattleInterface() UINT8 ubHPPercent, ubBPPercent; BOOLEAN fMouseInRetreatButtonArea; UINT8 ubJunk; + SGPRect ClipRect; + UINT16 ubDesiredParticipantsListHeight = 0; + UINT16 ubDesiredUninvolvedListHeight = 0; + UINT16 ubUninvolvedStartY = 0; + //PLAYERGROUP *pPlayer; // Make the background black! - //ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xResOffset, SCREEN_HEIGHT - 120, 0 ); + //ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, 0, 261 + xOffset, SCREEN_HEIGHT - 120, 0 ); //This code determines if the cursor is inside the rectangle consisting of the //retreat button. If it is inside, then we set up the variables so that the retreat @@ -1337,33 +1411,21 @@ void RenderPreBattleInterface() gfRenderPBInterface = FALSE; GetVideoObject( &hVObject, uiInterfaceImages ); //main panel - BltVideoObject( guiSAVEBUFFER, hVObject, MAINPANEL, xResOffset, yResOffset, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObject( guiSAVEBUFFER, hVObject, MAINPANEL, xOffset, yOffset, VO_BLT_SRCTRANSPARENCY, NULL ); //main title RenderPBHeader( &x, &width ); //now draw the title bars up to the text. for( i = x - 12; i > 20; i -= 10 ) { - BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xResOffset, 6 + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xOffset, 6 + yOffset, VO_BLT_SRCTRANSPARENCY, NULL ); } for( i = x + width + 2; i < 231; i += 10 ) { - BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xResOffset, 6 + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObject( guiSAVEBUFFER, hVObject, TITLE_BAR_PIECE, i + xOffset, 6 + yOffset, VO_BLT_SRCTRANSPARENCY, NULL ); } - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL); - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 10, VO_BLT_SRCTRANSPARENCY, NULL); - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 20, VO_BLT_SRCTRANSPARENCY, NULL); - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, BOTTOM_Y + yResOffset + 30, VO_BLT_SRCTRANSPARENCY, NULL); - //Draw the bottom edges - for (i = 0; i < max(guiNumUninvolved, 1); i++) - { - y = BOTTOM_Y + ROW_HEIGHT * (i + 1) + 30; - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_LINE, 0 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL); - } - BltVideoObject(guiSAVEBUFFER, hVObject, UNINVOLVED_HEADER, 8 + xResOffset, BOTTOM_Y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL); - BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_END, 0 + xResOffset, BOTTOM_Y + yResOffset + 35 + ROW_HEIGHT * max(guiNumUninvolved, 1), VO_BLT_SRCTRANSPARENCY, NULL); - + // header SetFont( BLOCKFONT ); SetFontForeground( FONT_BEIGE ); swprintf( str, gpStrategicString[ STR_PB_LOCATION ] ); @@ -1373,7 +1435,7 @@ void RenderPreBattleInterface() SetFont( BLOCKFONTNARROW ); width = StringPixLength( str, BLOCKFONTNARROW ); } - mprintf( 65 - width + xResOffset , 17 + yResOffset, str ); + mprintf( 65 - width + xOffset , 17 + yOffset, str ); SetFont( BLOCKFONT ); if( GetEnemyEncounterCode() == CREATURE_ATTACK_CODE ) @@ -1405,7 +1467,7 @@ void RenderPreBattleInterface() SetFont( BLOCKFONTNARROW ); width = StringPixLength( str, BLOCKFONTNARROW ); } - mprintf( 54 + xResOffset - width , 38 + yResOffset, str ); + mprintf( 54 + xOffset - width , 38 + yOffset, str ); SetFont( BLOCKFONT ); swprintf( str, gpStrategicString[ STR_PB_MERCS ] ); @@ -1415,7 +1477,7 @@ void RenderPreBattleInterface() SetFont( BLOCKFONTNARROW ); width = StringPixLength( str, BLOCKFONTNARROW ); } - mprintf( 139 + xResOffset - width , 38 + yResOffset, str ); + mprintf( 139 + xOffset - width , 38 + yOffset, str ); SetFont( BLOCKFONT ); swprintf( str, gpStrategicString[ STR_PB_MILITIA ] ); @@ -1425,29 +1487,53 @@ void RenderPreBattleInterface() SetFont( BLOCKFONTNARROW ); width = StringPixLength( str, BLOCKFONTNARROW ); } - mprintf( 224 + xResOffset - width , 38 + yResOffset, str ); + mprintf( 224 + xOffset - width , 38 + yOffset, str ); - //Draw the bottom columns - for( i = 0; i < (INT32)max( guiNumUninvolved, 1 ); i++ ) + ubDesiredParticipantsListHeight = guiNumInvolved * ROW_HEIGHT; + ubDesiredUninvolvedListHeight = UNINVOLVED_RELEVANT_HEIGHT + max(guiNumUninvolved, 1) * ROW_HEIGHT; + + ubDesiredListHeight = ubDesiredParticipantsListHeight + ubDesiredUninvolvedListHeight; + + if (ubDesiredListHeight >= ubAllowedListHeight) { - y = BOTTOM_Y + ROW_HEIGHT * (i+1) + 1 + ACTUAL_HEIGHT; - BltVideoObject( guiSAVEBUFFER, hVObject, BOTTOM_COLUMN, 161 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL ); + ubUninvolvedStartY = ubDesiredParticipantsListHeight; + } + else + { + ubUninvolvedStartY = ubAllowedListHeight - ubDesiredUninvolvedListHeight; } - // WDS - make number of mercenaries, etc. be configurable - for( i = 0; i < (INT32)(25/*3+ OUR_TEAM_SIZE_NO_VEHICLE - max( guiNumUninvolved, 1 )*/); i++ ) + ClipRect.iLeft = xOffset; + ClipRect.iTop = yOffset + TOP_Y; + ClipRect.iRight = xOffset + PREBATTLE_INTERFACE_WIDTH; + ClipRect.iBottom = yOffset + TOP_Y + ubAllowedListHeight;// + TOP_Y_BUFFER; + SetClippingRect(&ClipRect); + + // Draw the top columns + // Draw from the top to uninvolved header + for ( y = TOP_Y - bListOffset; y < TOP_Y - bListOffset + ubUninvolvedStartY; y += ROW_HEIGHT ) { - y = TOP_Y + ROW_HEIGHT * i; - BltVideoObject( guiSAVEBUFFER, hVObject, TOP_COLUMN, 186 + xResOffset, y + yResOffset, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObject(guiSAVEBUFFER, hVObject, TOP_COLUMN, 186 + xOffset, y + yOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL); } + // Draw extra empty participants rows to close off bottom of the content area + for ( y = TOP_Y - bListOffset + ubUninvolvedStartY + ROW_HEIGHT; y < TOP_Y - bListOffset + ubUninvolvedStartY + ubDesiredUninvolvedListHeight; y += ROW_HEIGHT ) + { + BltVideoObject(guiSAVEBUFFER, hVObject, BOTTOM_COLUMN, 161 + xOffset, y + yOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL); + } + + // Draw uninvolved header + BltVideoObject( guiSAVEBUFFER, hVObject, UNINVOLVED_HEADER, 8 + xOffset, yOffset + TOP_Y + ubUninvolvedStartY - UNINVOLVED_OFFSET_HEIGHT - bListOffset, VO_BLT_CLIP | VO_BLT_SRCTRANSPARENCY, NULL ); + + RestoreClipRegionToFullScreen(); + //location SetFont( FONT10ARIAL ); SetFontForeground( FONT_YELLOW ); SetFontShadow( FONT_NEARBLACK ); GetSectorIDString( gubPBSectorX, gubPBSectorY, gubPBSectorZ, pSectorName, TRUE ); - mprintf( 70 + xResOffset, 17 + yResOffset, L"%s %s", gpStrategicString[ STR_PB_SECTOR ], pSectorName ); + mprintf( 70 + xOffset, 17 + yOffset, L"%s %s", gpStrategicString[STR_PB_SECTOR], pSectorName ); //enemy SetFont( FONT14ARIAL ); @@ -1472,58 +1558,55 @@ void RenderPreBattleInterface() } x = 57 + (27 - StringPixLength( str, FONT14ARIAL )) / 2; y = 36; - mprintf( x + xResOffset, y + yResOffset, str ); + mprintf( x + xOffset, y + yOffset, str ); //player swprintf( str, L"%d", guiNumInvolved ); x = 142 + (27 - StringPixLength( str, FONT14ARIAL )) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + mprintf( x + xOffset, y + yOffset, str ); //militia swprintf( str, L"%d", NumNonPlayerTeamMembersInSector( gubPBSectorX, gubPBSectorY, MILITIA_TEAM ) ); x = 227 + (27 - StringPixLength( str, FONT14ARIAL )) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + mprintf( x + xOffset, y + yOffset, str ); SetFontShadow( FONT_NEARBLACK ); SetFont( BLOCKFONT2 ); SetFontForeground( FONT_YELLOW ); + SetFontDestBuffer( guiSAVEBUFFER, xOffset, yOffset + TOP_Y, + xOffset + PREBATTLE_INTERFACE_WIDTH, yOffset + TOP_Y + ubAllowedListHeight, FALSE ); + //print out the participants of the battle. // | NAME | ASSIGN | COND | HP | BP | line = 0; - y = TOP_Y + 1; - for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ ) + y = TOP_Y + TOP_Y_TEXT_BUFFER - bListOffset; + for( i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; i++) { - if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) + if( MercPtrs[i]->bActive && MercPtrs[i]->stats.bLife && !(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { - if ( PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) ) - { //involved - if( line == giHilitedInvolved ) - SetFontForeground( FONT_WHITE ); - else - SetFontForeground( FONT_YELLOW ); + if( PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) ) + { //NAME wcscpy( str, MercPtrs[ i ]->name ); - x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset , y + yResOffset, str ); + x = 17 + (52 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //ASSIGN GetMapscreenMercAssignmentString( MercPtrs[ i ], str ); - x = 72 + (54-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 72 + (54 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //COND GetSoldierConditionInfo( MercPtrs[ i ], str, &ubHPPercent, &ubBPPercent ); - x = 129 + (58-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 129 + (58 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //HP swprintf( str, L"%d%%", ubHPPercent ); - x = 189 + (25-StringPixLength( str, BLOCKFONT2)) / 2; + x = 189 + (25 - StringPixLength(str, BLOCKFONT2)) / 2; wcscat( str, sSpecialCharacters[0] ); - mprintf( x + xResOffset, y + yResOffset, str ); + mprintf( x + xOffset, y + yOffset, str ); //BP swprintf( str, L"%d%%", ubBPPercent ); x = 217 + (25-StringPixLength( str, BLOCKFONT2)) / 2; wcscat( str, sSpecialCharacters[0] ); - mprintf( x + xResOffset, y + yResOffset, str ); - - line++; + mprintf( x + xOffset, y + yOffset, str ); y += ROW_HEIGHT; } } @@ -1533,51 +1616,44 @@ void RenderPreBattleInterface() // | NAME | ASSIGN | LOC | DEST | DEP | if( !guiNumUninvolved ) { - SetFontForeground( FONT_YELLOW ); wcscpy( str, gpStrategicString[ STR_PB_NONE ] ); - x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2; - y = BOTTOM_Y + ROW_HEIGHT + 2 + ACTUAL_HEIGHT; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 17 + (52 - StringPixLength( str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, yOffset + TOP_Y + TOP_Y_TEXT_BUFFER + ubUninvolvedStartY + UNINVOLVED_RELEVANT_HEIGHT - bListOffset, str ); } else { pGroup = gpGroupList; - y = BOTTOM_Y + ROW_HEIGHT + 2 + ACTUAL_HEIGHT; - for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ ) + y = TOP_Y + TOP_Y_TEXT_BUFFER + ubUninvolvedStartY + UNINVOLVED_RELEVANT_HEIGHT - bListOffset; + for( i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; i++ ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { - if ( !PlayerMercInvolvedInThisCombat( MercPtrs[ i ] ) ) + if( !PlayerMercInvolvedInThisCombat(MercPtrs[ i ]) ) { - // uninvolved - if( line == giHilitedUninvolved ) - SetFontForeground( FONT_WHITE ); - else - SetFontForeground( FONT_YELLOW ); //NAME wcscpy( str, MercPtrs[ i ]->name ); - x = 17 + (52-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 17 + (52 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //ASSIGN GetMapscreenMercAssignmentString( MercPtrs[ i ], str ); - x = 72 + (54-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 72 + (54 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //LOC GetMapscreenMercLocationString( MercPtrs[ i ], str ); - x = 128 + (33-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 128 + (33 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); //DEST GetMapscreenMercDestinationString( MercPtrs[ i ], str ); - if( wcslen( str ) > 0 ) + if (wcslen(str) > 0) { - x = 164 + (41-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); + x = 164 + (41 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf( x + xOffset, y + yOffset, str ); } //DEP GetMapscreenMercDepartureString( MercPtrs[ i ], str, &ubJunk ); - x = 208 + (34-StringPixLength( str, BLOCKFONT2)) / 2; - mprintf( x + xResOffset, y + yResOffset, str ); - line++; + x = 208 + (34 - StringPixLength(str, BLOCKFONT2)) / 2; + mprintf(x + xOffset, y + yOffset, str); + y += ROW_HEIGHT; } } @@ -1587,12 +1663,7 @@ void RenderPreBattleInterface() // mark any and ALL pop up boxes as altered MarkAllBoxesAsAltered( ); - if(!gfZoomDone) - RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 359 + yResOffset ); - else if(!guiNumUninvolved) - RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, 389 + yResOffset ); - else - RestoreExternBackgroundRect( 0 + xResOffset, 0 + yResOffset, 261 + xResOffset, y + yResOffset ); + RestoreExternBackgroundRect( 0 + xOffset, 0 + yOffset, PREBATTLE_INTERFACE_WIDTH, iPrebattleInterfaceHeight ); // restore font destinanation buffer to the frame buffer SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); @@ -1602,7 +1673,7 @@ void RenderPreBattleInterface() RenderPBHeader( &x, &width ); //the text is important enough to blink. } - //InvalidateRegion( 0, 0, 261, 359 ); + InvalidateRegion( 0, 0, PREBATTLE_INTERFACE_WIDTH, iPrebattleInterfaceHeight ); if( gfEnterAutoResolveMode ) { gfEnterAutoResolveMode = FALSE; @@ -1611,7 +1682,6 @@ void RenderPreBattleInterface() } gfIgnoreAllInput = FALSE; - } void AutoResolveBattleCallback( GUI_BUTTON *btn, INT32 reason ) diff --git a/Strategic/PreBattle Interface.h b/Strategic/PreBattle Interface.h index 78070486..f0406674 100644 --- a/Strategic/PreBattle Interface.h +++ b/Strategic/PreBattle Interface.h @@ -7,6 +7,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ); void KillPreBattleInterface(); void RenderPreBattleInterface(); +void ScrollPreBattleInterface( BOOLEAN fUp ); extern BOOLEAN gfPreBattleInterfaceActive; extern BOOLEAN gfDisplayPotentialRetreatPaths; diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index 4d387161..655d6b50 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -5708,7 +5708,7 @@ UINT32 MapScreenHandle(void) HandleCharBarRender( ); } - if( (fShowInventoryFlag && !isWidescreenUI()) || fDisableDueToBattleRoster ) + if( ( fShowInventoryFlag || fDisableDueToBattleRoster ) && !isWidescreenUI() ) { for( iCounter = 0; iCounter < MAX_SORT_METHODS; iCounter++ ) { @@ -5824,9 +5824,6 @@ UINT32 MapScreenHandle(void) HandleContractRenewalSequence( ); - // handle dialog - HandleDialogue( ); - // handle display of inventory pop up // HEADROCK HAM 3.5: Externalize! HandleDisplayOfItemPopUpForSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ); @@ -6065,6 +6062,8 @@ UINT32 MapScreenHandle(void) //InvalidateRegion( 0,0, 640, 480); EndFrameBufferRender( ); + // handle dialog + HandleDialogue(); // if not going anywhere else if ( guiPendingScreen == NO_PENDING_SCREEN ) @@ -7225,14 +7224,29 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) break; case PGUP: - // WANNE: Jump to first merc in list - fResetMapCoords = TRUE; - GoToFirstCharacterInList( ); + if (gfPreBattleInterfaceActive) + { + ScrollPreBattleInterface(TRUE); + } + else + { + // WANNE: Jump to first merc in list + fResetMapCoords = TRUE; + GoToFirstCharacterInList(); + } + break; case PGDN: - // WANNE: Jump to last merc in list - fResetMapCoords = TRUE; - GoToLastCharacterInList( ); + if (gfPreBattleInterfaceActive) + { + ScrollPreBattleInterface(FALSE); + } + else + { + // WANNE: Jump to last merc in list + fResetMapCoords = TRUE; + GoToLastCharacterInList(); + } break; case SHIFT_PGUP: @@ -10927,6 +10941,10 @@ void BlitBackgroundToSaveBuffer( void ) ForceButtonUnDirty( giMapContractButton ); ForceButtonUnDirty( giCharInfoButton[ 0 ] ); ForceButtonUnDirty( giCharInfoButton[ 1 ] ); + if (isWidescreenUI()) + { + ForceButtonUnDirty(giMapInvDoneButton); + } RenderPreBattleInterface(); } diff --git a/Utils/Multi Language Graphic Utils.cpp b/Utils/Multi Language Graphic Utils.cpp index 0371e72e..102c7d3f 100644 --- a/Utils/Multi Language Graphic Utils.cpp +++ b/Utils/Multi Language Graphic Utils.cpp @@ -76,6 +76,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_PREBATTLEPANEL: sprintf( filename, "INTERFACE\\PreBattlePanel.sti" ); return TRUE; + case MLG_PREBATTLEPANEL_800x600: + sprintf(filename, "INTERFACE\\PreBattlePanel_800x600.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1024x768: + sprintf(filename, "INTERFACE\\PreBattlePanel_1024x768.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1280x720: + sprintf(filename, "INTERFACE\\PreBattlePanel_1280x720.sti"); + return TRUE; case MLG_SMALLTITLE: sprintf( filename, "LAPTOP\\SmallTitle.sti" ); return TRUE; @@ -203,6 +212,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_PREBATTLEPANEL: sprintf( filename, "GERMAN\\PreBattlePanel_german.sti" ); return TRUE; + case MLG_PREBATTLEPANEL_800x600: + sprintf(filename, "GERMAN\\PreBattlePanel_800x600_german.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1024x768: + sprintf(filename, "GERMAN\\PreBattlePanel_1024x768_german.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1280x720: + sprintf(filename, "GERMAN\\PreBattlePanel_1280x720_german.sti"); + return TRUE; case MLG_SMALLTITLE: sprintf( filename, "GERMAN\\SmallTitle_german.sti" ); return TRUE; @@ -368,6 +386,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_PREBATTLEPANEL: sprintf( filename, "%s\\PreBattlePanel_%s.sti", zLanguage, zLanguage ); break; + case MLG_PREBATTLEPANEL_800x600: + sprintf(filename, "%s\\PreBattlePanel_800x600_%s.sti", zLanguage, zLanguage); + break; + case MLG_PREBATTLEPANEL_1024x768: + sprintf(filename, "%s\\PreBattlePanel_1024x768_%s.sti", zLanguage, zLanguage); + break; + case MLG_PREBATTLEPANEL_1280x720: + sprintf(filename, "%s\\PreBattlePanel_1280x720_%s.sti", zLanguage, zLanguage); + break; case MLG_SMALLTITLE: sprintf( filename, "%s\\SmallTitle_%s.sti", zLanguage, zLanguage ); break; @@ -492,6 +519,15 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_PREBATTLEPANEL: sprintf( filename, "INTERFACE\\PreBattlePanel.sti" ); return TRUE; + case MLG_PREBATTLEPANEL_800x600: + sprintf(filename, "INTERFACE\\PreBattlePanel_800x600.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1024x768: + sprintf(filename, "INTERFACE\\PreBattlePanel_1024x768.sti"); + return TRUE; + case MLG_PREBATTLEPANEL_1280x720: + sprintf(filename, "INTERFACE\\PreBattlePanel_1280x720.sti"); + return TRUE; case MLG_SMALLTITLE: sprintf( filename, "LAPTOP\\SmallTitle.sti" ); return TRUE; diff --git a/Utils/Multi Language Graphic Utils.h b/Utils/Multi Language Graphic Utils.h index 12f74fd5..dcedbcc1 100644 --- a/Utils/Multi Language Graphic Utils.h +++ b/Utils/Multi Language Graphic Utils.h @@ -26,6 +26,9 @@ enum MLG_OPTIONHEADER, //OptionScreenAddOns MLG_ORDERGRID, MLG_PREBATTLEPANEL, + MLG_PREBATTLEPANEL_800x600, + MLG_PREBATTLEPANEL_1024x768, + MLG_PREBATTLEPANEL_1280x720, MLG_SECTORINVENTORY, MLG_SMALLFLORISTSYMBOL, //SmallSymbol MLG_SMALLTITLE, From 1e1d456fd27c9fe70e51f4e2da76347b138a64a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Mon, 21 Aug 2023 18:44:02 +0200 Subject: [PATCH 02/10] Prevent deadlocks due to self-healing interactive spots and self-attacking (#205) --- Tactical/Handle Items.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 9c9b47fc..a865d703 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -279,7 +279,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa { pTargetSoldier = MercPtrs[ usSoldierIndex ]; - if ( fFromUI ) + // anv: don't try to heal interactive spots + if (fFromUI && Item[usHandItem].usItemClass != IC_MEDKIT) { INT32 sInteractiveGridNo; @@ -325,6 +326,13 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa { if (pTargetSoldier->bTeam == gbPlayerNum || pTargetSoldier->aiData.bNeutral) { + // anv: don't try to attack yourself, it will only cause deadlock + if (pSoldier == pTargetSoldier) + { + TacticalCharacterDialogue(pSoldier, QUOTE_REFUSING_ORDER); + return(ITEM_HANDLE_REFUSAL); + } + // nice mercs won't shoot other nice guys or neutral civilians if ((gMercProfiles[pSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY) && ((pTargetSoldier->ubProfile == NO_PROFILE && pTargetSoldier->aiData.bNeutral && pTargetSoldier->ubBodyType != CROW) || From 1289c399ce8bffcaac099dd50c169339dabddef4 Mon Sep 17 00:00:00 2001 From: kitty624 <58940527+kitty624@users.noreply.github.com> Date: Tue, 22 Aug 2023 00:22:20 +0200 Subject: [PATCH 03/10] Update XML.h - added path to sub-directory for Extra Items - to avoid cluttering up the parent directory when using this feature - it allows to place extra items in sector via xml and based on difficulty level - the new directory "ExtraItems" will contain more details on how-to-use --- Tactical/XML.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tactical/XML.h b/Tactical/XML.h index 3505f1bb..03a95811 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -157,8 +157,8 @@ typedef PARSE_STAGE; #define ALTSECTORSFILENAME "Map\\AltSectors.xml" #define SAMSITESFILENAME "Map\\SamSites.xml" #define HELISITESFILENAME "Map\\HeliSites.xml" -#define EXTRAITEMSFILENAME "Map\\A9_0_ExtraItems" // ".xml" will be added @runtime -#define EXTRAITEMSFILENAME2 "Map\\A11_0_ExtraItems" // ".xml" will be added @runtime +#define EXTRAITEMSFILENAME "Map\\ExtraItems\\A9_0_ExtraItems" // ".xml" will be added @runtime +#define EXTRAITEMSFILENAME2 "Map\\ExtraItems\\A11_0_ExtraItems" // ".xml" will be added @runtime #define SHIPPINGDESTINATIONSFILENAME "Map\\ShippingDestinations.xml" #define DELIVERYMETHODSFILENAME "Map\\DeliveryMethods.xml" #define DELIVERYMETHODSFILENAME "Map\\DeliveryMethods.xml" From 6bae48658e66dc7bc732874f9c4cf163c38ba2ff Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 23 Aug 2023 00:34:54 -0700 Subject: [PATCH 04/10] Fix personality check for backgrounds during IMP creation (#208) --- Laptop/IMP Background.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Laptop/IMP Background.cpp b/Laptop/IMP Background.cpp index 9ea5c40e..b7cddab4 100644 --- a/Laptop/IMP Background.cpp +++ b/Laptop/IMP Background.cpp @@ -15,6 +15,7 @@ #include "CharProfile.h" #include "soldier profile type.h" #include "IMP Compile Character.h" + #include "IMP Disability Trait.h" #include "GameSettings.h" #include "Interface.h" @@ -671,7 +672,7 @@ BOOLEAN IsBackGroundAllowed( UINT16 ubNumber ) return FALSE; } - switch ( iPersonality ) + switch ( iChosenDisabilityTrait() ) { case HEAT_INTOLERANT: if ( zBackground[ ubNumber ].value[BG_DESERT] > 0 ) @@ -807,4 +808,4 @@ void BtnIMPBackgroundPreviousCallback(GUI_BUTTON *btn,INT32 reason) usBackground = 0; } } -} \ No newline at end of file +} From 8ec02b2d40b0c81eb1e3a6a58188b384b0c8dae4 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 23 Aug 2023 01:21:22 -0700 Subject: [PATCH 05/10] Add version info to main menu (#209) --- MainMenuScreen.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MainMenuScreen.cpp b/MainMenuScreen.cpp index 1db5e174..bebe6193 100644 --- a/MainMenuScreen.cpp +++ b/MainMenuScreen.cpp @@ -855,6 +855,9 @@ void RenderMainMenu() DrawTextToScreen( L"BLOCKFONTNARROW: ÄÀÁÂÇËÈÉÊÏÖÒÓÔÜÙÚÛäàáâçëèéêïöòóôüùúûÌÎìî"/*gzCopyrightText[ 0 ]*/, 0, 445, 640, BLOCKFONTNARROW, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); DrawTextToScreen( L"FONT14HUMANIST: ÄÀÁÂÇËÈÉÊÏÖÒÓÔÜÙÚÛäàáâçëèéêïöòóôüùúûÌÎìî"/*gzCopyrightText[ 0 ]*/, 0, 465, 640, FONT14HUMANIST, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); #else + CHAR16 text[128]; + swprintf(text, L"%s: %s %S %s", pMessageStrings[ MSG_VERSION ], zProductLabel, czVersionString, zBuildInformation ); + DrawTextToScreen( text, 10, 10, SCREEN_WIDTH, TINYFONT1, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); DrawTextToScreen( gzCopyrightText[ 0 ], 0, SCREEN_HEIGHT - 20, SCREEN_WIDTH, FONT10ARIAL, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED ); #endif From 3ddacf1a44fd5e378fbca8dac8845f2dfa4f1f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Mon, 28 Aug 2023 15:26:02 +0200 Subject: [PATCH 06/10] Fix vehicles consuming fuel after instant movement cancel (#213) --- Strategic/Strategic Movement.cpp | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index 68eb7123..cbabfed6 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -1951,33 +1951,33 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe SectorInfo[SECTOR( pGroup->ubSectorX, pGroup->ubSectorY )].bLastKnownEnemies = NumNonPlayerTeamMembersInSector( pGroup->ubSectorX, pGroup->ubSectorY, ENEMY_TEAM ); } - // award life 'experience' for travelling, based on travel time! - if ( !pGroup->fVehicle ) + // Flugente: do not award experience gain if we never left + if (!fNeverLeft) { - // Flugente: do not award experience gain if we never left - if ( !fNeverLeft ) + // award life 'experience' for travelling, based on travel time! + if (!pGroup->fVehicle) { // gotta be walking to get tougher - AwardExperienceForTravelling( pGroup ); + AwardExperienceForTravelling(pGroup); } - } - else if( !IsGroupTheHelicopterGroup( pGroup ) ) - { - SOLDIERTYPE *pSoldier; - INT32 iVehicleID; - iVehicleID = GivenMvtGroupIdFindVehicleId( pGroup->ubGroupID ); - AssertMsg( iVehicleID != -1, "GroupArrival for vehicle group. Invalid iVehicleID. " ); - - pSoldier = GetSoldierStructureForVehicle( iVehicleID ); - AssertMsg( pSoldier, "GroupArrival for vehicle group. Invalid soldier pointer." ); - - SpendVehicleFuel( pSoldier, (INT16)(pGroup->uiTraverseTime*6) ); - - if( !VehicleFuelRemaining( pSoldier ) ) + else if (!IsGroupTheHelicopterGroup(pGroup)) { - ReportVehicleOutOfGas( iVehicleID, pGroup->ubSectorX, pGroup->ubSectorY ); - //Nuke the group's path, so they don't continue moving. - ClearMercPathsAndWaypointsForAllInGroup( pGroup ); + SOLDIERTYPE* pSoldier; + INT32 iVehicleID; + iVehicleID = GivenMvtGroupIdFindVehicleId(pGroup->ubGroupID); + AssertMsg(iVehicleID != -1, "GroupArrival for vehicle group. Invalid iVehicleID. "); + + pSoldier = GetSoldierStructureForVehicle(iVehicleID); + AssertMsg(pSoldier, "GroupArrival for vehicle group. Invalid soldier pointer."); + + SpendVehicleFuel(pSoldier, (INT16)(pGroup->uiTraverseTime * 6)); + + if (!VehicleFuelRemaining(pSoldier)) + { + ReportVehicleOutOfGas(iVehicleID, pGroup->ubSectorX, pGroup->ubSectorY); + //Nuke the group's path, so they don't continue moving. + ClearMercPathsAndWaypointsForAllInGroup(pGroup); + } } } } From d56288e313729b2c6eecde92eb65e04ea01bec1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Mon, 28 Aug 2023 15:26:34 +0200 Subject: [PATCH 07/10] Fixed incorrect vehicle group id after reloading the game and vehicle movement plot issues. (#207) --- Strategic/Map Screen Interface.cpp | 42 ++++++++++++++++++++++++------ Tactical/Squads.cpp | 15 ++++++++++- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 37eb3087..678c4fd7 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -4582,6 +4582,28 @@ void HandleSettingTheSelectedListOfMercs( void ) INT8 pbErrorNumber = -1; pSoldier = MercPtrs[gCharactersList[GetSelectedDestChar()].usSolID]; INT8 bSquadValue = pSoldier->bAssignment; + if (bSquadValue == VEHICLE) + { + for (INT8 bCounter = 0; bCounter < NUMBER_OF_SQUADS; ++bCounter) + { + if (Squad[bCounter][0] != NULL && IsVehicle(Squad[bCounter][0]) && + Squad[bCounter][0]->bVehicleID == pSoldier->iVehicleId) + { + bSquadValue = bCounter; + break; + } + } + } + if (bSquadValue >= NUMBER_OF_SQUADS) + { + if (pbErrorNumber != -1) + { + ReportMapScreenMovementError(pbErrorNumber); + } + SetSelectedDestChar(-1); + giDestHighLine = -1; + return; + } // find number of characters in particular squad. for (INT8 bCounter = 0; bCounter < NUMBER_OF_SOLDIERS_PER_SQUAD; ++bCounter) @@ -4693,17 +4715,21 @@ INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier ) // run through the list of squads for( bCounter = 0; bCounter < NUMBER_OF_SQUADS; bCounter++ ) { - // is this squad in this sector - if( IsThisSquadInThisSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter ) ) + // anv: don't automatically put people in vehicle squads + if (Squad[bCounter][0] == NULL || !IsVehicle(Squad[bCounter][0])) { - // does it have room? - if( IsThisSquadFull( bCounter ) == FALSE ) + // is this squad in this sector + if (IsThisSquadInThisSector(pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter)) { - // is it doing the same thing as the soldier is (staying or going) ? - if( IsSquadSelectedForMovement( bCounter ) == IsSoldierSelectedForMovement( pSoldier ) ) + // does it have room? + if (IsThisSquadFull(bCounter) == FALSE) { - // go ourselves a match, then - return( bCounter ); + // is it doing the same thing as the soldier is (staying or going) ? + if (IsSquadSelectedForMovement(bCounter) == IsSoldierSelectedForMovement(pSoldier)) + { + // go ourselves a match, then + return(bCounter); + } } } } diff --git a/Tactical/Squads.cpp b/Tactical/Squads.cpp index 7fb7c6b3..a7dda1b1 100644 --- a/Tactical/Squads.cpp +++ b/Tactical/Squads.cpp @@ -1700,7 +1700,20 @@ void CheckSquadMovementGroups( void ) for (INT8 iSoldier = 0; iSoldier < NUMBER_OF_SOLDIERS_PER_SQUAD; iSoldier++) { if (Squad[iSquad][iSoldier] != NULL) { - Squad[iSquad][iSoldier]->ubGroupID = pGroup->ubGroupID; + if (IsVehicle(Squad[iSquad][iSoldier])) + { + INT32 iCounter = 0; + for (iCounter = 0; iCounter < ubNumberOfVehicles; iCounter++) + { + if (pVehicleList[iCounter].ubProfileID == Squad[iSquad][iSoldier]->ubProfile) + break; + } + Squad[iSquad][iSoldier]->ubGroupID = pVehicleList[iCounter].ubMovementGroup; + } + else + { + Squad[iSquad][iSoldier]->ubGroupID = pGroup->ubGroupID; + } } } } From 7edecd68495723af86bf62fd6b1c18a592d96615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Mon, 28 Aug 2023 15:26:46 +0200 Subject: [PATCH 08/10] Fixed vehicle body not properly removed when destroyed during ramming (#210) --- Tactical/Soldier Control.cpp | 20 ++++++++++++++++++++ Tactical/Soldier Control.h | 8 ++++++++ TileEngine/structure.cpp | 4 ++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 9a594ee2..271368d0 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -10700,6 +10700,22 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr return(ubCombinedLoss); } +void SOLDIERTYPE::SoldierTakeDelayedDamage(INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathLoss, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage) +{ + delayedDamageFunction = [this, bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage]() + { + this->SoldierTakeDamage(bHeight, sLifeDeduct, sBreathLoss, ubReason, ubAttacker, sSourceGrid, sSubsequent, fShowDamage); + }; +} + +void SOLDIERTYPE::ResolveDelayedDamage() +{ + if (delayedDamageFunction) + { + delayedDamageFunction(); + delayedDamageFunction = nullptr; + } +} extern BOOLEAN IsMercSayingDialogue( UINT8 ubProfileID ); @@ -11499,6 +11515,8 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR // OK, set new position this->EVENT_InternalSetSoldierPosition( dXPos, dYPos, FALSE, FALSE, FALSE ); + this->ResolveDelayedDamage(); + // Flugente: drag people if ( currentlydragging ) { @@ -26234,4 +26252,6 @@ void SOLDIERTYPE::InitializeExtraData(void) this->ubQuickItemSlot = 0; this->usGrenadeItem = 0; + + this->delayedDamageFunction = nullptr; } diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index e02e1de0..69745618 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -20,6 +20,7 @@ #include #include "GameSettings.h" // added by Flugente #include "Disease.h" // added by Flugente +#include #define PTR_CIVILIAN (pSoldier->bTeam == CIV_TEAM) #define PTR_CROUCHED (gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_CROUCH) @@ -1656,6 +1657,10 @@ public: UINT8 ubQuickItemSlot; UINT16 usGrenadeItem; + + // anv: resolve damage with delay, e.g. damage applied mid movement that would cause issues with world data if applied immediately + std::function delayedDamageFunction; + public: // CREATION FUNCTIONS BOOLEAN DeleteSoldier( void ); @@ -1719,6 +1724,9 @@ public: void ReviveSoldier( void ); UINT8 SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage ); + // anv: resolve damage with delay, e.g. damage applied mid movement that would cause issues with world data if applied immediately + void SoldierTakeDelayedDamage(INT8 bHeight, INT16 sLifeDeduct, INT16 sBreathDeduct, UINT8 ubReason, UINT8 ubAttacker, INT32 sSourceGrid, INT16 sSubsequent, BOOLEAN fShowDamage); + void ResolveDelayedDamage(); // Palette functions for soldiers BOOLEAN CreateSoldierPalettes( void ); diff --git a/TileEngine/structure.cpp b/TileEngine/structure.cpp index 49264a51..1d8b2fc2 100644 --- a/TileEngine/structure.cpp +++ b/TileEngine/structure.cpp @@ -1914,10 +1914,10 @@ INT8 DamageStructure( STRUCTURE * pStructure, UINT8 ubDamage, UINT8 ubReason, IN //Since the structure is being damaged, set the map element that a structure is damaged gpWorldLevelData[ tmpgridno ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED; - // handle structure revenge - damage to vehicle + // handle structure revenge - damage to vehicle - to be resolved after movement if ( ubOwner != NOBODY && MercPtrs[ubOwner] && !ARMED_VEHICLE( MercPtrs[ubOwner] ) ) { - MercPtrs[ ubOwner ]->SoldierTakeDamage( 0, Random(max(0,(ubBaseArmour-10)/5))+max(0,(ubBaseArmour-10)/5), 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE ); + MercPtrs[ubOwner]->SoldierTakeDelayedDamage(0, Random(max(0,(ubBaseArmour-10)/5)) + max(0,(ubBaseArmour-10)/5), 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE); } // recompile = TRUE means that we destroyed something From ee3d2472e720739add6445ad9bf01e2dc613b8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Fa=C5=82kowski?= Date: Tue, 29 Aug 2023 21:25:14 +0200 Subject: [PATCH 09/10] Removed unnecessary offset for face gear --- Tactical/Faces.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index aad59742..059ba827 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -1467,8 +1467,8 @@ void GetXYForRightIconPlacement_FaceGera( FACETYPE *pFace, UINT16 ubIndex, INT16 usHeight = pTrav->usHeight; usWidth = pTrav->usWidth; - sX = sFaceX + ( usWidth * bNumIcons ) + 1; - sY = sFaceY + pFace->usFaceHeight - usHeight - 1; + sX = sFaceX + ( usWidth * bNumIcons ); + sY = sFaceY + pFace->usFaceHeight - usHeight; *psX = sX; *psY = sY; From 7910be0ab7119895b1ab2fc166ad909e8d59f7b6 Mon Sep 17 00:00:00 2001 From: kitty624 <58940527+kitty624@users.noreply.github.com> Date: Wed, 30 Aug 2023 19:34:30 +0200 Subject: [PATCH 10/10] Fix personality check for backgrounds during IMP creation --- Laptop/IMP Background.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Laptop/IMP Background.cpp b/Laptop/IMP Background.cpp index b7cddab4..ec269423 100644 --- a/Laptop/IMP Background.cpp +++ b/Laptop/IMP Background.cpp @@ -16,6 +16,7 @@ #include "soldier profile type.h" #include "IMP Compile Character.h" #include "IMP Disability Trait.h" + #include "IMP Character Trait.h" #include "GameSettings.h" #include "Interface.h" @@ -708,7 +709,7 @@ BOOLEAN IsBackGroundAllowed( UINT16 ubNumber ) break; } - switch ( iAttitude ) + switch ( iChosenCharacterTrait() ) { case CHAR_TRAIT_SOCIABLE: if ( zBackground[ ubNumber ].uiFlags & BACKGROUND_XENOPHOBIC )