mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
New experimental NCTH options: LIMIT_MAX_DEVIATION, LIMIT_GROUND_SHOTS.
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8801 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3501,6 +3501,8 @@ void LoadCTHConstants()
|
||||
gGameCTHConstants.MAX_EFFECTIVE_RANGE_MULTIPLIER = iniReader.ReadFloat("Shooting Mechanism","MAX_EFFECTIVE_RANGE_MULTIPLIER",1.1f, 0.5f, 10.0f);
|
||||
gGameCTHConstants.MAX_EFFECTIVE_RANGE_REDUCTION = iniReader.ReadFloat("Shooting Mechanism","MAX_EFFECTIVE_RANGE_REDUCTION",0.5f, 0.0f, 1.0f);
|
||||
gGameCTHConstants.MAX_EFFECTIVE_USE_GRADIENT = iniReader.ReadBoolean("Shooting Mechanism","MAX_EFFECTIVE_USE_GRADIENT", FALSE );
|
||||
gGameCTHConstants.LIMIT_MAX_DEVIATION = iniReader.ReadBoolean("Shooting Mechanism", "LIMIT_MAX_DEVIATION", false, false);
|
||||
gGameCTHConstants.LIMIT_GROUND_SHOTS = iniReader.ReadBoolean("Shooting Mechanism", "LIMIT_GROUND_SHOTS", false, false);
|
||||
}
|
||||
|
||||
void LoadTauntsSettings()
|
||||
|
||||
@@ -2087,6 +2087,8 @@ typedef struct
|
||||
FLOAT MAX_EFFECTIVE_RANGE_MULTIPLIER;
|
||||
FLOAT MAX_EFFECTIVE_RANGE_REDUCTION;
|
||||
BOOLEAN MAX_EFFECTIVE_USE_GRADIENT;
|
||||
BOOLEAN LIMIT_MAX_DEVIATION;
|
||||
BOOLEAN LIMIT_GROUND_SHOTS;
|
||||
|
||||
} CTH_CONSTANTS;
|
||||
//DBrot: Grids
|
||||
|
||||
+88
-18
@@ -55,7 +55,7 @@
|
||||
#include "CampaignStats.h" // added by Flugente
|
||||
#include "AIInternals.h"//dnl ch61 180813
|
||||
#include "SkillCheck.h" // added by Flugente
|
||||
|
||||
#include "ai.h" // sevenfm
|
||||
#include "GameInitOptionsScreen.h"
|
||||
|
||||
//forward declarations of common classes to eliminate includes
|
||||
@@ -8768,8 +8768,25 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
|
||||
// affects accuracy of ALL shots in the game, and is enforced here a second time.
|
||||
|
||||
LimitImpactPointByFacing( pShooter, pTarget, &dShotOffsetX, &dShotOffsetY, dEndX, dEndY );
|
||||
LimitImpactPointToMaxAperture( &dShotOffsetX, &dShotOffsetY, iDistanceAperture );
|
||||
|
||||
UINT32 uiEffWeaponRange = uiRange;
|
||||
|
||||
if (gGameCTHConstants.LIMIT_MAX_DEVIATION)
|
||||
{
|
||||
// limit effective suppression range when using alt weapon holding
|
||||
if (pShooter->bScopeMode == USE_ALT_WEAPON_HOLD && uiRange > TACTICAL_RANGE / 2)
|
||||
{
|
||||
uiEffWeaponRange = (uiRange + TACTICAL_RANGE / 2) / 2;
|
||||
}
|
||||
// modify effective suppression range depending on weapon recoil
|
||||
FLOAT bGunRecoilX;
|
||||
FLOAT bGunRecoilY;
|
||||
GetRecoil(pShooter, pWeapon, &bGunRecoilX, &bGunRecoilY, 3);
|
||||
FLOAT bGunRecoil = sqrt(bGunRecoilX * bGunRecoilX + bGunRecoilY * bGunRecoilY);
|
||||
uiEffWeaponRange = uiEffWeaponRange / max(0.5f, min(2.0f, bGunRecoil / 10.0f));
|
||||
}
|
||||
|
||||
LimitImpactPointToMaxAperture(&dShotOffsetX, &dShotOffsetY, iDistanceAperture, (UINT32)d2DDistance, uiRange);
|
||||
|
||||
// DEBUGGING: Remove this!
|
||||
if (gGameSettings.fOptions[TOPTION_REPORT_MISS_MARGIN])
|
||||
@@ -9340,14 +9357,41 @@ void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzl
|
||||
|
||||
// Trigonometry!
|
||||
FLOAT dDeltaX = (sin(dRandomAngleRadians) * RandomMuzzleSway) * iAperture;
|
||||
FLOAT dDeltaY = (cos(dRandomAngleRadians) * RandomMuzzleSway) * iAperture;
|
||||
FLOAT dDeltaY = (cos(dRandomAngleRadians) * RandomMuzzleSway) * iAperture;
|
||||
FLOAT dVerticalBias;
|
||||
|
||||
// The new Vertical Bias constant turns circular deviation into an ellipse. This can be used to reduce the distance
|
||||
// of up/down deviation. To balance things out, lateral (left/right) deviation is increased by the same proportion.
|
||||
// Vertical bias is applied based on stance. You get a flatter ellipse when prone, and no ellipse (a circle) when standing.
|
||||
FLOAT dVerticalBias = gGameCTHConstants.VERTICAL_BIAS;
|
||||
switch (gAnimControl[ pShooter->usAnimState ].ubEndHeight)
|
||||
// sevenfm: possibly limit ground shots
|
||||
if(gGameCTHConstants.LIMIT_GROUND_SHOTS)
|
||||
{
|
||||
FLOAT dStartZ;
|
||||
FLOAT dMaxBias = 20.0f;
|
||||
FLOAT dMaxDown;
|
||||
|
||||
dVerticalBias = 1.0f;
|
||||
CalculateSoldierZPos(pShooter, FIRING_POS, &dStartZ);
|
||||
dMaxDown = -dStartZ;
|
||||
|
||||
// reduced chance of ground shot
|
||||
if (dDeltaY < dMaxDown)
|
||||
{
|
||||
dDeltaY *= -1.0f;
|
||||
|
||||
if (dDeltaX >= 0)
|
||||
dDeltaX += dDeltaY;
|
||||
else
|
||||
dDeltaX -= dDeltaY;
|
||||
}
|
||||
// limit vertical distribution
|
||||
dVerticalBias = dMaxBias / (dMaxBias + min(dMaxBias, iAperture));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The new Vertical Bias constant turns circular deviation into an ellipse. This can be used to reduce the distance
|
||||
// of up/down deviation. To balance things out, lateral (left/right) deviation is increased by the same proportion.
|
||||
// Vertical bias is applied based on stance. You get a flatter ellipse when prone, and no ellipse (a circle) when standing.
|
||||
dVerticalBias = gGameCTHConstants.VERTICAL_BIAS;
|
||||
switch (gAnimControl[pShooter->usAnimState].ubEndHeight)
|
||||
{
|
||||
case ANIM_STAND:
|
||||
dVerticalBias = 1.0;
|
||||
break;
|
||||
@@ -9357,11 +9401,11 @@ void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzl
|
||||
case ANIM_CROUCH:
|
||||
dVerticalBias = 1.0f + ((dVerticalBias - 1.0f) * 0.66f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the distance on both axes, we can apply it to the Muzzle Offset value which we were fed
|
||||
// from the calling function.
|
||||
|
||||
*dMuzzleOffsetX += dDeltaX;
|
||||
*dMuzzleOffsetY += dDeltaY * dVerticalBias;
|
||||
}
|
||||
@@ -9553,7 +9597,7 @@ void LimitImpactPointByFacing( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, FLOA
|
||||
}
|
||||
}
|
||||
|
||||
void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture )
|
||||
void LimitImpactPointToMaxAperture(FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture, UINT32 uiDistance, UINT32 uiWeaponRange)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -9581,17 +9625,43 @@ void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FL
|
||||
// Calculate how far from the target center will our shot impact. This is done by simple pythagorean formula.
|
||||
FLOAT dTotalShotOffset = sqrt((*dShotOffsetX * *dShotOffsetX)+(*dShotOffsetY * *dShotOffsetY));
|
||||
|
||||
// If our shot deviates more than the aperture allows, at the target's distance...
|
||||
if (dTotalShotOffset > dDistanceAperture )
|
||||
// sevenfm: possibly limit max deviation to improve suppression effect
|
||||
if (gGameCTHConstants.LIMIT_MAX_DEVIATION)
|
||||
{
|
||||
// Find out the ratio between the deviation and the limit.
|
||||
dReductionRatio = dDistanceAperture / dTotalShotOffset;
|
||||
// sevenfm: find max offset
|
||||
FLOAT dMaxOffset = 10.0f;
|
||||
|
||||
// Multiply both offsets by this ratio. This will effectively move them back into the aperture radius
|
||||
// without altering the ratio between vertical and horizontal offsets.
|
||||
*dShotOffsetX *= dReductionRatio;
|
||||
*dShotOffsetY *= dReductionRatio;
|
||||
// scale with weapon range
|
||||
if (uiDistance > uiWeaponRange && uiWeaponRange > 0)
|
||||
dMaxOffset = dMaxOffset * uiDistance * uiDistance / (uiWeaponRange * uiWeaponRange);
|
||||
|
||||
// limit to normal distance aperture
|
||||
dMaxOffset = min(dMaxOffset, dDistanceAperture / 2);
|
||||
|
||||
// sevenfm: limit max distance
|
||||
if (dTotalShotOffset > dMaxOffset)
|
||||
{
|
||||
FLOAT dNewOffset = (2 * dMaxOffset) * dTotalShotOffset / (dMaxOffset + dTotalShotOffset);
|
||||
dReductionRatio = dNewOffset / dTotalShotOffset;
|
||||
|
||||
*dShotOffsetX *= dReductionRatio;
|
||||
*dShotOffsetY *= dReductionRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If our shot deviates more than the aperture allows, at the target's distance...
|
||||
if (dTotalShotOffset > dDistanceAperture)
|
||||
{
|
||||
// Find out the ratio between the deviation and the limit.
|
||||
dReductionRatio = dDistanceAperture / dTotalShotOffset;
|
||||
|
||||
// Multiply both offsets by this ratio. This will effectively move them back into the aperture radius
|
||||
// without altering the ratio between vertical and horizontal offsets.
|
||||
*dShotOffsetX *= dReductionRatio;
|
||||
*dShotOffsetY *= dReductionRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FLOAT CalcCounterForceMax(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT8 uiStance)
|
||||
|
||||
+1
-1
@@ -243,7 +243,7 @@ void CalcRangeCompensationOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetY,
|
||||
void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, FLOAT iAperture );
|
||||
FLOAT CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
|
||||
void LimitImpactPointByFacing( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT *dEndX, FLOAT *dEndY );
|
||||
void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture );
|
||||
void LimitImpactPointToMaxAperture(FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture, UINT32 uiDistance, UINT32 uiWeaponRange);
|
||||
FLOAT CalcCounterForceMax(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT8 uiStance = 0);
|
||||
UINT32 CalcCounterForceAccuracy(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT32 uiRange, BOOLEAN fTracer, bool fAnticipate = false);
|
||||
void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, UINT32 uiRange );
|
||||
|
||||
Reference in New Issue
Block a user