Files
source/Tactical/Interface Control.cpp
T
Wanne f8a0a5eb2c New options in ja2_options.ini (by Sevenfm)
1) PLAYER_HIT_COUNT = 0
This works as ENEMY_HIT_COUNT option, but for player mercs.
Possible values: 0 - 4

2) SOLDIER_TOOLTIP_DISPLAY_SUPPRESSION_INFO = TRUE
Show additional info in tactical tooltip:
- APs lost due to suppression
- Suppression Tolerance
- Effective Shock Level ( Shock level modified by traits and backgrounds. This value is compared with current suppression tolerance to determine "cowering" effect )
- AI morale level

3) SHOW_ENEMY_WEAPON = TRUE
Show enemy weapon name above soldier - after health, name and rank.
You can see exact weapon name only on short distances, range calculation is similar to dynamic tooltips and based on soldiers actual viewing range and experience.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6691 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2013-12-16 09:13:55 +00:00

1304 lines
35 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdio.h>
#include <time.h>
#include "sgp.h"
#include "gameloop.h"
#include "himage.h"
#include "vobject.h"
#include "sysutil.h"
#include "overhead.h"
#include "mousesystem.h"
#include "Button System.h"
#include "interface.h"
#include "vsurface.h"
#include "input.h"
#include "Handle UI.h"
#include "Animation Control.h"
#include "Animation Data.h"
#include "renderworld.h"
#include "cursors.h"
#include "radar screen.h"
#include "worldman.h"
#include "Font Control.h"
#include "render dirty.h"
#include "utilities.h"
#include "interface cursors.h"
#include "lighting.h"
#include "Interface Panels.h"
#include "pathai.h"
#include "vobject_blitters.h"
#include "faces.h"
#include "Handle UI Plan.h"
#include "interface control.h"
#include "interface items.h"
#include "interface dialogue.h"
#include "interactive tiles.h"
#include "Game Clock.h"
#include "Strategic Exit GUI.h"
#include "PopUpBox.h"
#include "Assignments.h"
#include "spread burst.h"
#include "squads.h"
#include "line.h"
#include "Militia Control.h"
#include "Map Screen Interface.h"
#include "civ quotes.h"
#include "GameSettings.h"
#endif
#include "connect.h"
#include "Text.h"
#ifdef JA2UB
#include "Dialogue Control.h"
#endif
/* I deleted here declaration of clock coords for tactical screen i will declare them
* in functions that Initialize coord for SMPanet and TEAMPanel
* any questions? joker
*/
SGPRect gOldClippingRect, gOldDirtyClippingRect;
UINT32 guiTacticalInterfaceFlags;
UINT16 gusUICurIntTileEffectIndex;
INT32 gsUICurIntTileEffectGridNo;
UINT8 gsUICurIntTileOldShade;
BOOLEAN gfRerenderInterfaceFromHelpText = FALSE;
MOUSE_REGION gLockPanelOverlayRegion;
// CHRISL: Change function definition to allow passing of X,Y coords to control placement of TownID string
extern void RenderTownIDString( INT16 sX, INT16 sY );
extern BOOLEAN gfUIOverItemPool;
extern INT32 gfUIOverItemPoolGridNo;
extern BOOLEAN gfInMovementMenu;
extern BOOLEAN gfInItemPickupMenu;
extern BOOLEAN gfInOpenDoorMenu;
extern UINT32 guiUIMessageTimeDelay;
BOOLEAN gfPausedTacticalRenderInterfaceFlags = FALSE;
BOOLEAN gfPausedTacticalRenderFlags = FALSE;
// which assignment menu can be shown?
extern void DetermineWhichAssignmentMenusCanBeShown( void );
extern void DetermineWhichMilitiaControlMenusCanBeShown( void ); //lal
extern void HandleAnyMercInSquadHasCompatibleStuff( UINT8 ubSquad, OBJECTTYPE *pObject, BOOLEAN fReset );
extern BOOLEAN RemoveFlashItemSlot( ITEM_POOL *pItemPool );
void SetTacticalInterfaceFlags( UINT32 uiFlags )
{
guiTacticalInterfaceFlags = uiFlags;
}
void HandleTacticalPanelSwitch( )
{
if ( gfSwitchPanel )
{
SetCurrentInterfacePanel( gbNewPanel );
SetCurrentTacticalPanelCurrentMerc( gubNewPanelParam );
gfSwitchPanel = FALSE;
if ( !(guiTacticalInterfaceFlags & INTERFACE_NORENDERBUTTONS ) && !( guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) )
{
RenderButtons( );
}
}
}
// Flugente: handle flashlights
void HandleFlashLights()
{
if ( !fInterfacePanelDirty )
return;
SOLDIERTYPE* pSoldier = NULL;
for (UINT32 uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop )
{
pSoldier = MercSlots[ uiLoop ];
if ( pSoldier != NULL && pSoldier->bSoldierFlagMask & SOLDIER_REDOFLASHLIGHT )
{
pSoldier->HandleFlashLights();
}
}
}
void RenderTacticalInterface( )
{
// handle paused render of tactical
HandlePausedTacticalRender( );
if ( !(guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
HandleFlashingItems( );
HandleMultiPurposeLocator( );
}
// Handle degrading new items...
DegradeNewlyAddedItems( );
switch( gsCurInterfacePanel )
{
case SM_PANEL:
RenderSMPanel( &fInterfacePanelDirty );
break;
case TEAM_PANEL:
RenderTEAMPanel( fInterfacePanelDirty );
break;
}
// Handle faces
if( !(guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) )
HandleAutoFaces( );
// Flugente: handle flashlights
HandleFlashLights();
}
void HandlePausedTacticalRender( void )
{
// for a one frame paused render of tactical
if( gfPausedTacticalRenderFlags )
{
gRenderFlags|=gfPausedTacticalRenderFlags;
gfPausedTacticalRenderFlags = FALSE;
}
if ( gfPausedTacticalRenderInterfaceFlags )
{
fInterfacePanelDirty = gfPausedTacticalRenderInterfaceFlags;
gfPausedTacticalRenderInterfaceFlags = FALSE;
}
return;
}
void RenderTacticalInterfaceWhileScrolling( )
{
RenderButtons( );
switch( gsCurInterfacePanel )
{
case SM_PANEL:
RenderSMPanel( &fInterfacePanelDirty );
break;
case TEAM_PANEL:
RenderTEAMPanel( fInterfacePanelDirty );
break;
}
// Handle faces
HandleAutoFaces( );
}
void SetUpInterface( )
{
SOLDIERTYPE *pSoldier;
LEVELNODE *pIntTile;
if ( ( guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
return;
}
DrawUICursor( );
SetupPhysicsTrajectoryUI( );
if ( giUIMessageOverlay != -1 )
{
if ( ( GetJA2Clock( ) - guiUIMessageTime ) > guiUIMessageTimeDelay )
{
EndUIMessage( );
}
}
if ( gusSelectedSoldier != NOBODY )
{
GetSoldier( &pSoldier, gusSelectedSoldier );
}
if ( gCurrentUIMode == OPENDOOR_MENU_MODE )
{
HandleOpenDoorMenu( );
}
HandleTalkingMenu( );
if ( gCurrentUIMode == EXITSECTORMENU_MODE )
{
HandleSectorExitMenu( );
}
// FOR THE MOST PART - SHUTDOWN INTERFACE WHEN IT'S THE ENEMY'S TURN
if ( gTacticalStatus.ubCurrentTeam != gbPlayerNum )
{
return;
}
HandleInterfaceBackgrounds( );
if ( gfUIHandleSelection == NONSELECTED_GUY_SELECTION )
{
if ( gsSelectedLevel > 0 )
{
AddRoofToHead( gsSelectedGridNo, GOODRING1 );
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
AddObjectToHead( gsSelectedGridNo, GOODRING1 );
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
if ( gfUIHandleSelection == SELECTED_GUY_SELECTION )
{
if ( gsSelectedLevel > 0 )
{
//AddRoofToHead( gsSelectedGridNo, SELRING1 );
AddRoofToHead( gsSelectedGridNo, FIRSTPOINTERS2 );
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
//AddObjectToHead( gsSelectedGridNo, SELRING1 );
AddObjectToHead( gsSelectedGridNo, FIRSTPOINTERS2 );
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
if ( gfUIHandleSelection == ENEMY_GUY_SELECTION )
{
if ( gsSelectedLevel > 0 )
{
AddRoofToHead( gsSelectedGridNo, FIRSTPOINTERS2 );
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
AddObjectToHead( gsSelectedGridNo, FIRSTPOINTERS2 );
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsSelectedGridNo].pObjectHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
if ( gfUIHandleShowMoveGrid )
{
if ( gusSelectedSoldier != NOBODY )
{
if ( MercPtrs[ gusSelectedSoldier ]->sGridNo != gsUIHandleShowMoveGridLocation )
{
if ( gfUIHandleShowMoveGrid == 2 )
{
AddTopmostToHead( gsUIHandleShowMoveGridLocation, GetSnapCursorIndex( FIRSTPOINTERS4 ) );
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
if ( MercPtrs[ gusSelectedSoldier ]->bStealthMode )
{
AddTopmostToHead( gsUIHandleShowMoveGridLocation, GetSnapCursorIndex( FIRSTPOINTERS9 ) );
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
AddTopmostToHead( gsUIHandleShowMoveGridLocation, GetSnapCursorIndex( FIRSTPOINTERS2 ) );
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gsUIHandleShowMoveGridLocation].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
}
}
}
// Check if we are over an interactive tile...
if ( gfUIShowCurIntTile )
{
pIntTile = GetCurInteractiveTileGridNo( &gsUICurIntTileEffectGridNo );
if ( pIntTile != NULL )
{
gusUICurIntTileEffectIndex = pIntTile->usIndex;
// Shade green
gsUICurIntTileOldShade = pIntTile->ubShadeLevel;
pIntTile->ubShadeLevel = 0;
pIntTile->uiFlags |= LEVELNODE_DYNAMIC;
}
}
}
void ResetInterface( )
{
LEVELNODE *pNode;
if ( ( guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
return;
}
// find out if we need to show any menus
DetermineWhichAssignmentMenusCanBeShown();
CreateDestroyAssignmentPopUpBoxes( );
DetermineWhichMilitiaControlMenusCanBeShown( ); //lal
CreateDestroyMilitiaControlPopUpBoxes( );
HideUICursor( );
ResetPhysicsTrajectoryUI( );
if ( gfUIHandleSelection )
{
if ( gsSelectedLevel > 0 )
{
RemoveRoof( gsSelectedGridNo, GOODRING1 );
RemoveRoof( gsSelectedGridNo, FIRSTPOINTERS2 );
}
else
{
RemoveObject( gsSelectedGridNo, FIRSTPOINTERS2 );
RemoveObject( gsSelectedGridNo, GOODRING1 );
}
}
if ( gfUIHandleShowMoveGrid )
{
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS4 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS9 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS2 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS13 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS15 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS19 );
RemoveTopmost( gsUIHandleShowMoveGridLocation, FIRSTPOINTERS20 );
}
if ( fInterfacePanelDirty )
{
fInterfacePanelDirty = FALSE;
}
// Reset int tile cursor stuff
if ( gfUIShowCurIntTile )
{
if (!TileIsOutOfBounds(gsUICurIntTileEffectGridNo))
{
//Find our tile!
pNode = gpWorldLevelData[ gsUICurIntTileEffectGridNo].pStructHead;
while( pNode != NULL )
{
if ( pNode->usIndex == gusUICurIntTileEffectIndex )
{
pNode->ubShadeLevel = gsUICurIntTileOldShade;
pNode->uiFlags &= (~LEVELNODE_DYNAMIC);
break;
}
pNode = pNode->pNext;
}
}
}
}
extern BOOLEAN AnyItemsVisibleOnLevel( ITEM_POOL *pItemPool, INT8 bZLevel );
UINT32 guiColors[ 12 ] =
{
FROMRGB( 198, 163, 0 ),
FROMRGB( 185, 150, 0 ),
FROMRGB( 172, 136, 0 ),
FROMRGB( 159, 123, 0 ),
FROMRGB( 146, 110, 0 ),
FROMRGB( 133, 96, 0 ),
FROMRGB( 120, 83, 0 ),
FROMRGB( 133, 96, 0 ),
FROMRGB( 146, 110, 0 ),
FROMRGB( 159, 123, 0 ),
FROMRGB( 172, 136, 0 ),
FROMRGB( 185, 150, 0 )
};
void RenderRubberBanding( )
{
UINT16 usLineColor;
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
INT16 iLeft, iRight, iTop, iBottom;
INT32 iBack = -1;
static INT32 iFlashColor = 0;
static INT32 uiTimeOfLastUpdate = 0;
if ( !gRubberBandActive )
return;
iLeft = (INT16)gRubberBandRect.iLeft;
iRight = (INT16)gRubberBandRect.iRight;
iTop = (INT16)gRubberBandRect.iTop;
iBottom = (INT16)gRubberBandRect.iBottom;
if ( iLeft == iRight && iTop == iBottom )
{
return;
}
if ( ( GetJA2Clock( ) - uiTimeOfLastUpdate ) > 60 )
{
uiTimeOfLastUpdate = GetJA2Clock( );
iFlashColor++;
if ( iFlashColor == 12 )
{
iFlashColor = 0;
}
}
// Draw rectangle.....
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y );
usLineColor = Get16BPPColor( guiColors[ iFlashColor ] );
if ( ( iRight - iLeft ) > 0 )
{
LineDraw( TRUE, iLeft, iTop, iRight, iTop, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iLeft, iTop, (INT16)( iRight + 1 ), (INT16)( iTop + 1 ) );
}
else if ( ( iRight - iLeft ) < 0 )
{
LineDraw( TRUE, iLeft, iTop, iRight, iTop, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iRight, iTop, (INT16)( iLeft + 1 ), (INT16)( iTop + 1 ) );
}
if ( iBack != -1 )
{
SetBackgroundRectFilled( iBack );
}
iBack = -1;
if ( ( iRight - iLeft ) > 0 )
{
LineDraw( TRUE, iLeft, iBottom, iRight, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iLeft, iBottom, (INT16)( iRight +1 ), (INT16)( iBottom + 1 ) );
}
else if ( ( iRight - iLeft ) < 0 )
{
LineDraw( TRUE, iLeft, iBottom, iRight, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iRight, iBottom, (INT16)( iLeft + 1 ), (INT16)( iBottom + 1 ) );
}
if ( iBack != -1 )
{
SetBackgroundRectFilled( iBack );
}
iBack = -1;
if ( ( iBottom - iTop ) > 0 )
{
LineDraw( TRUE, iLeft, iTop, iLeft, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iLeft, iTop, (INT16)( iLeft +1 ), iBottom );
}
else if ( ( iBottom - iTop ) < 0 )
{
LineDraw( TRUE, iLeft, iTop, iLeft, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iLeft, iBottom, (INT16)( iLeft + 1 ), iTop );
}
if ( iBack != -1 )
{
SetBackgroundRectFilled( iBack );
}
iBack = -1;
if ( ( iBottom - iTop ) > 0 )
{
LineDraw( TRUE, iRight, iTop, iRight, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iRight, iTop, (INT16)( iRight +1 ), iBottom );
}
else if ( ( iBottom - iTop ) < 0 )
{
LineDraw( TRUE, iRight, iTop, iRight, iBottom, usLineColor, pDestBuf );
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, iRight, iBottom, (INT16)( iRight + 1 ), iTop );
}
if ( iBack != -1 )
{
SetBackgroundRectFilled( iBack );
}
UnLockVideoSurface( FRAME_BUFFER );
}
void RenderTopmostTacticalInterface( )
{
SOLDIERTYPE *pSoldier;
UINT32 cnt;
static UINT32 uiBogTarget = 0;
VOBJECT_DESC VObjectDesc;
INT16 sX, sY;
INT16 sOffsetX, sOffsetY, sTempY_S, sTempX_S;
INT32 usMapPos;
ITEM_POOL *pItemPool;
if ( gfRerenderInterfaceFromHelpText == TRUE )
{
fInterfacePanelDirty = DIRTYLEVEL2;
switch( gsCurInterfacePanel )
{
case SM_PANEL:
RenderSMPanel( &fInterfacePanelDirty );
break;
case TEAM_PANEL:
RenderTEAMPanel( fInterfacePanelDirty );
break;
}
gfRerenderInterfaceFromHelpText = FALSE;
}
if ( ( guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
if ( !(guiTacticalInterfaceFlags & INTERFACE_NORENDERBUTTONS ) )
{
// If we want to rederaw whole screen, dirty all buttons!
if ( fInterfacePanelDirty == DIRTYLEVEL2 )
{
MarkButtonsDirty( );
}
RenderButtons( );
}
return;
}
if ( InItemStackPopup( ) || InSectorStackPopup( ) )
{
RenderItemStackPopup( ( BOOLEAN )( fInterfacePanelDirty == DIRTYLEVEL2 ) );
}
if( ( InKeyRingPopup() ) && ( !InItemDescriptionBox( ) ) )
{
RenderKeyRingPopup( ( BOOLEAN )( fInterfacePanelDirty == DIRTYLEVEL2 ) );
}
if ( gfInMovementMenu )
{
RenderMovementMenu( );
}
// if IN PLAN MODE AND WE HAVE TARGETS, draw black targets!
if ( InUIPlanMode( ) )
{
// Zero out any planned soldiers
for( cnt = MAX_NUM_SOLDIERS; cnt < TOTAL_SOLDIERS; cnt++ )
{
if ( MercPtrs[ cnt ]->bActive )
{
if ( MercPtrs[ cnt ]->sPlannedTargetX != -1 )
{
// Blit bogus target
if ( uiBogTarget == 0 )
{
//Loadup cursor!
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP( "CURSORS\\targblak.sti", VObjectDesc.ImageFile);
AddVideoObject( &VObjectDesc, &uiBogTarget );
}
if ( GridNoOnScreen( MAPROWCOLTOPOS( ( MercPtrs[ cnt ]->sPlannedTargetY/CELL_Y_SIZE), ( MercPtrs[ cnt ]->sPlannedTargetX / CELL_X_SIZE ) ) ) )
{
// GET SCREEN COORDINATES
sOffsetX = (MercPtrs[ cnt ]->sPlannedTargetX - gsRenderCenterX);
sOffsetY = (MercPtrs[ cnt ]->sPlannedTargetY - gsRenderCenterY);
FromCellToScreenCoordinates( sOffsetX, sOffsetY, &sTempX_S, &sTempY_S );
sX = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + sTempX_S;
sY = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + sTempY_S;
// Adjust for offset position on screen
sX -= gsRenderWorldOffsetX;
sY -= gsRenderWorldOffsetY;
sX -= 10;
sY -= 10;
BltVideoObjectFromIndex( FRAME_BUFFER, uiBogTarget, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL );
InvalidateRegion( sX, sY, sX + 20, sY + 20 );
}
}
}
}
}
/*
if ( gfUIInDeadlock )
{
SetFont( LARGEFONT1 );
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( FONT_MCOLOR_WHITE );
gprintfdirty( 0, 300, L"OPPONENT %d DEADLOCKED - 'Q' TO DEBUG, <ALT><ENTER> END OPP TURN", gUIDeadlockedSoldier );
mprintf( 0, 300, L"OPPONENT %d DEADLOCKED - 'Q' TO DEBUG, <ALT><ENTER> END OPP TURN", gUIDeadlockedSoldier );
}
*/
// Syncronize for upcoming soldier counters
SYNCTIMECOUNTER( );
// Setup system for video overlay ( text and blitting ) Sets clipping rects, etc
StartViewportOverlays( );
RenderTopmostFlashingItems( );
RenderTopmostMultiPurposeLocator( );
RenderAccumulatedBurstLocations( );
// HEADROCK HAM 4: The NCTH indicator is now drawn to the FRAMEBUFFER instead of the MOUSEBUFFER. This is
// due to size constraints related to drawing directly on the cursor. This indicator follows the mouse, and
// is a mouse-cursor in everything but name. See the function itself for more details.
if (UsingNewCTHSystem() == true && gfUICtHBar)
{
DrawCTHIndicator();
}
// Loop through all mercs and make go
for ( cnt = 0; cnt < guiNumMercSlots; cnt++ )
{
pSoldier = MercSlots[ cnt ];
if (pSoldier != NULL )
{
if ( pSoldier->ubID == gsSelectedGuy && gfUIHandleSelectionAboveGuy )
{
}
else
{
DrawSelectedUIAboveGuy((UINT16)pSoldier->ubID);
}
DrawCounters( pSoldier );
}
}
if ( gusSelectedSoldier != NOBODY )
{
DrawSelectedUIAboveGuy( gusSelectedSoldier );
}
if ( gfUIHandleSelectionAboveGuy && gsSelectedGuy != NOBODY )
{
DrawSelectedUIAboveGuy((UINT16)gsSelectedGuy );
}
// FOR THE MOST PART, DISABLE INTERFACE STUFF WHEN IT'S ENEMY'S TURN
if ( gTacticalStatus.ubCurrentTeam == gbPlayerNum )
{
RenderArrows( );
}
RenderAimCubeUI( );
EndViewportOverlays( );
RenderRubberBanding( );
if ( !gfInItemPickupMenu && gpItemPointer == NULL )
{
HandleAnyMercInSquadHasCompatibleStuff( (INT8) CurrentSquad( ), NULL, TRUE );
}
// CHECK IF OUR CURSOR IS OVER AN INV POOL
if( GetMouseMapPos( &usMapPos) )
{
if ( gfUIOverItemPool )
{
if( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// Check if we are over an item pool
if ( GetItemPool( gfUIOverItemPoolGridNo, &pItemPool, pSoldier->pathing.bLevel ) )
{
STRUCTURE *pStructure = NULL;
INT32 sIntTileGridNo;
INT8 bZLevel = 0;
INT32 sActionGridNo = usMapPos;
// Get interactive tile...
if ( ConditionalGetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo , &pStructure, FALSE ) )
{
sActionGridNo = sIntTileGridNo;
}
bZLevel = GetZLevelOfItemPoolGivenStructure( sActionGridNo, pSoldier->pathing.bLevel, pStructure );
if ( AnyItemsVisibleOnLevel( pItemPool, bZLevel ) )
{
DrawItemPoolList( pItemPool, gfUIOverItemPoolGridNo , ITEMLIST_DISPLAY, bZLevel, gusMouseXPos, gusMouseYPos );
// ATE: If over items, remove locator....
RemoveFlashItemSlot( pItemPool );
}
}
else
{
INT8 bCheckLevel;
// ATE: Allow to see list if a different level....
if ( pSoldier->pathing.bLevel == 0 )
{
bCheckLevel = 1;
}
else
{
bCheckLevel = 0;
}
// Check if we are over an item pool
if ( GetItemPool( gfUIOverItemPoolGridNo, &pItemPool, bCheckLevel ) )
{
STRUCTURE *pStructure = NULL;
INT32 sIntTileGridNo;
INT8 bZLevel = 0;
INT32 sActionGridNo = usMapPos;
// Get interactive tile...
if ( ConditionalGetCurInteractiveTileGridNoAndStructure( &sIntTileGridNo , &pStructure, FALSE ) )
{
sActionGridNo = sIntTileGridNo;
}
bZLevel = GetZLevelOfItemPoolGivenStructure( sActionGridNo, bCheckLevel, pStructure );
if ( AnyItemsVisibleOnLevel( pItemPool, bZLevel ) )
{
DrawItemPoolList( pItemPool, gfUIOverItemPoolGridNo , ITEMLIST_DISPLAY, bZLevel, gusMouseXPos, gusMouseYPos );
// ATE: If over items, remove locator....
RemoveFlashItemSlot( pItemPool );
}
}
}
}
}
}
// Check if we should render item selection window
if ( gCurrentUIMode == GETTINGITEM_MODE )
{
SetItemPickupMenuDirty( DIRTYLEVEL2 );
// Handle item pickup will return true if it's been closed
RenderItemPickupMenu( );
}
// Check if we should render item selection window
if ( gCurrentUIMode == OPENDOOR_MENU_MODE )
{
RenderOpenDoorMenu( );
}
if ( gfInTalkPanel )
{
SetTalkingMenuDirty( DIRTYLEVEL2 );
// Handle item pickup will return true if it's been closed
RenderTalkingMenu( );
}
if ( gfInSectorExitMenu )
{
RenderSectorExitMenu( );
}
if( fRenderRadarScreen == TRUE )
{
// Render clock
/* Here we was rendering closk and position string now i moved it to functions
* that render SM or TEAM panel it will be usefull when RenderTownIDString will
* take position where render i will fix that
* any questions?? joker
*/
// RenderClock( CLOCK_X, CLOCK_Y );
// RenderTownIDString( );
// CreateMouseRegionForPauseOfClock( CLOCK_X, CLOCK_Y );
}
else
{
RemoveMouseRegionForPauseOfClock( );
}
if ( !(guiTacticalInterfaceFlags & INTERFACE_NORENDERBUTTONS ) )
{
// If we want to rederaw whole screen, dirty all buttons!
if ( fInterfacePanelDirty == DIRTYLEVEL2 )
{
MarkButtonsDirty( );
}
RenderButtons( );
RenderPausedGameBox( );
}
// mark all pop ups as dirty
MarkAllBoxesAsAltered( );
HandleShowingOfTacticalInterfaceFastHelpText( );
HandleShadingOfLinesForAssignmentMenus( );
DetermineBoxPositions( );
DisplayBoxes( FRAME_BUFFER );
}
void StartViewportOverlays( )
{
// Set Clipping Rect to be the viewscreen
// Save old one
memcpy( &gOldClippingRect, &ClippingRect, sizeof( gOldClippingRect ) );
// Save old dirty clipping rect
// memcpy( &gOldDirtyClippingRect, &ClippingRect, sizeof( gOldDirtyClippingRect ) );
memcpy( &gOldDirtyClippingRect, &gDirtyClipRect, sizeof( gOldDirtyClippingRect ) );
// Set bottom clipping value for blitter clipping rect
ClippingRect.iLeft = 0;
ClippingRect.iTop = gsVIEWPORT_WINDOW_START_Y;
ClippingRect.iRight = SCREEN_WIDTH;
ClippingRect.iBottom = gsVIEWPORT_WINDOW_END_Y;
// Set values for dirty rect clipping rect
gDirtyClipRect.iLeft = 0;
gDirtyClipRect.iTop = gsVIEWPORT_WINDOW_START_Y;
gDirtyClipRect.iRight = SCREEN_WIDTH;
gDirtyClipRect.iBottom = gsVIEWPORT_WINDOW_END_Y;
SaveFontSettings( );
SetFontDestBuffer( FRAME_BUFFER, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE );
}
void EndViewportOverlays( )
{
// Reset clipping rect
memcpy( &ClippingRect, &gOldClippingRect, sizeof( gOldClippingRect ) );
memcpy( &gDirtyClipRect, &gOldDirtyClippingRect, sizeof( gOldDirtyClippingRect ) );
if(gDirtyClipRect.iBottom < SCREEN_HEIGHT)
gDirtyClipRect.iBottom = SCREEN_HEIGHT;
RestoreFontSettings( );
}
void LockTacticalInterface( )
{
// OK, check and see if we are not locked, if so
// 1) create a mouse region over the entrie interface panel
// 2) set flag for use in tactical to indicate we are locked
if ( !(guiTacticalInterfaceFlags & INTERFACE_LOCKEDLEVEL1 ) )
{
MSYS_DefineRegion( &gLockPanelOverlayRegion, 0, gsVIEWPORT_WINDOW_END_Y ,SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST,
CURSOR_NORMAL, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
// Add region
MSYS_AddRegion( &gLockPanelOverlayRegion);
guiTacticalInterfaceFlags |= INTERFACE_LOCKEDLEVEL1;
}
}
void UnLockTacticalInterface( )
{
if ( (guiTacticalInterfaceFlags & INTERFACE_LOCKEDLEVEL1 ) )
{
// Remove region
MSYS_RemoveRegion( &gLockPanelOverlayRegion);
guiTacticalInterfaceFlags &= (~INTERFACE_LOCKEDLEVEL1);
}
}
void EraseInterfaceMenus( BOOLEAN fIgnoreUIUnLock )
{
// ATE: If we are currently talking, setup this flag so that the
// automatic handler in handledialogue doesn't adjust the UI setting
if ( ( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) && fIgnoreUIUnLock )
{
gTacticalStatus.uiFlags |= IGNORE_ENGAGED_IN_CONV_UI_UNLOCK;
}
// Remove item pointer if one active
CancelItemPointer( );
ShutDownQuoteBoxIfActive( );
PopDownMovementMenu( );
PopDownOpenDoorMenu( );
DeleteTalkingMenu( );
#ifdef JA2UB
RemoveJerryMiloBrokenLaptopOverlay();
#endif
}
BOOLEAN AreWeInAUIMenu( )
{
if ( gfInMovementMenu || gfInOpenDoorMenu || gfInItemPickupMenu || gfInSectorExitMenu || gfInTalkPanel )
{
return( TRUE );
}
else
{
return( FALSE );
}
}
void ResetInterfaceAndUI( )
{
// Erase menus
EraseInterfaceMenus( FALSE );
EraseRenderArrows( );
EndRubberBanding( );
//ResetMultiSelection( );
if ( giUIMessageOverlay != -1 )
{
RemoveVideoOverlay( giUIMessageOverlay );
giUIMessageOverlay = -1;
}
// Set UI back to movement...
guiPendingOverrideEvent = M_ON_TERRAIN;
HandleTacticalUI( );
}
BOOLEAN InterfaceOKForMeanwhilePopup()
{
if ( gfSwitchPanel )
{
return( FALSE );
}
return( TRUE );
}
void PrintCounter( INT16 x, INT16 y, INT16 data, UINT16 &width, UINT8 ubForegound, UINT8 scale )
{
CHAR16 pStr[100];
UINT8 num = 0;
UINT8 i;
if( data == 0)
return;
switch ( scale )
{
case PRINT_SCALE_ASTERISK_SUPPRESSION:
num = CalcScaleSuppression( abs(data) );
break;
case PRINT_SCALE_ASTERISK_DAMAGE:
num = CalcScaleDamage( abs(data) );
break;
case PRINT_SCALE_ASTERISK_MORALE:
num = CalcScaleMorale( abs(data) );
break;
case PRINT_SCALE_ASTERISK_AP:
num = CalcScaleAP( abs(data) );
break;
case PRINT_SCALE_ASTERISK_SHOCK:
num = CalcScaleShock( abs(data) );
break;
default:
num = 1;
}
if ( !gGameExternalOptions.ubShowSuppressionScaleAsterisk )
num = 1;
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( ubForegound );
// scale = 0 - print numbers
// scale = 1 - print one asterisk
// scale > 1 - print num asterisks
if( scale > PRINT_SCALE_PLAIN_NUMBER )
{
swprintf( pStr, L"*" );
for ( i = 1; i<num; i++)
wcscat( pStr, L"*" );
}
else
{
swprintf( pStr, L"%d ", data );
}
gprintfdirty( x+width, y, pStr );
mprintf( x+width, y, pStr );
width += StringPixLength ( pStr, TINYFONT1 );
SetFontForeground( FONT_MCOLOR_WHITE );
}
UINT8 CalcScaleSuppression( INT16 data )
{
if( data > 20 ) return 5;
if( data > 15 ) return 4;
if( data > 10 ) return 3;
if( data > 5 ) return 2;
return 1;
}
UINT8 CalcScaleDamage( INT16 data )
{
if( data > 100 ) return 5;
if( data > 60 ) return 4;
if( data > 30 ) return 3;
if( data > 10 ) return 2;
return 1;
}
UINT8 CalcScaleMorale( INT16 data )
{
return __min( 5, data );
}
UINT8 CalcScaleAP( INT16 data )
{
if( data > 100 ) return 5;
if( data > 60 ) return 4;
if( data > 30 ) return 3;
if( data > 10 ) return 2;
return 1;
}
UINT8 CalcScaleShock( INT16 data )
{
if( data > 20 ) return 5;
if( data > 12 ) return 4;
if( data > 7 ) return 3;
if( data > 3 ) return 2;
return 1;
}
void DrawCounters( SOLDIERTYPE *pSoldier )
{
// Use world coordinates!
INT16 sMercScreenX, sMercScreenY, sOffsetX, sOffsetY, sDamageX, sDamageY;
// sevenfm: added for suppression counters
INT16 sSuppressionX, sSuppressionY;
UINT16 widthDamage = 0; // print damage counters one after another in one line
UINT16 widthSuppression = 0; // print suppression counters (not moving) one after another in one line above soldier
BOOLEAN printSuppression = FALSE; // determines if any value is printed above soldier (only for new suppression counters)
UINT8 hitCount;
CHAR16 pStr[100];
if ( gGameExternalOptions.ubShowSuppressionCountAlt ||
gGameExternalOptions.ubShowSuppressionCount == 2 ||
gGameExternalOptions.ubShowShockCount == 2 ||
gGameExternalOptions.ubShowAPCount == 2 ||
gGameExternalOptions.ubShowMoraleCount == 2 )
printSuppression = TRUE;
if (!TileIsOutOfBounds(pSoldier->sGridNo) && pSoldier->bVisible != -1 )
{
GetSoldierScreenPos( pSoldier, &sMercScreenX, &sMercScreenY );
GetSoldierAnimOffsets( pSoldier, &sOffsetX, &sOffsetY );
// coordinates for suppression counter
if ( pSoldier->ubBodyType == QUEENMONSTER )
{
sSuppressionX = sMercScreenX - pSoldier->sBoundingBoxOffsetX;
sSuppressionY = sMercScreenY - pSoldier->sBoundingBoxOffsetY;
sSuppressionX += 25;
sSuppressionY += 10;
}
else
{
sSuppressionX = (INT16)(sMercScreenX + ( 2 * 30 / 3 ) );
sSuppressionY = (INT16)(sMercScreenY - 5 );
if ( sSuppressionY < gsVIEWPORT_WINDOW_START_Y )
sSuppressionY = ( sMercScreenY - sOffsetY );
}
// coordinates for damage counter
if ( pSoldier->ubBodyType == QUEENMONSTER )
{
sDamageX = sMercScreenX + pSoldier->sDamageX - pSoldier->sBoundingBoxOffsetX;
sDamageY = sMercScreenY + pSoldier->sDamageY - pSoldier->sBoundingBoxOffsetY;
sDamageX += 25;
sDamageY += 10;
}
else
{
sDamageX = pSoldier->sDamageX + (INT16)(sMercScreenX + ( 2 * 30 / 3 ) );
sDamageY = pSoldier->sDamageY + (INT16)(sMercScreenY - 5 );
sDamageX -= sOffsetX;
sDamageY -= sOffsetY;
// if showing suppression - move damage counter higher on screen
if( printSuppression)
// sDamageY -= 2*WFGetFontHeight ( TINYFONT1 );
sDamageY -= WFGetFontHeight ( TINYFONT1 );
if ( sSuppressionY < gsVIEWPORT_WINDOW_START_Y )
sSuppressionY = ( sMercScreenY - sOffsetY );
}
// print current ubSuppressionPoints counter
if( gGameExternalOptions.ubShowSuppressionCountAlt && pSoldier->stats.bLife >= OKLIFE )
{
if( pSoldier->ubSuppressionPoints >0 )
{
PrintCounter( sSuppressionX, sSuppressionY, pSoldier->ubSuppressionPoints, widthSuppression, FONT_MCOLOR_LTGRAY,
gGameExternalOptions.ubShowSuppressionUseAsterisks ? PRINT_SCALE_ASTERISK_SUPPRESSION : PRINT_SCALE_PLAIN_NUMBER );
}
}
if ( pSoldier->flags.fDisplayDamage )
{
// Display damage
SetFont( TINYFONT1 );
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( FONT_MCOLOR_WHITE );
if( pSoldier->bTeam == OUR_TEAM )
hitCount = gGameExternalOptions.ubPlayerHitCount;
else
hitCount = gGameExternalOptions.ubEnemyHitCount;
if( pSoldier->sDamage < 0 )
{
// Flugente: it is possible that someone might regain negative damage as zombies can regenerate health through bleeding
SetFontForeground( FONT_MCOLOR_LTGREEN );
swprintf( pStr, L"+%d ", -pSoldier->sDamage );
gprintfdirty( sDamageX, sDamageY, pStr );
mprintf( sDamageX, sDamageY, pStr );
widthDamage += StringPixLength ( pStr, TINYFONT1 );
SetFontForeground( FONT_MCOLOR_WHITE );
}
else // normal soldier
{
switch (hitCount)
{
case 0: // show damage as usual
if( pSoldier->sDamage > 0 )
//PrintCounter( sDamageX, sDamageY, pSoldier->sDamage, widthDamage, FONT_MCOLOR_WHITE, PRINT_SCALE_PLAIN_NUMBER );
swprintf( pStr, L"-%d ", pSoldier->sDamage );
gprintfdirty( sDamageX, sDamageY, pStr );
mprintf( sDamageX, sDamageY, pStr );
widthDamage += StringPixLength ( pStr, TINYFONT1 );
break;
case 1: // show ? indicator
if( pSoldier->sDamage != 0 )
{
swprintf( pStr, L"%s ", gzHiddenHitCountStr[0] );
gprintfdirty( sDamageX, sDamageY, pStr );
mprintf( sDamageX, sDamageY, pStr );
widthDamage += StringPixLength ( pStr, TINYFONT1 );
}
break;
case 2: // do not show anything
break;
case 3: // show white asterisks
PrintCounter( sDamageX, sDamageY, pSoldier->sDamage, widthDamage, FONT_MCOLOR_WHITE, PRINT_SCALE_ASTERISK_DAMAGE );
break;
case 4: // show red asterisks
PrintCounter( sDamageX, sDamageY, pSoldier->sDamage, widthDamage, FONT_MCOLOR_DKRED, PRINT_SCALE_ASTERISK_DAMAGE );
break;
default:
break;
}
}
// do not show suppression info for dying soldier
if ( pSoldier->stats.bLife >= OKLIFE )
{
// replace ubLastSuppression count on screen
if( gGameExternalOptions.ubShowSuppressionCountAlt && gGameExternalOptions.ubShowSuppressionCount == 2 && pSoldier->ubLastSuppression > 0 )
widthSuppression = 0;
// display suppression from last attack
PrintSuppressionCounter( sDamageX, sDamageY, sSuppressionX, sSuppressionY, pSoldier->ubLastSuppression, widthDamage, widthSuppression,
FONT_MCOLOR_LTGRAY, PRINT_SCALE_ASTERISK_SUPPRESSION, gGameExternalOptions.ubShowSuppressionCount );
// display shock from last attack
PrintSuppressionCounter( sDamageX, sDamageY, sSuppressionX, sSuppressionY, pSoldier->ubLastShock + pSoldier->ubLastShockFromHit, widthDamage, widthSuppression,
FONT_MCOLOR_LTYELLOW, PRINT_SCALE_ASTERISK_SHOCK, gGameExternalOptions.ubShowShockCount );
// display morale hit from last attack
PrintSuppressionCounter( sDamageX, sDamageY, sSuppressionX, sSuppressionY, pSoldier->ubLastMorale + pSoldier->ubLastMoraleFromHit, widthDamage, widthSuppression,
FONT_MCOLOR_LTGREEN, PRINT_SCALE_ASTERISK_MORALE, gGameExternalOptions.ubShowMoraleCount );
// display AP loss from last attack
PrintSuppressionCounter( sDamageX, sDamageY, sSuppressionX, sSuppressionY, pSoldier->ubLastAP + pSoldier->ubLastAPFromHit, widthDamage, widthSuppression,
FONT_MCOLOR_LTBLUE, PRINT_SCALE_ASTERISK_AP, gGameExternalOptions.ubShowAPCount );
}
}
}
}
void PrintSuppressionCounter( INT16 x, INT16 y, INT16 sX, INT16 sY, UINT8 data, UINT16 &widthDamage, UINT16 &widthSuppression, UINT8 ubForeground, UINT8 scale, UINT8 option)
{
if( option == 1 ) // show after damage counter
PrintCounter( x, y, data, widthDamage, ubForeground, gGameExternalOptions.ubShowSuppressionUseAsterisks ? scale : PRINT_SCALE_PLAIN_NUMBER );
if( option == 2 ) // show after suppression counter
PrintCounter( sX, sY, data, widthSuppression, ubForeground, gGameExternalOptions.ubShowSuppressionUseAsterisks ? scale : PRINT_SCALE_PLAIN_NUMBER );
}