From 815c44d439f84f02f8720b139936f337fab4324c Mon Sep 17 00:00:00 2001 From: Wanne Date: Sun, 16 Mar 2014 19:34:16 +0000 Subject: [PATCH] Merged from revision: 7077 More visual enemy gear info (by Sevenfm) - Show additional info in NCTH cursor (press ALT) (ADDITIONAL_NCTH_CURSOR_INFO = 2) -> You can only use this feature at certain distance - Updated 'show enemy weapon' feature (SHOW_ENEMY_WEAPON = TRUE, SHOW_ENEMY_EXTENDED_INFO = TRUE) - Now it can show armour and face items, too. Useful for OCTH users (SHOW_ENEMY_AWARENESS = TRUE) - Show total value of damage, absorbed by armour in last attack (SHOW_HIT_INFO = TRUE) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7078 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 5 +- GameSettings.h | 7 +- SaveLoadGame.cpp | 2 + Tactical/Interface Control.cpp | 14 + Tactical/Interface.cpp | 462 ++++++++++++++++++++++++--------- Tactical/Interface.h | 8 + Tactical/Overhead.cpp | 3 + Tactical/Soldier Control.cpp | 6 + Tactical/Soldier Control.h | 2 + Tactical/SoldierTooltips.cpp | 9 +- Tactical/Weapons.cpp | 13 +- 11 files changed, 396 insertions(+), 135 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 9bb9d80f..0750683a 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1066,6 +1066,8 @@ void LoadGameExternalOptions() gGameExternalOptions.ubEnemyHitCount = iniReader.ReadInteger("Tactical Interface Settings","ENEMY_HIT_COUNT", 0, 0, 4); // sevenfm: added similar option for player hit count gGameExternalOptions.ubPlayerHitCount = iniReader.ReadInteger("Tactical Interface Settings","PLAYER_HIT_COUNT", 0, 0, 4); + gGameExternalOptions.fShowHitInfo = iniReader.ReadBoolean("Tactical Interface Settings","SHOW_HIT_INFO", FALSE); + gGameExternalOptions.ubAdditionalNCTHCursorInfo = iniReader.ReadInteger("Tactical Interface Settings","ADDITIONAL_NCTH_CURSOR_INFO", 0, 0, 2); // sevenfm: show additional suppression info above soldier gGameExternalOptions.ubShowSuppressionCount = iniReader.ReadInteger("Tactical Interface Settings","SHOW_SUPPRESSION_COUNT", 0, 0, 2); @@ -1344,7 +1346,8 @@ void LoadGameExternalOptions() // sevenfm gGameExternalOptions.fShowEnemyWeapon = iniReader.ReadBoolean("Tactical Gameplay Settings","SHOW_ENEMY_WEAPON", FALSE); - gGameExternalOptions.ubShowEnemyAdditionalInfo = iniReader.ReadInteger("Tactical Gameplay Settings","SHOW_ENEMY_ADDITIONAL_INFO", 0, 0, 3); + gGameExternalOptions.fShowEnemyExtendedInfo = iniReader.ReadBoolean("Tactical Gameplay Settings","SHOW_ENEMY_EXTENDED_INFO", FALSE); + gGameExternalOptions.fShowEnemyAwareness = iniReader.ReadBoolean("Tactical Gameplay Settings","SHOW_ENEMY_AWARENESS", FALSE); //legion by Jazz gGameExternalOptions.fIndividualHiddenPersonNames = iniReader.ReadBoolean("Tactical Gameplay Settings","INDIVIDUAL_HIDDEN_PERSON_NAMES", FALSE); diff --git a/GameSettings.h b/GameSettings.h index 5d075432..329f6561 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1190,8 +1190,9 @@ typedef struct // sevenfm: show enemy weapon above soldier in tactical BOOLEAN fShowEnemyWeapon; - // show additional info in tactical (awareness, gas mask, nvg, armour) - UINT8 ubShowEnemyAdditionalInfo; + BOOLEAN fShowEnemyExtendedInfo; + // show awareness sight and level + BOOLEAN fShowEnemyAwareness; //legion by Jazz BOOLEAN fIndividualHiddenPersonNames; @@ -1232,6 +1233,8 @@ typedef struct UINT8 ubEnemyHitCount; UINT8 ubPlayerHitCount; + BOOLEAN fShowHitInfo; + UINT8 ubAdditionalNCTHCursorInfo; // sevenfm: new additional info above soldier UINT8 ubShowSuppressionCount; diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index ced2c058..66f4efa0 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -2654,6 +2654,8 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) this->ubLastShockFromHit=0; this->ubLastAPFromHit=0; this->ubLastMoraleFromHit=0; + this->iLastBulletImpact = 0; + this->iLastArmourProtection = 0; return TRUE; } diff --git a/Tactical/Interface Control.cpp b/Tactical/Interface Control.cpp index 08f241a9..2e2fe0f6 100644 --- a/Tactical/Interface Control.cpp +++ b/Tactical/Interface Control.cpp @@ -1271,6 +1271,20 @@ void DrawCounters( SOLDIERTYPE *pSoldier ) default: break; } + // show additional hit info + if( gGameExternalOptions.fShowHitInfo && ( pSoldier->iLastBulletImpact > 0 || pSoldier->iLastArmourProtection ) ) + { + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( COLOR_ORANGE ); + + //swprintf( pStr, L"%d/%d ", pSoldier->iLastBulletImpact, pSoldier->iLastArmourProtection ); + swprintf( pStr, L"%d ", pSoldier->iLastArmourProtection ); + gprintfdirty( sDamageX + widthDamage, sDamageY, pStr ); + mprintf( sDamageX + widthDamage, sDamageY, pStr ); + widthDamage += StringPixLength ( pStr, TINYFONT1 ); + + SetFontForeground( FONT_MCOLOR_WHITE ); + } } // do not show suppression info for dying soldier diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index 7fb2ff52..8e9f6276 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -273,6 +273,10 @@ RECT MagRect; RECT AimRect; RECT ModeRect; RECT APRect; +// sevenfm: additional rectangles +RECT RightRect; +RECT LeftRect; +RECT LeftRect2; // HEADROCK HAM 4: Externed this value which tracks whether we've clicked out final aiming click yet. extern BOOLEAN gfDisplayFullCountRing; @@ -1679,7 +1683,19 @@ void DrawCTHPixelToBuffer( UINT16 *pBuffer, UINT32 uiPitch, INT16 sLeft, INT16 s { return; } - + // sevenfm: added additional right, left rectangles + if ((sPixelX >= RightRect.left && sPixelX <= RightRect.right) && (sPixelY >= RightRect.top && sPixelY <= RightRect.bottom)) + { + return; + } + if ((sPixelX >= LeftRect.left && sPixelX <= LeftRect.right) && (sPixelY >= LeftRect.top && sPixelY <= LeftRect.bottom)) + { + return; + } + if ((sPixelX >= LeftRect2.left && sPixelX <= LeftRect2.right) && (sPixelY >= LeftRect2.top && sPixelY <= LeftRect2.bottom)) + { + return; + } pBuffer[sPixelX + uiPitch*sPixelY] = usColor; } @@ -2409,107 +2425,35 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) } // show weapon name and additional info - BOOLEAN showExactInfo = FALSE; - INT32 range; - INT32 maxExactWeaponDistance; + BOOLEAN showExactInfo = FALSE; INT16 height = 0; + SOLDIERTYPE *pSelectedSoldier, *pTargetSoldier; + pSelectedSoldier = MercPtrs[ gusSelectedSoldier ]; + pTargetSoldier = pSoldier; // calc max range for exact info if ( gusSelectedSoldier != NOBODY ) - { - range = GetRangeInCellCoordsFromGridNoDiff( MercPtrs[ gusSelectedSoldier ]->sGridNo, pSoldier->sGridNo ) / 10; + showExactInfo = ShowExactInfo( pSelectedSoldier, pTargetSoldier ); - // calc max range for exact weapon type based on visible distance - maxExactWeaponDistance = (INT32)( MercPtrs[ gusSelectedSoldier ]->GetMaxDistanceVisible( pSoldier->sGridNo, 0, CALC_FROM_WANTED_DIR) ) / 2 ; - // apply experience level factor - maxExactWeaponDistance *= 1 + (INT32)(FLOAT(EffectiveExpLevel(MercPtrs[ gusSelectedSoldier ]))/ 10); - - // check for bad weather conditions - if ( gGameExternalOptions.gfAllowLimitedVision ) - maxExactWeaponDistance *= 1 - (INT32)(FLOAT (gGameExternalOptions.ubVisDistDecreasePerRainIntensity) / 100); - - if ( maxExactWeaponDistance >= range ) - showExactInfo = TRUE; - } - // show weapon - if ( gGameExternalOptions.fShowEnemyWeapon && gTacticalStatus.ubCurrentTeam == OUR_TEAM ) + // show weapon/armour/items info + if ( gGameExternalOptions.fShowEnemyWeapon && gTacticalStatus.ubCurrentTeam == OUR_TEAM && pTargetSoldier->ubBodyType <= REGFEMALE ) { height = 30; + SetFont( TINYFONT1 ); + SetFontBackground( FONT_MCOLOR_BLACK ); + if( !gGameExternalOptions.fEnemyRank || !gGameExternalOptions.fEnemyNames ) height = 10; - if ( WeaponInHand( pSoldier ) ) - { - SetFont( TINYFONT1 ); - SetFontBackground( FONT_MCOLOR_BLACK ); - SetFontForeground( FONT_ORANGE ); - - if ( showExactInfo && gTacticalStatus.ubCurrentTeam == OUR_TEAM) - { - swprintf( NameStr, L"%s", ItemNames[ pSoldier->inv[ HANDPOS ].usItem ] ); - } - else - { - // display general weapon class - switch( Weapon[pSoldier->inv[ HANDPOS ].usItem].ubWeaponClass ) - { - case HANDGUNCLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HANDGUN] ); - break; - case SMGCLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SMG] ); - break; - case RIFLECLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_RIFLE] ); - break; - case MGCLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_MG] ); - break; - case SHOTGUNCLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SHOTGUN] ); - break; - case KNIFECLASS: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_KNIFE] ); - break; - default: - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HEAVY_WEAPON] ); - break; - } - } - + swprintf( NameStr, L"" ); + GetEnemyInfoString( pSelectedSoldier, pTargetSoldier, showExactInfo, NameStr ); + // print item name FindFontCenterCoordinates( sXPos, (INT16)( sYPos + height ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); gprintfdirty( sX, sY, NameStr ); mprintf( sX, sY, NameStr ); maxWidth = __max( maxWidth, StringPixLength ( NameStr, TINYFONT1 ) ); } - else - { - SetFont( TINYFONT1 ); - SetFontBackground( FONT_MCOLOR_BLACK ); - SetFontForeground( FONT_ORANGE ); - - if( showExactInfo && gTacticalStatus.ubCurrentTeam == OUR_TEAM ) - { - if( pSoldier->inv[ HANDPOS ].usItem ) - swprintf( NameStr, L"%s", Item[ pSoldier->inv[ HANDPOS ].usItem ].szItemName ); - else - swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_NO_WEAPON] ); - } - else - { - if( pSoldier->inv[ HANDPOS ].usItem ) - swprintf( NameStr, L"%s", L"Item" ); - else - swprintf( NameStr, L"%s", L"" ); - } - - FindFontCenterCoordinates( sXPos, (INT16)( sYPos + height ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); - gprintfdirty( sX, sY, NameStr ); - mprintf( sX, sY, NameStr ); - maxWidth = __max( maxWidth, StringPixLength ( NameStr, TINYFONT1 ) ); - } - } height = 0; FindFontCenterCoordinates( sXPos, (INT16)( sYPos + height ), (INT16)(80 ), 1, L"", TINYFONT1, &sX, &sY ); @@ -2537,7 +2481,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) sX-=maxWidth / 2 + StringPixLength ( L"***", TINYFONT1 ); // show additional info - if( gGameExternalOptions.ubShowEnemyAdditionalInfo && gTacticalStatus.ubCurrentTeam == OUR_TEAM ) + if( gGameExternalOptions.fShowEnemyAwareness && gTacticalStatus.ubCurrentTeam == OUR_TEAM ) { SetFont( TINYFONT1 ); SetFontBackground( FONT_MCOLOR_BLACK ); @@ -2582,46 +2526,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) height += 10; } } - - // show NVG - if( ( gGameExternalOptions.ubShowEnemyAdditionalInfo >1 ) && - ( Item[pSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus > 0 || Item[pSoldier->inv[HEAD2POS].usItem].nightvisionrangebonus > 0 ) ) - { - swprintf( NameStr, L"%s", L"NVG" ); - SetFontForeground( FONT_GRAY3 ); - if ( showExactInfo ) - { - gprintfdirty( sX, sY + height, NameStr ); - mprintf( sX, sY +height , NameStr ); - height += 10; } - } - - // show Gas mask - if( gGameExternalOptions.ubShowEnemyAdditionalInfo >1 && FindGasMask(pSoldier) != NO_SLOT ) - { - swprintf( NameStr, L"%s", L"GAS" ); - SetFontForeground( FONT_GRAY3 ); - if ( showExactInfo ) - { - gprintfdirty( sX, sY + height, NameStr ); - mprintf( sX, sY + height, NameStr ); - height += 10; - } - } - - // show armour - SetFontForeground( FONT_GRAY3 ); - swprintf( NameStr, L""); - if( gGameExternalOptions.ubShowEnemyAdditionalInfo > 2 && showExactInfo ) - { - wcscat( NameStr, pSoldier->inv[HELMETPOS].usItem ? L"H" : L"-" ); - wcscat( NameStr, pSoldier->inv[VESTPOS].usItem ? L"V" : L"-" ); - wcscat( NameStr, pSoldier->inv[LEGPOS].usItem ? L"L" : L"-" ); - gprintfdirty( sX, sY + height, NameStr ); - mprintf( sX, sY + height, NameStr ); - } - } // show rank icon if( gGameExternalOptions.ubShowEnemyRankIcon && gTacticalStatus.ubCurrentTeam == OUR_TEAM ) //&& (!gGameExternalOptions.fEnemyNames) && (!gGameExternalOptions.fEnemyRank)) @@ -3010,6 +2915,9 @@ BOOLEAN DrawCTHIndicator() APRect.right = sCenter + (usTotalWidth / 2); } + // sevenfm: draw item pics + DrawNCTHCursorItemPics( sStartScreenX, sStartScreenY ); + /////////////// MAG FACTOR { SetFont( TINYFONT1 ); @@ -6212,6 +6120,308 @@ void DrawRankIcon( INT8 rank, INT32 baseX, INT32 baseY ) UnLockVideoSurface( FRAME_BUFFER ); } +void DrawItemPic(INVTYPE *pItem, INT16 sX, INT16 sY ) +{ + UINT16 usGraphicNum; + + usGraphicNum = g_bUsePngItemImages ? 0 : pItem->ubGraphicNum; + + HVOBJECT hVObject; + ETRLEObject *pTrav; + GetVideoObject( &hVObject, GetInterfaceGraphicForItem( pItem ) ); + pTrav = &(hVObject->pETRLEObject[ usGraphicNum ] ); + + BltVideoObjectOutlineFromIndex( FRAME_BUFFER, GetInterfaceGraphicForItem( pItem ), usGraphicNum, sX - pTrav->sOffsetX, sY - pTrav->sOffsetY, Get16BPPColor( FROMRGB( 255, 255, 255 ) ), FALSE ); +} + +void GetItemDimensions( INVTYPE *pItem, INT16 &sWidth, INT16 &sHeight ) +{ + HVOBJECT hVObject; + ETRLEObject *pTrav; + UINT16 usGraphicNum; + + usGraphicNum = g_bUsePngItemImages ? 0 : pItem->ubGraphicNum; + GetVideoObject( &hVObject, GetInterfaceGraphicForItem( pItem ) ); + pTrav = &(hVObject->pETRLEObject[ usGraphicNum ] ); + + sWidth = (UINT32)(pTrav->usWidth); + sHeight = (UINT32)(pTrav->usHeight); +} + +BOOLEAN ShowExactInfo( SOLDIERTYPE* pSoldier, SOLDIERTYPE* pTargetSoldier ) +{ + INT32 range; + INT32 maxExactWeaponDistance; + + if( pTargetSoldier->bVisible == -1 ) + return FALSE; + + range = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, pTargetSoldier->sGridNo ) / 10; + + // visible distance + maxExactWeaponDistance = (INT32)( pSoldier->GetMaxDistanceVisible( pTargetSoldier->sGridNo, 0, CALC_FROM_WANTED_DIR) ) / 2 ; + + // apply experience level factor + maxExactWeaponDistance = (INT32)( maxExactWeaponDistance * ( 1 + FLOAT( EffectiveExpLevel( pSoldier ) ) / 10.0f ) ); + + if ( maxExactWeaponDistance >= range ) + return TRUE; + + return FALSE; +} + +void DrawNCTHCursorItemPics( INT16 sStartScreenX, INT16 sStartScreenY ) +{ + // find target soldier + SOLDIERTYPE *pSoldier; + SOLDIERTYPE *pTargetSoldier; + INT32 usItemID = 0; + INT16 sX, sY, sWidth, sHeight; + INT16 sXOffset = 0; + + GetSoldier( &pSoldier, gusSelectedSoldier ); + GetSoldier( &pTargetSoldier, gusUIFullTargetID ); + + // zero rects + RightRect.left = 0; RightRect.top = 0; RightRect.right = 0; RightRect.bottom = 0; + LeftRect.left = 0; LeftRect.top = 0; LeftRect.right = 0; LeftRect.bottom = 0; + LeftRect2.left = 0; LeftRect2.top = 0; LeftRect2.right = 0; LeftRect2.bottom = 0; + + if( gGameExternalOptions.ubAdditionalNCTHCursorInfo && + gfUIBodyHitLocation && + pSoldier->ubBodyType <= REGFEMALE && + _KeyDown( ALT ) && + ShowExactInfo( pSoldier, pTargetSoldier) ) + { + // show armour + switch( pSoldier->bAimShotLocation ) + { + case AIM_SHOT_HEAD: + if( pTargetSoldier->inv[HELMETPOS].exists() ) + usItemID = pTargetSoldier->inv[HELMETPOS].usItem; + break; + case AIM_SHOT_TORSO: + if( pTargetSoldier->inv[VESTPOS].exists() ) + usItemID = pTargetSoldier->inv[VESTPOS].usItem; + break; + case AIM_SHOT_LEGS: + if( pTargetSoldier->inv[LEGPOS].exists() ) + usItemID = pTargetSoldier->inv[LEGPOS].usItem; + break; + } + if( usItemID ) + { + sX = sStartScreenX+25; + sY = sStartScreenY-3; + DrawItemPic( &(Item[ usItemID ] ), sX, sY ); + GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight ); + RightRect.left = sX; + RightRect.top = sY; + RightRect.right = sX + sWidth; + RightRect.bottom = sY + sHeight; + } + + if( gGameExternalOptions.ubAdditionalNCTHCursorInfo > 1 ) + { + // show item in hands + if( pSoldier->bAimShotLocation == AIM_SHOT_TORSO ) + { + if( pTargetSoldier->inv[HANDPOS].exists() ) + { + usItemID = pTargetSoldier->inv[HANDPOS].usItem; + GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight ); + if( sWidth > 30 ) + sXOffset = 10; + sX = sStartScreenX - 25 - sWidth + sXOffset; + sY = sStartScreenY - 3; + DrawItemPic(&(Item[ usItemID ] ), sX, sY ); + LeftRect.left = sX; + LeftRect.top = sY; + LeftRect.right = sX + sWidth; + LeftRect.bottom = sY + sHeight; + } + } + // show items in head slots + else if( pSoldier->bAimShotLocation == AIM_SHOT_HEAD ) + { + if( pTargetSoldier->inv[HEAD2POS].exists() ) + { + usItemID = pTargetSoldier->inv[HEAD2POS].usItem; + GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight ); + sX = sStartScreenX - 25 - sWidth; + sY = sStartScreenY - 3; + DrawItemPic(&(Item[ usItemID ] ), sX, sY ); + LeftRect.left = sX; + LeftRect.top = sY; + LeftRect.right = sX + sWidth; + LeftRect.bottom = sY + sHeight; + } + + if( pTargetSoldier->inv[HEAD1POS].exists() ) + { + usItemID = pTargetSoldier->inv[HEAD1POS].usItem; + GetItemDimensions( &(Item[ usItemID ]), sWidth, sHeight ); + sX = sStartScreenX - 25 - sWidth; + sY = sStartScreenY - 3; + if( pTargetSoldier->inv[HEAD2POS].exists() ) + sX -= LeftRect.right - LeftRect.left; + DrawItemPic(&(Item[ usItemID ] ), sX, sY ); + LeftRect2.left = sX; + LeftRect2.top = sY; + LeftRect2.right = sX + sWidth; + LeftRect2.bottom = sY + sHeight; + } + } + } + } +} + +void GetEnemyInfoString( SOLDIERTYPE* pSelectedSoldier, SOLDIERTYPE* pTargetSoldier, BOOLEAN showExactInfo, CHAR16 *NameStr ) +{ + UINT16 usItemID; + + // if ALT pressed - show armour instead of weapon + if( gfUIBodyHitLocation && + _KeyDown( ALT ) ) + { + SetFontForeground( FONT_YELLOW ); + // show armour + usItemID = 0; + switch( pSelectedSoldier->bAimShotLocation ) + { + case AIM_SHOT_HEAD: + if( pTargetSoldier->inv[HELMETPOS].exists() ) + usItemID = pTargetSoldier->inv[HELMETPOS].usItem; + break; + case AIM_SHOT_TORSO: + if( pTargetSoldier->inv[VESTPOS].exists() ) + usItemID = pTargetSoldier->inv[VESTPOS].usItem; + break; + case AIM_SHOT_LEGS: + if( pTargetSoldier->inv[LEGPOS].exists() ) + usItemID = pTargetSoldier->inv[LEGPOS].usItem; + break; + } + if( usItemID ) + { + if( showExactInfo && gGameExternalOptions.fShowEnemyExtendedInfo ) + { // in range, show exact armour name + swprintf( NameStr, L"%s", ItemNames[ usItemID ] ); + } + else + { // show general armour type + switch( pSelectedSoldier->bAimShotLocation ) + { + case AIM_SHOT_HEAD: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HELMET] ); + break; + case AIM_SHOT_TORSO: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_VEST] ); + break; + case AIM_SHOT_LEGS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_LEGGINGS] ); + break; + } + } + } + } + else + { + if( gfUIBodyHitLocation && + pSelectedSoldier->bAimShotLocation == AIM_SHOT_HEAD ) + { + // show face items + SetFontForeground( FONT_ORANGE ); + if( pTargetSoldier->inv[HEAD1POS].exists() ) + { + if(gGameExternalOptions.fShowEnemyExtendedInfo) + { // show exact name + wcscat( NameStr, ItemNames[ pTargetSoldier->inv[HEAD1POS].usItem ] ); + } + else + { // show general name + if( Item[pTargetSoldier->inv[HEAD1POS].usItem].gasmask ) + wcscat( NameStr, L"Mask" ); + else if( Item[pTargetSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus || Item[pTargetSoldier->inv[HEAD1POS].usItem].cavevisionrangebonus ) + wcscat( NameStr, L"NVG" ); + } + } + if( pTargetSoldier->inv[HEAD2POS].exists() ) + { + if( pTargetSoldier->inv[HEAD1POS].exists() ) + wcscat( NameStr, L", " ); + if(gGameExternalOptions.fShowEnemyExtendedInfo) + { // show exact name + wcscat( NameStr, ItemNames[ pTargetSoldier->inv[HEAD2POS].usItem ] ); + } + else + { // show general name + if( Item[pTargetSoldier->inv[HEAD1POS].usItem].gasmask ) + wcscat( NameStr, L"Mask" ); + else if( Item[pTargetSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus || Item[pTargetSoldier->inv[HEAD1POS].usItem].cavevisionrangebonus ) + wcscat( NameStr, L"NVG" ); + } + } + } + else + { + // show weapon + SetFontForeground( FONT_ORANGE ); + if ( WeaponInHand( pTargetSoldier ) ) + { + if ( showExactInfo ) + { + swprintf( NameStr, L"%s", ItemNames[ pTargetSoldier->inv[ HANDPOS ].usItem ] ); + } + else + { + // display general weapon class + switch( Weapon[pTargetSoldier->inv[ HANDPOS ].usItem].ubWeaponClass ) + { + case HANDGUNCLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HANDGUN] ); + break; + case SMGCLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SMG] ); + break; + case RIFLECLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_RIFLE] ); + break; + case MGCLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_MG] ); + break; + case SHOTGUNCLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_SHOTGUN] ); + break; + case KNIFECLASS: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_KNIFE] ); + break; + default: + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_HEAVY_WEAPON] ); + break; + } + } + } + else + { + if( showExactInfo ) + { + if( pTargetSoldier->inv[ HANDPOS ].usItem ) + swprintf( NameStr, L"%s", Item[ pTargetSoldier->inv[ HANDPOS ].usItem ].szItemName ); + else + swprintf( NameStr, L"%s", gzTooltipStrings[STR_TT_NO_WEAPON] ); + } + else + { + if( pTargetSoldier->inv[ HANDPOS ].usItem ) + swprintf( NameStr, L"%s", L"Item" ); + else + swprintf( NameStr, L"%s", L"" ); + } + } + } + } +} void DrawLine( INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color8, UINT16 color16, UINT8 *pDestBuf ) { if(gbPixelDepth==16) diff --git a/Tactical/Interface.h b/Tactical/Interface.h index e4444bca..85e292cd 100644 --- a/Tactical/Interface.h +++ b/Tactical/Interface.h @@ -536,4 +536,12 @@ void DrawLine( INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color8, UINT16 col // Flugente: show enemy role BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier); +//sevenfm: draw additional info for NCTH indicator +void DrawItemPic( INVTYPE *pItem, INT16 sX, INT16 sY ); +void GetItemDimensions( INVTYPE *pItem, INT16 &sWidth, INT16 &sHeight ); +BOOLEAN ShowExactInfo( SOLDIERTYPE* pSoldier, SOLDIERTYPE* pTargetSoldier ); +void DrawNCTHCursorItemPics( INT16 sStartScreenX, INT16 sStartScreenY ); + +void GetEnemyInfoString( SOLDIERTYPE* pSelectedSoldier, SOLDIERTYPE* pTargetSoldier, BOOLEAN showExactInfo, CHAR16 *NameStr ); + #endif \ No newline at end of file diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 9348cab4..00c455ea 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -970,6 +970,9 @@ BOOLEAN ExecuteOverhead( ) pSoldier->bDisplayDamageCount = 0; pSoldier->sDamage = 0; pSoldier->flags.fDisplayDamage = FALSE; + // sevenfm: also zero damage info from this attack + pSoldier->iLastBulletImpact = 0; + pSoldier->iLastArmourProtection = 0; } } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index ebf648e6..8ebd2d1a 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1040,6 +1040,8 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src) this->ubLastShockFromHit = 0; this->ubLastMoraleFromHit = 0; this->ubLastAPFromHit = 0; + this->iLastBulletImpact = 0; + this->iLastArmourProtection = 0; } return *this; @@ -7758,6 +7760,8 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou this->ubLastAPFromHit = 0; this->ubLastShockFromHit = 0; this->ubLastMoraleFromHit = 0; + this->iLastBulletImpact = 0; + this->iLastArmourProtection = 0; this->flags.fCloseCall = FALSE; @@ -9963,6 +9967,8 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPo this->ubLastSuppression = 0; this->ubLastMorale = 0; this->ubLastAP = 0; + //this->iLastBulletImpact = 0; + //this->iLastArmourProtection = 0; } } diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 28e3a508..2e5c09d9 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1506,6 +1506,8 @@ public: UINT8 ubLastShockFromHit; UINT8 ubLastAPFromHit; UINT8 ubLastMoraleFromHit; + UINT8 iLastBulletImpact; + UINT8 iLastArmourProtection; public: // CREATION FUNCTIONS diff --git a/Tactical/SoldierTooltips.cpp b/Tactical/SoldierTooltips.cpp index dde00fc4..7d78f7ab 100644 --- a/Tactical/SoldierTooltips.cpp +++ b/Tactical/SoldierTooltips.cpp @@ -70,10 +70,11 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier ) BOOLEAN fDrawTooltip = FALSE; // sevenfm: do not show tooltip if ALT is pressed for adding autofire bullets - SOLDIERTYPE *pShooter; - GetSoldier( &pShooter, gusSelectedSoldier ); - if(gfUICtHBar && pShooter && pShooter->bDoAutofire > 1) - return; + // EDIT: commented this out because with default autofire bullets> 1 it will confuse players + //SOLDIERTYPE *pShooter; + //GetSoldier( &pShooter, gusSelectedSoldier ); + //if(gfUICtHBar && pShooter && pShooter->bDoAutofire > 1) + // return; if ( gfKeyState[ALT] && pSoldier && IsPointInScreenRectWithRelative( gusMouseXPos, gusMouseYPos, &aRect, &a1, &a2 ) ) diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 14a903ae..489b1a46 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -9343,6 +9343,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT16 usAttackingWeapon = 0; INT32 sOrigGridNo = 0; BOOLEAN fFragment = FALSE; + INT32 iTotalArmourProtection=0; + if (pBullet == NULL && pFirer ) { usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType; @@ -9413,7 +9415,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, // up to 50% extra impact for making particularly accurate successful shots iBonus = sHitBy / 2; - //NumMessage("Bonus = ",bonus); + //NumMessage("Bonus = ",bonus); iOrigImpact = iOrigImpact * (100 + iFluke + iBonus) / 100; @@ -9436,13 +9438,20 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, } } + // sevenfm: store original impact + pTarget->iLastBulletImpact += iOrigImpact; + if (pubSpecial && (*pubSpecial == FIRE_WEAPON_BLINDED_BY_SPIT_SPECIAL || *pubSpecial == FIRE_WEAPON_BLINDED_SPECIAL) ) { iImpact = iOrigImpact; } else { - iImpact = iOrigImpact - TotalArmourProtection( pTarget, ubHitLocation, iOrigImpact, ubAmmoType ); + iTotalArmourProtection = TotalArmourProtection( pTarget, ubHitLocation, iOrigImpact, ubAmmoType ); + iImpact = iOrigImpact - iTotalArmourProtection; + + // sevenfm: store armour protection + pTarget->iLastArmourProtection += iTotalArmourProtection; } // calc minimum damage