If ALLOW_TARGET_HEADANDLEG_IFPRONE is TRUE, head/torso/legs can be targetted on prone soldiers (until now, hits were always considered on torso).

Additionally soldiers are no longer protected from stray bullets in crouched and prone stance.

This option will be removed once this code change has been accepted (or deemed unacceptable).

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8264 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-07-02 18:04:49 +00:00
parent 9b2e65cade
commit 2a7abe5b0d
5 changed files with 140 additions and 17 deletions
+4 -3
View File
@@ -720,6 +720,9 @@ void LoadGameExternalOptions()
// see Tactical\Weapons.cpp funtion CalcNewChanceToHitGun() // see Tactical\Weapons.cpp funtion CalcNewChanceToHitGun()
gGameExternalOptions.fUseNewCTHCalculation = iniReader.ReadBoolean("System Limit Settings", "USE_NEW_CTH_CALCULATION", TRUE); gGameExternalOptions.fUseNewCTHCalculation = iniReader.ReadBoolean("System Limit Settings", "USE_NEW_CTH_CALCULATION", TRUE);
// Flugente: this change allows to target head/torso/legs of prone targets. This option will be removed once accepted
gGameExternalOptions.fAllowTargetHeadAndLegIfProne = iniReader.ReadBoolean( "System Limit Settings", "ALLOW_TARGET_HEADANDLEG_IFPRONE", TRUE );
//################# Data File Settings ################# //################# Data File Settings #################
// WANNE: Always use prof.dat?? // WANNE: Always use prof.dat??
@@ -1682,9 +1685,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_THUNDERSHOWERS] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_THUNDERSTORM", 0.8f, 0.0f, 1.0f ); gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_THUNDERSHOWERS] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_THUNDERSTORM", 0.8f, 0.0f, 1.0f );
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SANDSTORM] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SANDSTORM", 0.6f, 0.0f, 1.0f ); gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SANDSTORM] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SANDSTORM", 0.6f, 0.0f, 1.0f );
gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SNOW] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SNOW", 0.1f, 0.0f, 1.0f ); gGameExternalOptions.dHearingReduction[WEATHER_FORECAST_SNOW] = iniReader.ReadDouble( "Tactical Weather Settings", "HEARING_REDUCTION_SNOW", 0.1f, 0.0f, 1.0f );
FLOAT dHearingReduction[WEATHER_FORECAST_MAX];
//################# Tactical Weapon Overheating Settings ################## //################# Tactical Weapon Overheating Settings ##################
// Flugente: These settings control the behavior of Weapon Overheating, its severity, and its display. // Flugente: These settings control the behavior of Weapon Overheating, its severity, and its display.
gGameExternalOptions.fWeaponOverheating = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING",FALSE); gGameExternalOptions.fWeaponOverheating = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING",FALSE);
+3
View File
@@ -542,6 +542,9 @@ typedef struct
// see Tactical\Weapons.cpp funtion CalcNewChanceToHitGun() // see Tactical\Weapons.cpp funtion CalcNewChanceToHitGun()
BOOLEAN fUseNewCTHCalculation; BOOLEAN fUseNewCTHCalculation;
// Flugente: this change allows to target head/torso/legs of prone targets. This option will be removed once accepted
BOOLEAN fAllowTargetHeadAndLegIfProne;
//Sight range //Sight range
UINT32 ubStraightSightRange; UINT32 ubStraightSightRange;
+61 -7
View File
@@ -2714,7 +2714,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
{ {
// Flugente: kids are smaller. We have to keep hat in mind... otherwise we will never make a sucessful headshot // Flugente: kids are smaller. We have to keep hat in mind... otherwise we will never make a sucessful headshot
BOOLEAN iskid = ( pTarget->ubBodyType == HATKIDCIV || pTarget->ubBodyType == KIDCIV ); BOOLEAN iskid = ( pTarget->ubBodyType == HATKIDCIV || pTarget->ubBodyType == KIDCIV );
switch (gAnimControl[ pTarget->usAnimState ].ubEndHeight) switch (gAnimControl[ pTarget->usAnimState ].ubEndHeight)
{ {
case ANIM_STAND: case ANIM_STAND:
@@ -2800,7 +2800,58 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
} }
break; break;
case ANIM_PRONE: case ANIM_PRONE:
ubHitLocation = AIM_SHOT_TORSO; {
if ( gGameExternalOptions.fAllowTargetHeadAndLegIfProne )
{
FLOAT x = (FLOAT)FIXEDPT_TO_INT32( pBullet->qCurrX + FloatToFixed( 0.5f ) ); // + 0.5);
FLOAT y = (FLOAT)FIXEDPT_TO_INT32( pBullet->qCurrY + FloatToFixed( 0.5f ) ); // (dCurrY + 0.5);
// Flugente: we measure the distance of the bullet's location to the location of the soldier, and to the 2 gridnos his head and leg occupy
// From this we can decide what body part was hit
FLOAT bodycenterX = (FLOAT)CenterX( pTarget->sGridNo );
FLOAT bodycenterY = (FLOAT)CenterY( pTarget->sGridNo );
FLOAT difftobodycenter = std::sqrt( (bodycenterX - x) * (bodycenterX - x) + (bodycenterY - y) * (bodycenterY - y) );
INT32 viewdirectiongridno = NewGridNo( pTarget->sGridNo, DirectionInc( pTarget->ubDirection ) );
FLOAT nextgridnocenterX = (FLOAT)CenterX( viewdirectiongridno );
FLOAT nextgridnocenterY = (FLOAT)CenterY( viewdirectiongridno );
FLOAT difftonextgridno = std::sqrt( (nextgridnocenterX - x) * (nextgridnocenterX - x) + (nextgridnocenterY - y) * (nextgridnocenterY - y) );
INT32 oppositeviewdirectiongridno = NewGridNo( pTarget->sGridNo, DirectionInc( gOppositeDirection[pTarget->ubDirection] ) );
FLOAT oppositenextgridnocenterX = (FLOAT)CenterX( oppositeviewdirectiongridno );
FLOAT oppositenextgridnocenterY = (FLOAT)CenterY( oppositeviewdirectiongridno );
FLOAT difftooppositenextgridno = std::sqrt( (oppositenextgridnocenterX - x) * (oppositenextgridnocenterX - x) + (oppositenextgridnocenterY - y) * (oppositenextgridnocenterY - y) );
if ( difftobodycenter < difftonextgridno )
{
if ( difftobodycenter < difftooppositenextgridno )
{
ubHitLocation = AIM_SHOT_TORSO;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Torso hit" );
}
else
{
ubHitLocation = AIM_SHOT_LEGS;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Leg hit" );
}
}
else
{
ubHitLocation = AIM_SHOT_HEAD;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Headshot" );
}
}
else
{
ubHitLocation = AIM_SHOT_TORSO;
}
}
break; break;
} }
@@ -3664,7 +3715,7 @@ UINT8 CalcChanceToGetThrough( BULLET * pBullet )
// in actually moving the bullet, we consider only count friends as targets if the bullet is unaimed // in actually moving the bullet, we consider only count friends as targets if the bullet is unaimed
// (buckshot), if they are the intended target, or beyond the range of automatic friendly fire hits // (buckshot), if they are the intended target, or beyond the range of automatic friendly fire hits
// OR a 1 in 30 chance occurs // OR a 1 in 30 chance occurs
if (gAnimControl[ MercPtrs[pStructure->usStructureID]->usAnimState ].ubEndHeight == ANIM_STAND && if ( (gGameExternalOptions.fAllowTargetHeadAndLegIfProne || gAnimControl[MercPtrs[pStructure->usStructureID]->usAnimState].ubEndHeight == ANIM_STAND) &&
( (pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS) || ( (pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS) ||
(!pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS_UNAIMED) (!pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS_UNAIMED)
) )
@@ -6495,7 +6546,7 @@ void MoveBullet( INT32 iBullet )
} }
} }
else if ( MercPtrs[ pStructure->usStructureID ]->bVisible == TRUE && else if ( MercPtrs[ pStructure->usStructureID ]->bVisible == TRUE &&
gAnimControl[ MercPtrs[pStructure->usStructureID]->usAnimState ].ubEndHeight == ANIM_STAND && (gGameExternalOptions.fAllowTargetHeadAndLegIfProne || gAnimControl[ MercPtrs[pStructure->usStructureID]->usAnimState ].ubEndHeight == ANIM_STAND ) &&
( (pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS) || ( (pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS) ||
(!pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS_UNAIMED) || (!pBullet->fAimed && pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS_UNAIMED) ||
PreRandom( 100 ) < MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE PreRandom( 100 ) < MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE
@@ -6974,7 +7025,7 @@ void MoveBullet( INT32 iBullet )
} }
} }
else if ( pBullet->iLoop > CLOSE_TO_FIRER || (pStructure->fFlags & ALWAYS_CONSIDER_HIT) || (pBullet->iLoop > CLOSE_TO_FIRER) || (fIntended) ) else if ( pBullet->iLoop > CLOSE_TO_FIRER || (pStructure->fFlags & ALWAYS_CONSIDER_HIT) || fIntended )
{ {
if (pStructure->fFlags & STRUCTURE_WALLSTUFF) if (pStructure->fFlags & STRUCTURE_WALLSTUFF)
{ {
@@ -7123,7 +7174,8 @@ void MoveBullet( INT32 iBullet )
uiTileInc++; uiTileInc++;
// HEADROCK HAM 5: Ignore if moving a fragment. // HEADROCK HAM 5: Ignore if moving a fragment.
if(UsingNewCTHSystem() && pBullet->fFragment == false ){ if(UsingNewCTHSystem() && pBullet->fFragment == false )
{
// HEADROCK HAM 4: This is kind of a hack. I'm measuring the distance the tile has moved in 2D space, // HEADROCK HAM 4: This is kind of a hack. I'm measuring the distance the tile has moved in 2D space,
// for purposes of determining whether gravity should take effect. // for purposes of determining whether gravity should take effect.
FLOAT dDistanceMoved = PythSpacesAway( pBullet->pFirer->sGridNo, pBullet->sGridNo ) * 10.0f; FLOAT dDistanceMoved = PythSpacesAway( pBullet->pFirer->sGridNo, pBullet->sGridNo ) * 10.0f;
@@ -7142,7 +7194,9 @@ void MoveBullet( INT32 iBullet )
//pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2); //pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2);
pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * (gGameCTHConstants.GRAVITY_COEFFICIENT / 2) ); pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * (gGameCTHConstants.GRAVITY_COEFFICIENT / 2) );
} }
} else { }
else
{
if ( (pBullet->iLoop > pBullet->iRange * 2) ) if ( (pBullet->iLoop > pBullet->iRange * 2) )
{ {
// beyond max effective range, bullet starts to drop! // beyond max effective range, bullet starts to drop!
+50 -1
View File
@@ -903,7 +903,6 @@ BOOLEAN FindRelativeSoldierPosition( SOLDIERTYPE *pSoldier, UINT16 *usFlags, INT
INT16 sRelX, sRelY; INT16 sRelX, sRelY;
FLOAT dRelPer; FLOAT dRelPer;
// Get Rect contained in the soldier // Get Rect contained in the soldier
GetSoldierScreenRect( pSoldier, &aRect ); GetSoldierScreenRect( pSoldier, &aRect );
@@ -952,6 +951,56 @@ BOOLEAN FindRelativeSoldierPosition( SOLDIERTYPE *pSoldier, UINT16 *usFlags, INT
} }
break; break;
case ANIM_PRONE:
{
// Flugente: if we are prone, determining what part of the body we are aiming for is trickier.
// Instead of focusing on relative height, we simply determine whether we are looking at the gridno the body itself is at, or an adjacent gridno.
// Then, depending on whether this is the gridno we are looking at, this will be head or legs
if ( gGameExternalOptions.fAllowTargetHeadAndLegIfProne )
{
INT16 sWorldX, sWorldY;
GetMouseWorldCoords( &sWorldX, &sWorldY );
// Flugente: we measure the distance of the bullet's location to the location of the soldier, and to the 2 gridnos his head and leg occupy
// From this we can decide what body part was hit
FLOAT bodycenterX = (FLOAT)CenterX( pSoldier->sGridNo );
FLOAT bodycenterY = (FLOAT)CenterY( pSoldier->sGridNo );
FLOAT difftobodycenter = std::sqrt( (bodycenterX - sWorldX) * (bodycenterX - sWorldX) + (bodycenterY - sWorldY) * (bodycenterY - sWorldY) );
INT32 viewdirectiongridno = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->ubDirection ) );
FLOAT nextgridnocenterX = (FLOAT)CenterX( viewdirectiongridno );
FLOAT nextgridnocenterY = (FLOAT)CenterY( viewdirectiongridno );
FLOAT difftonextgridno = std::sqrt( (nextgridnocenterX - sWorldX) * (nextgridnocenterX - sWorldX) + (nextgridnocenterY - sWorldY) * (nextgridnocenterY - sWorldY) );
INT32 oppositeviewdirectiongridno = NewGridNo( pSoldier->sGridNo, DirectionInc( gOppositeDirection[pSoldier->ubDirection] ) );
FLOAT oppositenextgridnocenterX = (FLOAT)CenterX( oppositeviewdirectiongridno );
FLOAT oppositenextgridnocenterY = (FLOAT)CenterY( oppositeviewdirectiongridno );
FLOAT difftooppositenextgridno = std::sqrt( (oppositenextgridnocenterX - sWorldX) * (oppositenextgridnocenterX - sWorldX) + (oppositenextgridnocenterY - sWorldY) * (oppositenextgridnocenterY - sWorldY) );
if ( difftobodycenter < difftonextgridno )
{
if ( difftobodycenter < difftooppositenextgridno )
{
(*usFlags) = TILE_FLAG_MID;
return(TRUE);
}
else
{
(*usFlags) = TILE_FLAG_FEET;
return(TRUE);
}
}
else
{
(*usFlags) = TILE_FLAG_HEAD;
return(TRUE);
}
}
}
break;
} }
} }
+22 -6
View File
@@ -1687,13 +1687,33 @@ void GetTargetWorldPositions( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, FLOAT
switch( pSoldier->bAimShotLocation ) switch( pSoldier->bAimShotLocation )
{ {
case AIM_SHOT_HEAD: case AIM_SHOT_HEAD:
CalculateSoldierZPos( pTargetSoldier, HEAD_TARGET_POS, &dTargetZ ); {
CalculateSoldierZPos( pTargetSoldier, HEAD_TARGET_POS, &dTargetZ );
if ( gGameExternalOptions.fAllowTargetHeadAndLegIfProne && gAnimControl[pTargetSoldier->usAnimState].ubHeight == ANIM_PRONE )
{
INT32 viewdirectiongridno = NewGridNo( pTargetSoldier->sGridNo, DirectionInc( pTargetSoldier->ubDirection ) );
dTargetX = (0.3f * dTargetX + 0.7f * (FLOAT)CenterX( viewdirectiongridno )) / 1.0f;
dTargetY = (0.3f * dTargetY + 0.7f * (FLOAT)CenterY( viewdirectiongridno )) / 1.0f;
}
}
break; break;
case AIM_SHOT_TORSO: case AIM_SHOT_TORSO:
CalculateSoldierZPos( pTargetSoldier, TORSO_TARGET_POS, &dTargetZ ); CalculateSoldierZPos( pTargetSoldier, TORSO_TARGET_POS, &dTargetZ );
break; break;
case AIM_SHOT_LEGS: case AIM_SHOT_LEGS:
CalculateSoldierZPos( pTargetSoldier, LEGS_TARGET_POS, &dTargetZ ); {
CalculateSoldierZPos( pTargetSoldier, LEGS_TARGET_POS, &dTargetZ );
if ( gGameExternalOptions.fAllowTargetHeadAndLegIfProne && gAnimControl[pTargetSoldier->usAnimState].ubHeight == ANIM_PRONE )
{
INT32 viewdirectiongridno = NewGridNo( pTargetSoldier->sGridNo, DirectionInc( gOppositeDirection[pTargetSoldier->ubDirection] ) );
dTargetX = (0.3f * dTargetX + 0.7f * (FLOAT)CenterX( viewdirectiongridno )) / 1.0f;
dTargetY = (0.3f * dTargetY + 0.7f * (FLOAT)CenterY( viewdirectiongridno )) / 1.0f;
}
}
break; break;
default: default:
// %)@#&(%? // %)@#&(%?
@@ -12565,10 +12585,6 @@ void GunIncreaseHeat( OBJECTTYPE *pObj, SOLDIERTYPE* pSoldier )
FLOAT newguntemperature = min(guntemperature + singleshottemperature, OVERHEATING_MAX_TEMPERATURE ); // ... calculate new temperature ... FLOAT newguntemperature = min(guntemperature + singleshottemperature, OVERHEATING_MAX_TEMPERATURE ); // ... calculate new temperature ...
(*pObj)[0]->data.bTemperature = newguntemperature; // ... apply new temperature (*pObj)[0]->data.bTemperature = newguntemperature; // ... apply new temperature
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Gun temperature increased from %4.2f to %4.2f", guntemperature, newguntemperature );
#endif
} }
} }