mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Updates/Improvements (by Sevenfm) 1. Quick inventory items: Press [ALT] + [1..0] for quick access to predefined items in tactical (ja2_options.ini: QUICK_ITEM_0 to QUICK_ITEM_9) Press [ALT] + [`] (tilde key left to [1]) to put item back to inventory and switch hands. The item will be put in the same slot it was taken from (unless it was stacked or game was reloaded). 2. Also a few quick hotkeys: [ALT] + [q] - switch to sling (same as [SHIFT] + [k]) [CTRL] + [q] - switch hands [SHIFT] + [q] - drop item from main hand to the ground Additional info: -some hotkeys do not work in cheat mode -only NIV -only one-handed items supported -stacked items currently not supported -remembered item slot is lost when you reload game 3. A few small fixes for dynamic tooltips and other things git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7130 3b4a5df2-a311-0410-b5c6-a8a6f20db521
662 lines
27 KiB
C++
662 lines
27 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#else
|
|
#include "Types.h"
|
|
#include "Windows.h"
|
|
//#include "Soldier Control.h"
|
|
#include "Input.h"
|
|
#include "english.h"
|
|
#include "Isometric Utils.h"
|
|
#include "GameSettings.h"
|
|
#include "Overhead.h"
|
|
#include "Game Clock.h"
|
|
#include "Text.h"
|
|
#include "lighting.h"
|
|
#include "Interface.h"
|
|
#include "weapons.h"
|
|
#include "renderworld.h"
|
|
#include "Font Control.h"
|
|
#include "font.h"
|
|
#include "local.h"
|
|
#include "vsurface.h"
|
|
#include "line.h"
|
|
#include "los.h"
|
|
// added by SANDRO
|
|
#include "SkillCheck.h"
|
|
#include "soldier profile type.h"
|
|
#include "Soldier macros.h"
|
|
#include "Encyclopedia_new.h" ///< Encyclopedia item visibility
|
|
#endif
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
|
|
struct MOUSETT
|
|
{
|
|
CHAR16 FastHelpText[ 1024 ];
|
|
INT32 iX;
|
|
INT32 iY;
|
|
INT32 iW;
|
|
};
|
|
|
|
extern struct MOUSETT mouseTT;
|
|
extern BOOL mouseTTrender,mouseTTdone;
|
|
|
|
const int DL_Limited = 1;
|
|
const int DL_Basic = 2;
|
|
const int DL_Full = 3;
|
|
const int DL_Debug = 4;
|
|
|
|
void DisplayWeaponInfo( SOLDIERTYPE*, CHAR16*, UINT8, UINT8 );
|
|
void DrawMouseTooltip(void);
|
|
|
|
#define MAX(a, b) (a > b ? a : b)
|
|
|
|
void SoldierTooltip( SOLDIERTYPE* pSoldier )
|
|
{
|
|
if(!pSoldier)
|
|
return;
|
|
|
|
// WANNE: No tooltips on bloodcats, bugs, tanks, roboter
|
|
if ( CREATURE_OR_BLOODCAT( pSoldier ) || TANK ( pSoldier ) ||
|
|
AM_A_ROBOT( pSoldier))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SGPRect aRect;
|
|
extern void GetSoldierScreenRect(SOLDIERTYPE*,SGPRect*);
|
|
GetSoldierScreenRect( pSoldier, &aRect );
|
|
INT16 a1,a2;
|
|
BOOLEAN fDrawTooltip = FALSE;
|
|
|
|
// sevenfm: do not show tooltip if ALT is pressed for adding autofire bullets
|
|
// 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 ) )
|
|
{
|
|
MOUSETT *pRegion = &mouseTT;
|
|
CHAR16 pStrInfo[ sizeof( pRegion->FastHelpText ) ];
|
|
int iNVG = 0;
|
|
INT32 usSoldierGridNo;
|
|
BOOLEAN fDisplayBigSlotItem = FALSE;
|
|
BOOLEAN fMercIsUsingScope = FALSE;
|
|
UINT16 iCarriedRL = 0;
|
|
INT32 iRangeToTarget = 0;
|
|
UINT8 ubTooltipDetailLevel = gGameExternalOptions.ubSoldierTooltipDetailLevel;
|
|
UINT32 uiMaxTooltipDistance = gGameExternalOptions.ubStraightSightRange;
|
|
|
|
fDrawTooltip = TRUE;
|
|
|
|
// get the gridno the cursor is at
|
|
GetMouseMapPos( &usSoldierGridNo );
|
|
|
|
// get the distance to enemy's tile from the selected merc
|
|
if ( gusSelectedSoldier != NOBODY && gusUIFullTargetID != NOBODY )
|
|
{
|
|
//CHRISL: Changed the second parameter to use the same information as the 'F' hotkey uses.
|
|
//iRangeToTarget = GetRangeInCellCoordsFromGridNoDiff( MercPtrs[ gusSelectedSoldier ]->sGridNo, sSoldierGridNo ) / 10;
|
|
iRangeToTarget = GetRangeInCellCoordsFromGridNoDiff( MercPtrs[ gusSelectedSoldier ]->sGridNo, MercPtrs[ gusUIFullTargetID ]->sGridNo ) / 10;
|
|
}
|
|
// WANNE: If we want to show the tooltip of milita and no merc is present in the sector
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
//SCORE: If UDT range, we work it out as half actual LOS
|
|
// SANDRO - don't use this if detail set to debug!
|
|
if ( gGameExternalOptions.gfAllowUDTRange && gGameExternalOptions.ubSoldierTooltipDetailLevel != DL_Debug && !(gTacticalStatus.uiFlags & SHOW_ALL_MERCS) )
|
|
{
|
|
uiMaxTooltipDistance = (UINT32)( MercPtrs[ gusSelectedSoldier ]->GetMaxDistanceVisible(MercPtrs[ gusUIFullTargetID ]->sGridNo, 0, CALC_FROM_WANTED_DIR) * (gGameExternalOptions.ubUDTModifier));
|
|
uiMaxTooltipDistance /= 100;
|
|
}
|
|
//SCORE: Otherwise if we're using dynamics then do this
|
|
// SANDRO - don't use this if detail set to debug!
|
|
else if ( gGameExternalOptions.fEnableDynamicSoldierTooltips && gGameExternalOptions.ubSoldierTooltipDetailLevel != DL_Debug && !(gTacticalStatus.uiFlags & SHOW_ALL_MERCS) )
|
|
{
|
|
OBJECTTYPE* pObject = &(MercPtrs[gusSelectedSoldier]->inv[HANDPOS]);
|
|
for (attachmentList::iterator iter = (*pObject)[0]->attachments.begin(); iter != (*pObject)[0]->attachments.end(); ++iter) {
|
|
if ( Item[iter->usItem].visionrangebonus > 0 && iter->exists())
|
|
{
|
|
fMercIsUsingScope = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( fMercIsUsingScope )
|
|
{
|
|
// set detail level to (at least) Full
|
|
ubTooltipDetailLevel = MAX(DL_Full,ubTooltipDetailLevel);
|
|
}
|
|
}
|
|
//SCORE: removed to enable scopes to affect range of tooltips.
|
|
//else
|
|
//{
|
|
//If we're using original settings and no scope, we do this
|
|
if (gGameExternalOptions.fEnableDynamicSoldierTooltips && fMercIsUsingScope == 0 && !gGameExternalOptions.gfAllowUDTRange)
|
|
{
|
|
// add 10% to max tooltip viewing distance per level of the merc
|
|
// sevenfm: fixed incorrect integer calculation
|
|
uiMaxTooltipDistance = (INT32)( uiMaxTooltipDistance * ( 1 + ( (FLOAT)( EffectiveExpLevel( MercPtrs[ gusSelectedSoldier ] ) ) / 10.0 ) ) ); // SANDRO - changed to effective level calc
|
|
|
|
// sevenfm: this calculation doesn't make sense: disabled
|
|
//if ( gGameExternalOptions.gfAllowLimitedVision )
|
|
// uiMaxTooltipDistance *= 1 - (gGameExternalOptions.ubVisDistDecreasePerRainIntensity / 100);
|
|
|
|
if ( !(Item[MercPtrs[gusSelectedSoldier]->inv[HEAD1POS].usItem].nightvisionrangebonus > 0) &&
|
|
!(Item[MercPtrs[gusSelectedSoldier]->inv[HEAD2POS].usItem].nightvisionrangebonus > 0) &&
|
|
!DayTime() )
|
|
{
|
|
// if night reduce max tooltip viewing distance by a factor of 4 if merc is not wearing NVG
|
|
uiMaxTooltipDistance >>= 2;
|
|
}
|
|
}
|
|
//SCORE: Dynamic detail, otherwise do what we usually do
|
|
// SANDRO - don't use this if detail set to debug!
|
|
if ( gGameExternalOptions.gfAllowUDTDetail && gGameExternalOptions.ubSoldierTooltipDetailLevel != DL_Debug && !(gTacticalStatus.uiFlags & SHOW_ALL_MERCS) )
|
|
{
|
|
//Check range. Less than a third? Full. Less than 2 thirds? Basic. Otherwise Limited.
|
|
if ( iRangeToTarget <= (INT32)(uiMaxTooltipDistance / 3) )
|
|
{
|
|
ubTooltipDetailLevel = DL_Full;
|
|
}
|
|
else if ( iRangeToTarget <= (INT32)((uiMaxTooltipDistance / 3)*2) )
|
|
{
|
|
ubTooltipDetailLevel = DL_Basic;
|
|
}
|
|
else if ( iRangeToTarget <= (INT32)uiMaxTooltipDistance )
|
|
{
|
|
ubTooltipDetailLevel = DL_Limited;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( iRangeToTarget <= (INT32)(uiMaxTooltipDistance / 2) )
|
|
{
|
|
// at under half the maximum view distance set tooltip detail to (at least) Basic
|
|
ubTooltipDetailLevel = MAX(DL_Basic,ubTooltipDetailLevel);
|
|
}
|
|
else if ( iRangeToTarget <= (INT32)uiMaxTooltipDistance )
|
|
{
|
|
// at under the maximum view distance set tooltip detail to (at least) Limited
|
|
ubTooltipDetailLevel = MAX(DL_Limited,ubTooltipDetailLevel);
|
|
}
|
|
else
|
|
{
|
|
// beyond visual range, do not display tooltip if player has not chosen full or debug details
|
|
if ( ubTooltipDetailLevel < DL_Full )
|
|
return;
|
|
}
|
|
}
|
|
//} // fMercIsUsingScope is false
|
|
// gGameExternalOptions.fEnableDynamicSoldierTooltips
|
|
|
|
|
|
|
|
// WANNE: Check if enemy soldier is in line of sight but only if player has not choosen debug details
|
|
if ( ubTooltipDetailLevel < DL_Full)
|
|
{
|
|
// Get the current selected merc
|
|
SOLDIERTYPE* pMerc = MercPtrs[ gusSelectedSoldier ];
|
|
|
|
if ( pMerc->aiData.bOppList[pSoldier->ubID] != SEEN_CURRENTLY )
|
|
{
|
|
// We do not see the enemy. Return and do not display the tooltip.
|
|
return;
|
|
}
|
|
}
|
|
|
|
swprintf( pStrInfo, L"" );
|
|
if ( ubTooltipDetailLevel == DL_Debug )
|
|
{
|
|
// display "debug" info
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipLocation )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_LOCATION], pStrInfo, usSoldierGridNo );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipBrightness )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_BRIGHTNESS], pStrInfo, SHADE_MIN - LightTrueLevel( usSoldierGridNo, gsInterfaceLevel ), SHADE_MIN );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipRangeToTarget )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_RANGE_TO_TARGET], pStrInfo, iRangeToTarget );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipID )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ID], pStrInfo, pSoldier->ubID );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipOrders )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ORDERS], pStrInfo, pSoldier->aiData.bOrders );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipAttitude )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ATTITUDE], pStrInfo, pSoldier->aiData.bAttitude );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipActionPoints )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_CURRENT_APS], pStrInfo, pSoldier->bActionPoints );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipHealth )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_CURRENT_HEALTH], pStrInfo, pSoldier->stats.bLife );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipEnergy )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_CURRENT_ENERGY], pStrInfo, pSoldier->bBreath );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipMorale )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_CURRENT_MORALE], pStrInfo, pSoldier->aiData.bMorale );
|
|
//Moa: show shock and suppression values in debug tooltip
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipShock )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_SHOCK], pStrInfo, pSoldier->aiData.bShock );
|
|
// sevenfm: ubSuppressionPoints always show 0 because this value is cleared after each attack
|
|
// changed this to ubLastSuppression - it stores suppression points from last attack
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipSuppressionPoints )
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_SUPPRESION], pStrInfo, pSoldier->ubLastSuppression );
|
|
// sevenfm: show additional suppression info
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipSuppressionInfo )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SUPPRESSION_AP], pStrInfo, pSoldier->ubAPsLostToSuppression );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SUPPRESSION_TOLERANCE], pStrInfo, CalcSuppressionTolerance( pSoldier ) );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_EFFECTIVE_SHOCK], pStrInfo, CalcEffectiveShockLevel( pSoldier ) );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_AI_MORALE], pStrInfo, pSoldier->aiData.bAIMorale );
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Added by SANDRO - show enemy skills
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipTraits )
|
|
{
|
|
if ( gGameOptions.fNewTraitSystem )
|
|
{
|
|
if (( pSoldier->stats.ubSkillTraits[0] == pSoldier->stats.ubSkillTraits[1] ) && pSoldier->stats.ubSkillTraits[0] != 0 )
|
|
{
|
|
CHAR16 pStrAux[50];
|
|
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[0] ]);
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[1] + NEWTRAIT_MERCSKILL_EXPERTOFFSET ] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[2] ] );
|
|
//swprintf( pStrInfo, L"%s\n", pStrInfo );
|
|
}
|
|
else if (( pSoldier->stats.ubSkillTraits[1] == pSoldier->stats.ubSkillTraits[2] ) && pSoldier->stats.ubSkillTraits[1] != 0 )
|
|
{
|
|
CHAR16 pStrAux[50];
|
|
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[1] ]);
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[2] + NEWTRAIT_MERCSKILL_EXPERTOFFSET ] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[0] ] );
|
|
}
|
|
else if (( pSoldier->stats.ubSkillTraits[0] == pSoldier->stats.ubSkillTraits[2] ) && pSoldier->stats.ubSkillTraits[0] != 0 )
|
|
{
|
|
CHAR16 pStrAux[50];
|
|
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[0] ]);
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[2] + NEWTRAIT_MERCSKILL_EXPERTOFFSET ] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[1] ] );
|
|
}
|
|
else
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[0] ] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[1] ] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[ pSoldier->stats.ubSkillTraits[2] ] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, gzMercSkillText[pSoldier->stats.ubSkillTraits[0]] );
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillText[pSoldier->stats.ubSkillTraits[1]] );
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
// armor info code block start
|
|
if ( ubTooltipDetailLevel >= DL_Full )
|
|
{
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipHelmet )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_HELMET], pStrInfo, pSoldier->inv[HELMETPOS].usItem ? ItemNames[ pSoldier->inv[HELMETPOS].usItem ] : gzTooltipStrings[STR_TT_NO_HELMET] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[HELMETPOS].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[HELMETPOS].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipVest )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_VEST], pStrInfo, pSoldier->inv[VESTPOS].usItem ? ItemNames[ pSoldier->inv[VESTPOS].usItem ] : gzTooltipStrings[STR_TT_NO_VEST] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[VESTPOS].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[VESTPOS].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipLeggings )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_LEGGINGS], pStrInfo, pSoldier->inv[LEGPOS].usItem ? ItemNames[ pSoldier->inv[LEGPOS].usItem ] : gzTooltipStrings[STR_TT_NO_LEGGING] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[LEGPOS].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[LEGPOS].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !( !gGameExternalOptions.fEnableSoldierTooltipHelmet &&
|
|
!gGameExternalOptions.fEnableSoldierTooltipVest &&
|
|
!gGameExternalOptions.fEnableSoldierTooltipLeggings) )
|
|
// do not display the armor line if all the armor toggles are set to false
|
|
{
|
|
if ( ArmourPercent( pSoldier ) )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ARMOR] );
|
|
if ( ubTooltipDetailLevel == DL_Basic )
|
|
{
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipHelmet && pSoldier->inv[HELMETPOS].usItem )
|
|
swprintf( pStrInfo, L"%s%s ", pStrInfo, gzTooltipStrings[STR_TT_HELMET] );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipVest && pSoldier->inv[VESTPOS].usItem )
|
|
swprintf( pStrInfo, L"%s%s ", pStrInfo, gzTooltipStrings[STR_TT_VEST] );
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipLeggings && pSoldier->inv[LEGPOS].usItem )
|
|
swprintf( pStrInfo, L"%s%s", pStrInfo, gzTooltipStrings[STR_TT_LEGGINGS] );
|
|
wcscat( pStrInfo, L"\n" );
|
|
}
|
|
else // ubTooltipDetailLevel == DL_Limited
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ARMOR_2], gzTooltipStrings[STR_TT_WORN] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_ARMOR_2], gzTooltipStrings[STR_TT_NO_ARMOR] );
|
|
}
|
|
}
|
|
}
|
|
// armor info code block end
|
|
|
|
// head slots info code block start
|
|
if ( ubTooltipDetailLevel != DL_Debug )
|
|
{
|
|
|
|
if( Item[pSoldier->inv[HEAD1POS].usItem].nightvisionrangebonus > 0 )
|
|
iNVG = HEAD1POS;
|
|
else if( Item[pSoldier->inv[HEAD2POS].usItem].nightvisionrangebonus > 0 )
|
|
iNVG = HEAD2POS;
|
|
|
|
if ( !( !gGameExternalOptions.fEnableSoldierTooltipHeadItem1 &&
|
|
!gGameExternalOptions.fEnableSoldierTooltipHeadItem2) )
|
|
// do not display the NVG/mask lines if both head slot toggles are set to false
|
|
{
|
|
if ( ubTooltipDetailLevel >= DL_Full )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_NVG], pStrInfo,
|
|
iNVG ? ItemNames[ pSoldier->inv[ iNVG ].usItem ] : gzTooltipStrings[STR_TT_NO_NVG] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( iNVG )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[ iNVG ].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
else
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_NVG], pStrInfo, iNVG ? gzTooltipStrings[STR_TT_WORN] : gzTooltipStrings[STR_TT_NO_NVG] );
|
|
}
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_GAS_MASK], pStrInfo,
|
|
( FindGasMask(pSoldier) != NO_SLOT ) ? gzTooltipStrings[STR_TT_WORN] : gzTooltipStrings[STR_TT_NO_MASK] );
|
|
}
|
|
}
|
|
else // gGameExternalOptions.ubSoldierTooltipDetailLevel == DL_Debug
|
|
{
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipHeadItem1 )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_HEAD_POS_1], pStrInfo, ItemNames[ pSoldier->inv[HEAD1POS].usItem ] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[HEAD1POS].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[ HEAD1POS ].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipHeadItem2 )
|
|
{
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_HEAD_POS_2], pStrInfo, ItemNames[ pSoldier->inv[HEAD2POS].usItem ] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[HEAD2POS].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[ HEAD2POS ].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
}
|
|
// head slots info code block end
|
|
|
|
// weapon in primary hand info code block start
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipWeapon )
|
|
{
|
|
DisplayWeaponInfo( pSoldier, pStrInfo, HANDPOS, ubTooltipDetailLevel );
|
|
} // gGameExternalOptions.fEnableSoldierTooltipWeapon
|
|
// weapon in primary hand info code block end
|
|
|
|
// weapon in off hand info code block start
|
|
if ( gGameExternalOptions.fEnableSoldierTooltipSecondHand )
|
|
{
|
|
if ( pSoldier->inv[SECONDHANDPOS].usItem )
|
|
{
|
|
// if there's something in the slot display it
|
|
wcscat( pStrInfo, L"\n" );
|
|
DisplayWeaponInfo( pSoldier, pStrInfo, SECONDHANDPOS, ubTooltipDetailLevel );
|
|
}
|
|
}
|
|
// weapon in off hand info code block end
|
|
|
|
// large objects in big inventory slots info code block start
|
|
for ( UINT8 BigSlot = BIGPOCKSTART; BigSlot < BIGPOCKFINAL; BigSlot++ )
|
|
{
|
|
if ( pSoldier->inv[ BigSlot ].exists() == false )
|
|
continue; // slot is empty, move on to the next slot
|
|
|
|
switch( BigSlot )
|
|
{
|
|
// if display of this big slot is toggled off then move on to the next slot
|
|
case BIGPOCK1POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot1 )
|
|
continue;
|
|
break;
|
|
case BIGPOCK2POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot2 )
|
|
continue;
|
|
break;
|
|
case BIGPOCK3POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot3 )
|
|
continue;
|
|
break;
|
|
case BIGPOCK4POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot4 )
|
|
continue;
|
|
break;
|
|
// CHRISL: Added new large pockets introduced by new inventory system
|
|
case BIGPOCK5POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot5 )
|
|
continue;
|
|
break;
|
|
case BIGPOCK6POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot6 )
|
|
continue;
|
|
break;
|
|
case BIGPOCK7POS:
|
|
if ( !gGameExternalOptions.fEnableSoldierTooltipBigSlot7 )
|
|
continue;
|
|
break;
|
|
}
|
|
|
|
if ( Item[ pSoldier->inv[ BigSlot ].usItem ].rocketlauncher )
|
|
iCarriedRL = pSoldier->inv[ BigSlot ].usItem; // remember that enemy is carrying a rocket launcher when check for rocket ammo is made later on
|
|
|
|
if ( ( Item[ pSoldier->inv[ BigSlot ].usItem ].usItemClass == IC_LAUNCHER ) ||
|
|
( Item[ pSoldier->inv[ BigSlot ].usItem ].usItemClass == IC_GUN ) )
|
|
{
|
|
// it's a firearm
|
|
if ( ( Weapon[pSoldier->inv[ BigSlot ].usItem].ubWeaponClass != HANDGUNCLASS ) &&
|
|
( Weapon[pSoldier->inv[ BigSlot ].usItem].ubWeaponClass != SMGCLASS ) )
|
|
{
|
|
// it's a long gun or heavy weapon
|
|
fDisplayBigSlotItem = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// check for rocket ammo
|
|
if ( ( iCarriedRL != 0 ) && // soldier is carrying a RL ...
|
|
ValidLaunchable( pSoldier->inv[ BigSlot ].usItem, iCarriedRL ) ) // this item is launchable by the RL
|
|
{
|
|
fDisplayBigSlotItem = TRUE;
|
|
}
|
|
}
|
|
if ( fDisplayBigSlotItem )
|
|
{
|
|
wcscat( pStrInfo, gzTooltipStrings[STR_TT_IN_BACKPACK] );
|
|
DisplayWeaponInfo( pSoldier, pStrInfo, BigSlot, ubTooltipDetailLevel );
|
|
fDisplayBigSlotItem = FALSE;
|
|
}
|
|
}
|
|
// large objects in big inventory slots info code block end
|
|
|
|
pRegion->iX = gusMouseXPos;
|
|
pRegion->iY = gusMouseYPos;
|
|
|
|
// if ( gGameExternalOptions.ubSoldierTooltipDetailLevel == DL_Debug )
|
|
// swprintf( pRegion->FastHelpText, L"%s\n|String |Length|: %d", pStrInfo, wcslen(pStrInfo) );
|
|
// else
|
|
wcscpy( pRegion->FastHelpText, pStrInfo );
|
|
}
|
|
|
|
if ( gfKeyState[ ALT ] && fDrawTooltip )
|
|
{
|
|
DrawMouseTooltip();
|
|
SetRenderFlags( RENDER_FLAG_FULL );
|
|
}
|
|
} // SoldierTooltip(SOLDIERTYPE* pSoldier)
|
|
|
|
|
|
void DisplayWeaponInfo( SOLDIERTYPE* pSoldier, CHAR16* pStrInfo, UINT8 ubSlot, UINT8 ubTooltipDetailLevel )
|
|
{
|
|
INT32 iNumAttachments = 0;
|
|
BOOLEAN fDisplayAttachment = FALSE;
|
|
|
|
if ( ubTooltipDetailLevel >= DL_Full )
|
|
{
|
|
// display exact weapon model
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo,
|
|
WeaponInHand( pSoldier ) ? ItemNames[ pSoldier->inv[ubSlot].usItem ] : gzTooltipStrings[STR_TT_NO_WEAPON] );
|
|
//Moa: encyclopedia item visibility
|
|
if ( pSoldier->inv[ubSlot].usItem )
|
|
EncyclopediaSetItemAsVisible( pSoldier->inv[ ubSlot ].usItem, ENC_ITEM_DISCOVERED_NOT_REACHABLE );
|
|
}
|
|
else
|
|
{
|
|
if ( ubTooltipDetailLevel == DL_Limited )
|
|
{
|
|
// display general weapon class
|
|
switch( Weapon[pSoldier->inv[ubSlot].usItem].ubWeaponClass )
|
|
{
|
|
case HANDGUNCLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_HANDGUN] );
|
|
break;
|
|
case SMGCLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_SMG] );
|
|
break;
|
|
case RIFLECLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_RIFLE] );
|
|
break;
|
|
case MGCLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_MG] );
|
|
break;
|
|
case SHOTGUNCLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_SHOTGUN] );
|
|
break;
|
|
case KNIFECLASS:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_KNIFE] );
|
|
break;
|
|
default:
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo, gzTooltipStrings[STR_TT_HEAVY_WEAPON] );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// display general weapon type
|
|
swprintf( pStrInfo, gzTooltipStrings[STR_TT_CAT_WEAPON], pStrInfo,
|
|
WeaponInHand( pSoldier) ? WeaponType[Weapon[pSoldier->inv[ubSlot].usItem].ubWeaponType] : gzTooltipStrings[STR_TT_NO_WEAPON] );
|
|
}
|
|
}
|
|
|
|
if ( gGameExternalOptions.ubSoldierTooltipDetailLevel >= DL_Basic )
|
|
{
|
|
// display weapon attachments
|
|
for (attachmentList::iterator iter = pSoldier->inv[ubSlot][0]->attachments.begin(); iter != pSoldier->inv[ubSlot][0]->attachments.end(); ++iter) {
|
|
if(iter->exists()){
|
|
fDisplayAttachment = FALSE; //Madd: changed this, it was incorrectly showing attachments when it shouldn't be
|
|
|
|
if ( ubTooltipDetailLevel == DL_Basic || ubTooltipDetailLevel == DL_Full ) // Madd: also hidden attachments should be hidden at the full level as well... unless the mercs have x-ray vision to see that rod&spring inside the gun!! :p
|
|
{
|
|
// display only externally-visible weapon attachments
|
|
if ( Item[iter->usItem].hiddenattachment )
|
|
fDisplayAttachment = FALSE;
|
|
else
|
|
fDisplayAttachment = TRUE;
|
|
}
|
|
|
|
if ( fDisplayAttachment )
|
|
{
|
|
iNumAttachments++;
|
|
if ( iNumAttachments == 1 )
|
|
wcscat( pStrInfo, L"\n[" );
|
|
else
|
|
wcscat( pStrInfo, L", " );
|
|
wcscat( pStrInfo, ItemNames[ iter->usItem ] );
|
|
}
|
|
}
|
|
} // for
|
|
if ( iNumAttachments > 0 )
|
|
wcscat( pStrInfo, pMessageStrings[ MSG_END_ATTACHMENT_LIST ] ); // append ' attached]' to end of string
|
|
} // gGameExternalOptions.ubSoldierTooltipDetailLevel >= DL_Basic
|
|
}
|
|
|
|
MOUSETT mouseTT;
|
|
BOOL mouseTTrender, mouseTTdone;
|
|
|
|
void DrawMouseTooltip()
|
|
{
|
|
UINT8 *pDestBuf;
|
|
UINT32 uiDestPitchBYTES;
|
|
static INT32 iX, iY, iW, iH;
|
|
|
|
extern INT16 GetWidthOfString(const STR16);
|
|
extern INT16 GetNumberOfLinesInHeight(const STR16);
|
|
extern void DisplayHelpTokenizedString(const STR16,INT16,INT16);
|
|
extern BOOLEAN initTooltipBuffer();
|
|
extern PTR LockTooltipBuffer(UINT32*);
|
|
extern void UnlockTooltipBuffer();
|
|
extern void DisplayTooltipString( const STR16 pStringA, INT16 sX, INT16 sY );
|
|
extern void j_log(PTR,...);
|
|
|
|
iX = mouseTT.iX;iY = mouseTT.iY;
|
|
iW = (INT32)GetWidthOfString( mouseTT.FastHelpText ) + 10;
|
|
iH = (INT32)( GetNumberOfLinesInHeight( mouseTT.FastHelpText ) * (GetFontHeight(FONT10ARIAL)+1) + 8 );
|
|
|
|
if(1)//draw at cursor
|
|
{
|
|
iY -= (iH / 2);
|
|
if (gusMouseXPos > (SCREEN_WIDTH / 2))
|
|
iX = gusMouseXPos - iW - 24;
|
|
else
|
|
iX = gusMouseXPos + 24;
|
|
//if (gusMouseYPos > (SCREEN_HEIGHT / 2))
|
|
// iY -= 32;
|
|
|
|
if (iY <= 0) iY += 32;
|
|
}
|
|
else
|
|
{ //draw in panel
|
|
//502,485 658,596 160*110 580,540
|
|
iX = 580 - (iW / 2);
|
|
iY = 540 - (iH/2);
|
|
if (iY + iH > SCREEN_HEIGHT) iY = SCREEN_HEIGHT - iH - 3 ;
|
|
}
|
|
|
|
pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
|
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf );
|
|
RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf );
|
|
UnLockVideoSurface( FRAME_BUFFER );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 );
|
|
|
|
SetFont( FONT10ARIAL );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
DisplayHelpTokenizedString( mouseTT.FastHelpText ,( INT16 )( iX + 5 ), ( INT16 )( iY + 5 ) );
|
|
InvalidateRegion( iX, iY, (iX + iW) , (iY + iH) );
|
|
|
|
//InvalidateScreen();
|
|
} |