- 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.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.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.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 -------------- // ------------ MISC MODIFIERS --------------
gItemSettings.fShieldMovementAPCostModifier = iniReader.ReadFloat ("Misc Settings", "SHIELD_MOVEMENT_APCOST_MODIFIER", 1.7f, 1.0f, 10.0f ); 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 fDamageBreathModifierExplosive;
FLOAT fDamageHealthMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask 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 FLOAT fDamageBreathMoveModifierExplosive; // applies when character moves through gas cloud without a gas mask
UINT8 usMissMaxRadiusGrenade;
UINT8 usMissMaxRadiusMortar;
// ------------ MISC MODIFIERS -------------- // ------------ MISC MODIFIERS --------------
// Flugente // Flugente
+2 -2
View File
@@ -55,8 +55,8 @@
#endif #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 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 // 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! // 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 // OK, goto throw animation
HandleSoldierThrowItem( gpItemPointerSoldier, usMapPos ); 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 ) BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{ {
UINT32 uiHitChance, uiDiceRoll; UINT32 uiHitChance;
INT8 bLoop; INT8 bLoop;
UINT8 ubTargetID; UINT8 ubTargetID;
SOLDIERTYPE * pTargetSoldier; SOLDIERTYPE * pTargetSoldier;
@@ -4069,12 +4069,10 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO ); uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO );
uiDiceRoll = PreRandom( 100 );
#ifdef JA2BETAVERSION #ifdef JA2BETAVERSION
if ( gfReportHitChances ) 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 #endif
@@ -4132,7 +4130,8 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
// Snap: calculate experience points for dexterity and marksmanship // Snap: calculate experience points for dexterity and marksmanship
usExpGain = 5 // For at least one target usExpGain = 5 // For at least one target
+ 2*(usNumTargets-1); // For every additional 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 :) if ( fGonnaHit ) usExpGain *= 2; // For actually hitting the target :)
usExpGain += (UINT16) (100 - uiHitChance) / 10; // Extra exp for a difficult target usExpGain += (UINT16) (100 - uiHitChance) / 10; // Extra exp for a difficult target
StatChange( pSoldier, DEXTAMT, usExpGain / 2, ( fGonnaHit ? FALSE : FROM_FAILURE ) ); 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 #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 //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 ) BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{ {
UINT32 uiHitChance, uiDiceRoll; UINT32 uiHitChance;
INT16 sAPCost = 0; INT16 sAPCost = 0;
INT32 iBPCost = 0; INT32 iBPCost = 0;
OBJECTTYPE Launchable; OBJECTTYPE Launchable;
@@ -4323,12 +4322,10 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO ); uiHitChance = CalcThrownChanceToHit( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, AIM_SHOT_TORSO );
uiDiceRoll = PreRandom( 100 );
#ifdef JA2BETAVERSION #ifdef JA2BETAVERSION
if ( gfReportHitChances ) 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 #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 ); 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 // 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 // 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 ); 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 // Lesh: needed to fix item throwing through window
extern INT16 DirIncrementer[8]; 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; FLOAT dForce, dDegrees;
INT16 sDestX, sDestY, sSrcX, sSrcY; INT16 sDestX, sDestY, sSrcX, sSrcY;
@@ -2216,7 +2212,6 @@ void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UI
UINT16 usLauncher; UINT16 usLauncher;
INT16 sStartZ; INT16 sStartZ;
INT8 bMinMissRadius, bMaxMissRadius, bMaxRadius; INT8 bMinMissRadius, bMaxMissRadius, bMaxRadius;
FLOAT fScale;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemParamsForThrow"); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemParamsForThrow");
@@ -2228,74 +2223,31 @@ void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT32 sGridNo, UI
fArmed = TRUE; fArmed = TRUE;
} }
if ( bMissBy < 0 ) // set the max miss radius
if ( Item[usItemNum].mortar )
{ {
// then we hit! bMaxRadius = gItemSettings.usMissMaxRadiusMortar;
bMissBy = 0; }
else
// SANDRO - new merc records {
if( pSoldier->bTeam == 0 && pSoldier->ubProfile != NO_PROFILE ) bMaxRadius = gItemSettings.usMissMaxRadiusGrenade;
{
gMercProfiles[ pSoldier->ubProfile ].records.usShotsHit++;
}
} }
//if ( 0 ) // calculate the actual min and max miss radius based on CtH
if ( bMissBy > 0 ) bMinMissRadius = ( (FLOAT)bMaxRadius * ( 10.0f - sqrt((FLOAT)uiHitChance) ) / 10.0f );
{ bMaxMissRadius = bMaxRadius * ( 100 - uiHitChance ) / 100;
// Max the miss variance
if ( bMissBy > MAX_MISS_BY )
{
bMissBy = MAX_MISS_BY;
}
// Min the miss varience... // modify by a bit of luck
if ( bMissBy < MIN_MISS_BY ) bMinMissRadius = __max( (bMinMissRadius - Random(2)), 0);
{ bMinMissRadius = __min( (bMinMissRadius + Random(2)), bMaxRadius);
bMissBy = MIN_MISS_BY;
}
// Adjust position, force, angle bMaxMissRadius = __max( (bMaxMissRadius - Random(2)), 0);
#ifdef JA2TESTVERSION bMaxMissRadius = __min( (bMaxMissRadius + Random(2)), bMaxRadius);
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Throw miss by: %d", bMissBy );
#endif
// Default to max radius... // min miss radius cannot be greater than max miss radius
bMaxRadius = 5; bMinMissRadius = __min( bMinMissRadius, bMaxMissRadius);
// scale if pyth spaces away is too far sGridNo = RandomGridFromRadius( sGridNo, bMinMissRadius, bMaxMissRadius );
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 );
}
// Get basic launch params... // Get basic launch params...
CalculateLaunchItemBasicParams( pSoldier, pItem, sGridNo, ubLevel, sEndZ, &dForce, &dDegrees, &sFinalGridNo, fArmed ); 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.y = (float)(sDestY - sSrcY);
vDirNormal.z = 0; vDirNormal.z = 0;
// NOmralize // Normalize
vDirNormal = VGetNormal( &vDirNormal ); vDirNormal = VGetNormal( &vDirNormal );
// From degrees, calculate Z portion of normal // From degrees, calculate Z portion of normal
@@ -2845,15 +2797,19 @@ INT32 RandomGridFromRadius( INT32 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadi
BOOLEAN fFound = FALSE; BOOLEAN fFound = FALSE;
UINT32 cnt = 0; 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 ); return( sSweetGridNo );
} }
do do
{ {
sX = (UINT16)PreRandom( ubMaxRadius ); sX = (UINT16)PreRandom( ubMaxRadius + 1 );
sY = (UINT16)PreRandom( ubMaxRadius ); sY = (UINT16)PreRandom( ubMaxRadius + 1 );
if ( ( sX < ubMinRadius || sY < ubMinRadius ) && ubMaxRadius != ubMinRadius ) 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 ); 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 );