Bugfix: Feature Swap merc faces

When swapping merc faces in tactical the game will now rebuild the mercs squad.

Changed NCTH behaviour for lasers: 

When USE_NEW_CTH_CALCULATION = TRUE in Ja2_Options.ini the game now uses the item property <BestLaserRange> now for a laser specific bonus instead of <ProjectionFactor>. This bonus is a percentage reduction of the base aperture in NCTH. This functionality will only be used if one of the following new parameters in CTHConstants.ini is NOT 0.

LASER_PERFORMANCE_BONUS_HIP
LASER_PERFORMANCE_BONUS_IRON
LASER_PERFORMANCE_BONUS_SCOPE

This functionality also affects the laser property that is displayed in UDB.

Changed NCTH behaviour for Iron Sights and other 1x sights:

Iron sights and other 1x sights can now receive a bonus in NCTH to make them more useful compared to scopes. This bonus is a percentage reduction of the base aperture just like lasers can do.
There is a new parameter in CTHConstants.ini for this:

IRON_SIGHT_PERFORMANCE_BONUS


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6370 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
silversurfer
2013-09-07 12:10:45 +00:00
parent 98f9831057
commit 4808850814
20 changed files with 295 additions and 67 deletions
+1
View File
@@ -229,6 +229,7 @@ typedef struct
UINT8 MuzzleSwayPercentage;
FLOAT ScopeMagFactor;
FLOAT ProjectionFactor;
INT16 iBestLaserRange;
FLOAT FinalMagFactor;
INT32 iShooterGridNo;
INT32 iTargetGridNo;
+79 -16
View File
@@ -1605,8 +1605,11 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
/////////////////// PROJECTION FACTOR
if (UsingNewCTHSystem() == true &&
(Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) )
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we still need the mouse region
if (UsingNewCTHSystem() == true &&
( (Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) ||
( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
ubRegionOffset = 6;
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] );
@@ -2957,7 +2960,29 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
///////////////////// PROJECTION FACTOR
if (GetProjectionFactor( gpItemDescObject ) > 1.0 )
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
if ( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
if( UsingNewCTHSystem() == true )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
if (Item[ gpItemDescObject->usItem ].usItemClass & (IC_WEAPON|IC_PUNCH))
{
swprintf( pStr, L"%s%s", szUDBAdvStatsTooltipText[ 64 ], szUDBAdvStatsExplanationsTooltipTextForWeapons[ 14 ]);
}
else
{
swprintf( pStr, L"%s%s", szUDBAdvStatsTooltipText[ 64 ], szUDBAdvStatsExplanationsTooltipText[ 14 ]);
}
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + (cnt-sFirstLine) ] );
}
cnt++;
}
}
else if (GetProjectionFactor( gpItemDescObject ) > 1.0 )
{
if( UsingNewCTHSystem() == true )
{
@@ -4100,8 +4125,11 @@ void DrawWeaponStats( OBJECTTYPE * gpItemDescObject )
}
//////////////////// PROJECTION FACTOR
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we use the same icon
if (UsingNewCTHSystem() == true &&
(Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) )
( (Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) ||
( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
ubNumLine = 6;
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWeaponIcon, 14, gItemDescGenRegions[ubNumLine][0].sLeft+sOffsetX, gItemDescGenRegions[ubNumLine][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
@@ -4819,8 +4847,11 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
}
///////////////////// PROJECTION FACTOR
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor but we use the same icon
if (cnt-sFirstLine < sLastLine &&
GetProjectionFactor( gpItemDescObject ) > 1.0 )
( GetProjectionFactor( gpItemDescObject ) > 1.0 ||
( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
if( UsingNewCTHSystem() == true )
{
@@ -6267,21 +6298,40 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
}
///////////////// (LASER) PROJECTION FACTOR
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
if (UsingNewCTHSystem() == true &&
(Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) )
( (Item[gpItemDescObject->usItem].projectionfactor > 1.0 || GetProjectionFactor( gpItemDescObject ) > 1.0) ||
( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) ) ) )
{
// Set line to draw into
ubNumLine = 6;
// Set Y coordinates
sTop = gItemDescGenRegions[ubNumLine][1].sTop;
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
FLOAT iProjectionValue = 0;
FLOAT iProjectionModifier = 0;
FLOAT iFinalProjectionValue = 0;
// Get base Projection value
FLOAT iProjectionValue = __max(1.0f, Item[ gpItemDescObject->usItem ].projectionfactor);
// Get best Projection value
FLOAT iProjectionModifier = GetProjectionFactor( gpItemDescObject );
// Get final Projection value
FLOAT iFinalProjectionValue = __max( iProjectionValue, iProjectionModifier );
if ( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
// Get base laser range
iProjectionValue = __max(1.0f, Item[ gpItemDescObject->usItem ].bestlaserrange / CELL_X_SIZE);
// Get best laser range
iProjectionModifier = ((FLOAT)GetBestLaserRange( gpItemDescObject ) / CELL_X_SIZE);
// Get final laser range
iFinalProjectionValue = __max( iProjectionValue, iProjectionModifier );
}
else
{
// Get base Projection value
iProjectionValue = __max(1.0f, Item[ gpItemDescObject->usItem ].projectionfactor);
// Get best Projection value
iProjectionModifier = GetProjectionFactor( gpItemDescObject );
// Get final Projection value
iFinalProjectionValue = __max( iProjectionValue, iProjectionModifier );
}
// Print base value
SetFontForeground( 5 );
@@ -9490,11 +9540,21 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
cnt++;
}
BOOLEAN bNewCode = FALSE;
///////////////////// PROJECTION FACTOR
iFloatModifier[0] = GetProjectionFactor( gpItemDescObject );
// with the reworked NCTH code and the laser performance factor we will display BestLaserRange instead of ProjectionFactor
if ( gGameExternalOptions.fUseNewCTHCalculation && GetBestLaserRange( gpItemDescObject ) > 0
&& (gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
iFloatModifier[0] = ((FLOAT)GetBestLaserRange( gpItemDescObject ) / CELL_X_SIZE);
bNewCode = TRUE;
}
else
iFloatModifier[0] = GetProjectionFactor( gpItemDescObject );
iFloatModifier[1] = iFloatModifier[0];
iFloatModifier[2] = iFloatModifier[0];
if (iFloatModifier[0] > 1.0 && UsingNewCTHSystem() == true )
if ( UsingNewCTHSystem() == true && (iFloatModifier[0] > 1.0 || bNewCode) )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -9508,10 +9568,13 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
if (iFloatModifier[cnt2] > 1.0)
if (iFloatModifier[cnt2] > 1.0 || bNewCode)
{
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"%3.1fx", iFloatModifier[cnt2] );
if ( bNewCode )
swprintf( pStr, L"%3.0f", iFloatModifier[cnt2] );
else
swprintf( pStr, L"%3.1fx", iFloatModifier[cnt2] );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else
+97 -34
View File
@@ -61,6 +61,7 @@
// HEADROCK HAM 4: Included for new CTH indicator
#include "weapons.h"
#include "Map Screen Interface.h" // added by Flugente for SquadNames
#include "environment.h"
#endif
@@ -2273,11 +2274,11 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
if ( zEnemyRank[iCounter2].Stats == 0 && pSoldier->stats.bExpLevel == zEnemyRank[iCounter2].ExpLevel )
{
swprintf(NameStr, zEnemyRank[iCounter2].szCurRank);
SetFont( TINYFONT1 );
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( FONT_YELLOW );
// need to adjust sYPos because default position already occupied by the name
if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile || gGameExternalOptions.fEnemyNames )
FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 10 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY );
@@ -2451,6 +2452,54 @@ BOOLEAN DrawCTHIndicator()
// Calculate the size of a "normal" aperture. This is how wide a shot can go at 1x Normal Distance.
FLOAT iBasicAperture = (FLOAT)((sin(ddMaxAngleRadians) * gGameCTHConstants.NORMAL_SHOOTING_DISTANCE) * 2); // The *2 compensates for the difference between CellXY and ScreenXY
// when using the reworked NCTH code we do additional calculations for iron sights and lasers
if (gGameExternalOptions.fUseNewCTHCalculation)
{
// iron sights can get a percentage bonus to make them overall better but only when not shooting from hip
if ( gCTHDisplay.ScopeMagFactor <= 1.0 && !pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
iBasicAperture = iBasicAperture * (FLOAT)( (100 - gGameCTHConstants.IRON_SIGHT_PERFORMANCE_BONUS) / 100);
// laser pointers can provide a percentage bonus to base aperture
if ( gCTHDisplay.iBestLaserRange > 0
&& ( gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
INT8 bLightLevel = LightTrueLevel(gCTHDisplay.iTargetGridNo, gsInterfaceLevel );
INT32 iMaxLaserRange = ( gCTHDisplay.iBestLaserRange*( 2*bLightLevel + 3*NORMAL_LIGHTLEVEL_NIGHT - 5*NORMAL_LIGHTLEVEL_DAY ) ) / ( 2 * ( NORMAL_LIGHTLEVEL_NIGHT - NORMAL_LIGHTLEVEL_DAY ) );
// laser only has effect when in range
if ( iMaxLaserRange > d2DDistance )
{
FLOAT fLaserBonus = 0;
// which bonus do we want to apply?
if ( pSoldier->IsValidAlternativeFireMode( pSoldier->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
// shooting from hip
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP;
else if ( gCTHDisplay.ScopeMagFactor <= 1.0 )
// using iron sights or other 1x sights
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON;
else
// must be using a scope
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE;
// light level influences how easy it is to spot the laser dot on the target
FLOAT fBrightnessModifier = 1.0 - ( (FLOAT)(bLightLevel - SHADE_MAX) / (FLOAT)(SHADE_MIN - SHADE_MAX) );
// laser fully efficient
if ( gCTHDisplay.iBestLaserRange > d2DDistance )
// apply full bonus
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier)) / 100);
else
{
// beyond BestLaserRange laser bonus drops linearly to 0
FLOAT fEffectiveLaserRatio = (FLOAT)(iMaxLaserRange - d2DDistance) / (FLOAT)(iMaxLaserRange - gCTHDisplay.iBestLaserRange);
// apply partial bonus
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier * fEffectiveLaserRatio)) / 100);
}
}
}
}
// Calculate the Maximum Aperture. This is the margin of error for the "worst" shot we can have given the
// target's actual distance. This will later be used to draw the Outer Circle around the target.
FLOAT iMaxAperture = iBasicAperture * iDistanceRatio;
@@ -3152,18 +3201,18 @@ BOOLEAN DrawCTHIndicator()
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
// Draw a border circle which is 1 point wider
curX = (INT16)((iMaxAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curX = (INT16)((iMaxAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curY = (INT16)(((iMaxAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// if (curX != firstX || curY != firstY)
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// Draw a border circle which is 1 point narrower
curX = (INT16)((iMaxAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curX = (INT16)((iMaxAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curY = (INT16)(((iMaxAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// if (curX != firstX || curY != firstY)
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
Circ = (INT32)((iAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
@@ -3178,18 +3227,18 @@ BOOLEAN DrawCTHIndicator()
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
// Draw a border circle which is 1 point wider
curX = (INT16)((iAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curX = (INT16)((iAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curY = (INT16)(((iAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// if (curX != firstX || curY != firstY)
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// Draw a border circle which is 1 point narrower
curX = (INT16)((iAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curX = (INT16)((iAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// curY = (INT16)(((iAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// if (curX != firstX || curY != firstY)
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
// Aperture Crosshairs
@@ -3199,18 +3248,25 @@ BOOLEAN DrawCTHIndicator()
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBorder );
}
for (INT16 cnt = (INT16)(iAperture * dVerticalBias); cnt <= (INT16)((iAperture * dVerticalBias) + uiApertureBarLength); cnt++)
@@ -3219,18 +3275,25 @@ BOOLEAN DrawCTHIndicator()
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
}
}
+24 -4
View File
@@ -3128,7 +3128,7 @@ UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier )
{
ubStrengthForCarrying = (ubStrengthForCarrying * (100 + gSkillTraitValues.ubBBCarryWeightBonus) / 100); // plus one third
}
ubStrengthForCarrying = (ubStrengthForCarrying * (100 + pSoldier->GetBackgroundValue(BG_PERC_CARRYSTRENGTH)) / 100);
// for now, assume soldiers can carry 1/2 their strength in KGs without penalty.
@@ -9406,7 +9406,7 @@ BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs
pSoldier->bSoldierFlagMask |= SOLDIER_COVERT_SOLDIER;
if ( pSoldier->bTeam == OUR_TEAM )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_DISGUISED_AS_SOLDIER], pSoldier->GetName() );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_DISGUISED_AS_SOLDIER], pSoldier->GetName() );
break;
}
@@ -9418,7 +9418,7 @@ BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs
pSoldier->bSoldierFlagMask |= SOLDIER_COVERT_CIV;
if ( pSoldier->bTeam == OUR_TEAM )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_DISGUISED_AS_CIVILIAN], pSoldier->GetName() );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_DISGUISED_AS_CIVILIAN], pSoldier->GetName() );
}
// reevaluate sight - otherwise we could hide by changing clothes in plain sight!
@@ -13353,7 +13353,7 @@ INT16 GetWornStealth( SOLDIERTYPE * pSoldier )
// Add some default stealth ability to mercs with STEALTHY trait - SANDRO
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, STEALTHY_NT ))
ttl += gSkillTraitValues.ubSTStealthBonus;
ttl += gSkillTraitValues.ubSTStealthBonus;
ttl += pSoldier->GetBackgroundValue(BG_PERC_STEALTH);
@@ -13499,6 +13499,26 @@ INT16 GetAverageBestLaserRange( OBJECTTYPE * pObj )
return( bonus );
}
// get the best laser range from the weapon and attachments
INT16 GetBestLaserRange( OBJECTTYPE * pObj )
{
INT16 range=0;
if (Item[pObj->usItem].bestlaserrange > 0)
{
range = Item[pObj->usItem].bestlaserrange;
}
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (Item[iter->usItem].bestlaserrange > range && iter->exists())
{
range = Item[iter->usItem].bestlaserrange;
}
}
return( range );
}
// HEADROCK: This function determines the bipod bonii of the gun or its attachments
INT16 GetBipodBonus( OBJECTTYPE * pObj )
{
+2
View File
@@ -253,6 +253,8 @@ INT16 GetToHitBonus( OBJECTTYPE * pObj, INT32 iRange, UINT8 bLightLevel, BOOLEAN
INT16 GetFlatToHitBonus( OBJECTTYPE * pObj );
// HEADROCK: Function to get average of best laser ranges from weapon and attachments
INT16 GetAverageBestLaserRange( OBJECTTYPE * pObj );
// get the best laser range from the weapon and attachments
INT16 GetBestLaserRange( OBJECTTYPE * pObj );
// HEADROCK: Function to get bipod bonus from weapon and its attachments
INT16 GetBipodBonus( OBJECTTYPE * pObj );
INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
+49 -1
View File
@@ -7530,7 +7530,55 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
// First, let's calculate the basic Aperture. This is the size of an unmodified aperture at 1x Normal Distance.
iBasicAperture = CalcBasicAperture( );
// when using the reworked NCTH code we do additional calculations for iron sights and lasers
if (gGameExternalOptions.fUseNewCTHCalculation)
{
// iron sights can get a percentage bonus to make them overall better but only when not shooting from hip
if ( gCTHDisplay.ScopeMagFactor <= 1.0 && !pShooter->IsValidAlternativeFireMode( pShooter->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
iBasicAperture = iBasicAperture * (FLOAT)( (100 - gGameCTHConstants.IRON_SIGHT_PERFORMANCE_BONUS) / 100);
// laser pointers can provide a percentage bonus to base aperture
if ( gCTHDisplay.iBestLaserRange > 0
&& ( gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0) )
{
INT8 bLightLevel = LightTrueLevel(gCTHDisplay.iTargetGridNo, gsInterfaceLevel );
INT32 iMaxLaserRange = ( gCTHDisplay.iBestLaserRange*( 2*bLightLevel + 3*NORMAL_LIGHTLEVEL_NIGHT - 5*NORMAL_LIGHTLEVEL_DAY ) ) / ( 2 * ( NORMAL_LIGHTLEVEL_NIGHT - NORMAL_LIGHTLEVEL_DAY ) );
// laser only has effect when in range
if ( iMaxLaserRange > d2DDistance )
{
FLOAT fLaserBonus = 0;
// which bonus do we want to apply?
if ( pShooter->IsValidAlternativeFireMode( pShooter->aiData.bAimTime, gCTHDisplay.iTargetGridNo ) )
// shooting from hip
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP;
else if ( gCTHDisplay.ScopeMagFactor <= 1.0 )
// using iron sights or other 1x sights
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON;
else
// must be using a scope
fLaserBonus = gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE;
// light level influences how easy it is to spot the laser dot on the target
FLOAT fBrightnessModifier = 1.0 - ( (FLOAT)(bLightLevel - SHADE_MAX) / (FLOAT)(SHADE_MIN - SHADE_MAX) );
// laser fully efficient
if ( gCTHDisplay.iBestLaserRange > d2DDistance )
// apply full bonus
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier)) / 100);
else
{
// beyond BestLaserRange laser bonus drops linearly to 0
FLOAT fEffectiveLaserRatio = (FLOAT)(iMaxLaserRange - d2DDistance) / (FLOAT)(iMaxLaserRange - gCTHDisplay.iBestLaserRange);
// apply partial bonus
iBasicAperture = iBasicAperture * (FLOAT)( (100 - (fLaserBonus * fBrightnessModifier * fEffectiveLaserRatio)) / 100);
}
}
}
}
// Next, find out how large the aperture can be around the target, given range. The further the target is, the
// larger the aperture can be.
iDistanceAperture = iBasicAperture * (d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
+2
View File
@@ -7222,6 +7222,8 @@ void SwapMercPortraits ( SOLDIERTYPE *pSoldier, INT8 bDirection )
RemovePlayerFromGroup( ubGroupID, MercPtrs[ ubTargetMerc ] );
AddPlayerToGroup( ubGroupID, MercPtrs[ ubSourceMerc ] );
AddPlayerToGroup( ubGroupID, MercPtrs[ ubTargetMerc ] );
SortSquadByID( MercPtrs[ ubSourceMerc ]->bAssignment );
RebuildCurrentSquad( );
// don't forget to renew selection of merc
gusSelectedSoldier = ubTargetMerc;
+21 -9
View File
@@ -5188,11 +5188,11 @@ if (gGameExternalOptions.fUseNewCTHCalculation)
// apply bonus from traits
// Flugente: moved trait modifiers into a member function
UINT8 targetprofile = NOBODY;
if ( pTarget && pTarget->ubProfile != NOBODY )
targetprofile = pTarget->ubProfile;
UINT8 targetprofile = NOBODY;
if ( pTarget && pTarget->ubProfile != NOBODY )
targetprofile = pTarget->ubProfile;
fAimModifier += pSoldier->GetTraitCTHModifier( usInHand, ubAimTime, targetprofile );
fAimModifier += pSoldier->GetTraitCTHModifier( usInHand, ubAimTime, targetprofile );
// Flugente: backgrounds
if ( pTarget && pTarget->bTeam == CREATURE_TEAM )
@@ -6098,8 +6098,8 @@ else
iChance = __max(iChance + (INT32)iAimPoints, iChance);
iChance = __min(iChance, (INT32)uiCap);
}
// Impose global limits.
// Impose global limits.
// Flugente: backgrounds
iChance = min(iChance, min(100, gGameExternalOptions.ubMaximumCTH + (UINT8)(pSoldier->GetBackgroundValue(BG_PERC_CTH_MAX))) );
iChance = __max(iChance, gGameExternalOptions.ubMinimumCTH);
@@ -6941,7 +6941,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
targetprofile = pTarget->ubProfile;
iChance += pSoldier->GetTraitCTHModifier( usInHand, ubAimTime, targetprofile );
// Flugente: backgrounds
if ( pTarget && pTarget->bTeam == CREATURE_TEAM )
iChance += pSoldier->GetBackgroundValue(BG_PERC_CTH_CREATURE);
@@ -10297,7 +10297,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
else if ( bNumMercs > 0 )
iAttRating += 2;
}
}
}
// Flugente: backgrounds
if (ubMode == HTH_MODE_STAB)
@@ -11898,10 +11898,21 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
gCTHDisplay.ScopeMagFactor = iScopeFactor;
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// With the reworked NCTH code we don't want to use iProjectionFactor anymore.
// Instead we use the performance bonus if at least one bonus is != 0. Otherwise -> continue using Projection Factor.
if (gGameExternalOptions.fUseNewCTHCalculation
&& ( gGameCTHConstants.LASER_PERFORMANCE_BONUS_HIP + gGameCTHConstants.LASER_PERFORMANCE_BONUS_IRON + gGameCTHConstants.LASER_PERFORMANCE_BONUS_SCOPE != 0 ))
iProjectionFactor = 1.0;
else
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// Set a display variable
gCTHDisplay.ProjectionFactor = iProjectionFactor;
// Set a display variable
gCTHDisplay.iBestLaserRange = GetBestLaserRange( pWeapon );
// The final factor is the largest of the two.
iHighestMagFactor = __max( iScopeFactor, iProjectionFactor );
}
@@ -11909,6 +11920,7 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
{
gCTHDisplay.ScopeMagFactor = 1.0;
gCTHDisplay.ProjectionFactor = 1.0;
gCTHDisplay.iBestLaserRange = GetBestLaserRange( pWeapon );
iHighestMagFactor = 1.0;
}