diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 4ef71697..42e31755 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -4857,17 +4857,18 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UINT8 ubAttackerID, UINT16 sXPos, INT16 sYPos, INT16 sZPos, UINT16 usStructureID, INT32 iImpact, BOOLEAN fStopped ) { - BOOLEAN fDoMissForGun = FALSE; - ANITILE *pNode; - INT32 sGridNo; + BOOLEAN fDoMissForGun = FALSE; + ANITILE *pNode; + INT32 sGridNo; + INT8 bLevel; ANITILE_PARAMS AniParams; - UINT16 usMissTileIndex, usMissTileType; - STRUCTURE *pStructure = NULL; - UINT32 uiMissVolume = MIDVOLUME; - BOOLEAN fHitSameStructureAsBefore; - BULLET * pBullet; - SOLDIERTYPE * pAttacker = NULL; - OBJECTTYPE * pObj = NULL; + UINT16 usMissTileIndex, usMissTileType; + STRUCTURE *pStructure = NULL; + UINT32 uiMissVolume = MIDVOLUME; + BOOLEAN fHitSameStructureAsBefore; + BULLET *pBullet; + SOLDIERTYPE *pAttacker = NULL; + OBJECTTYPE *pObj = NULL; pBullet = GetBulletPtr( iBullet ); Assert(pBullet); @@ -4923,16 +4924,15 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN } sGridNo = MAPROWCOLTOPOS( (sYPos/CELL_Y_SIZE), (sXPos/CELL_X_SIZE) ); + + if (sZPos >= WALL_HEIGHT) + bLevel = 1; + else + bLevel = 0; + if ( !fHitSameStructureAsBefore ) { - if (sZPos > WALL_HEIGHT) - { - MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT ); - } - else - { - MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT ); - } + MakeNoise(ubAttackerID, sGridNo, bLevel, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT); } if (fStopped) @@ -4961,11 +4961,11 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN { if ( Item[usWeaponIndex].usBuddyItem != 0 && Item[Item[usWeaponIndex].usBuddyItem].usItemClass & IC_EXPLOSV ) { - IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, Item[usWeaponIndex].usBuddyItem, (INT8)(sZPos >= WALL_HEIGHT), usDirection ); + IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, Item[usWeaponIndex].usBuddyItem, bLevel, usDirection ); } else { - IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)(sZPos >= WALL_HEIGHT), usDirection ); + IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, bLevel, usDirection ); } } // changed too to use 2 flag to determine @@ -4973,7 +4973,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN //there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) ); - IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand][0]->data.gun.usGunAmmoItem, (INT8)(sZPos >= WALL_HEIGHT), usDirection ); + IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand][0]->data.gun.usGunAmmoItem, bLevel, usDirection ); //This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now. OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem ); @@ -4989,7 +4989,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1) { // re-routed the Highexplosive value to define exposion type - IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].highExplosive, (INT8)(sZPos >= WALL_HEIGHT), usDirection ); + IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].highExplosive, bLevel, usDirection ); // pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE; } } @@ -5007,7 +5007,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN //FreeUpAttacker( ubAttackerID ); // HEADROCK HAM 5 TODO: Tank shell!! - IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, TANK_SHELL, (INT8)(sZPos >= WALL_HEIGHT), usDirection ); + IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, TANK_SHELL, bLevel, usDirection ); //FreeUpAttacker( (UINT8) ubAttackerID ); // Moved here to keep ABC >0 as long as possible @@ -5251,7 +5251,9 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN usMissTileType = FIRSTMISS; // Check if we are in water... - if ( TERRAIN_IS_WATER( gpWorldLevelData[ sGridNo ].ubTerrainID) ) + // sevenfm: check level + if (Water(sGridNo, bLevel)) + //if ( TERRAIN_IS_WATER( gpWorldLevelData[ sGridNo ].ubTerrainID) ) { usMissTileIndex = SECONDMISS1; usMissTileType = SECONDMISS; @@ -11280,7 +11282,7 @@ BOOLEAN ArtilleryStrike( UINT16 usItem, UINT8 ubOwnerID, UINT32 usStartingGridNo CreateItem( usItem, 100, &shellobj ); // Get basic launch params... - if ( !GetArtilleryLaunchParams(usStartingGridNo, sTargetGridNo, sStartZ, sEndZ, usItem, &shellobj, &dForce, &dDegrees) ) + if (!GetArtilleryLaunchParams(usStartingGridNo, sTargetGridNo, ubLevel, sStartZ, sEndZ, usItem, &shellobj, &dForce, &dDegrees)) return FALSE; // Get XY from gridno diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 6d89b23e..93bcfe88 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -388,7 +388,8 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 } // HEADROCK HAM 5.1: Launch fragments from the explosion. - if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 ) + // sevenfm: no fragments in water + if (Explosive[Item[usItem].ubClassIndex].usNumFragments > 0 && !Water(sGridNo, bLevel)) { // HEADROCK HAM 5: Deactivated until the release of HAM 5.1. FireFragments( ubOwner, sX, sY, sZ, usItem, ubDirection ); @@ -534,14 +535,15 @@ void GenerateExplosionFromExplosionPointer( EXPLOSIONTYPE *pExplosion ) AniParams.sStartFrame = pExplosion->sCurrentFrame; AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_EXPLOSION; - if ( TERRAIN_IS_WATER(ubTerrainType) ) + // sevenfm: check level + //if ( TERRAIN_IS_WATER(ubTerrainType) ) + if (Water(sGridNo, bLevel)) { // Change type to water explosion... ubTypeID = WATER_BLAST; AniParams.uiFlags |= ANITILE_ALWAYS_TRANSLUCENT; } - if ( sZ < WALL_HEIGHT ) { AniParams.uiFlags |= ANITILE_NOZBLITTER; @@ -2216,6 +2218,13 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte //Init the variables sX = sY = -1; + // sevenfm: don't spread fire on water + if (Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_BURNABLEGAS && + Water(sGridNo, bLevel)) + { + return FALSE; + } + if ( sSubsequent == BLOOD_SPREAD_EFFECT ) { fSmokeEffect = FALSE; diff --git a/TileEngine/physics.cpp b/TileEngine/physics.cpp index 4597ee52..4983bd2f 100644 --- a/TileEngine/physics.cpp +++ b/TileEngine/physics.cpp @@ -107,10 +107,10 @@ BOOLEAN PhysicsComputeForces( REAL_OBJECT *pObject ); BOOLEAN PhysicsIntegrate( REAL_OBJECT *pObject, real DeltaTime ); BOOLEAN PhysicsMoveObject( REAL_OBJECT *pObject ); BOOLEAN PhysicsCheckForCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID ); -void PhysicsResolveCollision( REAL_OBJECT *pObject, vector_3 *pVelocity, vector_3 *pNormal, real CoefficientOfRestitution ); -void PhysicsDeleteObject( REAL_OBJECT *pObject ); +void PhysicsResolveCollision( REAL_OBJECT *pObject, vector_3 *pVelocity, vector_3 *pNormal, real CoefficientOfRestitution ); +void PhysicsDeleteObject( REAL_OBJECT *pObject ); BOOLEAN PhysicsHandleCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID, real DeltaTime ); -FLOAT CalculateForceFromRange( UINT16 usItem, INT16 sRange, FLOAT dDegrees ); +FLOAT CalculateForceFromRange(UINT16 usItem, INT16 sRange, FLOAT dDegrees, INT32 sTargetSpot, UINT8 ubTargetLevel); INT32 RandomGridFromRadius( INT32 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadius ); @@ -122,7 +122,7 @@ void ObjectHitWindow( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSo FLOAT CalculateObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT32 *psFinalGridNo ); vector_3 FindBestForceForTrajectory( INT32 sSrcGridNo, INT32 sGridNo,INT16 sStartZ, INT16 sEndZ, real dzDegrees, OBJECTTYPE *pItem, INT32 *psGridNo, FLOAT *pzMagForce ); INT32 ChanceToGetThroughObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT32 *psFinalGridNo, INT8 *pbLevel, BOOLEAN fFromUI ); -FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees, OBJECTTYPE *pObject, BOOLEAN fArmed ); +FLOAT CalculateSoldierMaxForce(SOLDIERTYPE *pSoldier, FLOAT dDegrees, OBJECTTYPE *pObject, BOOLEAN fArmed, INT32 sTargetSpot, UINT8 ubTargetLevel); BOOLEAN AttemptToCatchObject( REAL_OBJECT *pObject ); BOOLEAN CheckForCatchObject( REAL_OBJECT *pObject ); BOOLEAN DoCatchObject( REAL_OBJECT *pObject ); @@ -1087,8 +1087,12 @@ BOOLEAN PhysicsCheckForCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID ) AniParams.sStartFrame = 0; AniParams.uiFlags = ANITILE_FORWARD; - - if ( pObject->ubActionCode == THROW_ARM_ITEM ) + // sevenfm: explosion animation only for normal, stun and flashbang type explosives + if (pObject->ubActionCode == THROW_ARM_ITEM && + (Item[pObject->Obj.usItem].usItemClass & IC_EXPLOSV) && + (Explosive[Item[pObject->Obj.usItem].ubClassIndex].ubType == EXPLOSV_NORMAL || + Explosive[Item[pObject->Obj.usItem].ubClassIndex].ubType == EXPLOSV_STUN || + Explosive[Item[pObject->Obj.usItem].ubClassIndex].ubType == EXPLOSV_FLASHBANG)) { gTacticalStatus.ubAttackBusyCount++; DebugAttackBusy( String( "Incrementing attack busy because of delayed water explosion. Now %d\n", gTacticalStatus.ubAttackBusyCount ) ); @@ -1111,7 +1115,7 @@ BOOLEAN PhysicsCheckForCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID ) CHAR8 zFilename[512]; sprintf(zFilename, "sounds\\misc\\Splash%d.ogg", Random(3) + 1); if (FileExists(zFilename)) - PlayJA2SampleFromFile(zFilename, RATE_11025, SoundVolume(LOWVOLUME, pObject->sGridNo), 1, SoundDir(pObject->sGridNo)); + PlayJA2SampleFromFile(zFilename, RATE_11025, SoundVolume(MIDVOLUME, pObject->sGridNo), 1, SoundDir(pObject->sGridNo)); } } @@ -2022,7 +2026,7 @@ void CalculateLaunchItemBasicParams( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, I FindBestForceForTrajectory( pSoldier->sGridNo, sGridNo, sStartZ, sEndZ, dDegrees, pItem, psFinalGridNo, &dMagForce ); // Adjust due to max range.... - dMaxForce = CalculateSoldierMaxForce( pSoldier, dDegrees, pItem, fArmed ); + dMaxForce = CalculateSoldierMaxForce(pSoldier, dDegrees, pItem, fArmed, sGridNo, ubLevel); if ( fIndoors ) { @@ -2038,7 +2042,7 @@ void CalculateLaunchItemBasicParams( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, I if ( fMortar || fGLauncher ) { // find min force - dMinForce = CalculateForceFromRange( pItem->usItem, (INT16)( sMinRange / 10 ), (FLOAT)( PI / 4 ) ); + dMinForce = CalculateForceFromRange(pItem->usItem, (INT16)(sMinRange / 10), (FLOAT)(PI / 4), sGridNo, ubLevel); if ( dMagForce < dMinForce ) { @@ -2055,7 +2059,7 @@ void CalculateLaunchItemBasicParams( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, I else { // Use MAX force, vary angle.... - dMagForce = CalculateSoldierMaxForce( pSoldier, dDegrees, pItem, fArmed ); + dMagForce = CalculateSoldierMaxForce(pSoldier, dDegrees, pItem, fArmed, sGridNo, ubLevel); if ( ubLevel == 0 ) { @@ -2155,7 +2159,7 @@ BOOLEAN CalculateLaunchItemChanceToGetThrough( SOLDIERTYPE *pSoldier, OBJECTTYPE -FLOAT CalculateForceFromRange(UINT16 usItem, INT16 sRange, FLOAT dDegrees ) +FLOAT CalculateForceFromRange(UINT16 usItem, INT16 sRange, FLOAT dDegrees, INT32 sTargetSpot, UINT8 ubTargetLevel) { FLOAT dMagForce; INT32 sSrcGridNo, sDestGridNo; @@ -2173,7 +2177,9 @@ FLOAT CalculateForceFromRange(UINT16 usItem, INT16 sRange, FLOAT dDegrees ) // Buggler: impact explosives requiring larger force to reach desired range due to no bounce // Please change the if conditions too when definition of OBJECT_DETONATE_ON_IMPACT( object ) changes - if ((Item[usItem].usItemClass == IC_BOMB) || ((Item[usItem].usItemClass & IC_EXPLOSV) && Explosive[Item[usItem].ubClassIndex].fExplodeOnImpact)) + if ((Item[usItem].usItemClass == IC_BOMB) || + ((Item[usItem].usItemClass & IC_EXPLOSV) && Explosive[Item[usItem].ubClassIndex].fExplodeOnImpact) || + Water(sTargetSpot, ubTargetLevel)) // Use a mortar shell objecttype to simulate impact explosives CreateItem( MORTAR_SHELL, 100, &gTempObject ); else @@ -2189,7 +2195,7 @@ FLOAT CalculateForceFromRange(UINT16 usItem, INT16 sRange, FLOAT dDegrees ) } -FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees , OBJECTTYPE *pItem , BOOLEAN fArmed ) +FLOAT CalculateSoldierMaxForce(SOLDIERTYPE *pSoldier, FLOAT dDegrees, OBJECTTYPE *pItem, BOOLEAN fArmed, INT32 sTargetSpot, UINT8 ubTargetLevel) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateSoldierMaxForce"); @@ -2200,7 +2206,7 @@ FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees , OBJECTTY uiMaxRange = CalcMaxTossRange( pSoldier, pItem->usItem, fArmed, pItem ); - dMagForce = CalculateForceFromRange( pItem->usItem, (INT16) uiMaxRange, dDegrees ); + dMagForce = CalculateForceFromRange(pItem->usItem, (INT16)uiMaxRange, dDegrees, sTargetSpot, ubTargetLevel); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateSoldierMaxForce: done"); return( dMagForce ); @@ -2864,7 +2870,7 @@ UINT32 GetArtilleryTargetGridNo( UINT32 sTargetGridNo, INT8 bRadius ) return RandomGridFromRadius( sTargetGridNo, 1, bRadius ); } -BOOLEAN GetArtilleryLaunchParams( UINT32 sStartingGridNo, UINT32 sTargetGridNo, INT16 sStartZ, INT16 sEndZ, UINT16 usLauncher, OBJECTTYPE* pObj, FLOAT* pdForce, FLOAT* pdDegrees) +BOOLEAN GetArtilleryLaunchParams(UINT32 sStartingGridNo, UINT32 sTargetGridNo, UINT8 ubTargetLevel, INT16 sStartZ, INT16 sEndZ, UINT16 usLauncher, OBJECTTYPE* pObj, FLOAT* pdForce, FLOAT* pdDegrees) { FLOAT dMagForce, dMaxForce, dMinForce; FLOAT dDegrees = OUTDOORS_START_ANGLE; @@ -2878,12 +2884,12 @@ BOOLEAN GetArtilleryLaunchParams( UINT32 sStartingGridNo, UINT32 sTargetGridNo, INT32 uiMaxRange = GetModifiedGunRange(usLauncher) / CELL_X_SIZE; - dMaxForce = CalculateForceFromRange( NULL, (INT16) uiMaxRange, (FLOAT)( PI/4 ) ); + dMaxForce = CalculateForceFromRange(NULL, (INT16)uiMaxRange, (FLOAT)(PI / 4), sTargetGridNo, ubTargetLevel); if ( dMagForce > dMaxForce ) dMagForce = dMaxForce; - dMinForce = CalculateForceFromRange( NULL, (INT16)( sMinRange / 10 ), (FLOAT)( PI / 4 ) ); + dMinForce = CalculateForceFromRange(NULL, (INT16)(sMinRange / 10), (FLOAT)(PI / 4), sTargetGridNo, ubTargetLevel); if ( dMagForce < dMinForce ) dMagForce = dMinForce; diff --git a/TileEngine/physics.h b/TileEngine/physics.h index 4a3223d6..7fcf3b4a 100644 --- a/TileEngine/physics.h +++ b/TileEngine/physics.h @@ -184,7 +184,6 @@ BOOLEAN LoadPhysicsTableFromSavedGameFile( HWFILE hFile ); // Flugente: artillery functions INT32 RandomGridFromRadius( INT32 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadius ); UINT32 GetArtilleryTargetGridNo( UINT32 sTargetGridNo, INT8 bRadius ); -BOOLEAN GetArtilleryLaunchParams( UINT32 sStartingGridNo, UINT32 sTargetGridNo, INT16 sStartZ, INT16 sEndZ, UINT16 usLauncher, OBJECTTYPE* pObj, FLOAT* pdForce, FLOAT* pdDegrees); - +BOOLEAN GetArtilleryLaunchParams(UINT32 sStartingGridNo, UINT32 sTargetGridNo, UINT8 ubTargetLevel, INT16 sStartZ, INT16 sEndZ, UINT16 usLauncher, OBJECTTYPE* pObj, FLOAT* pdForce, FLOAT* pdDegrees); #endif \ No newline at end of file