- new modifiers "MISS_MAX_RADIUS_x" for grenades and mortar to set a max radius where they will land. Chance to hit something with explosives is now based more on skill than on luck.

- fixed infinite loop in function "RandomGridFromRadius" when min and max radius were 1
- fixed incorrect exit condition in function "RandomGridFromRadius" when min radius was 0
- fixed incorrect CtH calculation for mortar

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8598 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
silversurfer
2018-08-22 17:54:24 +00:00
parent 6058911c34
commit fed9ca298c
7 changed files with 44 additions and 87 deletions
+2
View File
@@ -3104,6 +3104,8 @@ void LoadItemSettings()
gItemSettings.fDamageBreathModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_BREATH_EXPLOSIVE_MODIFIER", 1.0f, 0.1f, 5.0f);
gItemSettings.fDamageHealthMoveModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_HEALTH_MOVE_EXPLOSIVE_MODIFIER", 0.1f, 0.0f, 1.0f);
gItemSettings.fDamageBreathMoveModifierExplosive = iniReader.ReadFloat ("Explosives Settings","DAMAGE_BREATH_MOVE_EXPLOSIVE_MODIFIER", 0.1f, 0.0f, 1.0f);
gItemSettings.usMissMaxRadiusGrenade = iniReader.ReadInteger("Explosives Settings","MISS_MAX_RADIUS_GRENADE", 5, 0, 30 );
gItemSettings.usMissMaxRadiusMortar = iniReader.ReadInteger("Explosives Settings","MISS_MAX_RADIUS_MORTAR", 10, 0, 30 );
// ------------ MISC MODIFIERS --------------
gItemSettings.fShieldMovementAPCostModifier = iniReader.ReadFloat ("Misc Settings", "SHIELD_MOVEMENT_APCOST_MODIFIER", 1.7f, 1.0f, 10.0f );
+2
View File
@@ -2348,6 +2348,8 @@ typedef struct
FLOAT fDamageBreathModifierExplosive;
FLOAT fDamageHealthMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask
FLOAT fDamageBreathMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask
UINT8 usMissMaxRadiusGrenade;
UINT8 usMissMaxRadiusMortar;
// ------------ MISC MODIFIERS --------------
// Flugente
+2 -2
View File
@@ -55,8 +55,8 @@
#endif
CHAR8 czVersionNumber[16] = { "Build 18.08.15" }; //YY.MM.DD
CHAR8 czVersionNumber[16] = { "Build 18.08.22" }; //YY.MM.DD
CHAR16 zTrackingNumber[16] = { L"Z" };
CHAR16 zRevisionNumber[16] = { L"Revision 8594" };
CHAR16 zRevisionNumber[16] = { L"Revision 8598" };
// SAVE_GAME_VERSION is defined in header, change it there
+1 -1
View File
@@ -9528,7 +9528,7 @@ BOOLEAN HandleItemPointerClick( INT32 usMapPos )
// Given our gridno, throw grenate!
CalculateLaunchItemParamsForThrow( gpItemPointerSoldier, sGridNo, gpItemPointerSoldier->pathing.bLevel, (INT16)( ( gsInterfaceLevel * 256 ) + sEndZ ), gpItemPointer, 0, ubThrowActionCode, uiThrowActionData );
CalculateLaunchItemParamsForThrow( gpItemPointerSoldier, sGridNo, gpItemPointerSoldier->pathing.bLevel, (INT16)( ( gsInterfaceLevel * 256 ) + sEndZ ), gpItemPointer, 100, ubThrowActionCode, uiThrowActionData, gpItemPointer->usItem );
// OK, goto throw animation
HandleSoldierThrowItem( gpItemPointerSoldier, usMapPos );
+9 -12
View File
@@ -4061,7 +4061,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea
BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{
UINT32 uiHitChance, uiDiceRoll;
UINT32 uiHitChance;
INT8 bLoop;
UINT8 ubTargetID;
SOLDIERTYPE * pTargetSoldier;
@@ -4069,12 +4069,10 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO );
uiDiceRoll = PreRandom( 100 );
#ifdef JA2BETAVERSION
if ( gfReportHitChances )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Hit chance was %ld, roll %ld (range %d)", uiHitChance, uiDiceRoll, PythSpacesAway( pSoldier->sGridNo, sTargetGridNo ) );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Hit chance was %ld, (range %d)", uiHitChance, PythSpacesAway( pSoldier->sGridNo, sTargetGridNo ) );
}
#endif
@@ -4132,7 +4130,8 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
// Snap: calculate experience points for dexterity and marksmanship
usExpGain = 5 // For at least one target
+ 2*(usNumTargets-1); // For every additional target
BOOLEAN fGonnaHit = uiDiceRoll < uiHitChance;
// how likely is it that we hit the target?
BOOLEAN fGonnaHit = PreRandom(100) < uiHitChance;
if ( fGonnaHit ) usExpGain *= 2; // For actually hitting the target :)
usExpGain += (UINT16) (100 - uiHitChance) / 10; // Extra exp for a difficult target
StatChange( pSoldier, DEXTAMT, usExpGain / 2, ( fGonnaHit ? FALSE : FROM_FAILURE ) );
@@ -4162,7 +4161,7 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
}
/////////////////////////////////////////////////////////////////////////////////////
CalculateLaunchItemParamsForThrow( pSoldier, sTargetGridNo, pSoldier->bTargetLevel, (INT16)(pSoldier->bTargetLevel * 256 ), &(pSoldier->inv[ HANDPOS ] ), (INT8)(uiDiceRoll - uiHitChance), THROW_ARM_ITEM, 0 );
CalculateLaunchItemParamsForThrow( pSoldier, sTargetGridNo, pSoldier->bTargetLevel, (INT16)(pSoldier->bTargetLevel * 256 ), &(pSoldier->inv[ HANDPOS ] ), uiHitChance, THROW_ARM_ITEM, 0, pSoldier->inv[HANDPOS].usItem );
#if 0//dnl ch72 180913 bad idea to charge APs before stance and turn really occurs, this was not here in v1.12
//AXP 25.03.2007: Cleaned up throwing AP costs. Now only turning + stance change AP
@@ -4203,7 +4202,7 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{
UINT32 uiHitChance, uiDiceRoll;
UINT32 uiHitChance;
INT16 sAPCost = 0;
INT32 iBPCost = 0;
OBJECTTYPE Launchable;
@@ -4323,12 +4322,10 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO );
uiDiceRoll = PreRandom( 100 );
#ifdef JA2BETAVERSION
if ( gfReportHitChances )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Hit chance was %ld, roll %ld (range %d)", uiHitChance, uiDiceRoll, PythSpacesAway( pSoldier->sGridNo, sTargetGridNo ) );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Hit chance was %ld, (range %d)", uiHitChance, PythSpacesAway( pSoldier->sGridNo, sTargetGridNo ) );
}
#endif
@@ -4379,7 +4376,7 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
}
/////////////////////////////////////////////////////////////////////////////////////
CalculateLaunchItemParamsForThrow( pSoldier, sTargetGridNo, pSoldier->bTargetLevel, 0, &Launchable, (INT8)(uiDiceRoll - uiHitChance), THROW_ARM_ITEM, 0 );
CalculateLaunchItemParamsForThrow( pSoldier, sTargetGridNo, pSoldier->bTargetLevel, 0, &Launchable, uiHitChance, THROW_ARM_ITEM, 0, usItemNum );
iID = CreatePhysicalObject( pSoldier->pTempObject, pSoldier->pThrowParams->dLifeSpan, pSoldier->pThrowParams->dX, pSoldier->pThrowParams->dY, pSoldier->pThrowParams->dZ, pSoldier->pThrowParams->dForceX, pSoldier->pThrowParams->dForceY, pSoldier->pThrowParams->dForceZ, pSoldier->ubID, pSoldier->pThrowParams->ubActionCode, pSoldier->pThrowParams->uiActionData, FALSE );
@@ -10510,7 +10507,7 @@ UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
{
// MECHANICALLY FIRED arced projectile (ie. mortar), need brains & know-how
iChance = ( EffectiveDexterity( pSoldier, FALSE ) + EffectiveMarksmanship( pSoldier ) + EffectiveWisdom( pSoldier ) + pSoldier->stats.bExpLevel ) / 4;
iChance = ( EffectiveDexterity( pSoldier, FALSE ) + EffectiveMarksmanship( pSoldier ) + EffectiveWisdom( pSoldier ) + (pSoldier->stats.bExpLevel * 10) ) / 4;
////////////////////////////////////////////////////////////////////////////////////////////////
// SANDRO - old/new traits
+27 -71
View File
@@ -115,10 +115,6 @@ FLOAT CalculateForceFromRange( UINT16 usItem, INT16 sRange, FLOAT dDegrees
INT32 RandomGridFromRadius( INT32 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadius );
// Parameters for item throwing
#define MAX_MISS_BY 30
#define MIN_MISS_BY 1
#define MAX_MISS_RADIUS 5
// Lesh: needed to fix item throwing through window
extern INT16 DirIncrementer[8];
@@ -2206,7 +2202,7 @@ FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees , OBJECTTY
}
void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubLevel, INT16 sEndZ, OBJECTTYPE *pItem, INT8 bMissBy, UINT8 ubActionCode, UINT32 uiActionData )
void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubLevel, INT16 sEndZ, OBJECTTYPE *pItem, UINT32 uiHitChance, UINT8 ubActionCode, UINT32 uiActionData, UINT16 usItemNum )
{
FLOAT dForce, dDegrees;
INT16 sDestX, sDestY, sSrcX, sSrcY;
@@ -2216,7 +2212,6 @@ void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UI
UINT16 usLauncher;
INT16 sStartZ;
INT8 bMinMissRadius, bMaxMissRadius, bMaxRadius;
FLOAT fScale;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemParamsForThrow");
@@ -2228,74 +2223,31 @@ void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UI
fArmed = TRUE;
}
if ( bMissBy < 0 )
// set the max miss radius
if ( Item[usItemNum].mortar )
{
// then we hit!
bMissBy = 0;
// SANDRO - new merc records
if( pSoldier->bTeam == 0 && pSoldier->ubProfile != NO_PROFILE )
{
gMercProfiles[ pSoldier->ubProfile ].records.usShotsHit++;
}
bMaxRadius = gItemSettings.usMissMaxRadiusMortar;
}
else
{
bMaxRadius = gItemSettings.usMissMaxRadiusGrenade;
}
//if ( 0 )
if ( bMissBy > 0 )
{
// Max the miss variance
if ( bMissBy > MAX_MISS_BY )
{
bMissBy = MAX_MISS_BY;
}
// calculate the actual min and max miss radius based on CtH
bMinMissRadius = ( (FLOAT)bMaxRadius * ( 10.0f - sqrt((FLOAT)uiHitChance) ) / 10.0f );
bMaxMissRadius = bMaxRadius * ( 100 - uiHitChance ) / 100;
// Min the miss varience...
if ( bMissBy < MIN_MISS_BY )
{
bMissBy = MIN_MISS_BY;
}
// modify by a bit of luck
bMinMissRadius = __max( (bMinMissRadius - Random(2)), 0);
bMinMissRadius = __min( (bMinMissRadius + Random(2)), bMaxRadius);
// Adjust position, force, angle
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Throw miss by: %d", bMissBy );
#endif
bMaxMissRadius = __max( (bMaxMissRadius - Random(2)), 0);
bMaxMissRadius = __min( (bMaxMissRadius + Random(2)), bMaxRadius);
// Default to max radius...
bMaxRadius = 5;
// min miss radius cannot be greater than max miss radius
bMinMissRadius = __min( bMinMissRadius, bMaxMissRadius);
// scale if pyth spaces away is too far
if ( PythSpacesAway( sGridNo, pSoldier->sGridNo ) < ( (float)bMaxRadius / (float)1.5 ) )
{
bMaxRadius = PythSpacesAway( sGridNo, pSoldier->sGridNo ) / 2;
}
// Get radius
fScale = ( (float)bMissBy / (float) MAX_MISS_BY );
bMaxMissRadius = (INT8)( bMaxRadius * fScale );
// Limit max radius...
if ( bMaxMissRadius > 4 )
{
bMaxMissRadius = 4;
}
bMinMissRadius = bMaxMissRadius - 1;
if ( bMinMissRadius < 2 )
{
bMinMissRadius = 2;
}
if ( bMaxMissRadius < bMinMissRadius )
{
bMaxMissRadius = bMinMissRadius;
}
sGridNo = RandomGridFromRadius( sGridNo, bMinMissRadius, bMaxMissRadius );
}
sGridNo = RandomGridFromRadius( sGridNo, bMinMissRadius, bMaxMissRadius );
// Get basic launch params...
CalculateLaunchItemBasicParams( pSoldier, pItem, sGridNo, ubLevel, sEndZ, &dForce, &dDegrees, &sFinalGridNo, fArmed );
@@ -2309,7 +2261,7 @@ void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UI
vDirNormal.y = (float)(sDestY - sSrcY);
vDirNormal.z = 0;
// NOmralize
// Normalize
vDirNormal = VGetNormal( &vDirNormal );
// From degrees, calculate Z portion of normal
@@ -2845,15 +2797,19 @@ INT32 RandomGridFromRadius( INT32 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadi
BOOLEAN fFound = FALSE;
UINT32 cnt = 0;
if ( ubMaxRadius == 0 || ubMinRadius == 0 )
// just a precaution...
ubMaxRadius = __max( ubMaxRadius, 0 );
ubMinRadius = __max( __min( ubMinRadius, ubMaxRadius ), 0 );
if ( ubMaxRadius == 0)
{
return( sSweetGridNo );
}
do
{
sX = (UINT16)PreRandom( ubMaxRadius );
sY = (UINT16)PreRandom( ubMaxRadius );
sX = (UINT16)PreRandom( ubMaxRadius + 1 );
sY = (UINT16)PreRandom( ubMaxRadius + 1 );
if ( ( sX < ubMinRadius || sY < ubMinRadius ) && ubMaxRadius != ubMinRadius )
{
+1 -1
View File
@@ -167,7 +167,7 @@ FLOAT CalculateLaunchItemAngle( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubHe
BOOLEAN CalculateLaunchItemChanceToGetThrough( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, INT32 sGridNo, UINT8 ubLevel, INT16 sEndZ, INT32 *psFinalGridNo, BOOLEAN fArmed, INT8 *pbLevel, BOOLEAN fFromUI );
void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubLevel, INT16 sZPos, OBJECTTYPE *pItem, INT8 bMissBy, UINT8 ubActionCode, UINT32 uiActionData );
void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubLevel, INT16 sZPos, OBJECTTYPE *pItem, UINT32 uiHitChance, UINT8 ubActionCode, UINT32 uiActionData, UINT16 usItemNum = 0 );