mirror of
https://github.com/1dot13/source.git
synced 2026-09-09 14:46:05 +02:00
- updated NCTH targeting optics in Interface.cpp to use the same order and formulas as LOS.cpp. It's easier to read and compare this way.
- added scope effectiveness which defines the maximum magnification bonus a shooter can get using scopes. With the default settings a poor shooter like Juan will not benefit much from scopes while a good shooter will use the full potential. See also: http://www.ja-galaxy-forum.com/board/ubbthreads.php/topics/330194/Re:_Cth/INI_Settings_for_new_s.html#Post330194 http://www.ja-galaxy-forum.com/board/ubbthreads.php/topics/330236/Re:_Cth/INI_Settings_for_new_s.html#Post330236 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6870 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3161,6 +3161,11 @@ void LoadCTHConstants()
|
|||||||
gGameCTHConstants.GRAVITY_COEFFICIENT = iniReader.ReadFloat("General", "GRAVITY_COEFFICIENT", 1.0, 0.001f, 100.0);
|
gGameCTHConstants.GRAVITY_COEFFICIENT = iniReader.ReadFloat("General", "GRAVITY_COEFFICIENT", 1.0, 0.001f, 100.0);
|
||||||
gGameCTHConstants.VERTICAL_BIAS = iniReader.ReadFloat("General", "VERTICAL_BIAS", 1.0f, 0.01f, 2.0f);
|
gGameCTHConstants.VERTICAL_BIAS = iniReader.ReadFloat("General", "VERTICAL_BIAS", 1.0f, 0.01f, 2.0f);
|
||||||
gGameCTHConstants.SCOPE_RANGE_MULTIPLIER = iniReader.ReadFloat("General", "SCOPE_RANGE_MULTIPLIER", 0.7f, 0.5f, 1.5f);
|
gGameCTHConstants.SCOPE_RANGE_MULTIPLIER = iniReader.ReadFloat("General", "SCOPE_RANGE_MULTIPLIER", 0.7f, 0.5f, 1.5f);
|
||||||
|
gGameCTHConstants.SCOPE_EFFECTIVENESS_MULTIPLIER = iniReader.ReadFloat("General", "SCOPE_EFFECTIVENESS_MULTIPLIER", 1.1f, 0.5f, 1.5f);
|
||||||
|
gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM = iniReader.ReadInteger("General", "SCOPE_EFFECTIVENESS_MINIMUM", 50, 0, 100);
|
||||||
|
gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_RANGER = iniReader.ReadInteger("General", "SCOPE_EFFECTIVENESS_MINIMUM_RANGER", 80, 0, 100);
|
||||||
|
gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_MARKSMAN = iniReader.ReadInteger("General", "SCOPE_EFFECTIVENESS_MINIMUM_MARKSMAN", 90, 0, 100);
|
||||||
|
gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_SNIPER = iniReader.ReadInteger("General", "SCOPE_EFFECTIVENESS_MINIMUM_SNIPER", 100, 0, 100);
|
||||||
gGameCTHConstants.SIDE_FACING_DIVISOR = iniReader.ReadFloat("General", "SIDE_FACING_DIVISOR", 2.0, 1.0f, 10.0f);
|
gGameCTHConstants.SIDE_FACING_DIVISOR = iniReader.ReadFloat("General", "SIDE_FACING_DIVISOR", 2.0, 1.0f, 10.0f);
|
||||||
// HEADROCK HAM 5: Basic chance to lose condition point when firing
|
// HEADROCK HAM 5: Basic chance to lose condition point when firing
|
||||||
gGameCTHConstants.BASIC_RELIABILITY_ODDS = iniReader.ReadInteger("General", "BASIC_RELIABILITY_ODDS", 15, 0, 100);
|
gGameCTHConstants.BASIC_RELIABILITY_ODDS = iniReader.ReadInteger("General", "BASIC_RELIABILITY_ODDS", 15, 0, 100);
|
||||||
|
|||||||
@@ -1815,6 +1815,11 @@ typedef struct
|
|||||||
FLOAT GRAVITY_COEFFICIENT; // Changes the way gravity works in the game. Higher values mean bullets don't drop as quickly after reaching max range.
|
FLOAT GRAVITY_COEFFICIENT; // Changes the way gravity works in the game. Higher values mean bullets don't drop as quickly after reaching max range.
|
||||||
FLOAT VERTICAL_BIAS; // This float can be used to reduce the chance of missing too far upwards or downwards (compared to left/right).
|
FLOAT VERTICAL_BIAS; // This float can be used to reduce the chance of missing too far upwards or downwards (compared to left/right).
|
||||||
FLOAT SCOPE_RANGE_MULTIPLIER; // Adjusts the minimum effective range of scopes
|
FLOAT SCOPE_RANGE_MULTIPLIER; // Adjusts the minimum effective range of scopes
|
||||||
|
FLOAT SCOPE_EFFECTIVENESS_MULTIPLIER; // This modifies the maximum effective magnification that is applied to the shooting aperture.
|
||||||
|
UINT16 SCOPE_EFFECTIVENESS_MINIMUM; // Defines a minimum effectiveness level that every shooter gets. 0 = fully dynamic, no minimum, 100 = no skills required to use scopes
|
||||||
|
UINT16 SCOPE_EFFECTIVENESS_MINIMUM_RANGER; // the minimum effectiveness for the ranger. He can reach more using the normal formula.
|
||||||
|
UINT16 SCOPE_EFFECTIVENESS_MINIMUM_MARKSMAN; // the minimum effectiveness for the marksman. He can reach more using the normal formula.
|
||||||
|
UINT16 SCOPE_EFFECTIVENESS_MINIMUM_SNIPER; // the minimum effectiveness for the sniper. He can reach more using the normal formula.
|
||||||
FLOAT SIDE_FACING_DIVISOR; // Deals with a visual error in NCTH relating to shooting at a target who is facing directly perpendicular to the shooters facing.
|
FLOAT SIDE_FACING_DIVISOR; // Deals with a visual error in NCTH relating to shooting at a target who is facing directly perpendicular to the shooters facing.
|
||||||
UINT16 BASIC_RELIABILITY_ODDS; // Determines the base chance to lose one condition point when firing a gun.
|
UINT16 BASIC_RELIABILITY_ODDS; // Determines the base chance to lose one condition point when firing a gun.
|
||||||
|
|
||||||
|
|||||||
+40
-28
@@ -297,6 +297,8 @@ UINT32 CalcUIMessageDuration( STR16 wString );
|
|||||||
// sevenfm: this function is needed to show cover in health bar
|
// sevenfm: this function is needed to show cover in health bar
|
||||||
extern void CalculateCoverForSoldier( SOLDIERTYPE* pForSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover );
|
extern void CalculateCoverForSoldier( SOLDIERTYPE* pForSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover );
|
||||||
|
|
||||||
|
extern FLOAT Distance2D( FLOAT dDeltaX, FLOAT dDeltaY );
|
||||||
|
|
||||||
BOOLEAN InitializeFaceGearGraphics()
|
BOOLEAN InitializeFaceGearGraphics()
|
||||||
{
|
{
|
||||||
VOBJECT_DESC VObjectDesc;
|
VOBJECT_DESC VObjectDesc;
|
||||||
@@ -2693,6 +2695,8 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
SOLDIERTYPE *pSoldier;
|
SOLDIERTYPE *pSoldier;
|
||||||
GetSoldier( &pSoldier, gusSelectedSoldier );
|
GetSoldier( &pSoldier, gusSelectedSoldier );
|
||||||
|
|
||||||
|
OBJECTTYPE* pWeapon = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
|
||||||
|
|
||||||
// Create a Background Rect for us to draw our indicator on. With NCTH, the size and position of this rectangle
|
// Create a Background Rect for us to draw our indicator on. With NCTH, the size and position of this rectangle
|
||||||
// is equal exactly to the size of the tactical screen viewport. Unlike the OCTH indicator, the NCTH one can grow
|
// is equal exactly to the size of the tactical screen viewport. Unlike the OCTH indicator, the NCTH one can grow
|
||||||
// so large as to fill the entire screen.
|
// so large as to fill the entire screen.
|
||||||
@@ -2755,7 +2759,7 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
FLOAT dDeltaY = dEndY - dStartY;
|
FLOAT dDeltaY = dEndY - dStartY;
|
||||||
|
|
||||||
// Calculate the distance of the shot, using Pythagorean Theorem
|
// Calculate the distance of the shot, using Pythagorean Theorem
|
||||||
DOUBLE d2DDistance = sqrt( (DOUBLE) (dDeltaX * dDeltaX + dDeltaY * dDeltaY ));
|
DOUBLE d2DDistance = Distance2D( dDeltaX, dDeltaY );
|
||||||
// Round it upwards.
|
// Round it upwards.
|
||||||
INT32 iDistance = (INT32) d2DDistance;
|
INT32 iDistance = (INT32) d2DDistance;
|
||||||
if ( d2DDistance != iDistance )
|
if ( d2DDistance != iDistance )
|
||||||
@@ -2764,11 +2768,6 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
d2DDistance = (FLOAT) ( iDistance);
|
d2DDistance = (FLOAT) ( iDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the Distance Ratio. This will increase or decrease the size of the Shooting Aperture based
|
|
||||||
// on both distance and Magnification Factor.
|
|
||||||
FLOAT iDistanceRatio = (FLOAT)(d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
|
||||||
FLOAT iFinalRatio = iDistanceRatio / gCTHDisplay.FinalMagFactor;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Now we calculate the Aperture size. This is done using the same method as the shooting formula uses.
|
// Now we calculate the Aperture size. This is done using the same method as the shooting formula uses.
|
||||||
|
|
||||||
@@ -2826,22 +2825,35 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the Maximum Aperture. This is the margin of error for the "worst" shot we can have given the
|
// Next, find out how large the aperture can be around the target, given range. The further the target is, the
|
||||||
// target's actual distance. This will later be used to draw the Outer Circle around the target.
|
// larger the aperture can be.
|
||||||
FLOAT iMaxAperture = iBasicAperture * iDistanceRatio;
|
FLOAT iDistanceAperture = iBasicAperture * (d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
||||||
|
|
||||||
// Calculate the aperture for our shot by applying both distance and scope magnification (which work against each
|
///////////////////////////////////////////////////////////////
|
||||||
// other) to the size of a normal aperture.
|
// To make things easier for us, we now calculate the Magnification Factor for this shot. A Mag Factor
|
||||||
FLOAT iAperture = iBasicAperture * iFinalRatio;
|
// is a divisor to the sway of the muzzle. It's about the same as multiplying CTH by a certain amount.
|
||||||
|
// Note that both optical magnification devices (like scopes) and dot-projection devices (like lasers and
|
||||||
|
// reflex sights) provide this sort of bonus.
|
||||||
|
FLOAT iMagFactor = CalcMagFactor( pSoldier, pWeapon, d2DDistance, gCTHDisplay.iTargetGridNo, (UINT8)pSoldier->aiData.bAimTime );
|
||||||
|
|
||||||
// Apply CTH to the aperture to find out how much smaller it's become thanks to skills and extra aiming.
|
// Get effective mag factor for this shooter. This represents his ability to use scopes.
|
||||||
UINT8 actualPct = __min(gCTHDisplay.MuzzleSwayPercentage,99);
|
FLOAT fEffectiveMagFactor = CalcEffectiveMagFactor( pSoldier, iMagFactor );
|
||||||
iAperture = ((100 - actualPct) * iAperture) / 100;
|
|
||||||
|
// Next step is to apply scope/projection factor to decrease the size of the aperture. This gives us the "Max
|
||||||
|
// Aperture" value - the size of the shooting circle if the gun is as unstable as possible.
|
||||||
|
FLOAT iMaxAperture = iDistanceAperture / fEffectiveMagFactor;
|
||||||
|
|
||||||
|
// We now use the Muzzle Sway value, calculated by the CTH formula, to decrease the size of the shot aperture.
|
||||||
|
// It is used as a percentage: a 50% muzzle sway value gives a cone with half the maximum radius. A cone with
|
||||||
|
// 0% Muzzle Sway is a single line with no width (meaning all shots will fly right down the center, and all will
|
||||||
|
// hit the target), while a cone with 100% muzzle sway is as wide as possible.
|
||||||
|
FLOAT iAperture = ( iMaxAperture * (100.0f - (FLOAT)gCTHDisplay.MuzzleSwayPercentage) / 100.0f);
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
// Factor in Weapon "Effective Range".
|
// Factor in Weapon "Effective Range".
|
||||||
UINT16 sEffRange = Weapon[Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pSoldier->inv[ pSoldier->ubAttackingHand ]));
|
UINT16 sEffRange = Weapon[Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pSoldier->inv[ pSoldier->ubAttackingHand ]));
|
||||||
FLOAT iRangeRatio = __max(1.0f, (FLOAT)(d2DDistance / sEffRange));
|
FLOAT iRangeRatio = __max(1.0f, (FLOAT)(d2DDistance / sEffRange));
|
||||||
|
FLOAT iDistanceRatio = (FLOAT)(d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
// Factor in Gun Accuracy.
|
// Factor in Gun Accuracy.
|
||||||
@@ -2858,7 +2870,7 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
|
|
||||||
// Since bullet dev is only affected by distance, we add it last as a flat modifier.
|
// Since bullet dev is only affected by distance, we add it last as a flat modifier.
|
||||||
iBasicAperture += iBulletDev;
|
iBasicAperture += iBulletDev;
|
||||||
iMaxAperture += iBulletDev;
|
iDistanceAperture += iBulletDev;
|
||||||
iAperture += iBulletDev;
|
iAperture += iBulletDev;
|
||||||
|
|
||||||
// CHRISL: Moved here so we can base the cursor color on the iAperture value
|
// CHRISL: Moved here so we can base the cursor color on the iAperture value
|
||||||
@@ -3076,7 +3088,7 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
SetFont( TINYFONT1 );
|
SetFont( TINYFONT1 );
|
||||||
|
|
||||||
// Find coordinates, using full string ("X.X x")
|
// Find coordinates, using full string ("X.X x")
|
||||||
swprintf( pStr, L"%3.2f", iMaxAperture );
|
swprintf( pStr, L"%3.2f", iDistanceAperture );
|
||||||
FindFontCenterCoordinates( (INT16)MagRect.left, (INT16)MagRect.top-5, (INT16)MagRect.right-(INT16)MagRect.left, 5, pStr, TINYFONT1, &curX, &curY);
|
FindFontCenterCoordinates( (INT16)MagRect.left, (INT16)MagRect.top-5, (INT16)MagRect.right-(INT16)MagRect.left, 5, pStr, TINYFONT1, &curX, &curY);
|
||||||
// Find width of this string.
|
// Find width of this string.
|
||||||
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
|
||||||
@@ -3486,10 +3498,10 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
sRight = gsVIEWPORT_END_X;
|
sRight = gsVIEWPORT_END_X;
|
||||||
sBottom = gsVIEWPORT_WINDOW_END_Y;
|
sBottom = gsVIEWPORT_WINDOW_END_Y;
|
||||||
|
|
||||||
INT16 lastY = 0;
|
// INT16 lastY = 0;
|
||||||
INT16 diffY = 0;
|
// INT16 diffY = 0;
|
||||||
UINT32 uiAperture = __max(2,(UINT32)iAperture);
|
// UINT32 uiAperture = __max(2,(UINT32)iAperture);
|
||||||
UINT32 uiMaxAperture = __max(2,(UINT32)iMaxAperture);
|
// UINT32 uiMaxAperture = __max(2,(UINT32)iDistanceAperture);
|
||||||
UINT32 uiApertureBarLength = 10;
|
UINT32 uiApertureBarLength = 10;
|
||||||
|
|
||||||
INT32 cnt = 0;
|
INT32 cnt = 0;
|
||||||
@@ -3513,29 +3525,29 @@ BOOLEAN DrawCTHIndicator()
|
|||||||
FLOAT RADIANS_IN_CIRCLE = (FLOAT)(PI * 2);
|
FLOAT RADIANS_IN_CIRCLE = (FLOAT)(PI * 2);
|
||||||
INT32 Circ = 0;
|
INT32 Circ = 0;
|
||||||
|
|
||||||
Circ = (INT32)((iMaxAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
|
Circ = (INT32)((iDistanceAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
|
||||||
if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
||||||
{
|
{
|
||||||
// Draw outer circle
|
// Draw outer circle
|
||||||
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
|
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
|
||||||
{
|
{
|
||||||
curX = (INT16)(iMaxAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
curX = (INT16)(iDistanceAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
curY = (INT16)((iMaxAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
curY = (INT16)((iDistanceAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
INT16 firstX = curX;
|
INT16 firstX = curX;
|
||||||
INT16 firstY = curY;
|
INT16 firstY = curY;
|
||||||
|
|
||||||
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
|
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
|
||||||
|
|
||||||
// Draw a border circle which is 1 point wider
|
// Draw a border circle which is 1 point wider
|
||||||
// curX = (INT16)((iMaxAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
// curX = (INT16)((iDistanceAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
// curY = (INT16)(((iMaxAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
// curY = (INT16)(((iDistanceAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
|
|
||||||
// if (curX != firstX || curY != firstY)
|
// if (curX != firstX || curY != firstY)
|
||||||
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
||||||
|
|
||||||
// Draw a border circle which is 1 point narrower
|
// Draw a border circle which is 1 point narrower
|
||||||
// curX = (INT16)((iMaxAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
// curX = (INT16)((iDistanceAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
// curY = (INT16)(((iMaxAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
// curY = (INT16)(((iDistanceAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
|
||||||
|
|
||||||
// if (curX != firstX || curY != firstY)
|
// if (curX != firstX || curY != firstY)
|
||||||
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
// DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
|
||||||
|
|||||||
+46
-3
@@ -7601,18 +7601,20 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
|
|||||||
// is a divisor to the sway of the muzzle. It's about the same as multiplying CTH by a certain amount.
|
// is a divisor to the sway of the muzzle. It's about the same as multiplying CTH by a certain amount.
|
||||||
// Note that both optical magnification devices (like scopes) and dot-projection devices (like lasers and
|
// Note that both optical magnification devices (like scopes) and dot-projection devices (like lasers and
|
||||||
// reflex sights) provide this sort of bonus.
|
// reflex sights) provide this sort of bonus.
|
||||||
|
|
||||||
FLOAT iMagFactor = CalcMagFactor( pShooter, pWeapon, d2DDistance, iTargetGridNo, (UINT8)pShooter->aiData.bAimTime );
|
FLOAT iMagFactor = CalcMagFactor( pShooter, pWeapon, d2DDistance, iTargetGridNo, (UINT8)pShooter->aiData.bAimTime );
|
||||||
|
|
||||||
|
// Get effective mag factor for this shooter. This represents his ability to use scopes.
|
||||||
|
FLOAT fEffectiveMagFactor = CalcEffectiveMagFactor( pShooter, iMagFactor );
|
||||||
|
|
||||||
// Next step is to apply scope/projection factor to decrease the size of the aperture. This gives us the "Max
|
// Next step is to apply scope/projection factor to decrease the size of the aperture. This gives us the "Max
|
||||||
// Aperture" value - the size of the shooting circle if the gun is as unstable as possible.
|
// Aperture" value - the size of the shooting circle if the gun is as unstable as possible.
|
||||||
iMaxAperture = iDistanceAperture / iMagFactor;
|
iMaxAperture = iDistanceAperture / fEffectiveMagFactor;
|
||||||
|
|
||||||
// We now use the Muzzle Sway value, calculated by the CTH formula, to decrease the size of the shot aperture.
|
// We now use the Muzzle Sway value, calculated by the CTH formula, to decrease the size of the shot aperture.
|
||||||
// It is used as a percentage: a 50% muzzle sway value gives a cone with half the maximum radius. A cone with
|
// It is used as a percentage: a 50% muzzle sway value gives a cone with half the maximum radius. A cone with
|
||||||
// 0% Muzzle Sway is a single line with no width (meaning all shots will fly right down the center, and all will
|
// 0% Muzzle Sway is a single line with no width (meaning all shots will fly right down the center, and all will
|
||||||
// hit the target), while a cone with 100% muzzle sway is as wide as possible.
|
// hit the target), while a cone with 100% muzzle sway is as wide as possible.
|
||||||
iAperture = (FLOAT)((iMaxAperture * uiMuzzleSway) / 100);
|
iAperture = ((iMaxAperture * (FLOAT)uiMuzzleSway) / 100.0f);
|
||||||
|
|
||||||
// Aperture ratio below is used for Experience Gain. The smaller the aperture, compared to the size of the
|
// Aperture ratio below is used for Experience Gain. The smaller the aperture, compared to the size of the
|
||||||
// Distance Aperture, the more experience we get.
|
// Distance Aperture, the more experience we get.
|
||||||
@@ -7944,6 +7946,47 @@ FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistan
|
|||||||
return iFinalMagFactor;
|
return iFinalMagFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// silversurfer: Effectivity in using scopes is determined by this function. Good shooters can use the full potential of scopes.
|
||||||
|
// Iron sights and reflex sights always provide full potential.
|
||||||
|
FLOAT CalcEffectiveMagFactor( SOLDIERTYPE *pShooter, FLOAT fRealMagFactor )
|
||||||
|
{
|
||||||
|
// can't be a scope...
|
||||||
|
if ( fRealMagFactor <= 1.0 )
|
||||||
|
return fRealMagFactor;
|
||||||
|
|
||||||
|
FLOAT fMaxEffectiveMagFactor = fRealMagFactor * gGameCTHConstants.SCOPE_EFFECTIVENESS_MULTIPLIER;
|
||||||
|
FLOAT fFinalEffectiveFactor = 0.1;
|
||||||
|
|
||||||
|
// new trait system grants special thresholds
|
||||||
|
if ( gGameOptions.fNewTraitSystem )
|
||||||
|
{
|
||||||
|
// snipers have most training
|
||||||
|
if ( NUM_SKILL_TRAITS( pShooter, SNIPER_NT ) == 2 )
|
||||||
|
fFinalEffectiveFactor = fMaxEffectiveMagFactor * (FLOAT)gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_SNIPER / 100.0f;
|
||||||
|
|
||||||
|
// marksmen also have sniper training but not as much
|
||||||
|
else if ( NUM_SKILL_TRAITS( pShooter, SNIPER_NT ) == 1 )
|
||||||
|
fFinalEffectiveFactor = fMaxEffectiveMagFactor * (FLOAT)gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_MARKSMAN / 100.0f;
|
||||||
|
|
||||||
|
// rangers have some scope training too
|
||||||
|
else if ( NUM_SKILL_TRAITS( pShooter, RANGER_NT ) == 2 )
|
||||||
|
fFinalEffectiveFactor = fMaxEffectiveMagFactor * (FLOAT)gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM_RANGER / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this defines the minimum effective magnification any shooter gets
|
||||||
|
FLOAT fFixedPart = fMaxEffectiveMagFactor * (FLOAT)gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM / 100.0f;
|
||||||
|
|
||||||
|
// this is the variable part that is based on the shooters skills (experience and marksmanship)
|
||||||
|
FLOAT fVariablePart = ( fMaxEffectiveMagFactor * (FLOAT)(100 - gGameCTHConstants.SCOPE_EFFECTIVENESS_MINIMUM) / 100.0f ) *
|
||||||
|
( ( (FLOAT)EffectiveExpLevel( pShooter ) * 10.0f * gGameCTHConstants.AIM_EXP + (FLOAT)EffectiveMarksmanship( pShooter ) * gGameCTHConstants.AIM_MARKS ) /
|
||||||
|
( gGameCTHConstants.AIM_EXP + gGameCTHConstants.AIM_MARKS ) / 100.0f );
|
||||||
|
|
||||||
|
// now add them together and enforce limits
|
||||||
|
fFinalEffectiveFactor = __min( fMaxEffectiveMagFactor, __max( fFixedPart + fVariablePart, fFinalEffectiveFactor ) );
|
||||||
|
|
||||||
|
return fFinalEffectiveFactor;
|
||||||
|
}
|
||||||
|
|
||||||
// HEADROCK HAM 4: This function calculates and returns the maximum shot aperture as a radius to which the muzzle of
|
// HEADROCK HAM 4: This function calculates and returns the maximum shot aperture as a radius to which the muzzle of
|
||||||
// the gun might sway off the target center when the trigger is pulled.
|
// the gun might sway off the target center when the trigger is pulled.
|
||||||
FLOAT CalcBasicAperture()
|
FLOAT CalcBasicAperture()
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ extern INT32 GetSpreadPattern( OBJECTTYPE * pObj );
|
|||||||
// which completely redesigns the way we calculate and handle CTH for the purposes of firing weapons.
|
// which completely redesigns the way we calculate and handle CTH for the purposes of firing weapons.
|
||||||
void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT *dEndX, FLOAT *dEndY, FLOAT *dEndZ, OBJECTTYPE *pWeapon, UINT32 uiMuzzleSway, INT16 *sApertureRatio );
|
void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT *dEndX, FLOAT *dEndY, FLOAT *dEndZ, OBJECTTYPE *pWeapon, UINT32 uiMuzzleSway, INT16 *sApertureRatio );
|
||||||
FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, INT32 iTargetGridNo, UINT8 ubAimTime );
|
FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, INT32 iTargetGridNo, UINT8 ubAimTime );
|
||||||
|
FLOAT CalcEffectiveMagFactor( SOLDIERTYPE *pShooter, FLOAT fRealMagFactor );
|
||||||
FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime );
|
FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime );
|
||||||
FLOAT CalcBasicAperture();
|
FLOAT CalcBasicAperture();
|
||||||
void CalcTargetMovementOffset( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, DOUBLE ddShootingAngle, INT32 iAperture );
|
void CalcTargetMovementOffset( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, DOUBLE ddShootingAngle, INT32 iAperture );
|
||||||
|
|||||||
@@ -9032,14 +9032,18 @@ UINT32 AICalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTim
|
|||||||
|
|
||||||
// distance to target
|
// distance to target
|
||||||
FLOAT d2DDistance = (FLOAT) PythSpacesAway( pSoldier->sGridNo, sGridNo ) * (FLOAT) CELL_X_SIZE;
|
FLOAT d2DDistance = (FLOAT) PythSpacesAway( pSoldier->sGridNo, sGridNo ) * (FLOAT) CELL_X_SIZE;
|
||||||
// magnification (1.0 or higher if scope is used)
|
|
||||||
FLOAT dMagFactor = CalcMagFactor( pSoldier, &(pSoldier->inv[pSoldier->ubAttackingHand]), d2DDistance, sGridNo, (UINT8)ubAimTime );
|
|
||||||
// basic aperture that is equal for everyone
|
// basic aperture that is equal for everyone
|
||||||
FLOAT dBasicAperture = CalcBasicAperture( );
|
FLOAT dBasicAperture = CalcBasicAperture( );
|
||||||
// aperture at target distance without magnification
|
// aperture at target distance without magnification
|
||||||
FLOAT dAperture = dBasicAperture * (d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
FLOAT dAperture = dBasicAperture * (d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
|
||||||
|
|
||||||
|
// magnification (1.0 or higher if scope is used)
|
||||||
|
FLOAT dMagFactor = CalcMagFactor( pSoldier, &(pSoldier->inv[pSoldier->ubAttackingHand]), d2DDistance, sGridNo, (UINT8)ubAimTime );
|
||||||
|
// Get effective mag factor for this shooter. This represents his ability to use scopes.
|
||||||
|
FLOAT fEffectiveMagFactor = CalcEffectiveMagFactor( pSoldier, dMagFactor );
|
||||||
// modify aperture with magnification
|
// modify aperture with magnification
|
||||||
dAperture = dAperture / dMagFactor;
|
dAperture = dAperture / fEffectiveMagFactor;
|
||||||
|
|
||||||
// real aperture for shooter based on CTH calculation
|
// real aperture for shooter based on CTH calculation
|
||||||
dAperture = dAperture * ( 100 - uiChance ) / 100.0f;
|
dAperture = dAperture * ( 100 - uiChance ) / 100.0f;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user