From fed9ca298cf325460cd4c6bae91258dad544ccb0 Mon Sep 17 00:00:00 2001 From: silversurfer Date: Wed, 22 Aug 2018 17:54:24 +0000 Subject: [PATCH] - 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 --- GameSettings.cpp | 2 + GameSettings.h | 2 + GameVersion.cpp | 4 +- Tactical/Interface Items.cpp | 2 +- Tactical/Weapons.cpp | 21 ++++---- TileEngine/physics.cpp | 98 ++++++++++-------------------------- TileEngine/physics.h | 2 +- 7 files changed, 44 insertions(+), 87 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 68210c19..8813e330 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -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 ); diff --git a/GameSettings.h b/GameSettings.h index 8779a4b4..eac9f61b 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -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 diff --git a/GameVersion.cpp b/GameVersion.cpp index e60d1cb3..c58d86f2 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -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 diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index a90caa67..4c2373e4 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -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 ); diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 287c120b..ad7c9b0d 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -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 diff --git a/TileEngine/physics.cpp b/TileEngine/physics.cpp index faec7c4a..7255503a 100644 --- a/TileEngine/physics.cpp +++ b/TileEngine/physics.cpp @@ -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 ) { diff --git a/TileEngine/physics.h b/TileEngine/physics.h index aa870220..4a3223d6 100644 --- a/TileEngine/physics.h +++ b/TileEngine/physics.h @@ -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 );