ExpAffect: don't spread fire on water.

StructureHit: check water level.
Only normal, stun and flashbang explosives create water explosion.
Increase max force when throwing items into water (to compensate for no bouncing).
Increased splash volume from LOWVOLUME to MIDVOLUME.
InternalIgniteExplosion: no fragments in water.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8752 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2020-02-13 15:57:10 +00:00
parent b57e4eba00
commit a6271e2e47
4 changed files with 63 additions and 47 deletions
+27 -25
View File
@@ -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
+12 -3
View File
@@ -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;
+23 -17
View File
@@ -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;
+1 -2
View File
@@ -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