diff --git a/GameSettings.cpp b/GameSettings.cpp index 32bd06c1..faa38f71 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1074,6 +1074,9 @@ void LoadGameExternalOptions() // Add smoke after regular explosions gGameExternalOptions.bAddSmokeAfterExplosion = iniReader.ReadBoolean("Tactical Interface Settings","ADD_SMOKE_AFTER_EXPLOSION",FALSE); + // Add light after fire or signal explosions + gGameExternalOptions.bAddLightAfterExplosion = iniReader.ReadBoolean("Tactical Interface Settings", "ADD_LIGHT_AFTER_EXPLOSION", FALSE); + // Attachments now can explode gGameExternalOptions.bAllowExplosiveAttachments = iniReader.ReadBoolean("Tactical Interface Settings","ALLOW_EXPLOSIVE_ATTACHMENTS",FALSE); @@ -1489,7 +1492,6 @@ void LoadGameExternalOptions() gGameExternalOptions.fEnemyJams = iniReader.ReadBoolean("Tactical Gameplay Settings", "ENEMY_JAMS", true, false); gGameExternalOptions.fNewRandom = iniReader.ReadBoolean("Tactical Gameplay Settings", "NEW_RANDOM", true, false); - //################# Tactical Enemy Role Settings ################## // Flugente: enemy roles gGameExternalOptions.fEnemyRoles = iniReader.ReadBoolean("Tactical Enemy Role Settings", "ENEMYROLES", TRUE); diff --git a/GameSettings.h b/GameSettings.h index 181c4b61..0b168714 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -893,6 +893,7 @@ typedef struct BOOLEAN bExtraCivilians; // Flugente: add civilians via LUA BOOLEAN bExtraMerchants; // Flugente: add non-profile-based merchants via LUA BOOLEAN bAddSmokeAfterExplosion; + BOOLEAN bAddLightAfterExplosion; BOOLEAN bAllowExplosiveAttachments; BOOLEAN bAllowSpecialExplosiveAttachments; BOOLEAN fDelayedGrenadeExplosion; diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 6c8518c8..6d89b23e 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -401,14 +401,28 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 if( gGameExternalOptions.bAllowExplosiveAttachments ) HandleAttachedExplosions(ubOwner, sX, sY, sZ, sGridNo, usItem, fLocate, bLevel, ubDirection, pObj ); - // sevenfm: add smoke effect if not in room and not underground, only for normal explosions - if(!InARoom( sGridNo, &tmp ) && !gbWorldSectorZ && gGameExternalOptions.bAddSmokeAfterExplosion) + // sevenfm: add smoke effect, only for normal explosions + if (gGameExternalOptions.bAddSmokeAfterExplosion && + !Water(sGridNo, bLevel)) { - if( Explosive[ Item[ usItem ].ubClassIndex ].ubType == 0 ) + if (Explosive[Item[usItem].ubClassIndex].ubType == 0 && + Item[usItem].usBuddyItem == 0 && + Explosive[Item[usItem].ubClassIndex].ubDamage > 20) { - NewSmokeEffect( sGridNo, SMALL_SMOKE, 0, NOBODY ); + NewSmokeEffect(sGridNo, SMOKE_GRENADE, bLevel, ubOwner, 0, 2, 1); } } + + // sevenfm: add light for fire and signal effects + if (gGameExternalOptions.bAddLightAfterExplosion && + ((gubEnvLightValue >= NORMAL_LIGHTLEVEL_NIGHT - 3) || gbWorldSectorZ) && + (Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_BURNABLEGAS || Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_SIGNAL_SMOKE) && + bLevel == 0 && + !Water(sGridNo, bLevel)) + { + // add light + NewLightEffect(sGridNo, (UINT8)Explosive[Item[usItem].ubClassIndex].ubDuration + 2, (UINT8)Explosive[Item[usItem].ubClassIndex].ubRadius + 1); + } } @@ -1966,8 +1980,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN fGasDamageModifier = gItemSettings.fDamageHealthMoveModifierExplosive; fGasBreathDamageModifier = gItemSettings.fDamageBreathMoveModifierExplosive; // modify damage values - sWoundAmt *= fGasDamageModifier; - sBreathAmt *= fGasBreathDamageModifier; + sWoundAmt = (INT16)(sWoundAmt * fGasDamageModifier); + sBreathAmt = (INT16)(sBreathAmt * fGasBreathDamageModifier); //return( fRecompileMovementCosts ); } } @@ -2027,8 +2041,8 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN } // modify damage values - sWoundAmt *= fGasDamageModifier; - sBreathAmt *= fGasBreathDamageModifier; + sWoundAmt = (INT16)(sWoundAmt * fGasDamageModifier); + sBreathAmt = (INT16)(sBreathAmt * fGasBreathDamageModifier); bPosOfMask = FindGasMask(pSoldier); if(!DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909 diff --git a/TileEngine/SmokeEffects.cpp b/TileEngine/SmokeEffects.cpp index 865387d5..16b9054f 100644 --- a/TileEngine/SmokeEffects.cpp +++ b/TileEngine/SmokeEffects.cpp @@ -189,8 +189,8 @@ UINT16 FromSmokeTypeToWorldFlags( INT8 bType ) INT32 NewSmokeEffect( INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, BOOL fFromRemoteClient ) { SMOKEEFFECT *pSmoke; - INT32 iSmokeIndex; - INT8 bSmokeEffectType=0; + INT32 iSmokeIndex; + INT8 bSmokeEffectType=0; if( ( iSmokeIndex = GetFreeSmokeEffect() )==(-1) ) return(-1); @@ -313,7 +313,7 @@ INT32 NewSmokeEffect( INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, if ( bLevel ) { - pSmoke->bFlags |= SMOKE_EFFECT_ON_ROOF; + pSmoke->bFlags |= SMOKE_EFFECT_ON_ROOF; } // ATE: FALSE into subsequent-- it's the first one! @@ -322,6 +322,130 @@ INT32 NewSmokeEffect( INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, return( iSmokeIndex ); } +INT32 NewSmokeEffect(INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, BOOLEAN fFromRemoteClient, UINT8 ubDuration, UINT8 ubRadius, UINT8 ubGeneration) +{ + SMOKEEFFECT *pSmoke; + INT32 iSmokeIndex; + INT8 bSmokeEffectType = 0; + + iSmokeIndex = GetFreeSmokeEffect(); + + if (iSmokeIndex == -1) + { + return -1; + } + + // OJW - 20091027 - Synchronizing smoke effect start for multiplayer + if (is_networked && is_client) + { + SOLDIERTYPE* pSoldier = MercPtrs[ubOwner]; + if (pSoldier != NULL) + { + if (pSoldier->bTeam == 0 || (pSoldier->bTeam == 1 && is_server)) + { + // let all the other clients know we are spawning this effect + // and align them with our random number generator + send_newsmokeeffect(sGridNo, usItem, ubOwner, bLevel, iSmokeIndex); + } + else if (!fFromRemoteClient) + { + // skip executing locally because we want the random number generator to be aligned + // with the client that spawns set off the smoke effect + return -1; + } + } +#ifdef JA2BETAVERSION + CHAR tmpMPDbgString[512]; + sprintf(tmpMPDbgString, "NewSmokeEffect ( sGridNo : %i , usItem : %i , ubOwner : %i , bLevel : %i , iSmokeEffectID : %i )\n", sGridNo, usItem, ubOwner, bLevel, iSmokeIndex); + MPDebugMsg(tmpMPDbgString); + gfMPDebugOutputRandoms = true; +#endif + } + + memset(&gSmokeEffectData[iSmokeIndex], 0, sizeof(SMOKEEFFECT)); + pSmoke = &gSmokeEffectData[iSmokeIndex]; + + // Set some values... + pSmoke->sGridNo = sGridNo; + pSmoke->usItem = usItem; + pSmoke->uiTimeOfLastUpdate = GetWorldTotalSeconds(); + + switch (Explosive[Item[usItem].ubClassIndex].ubType) + { + case EXPLOSV_MUSTGAS: + bSmokeEffectType = MUSTARDGAS_SMOKE_EFFECT; + break; + case EXPLOSV_BURNABLEGAS: + bSmokeEffectType = BURNABLEGAS_SMOKE_EFFECT; + break; + case EXPLOSV_TEARGAS: + bSmokeEffectType = TEARGAS_SMOKE_EFFECT; + break; + case EXPLOSV_SMOKE: + bSmokeEffectType = NORMAL_SMOKE_EFFECT; + break; + case EXPLOSV_CREATUREGAS: + bSmokeEffectType = CREATURE_SMOKE_EFFECT; + break; + case EXPLOSV_SIGNAL_SMOKE: + bSmokeEffectType = SIGNAL_SMOKE_EFFECT; + break; + case EXPLOSV_SMOKE_DEBRIS: + bSmokeEffectType = DEBRIS_SMOKE_EFFECT; + break; + } + + // sevenfm: use custom duration/radius + if (ubDuration) + pSmoke->ubDuration = ubDuration; + else + pSmoke->ubDuration = (UINT8)Explosive[Item[usItem].ubClassIndex].ubDuration; + + if (ubRadius) + pSmoke->ubRadius = ubRadius; + else + pSmoke->ubRadius = (UINT8)Explosive[Item[usItem].ubClassIndex].ubStartRadius; + + pSmoke->bAge = 0; + pSmoke->fAllocated = TRUE; + pSmoke->bType = bSmokeEffectType; + pSmoke->ubOwner = ubOwner; + pSmoke->ubGeneration = ubGeneration; + + // Are we indoors? + // sevenfm: check also roof above + if (GetTerrainType(sGridNo) == FLAT_FLOOR && bLevel == 0 && FindStructure(sGridNo, STRUCTURE_ROOF) != NULL) + { + pSmoke->bFlags |= SMOKE_EFFECT_INDOORS; + } + + if (pSmoke->bFlags & SMOKE_EFFECT_INDOORS) + { + // Duration is increased by 2 turns...indoors + pSmoke->ubDuration += 2; + } + else + { + // limit smoke effects in the rain + switch (SectorInfo[SECTOR(gWorldSectorX, gWorldSectorY)].usWeather) + { + case WEATHER_FORECAST_RAIN: pSmoke->ubDuration = max(0, pSmoke->ubDuration - 2); break; + case WEATHER_FORECAST_THUNDERSHOWERS: pSmoke->ubDuration = max(0, pSmoke->ubDuration - 3); break; + case WEATHER_FORECAST_SANDSTORM: pSmoke->ubDuration = max(0, pSmoke->ubDuration - 1); break; + case WEATHER_FORECAST_SNOW: pSmoke->ubDuration = max(0, pSmoke->ubDuration - 1); break; + } + } + + if (bLevel) + { + pSmoke->bFlags |= SMOKE_EFFECT_ON_ROOF; + } + + // ATE: FALSE into subsequent-- it's the first one! + SpreadEffect(pSmoke->sGridNo, pSmoke->ubRadius, pSmoke->usItem, pSmoke->ubOwner, FALSE, bLevel, iSmokeIndex, fFromRemoteClient, TRUE); + + return(iSmokeIndex); +} // Add smoke to gridno // ( Replacement algorithm uses distance away ) diff --git a/TileEngine/SmokeEffects.h b/TileEngine/SmokeEffects.h index ee601c25..af185f38 100644 --- a/TileEngine/SmokeEffects.h +++ b/TileEngine/SmokeEffects.h @@ -33,7 +33,7 @@ typedef struct TAG_SMOKE_EFFECT INT8 bType; UINT16 usItem; UINT8 ubOwner; - UINT8 ubPadding; + UINT8 ubGeneration; UINT32 uiTimeOfLastUpdate; INT8 iMPTeamIndex; INT32 iMPSmokeEffectID; @@ -56,13 +56,11 @@ void AddSmokeEffectToTile( INT32 iSmokeEffectID, INT8 bType, INT32 sGridNo, INT8 void RemoveSmokeEffectFromTile( INT32 sGridNo, INT8 bLevel ); -INT32 NewSmokeEffect( INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, BOOL fFromRemoteClient = 0 ); - +INT32 NewSmokeEffect(INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, BOOLEAN fFromRemoteClient = 0, UINT8 ubDuration = 0, UINT8 ubRadius = 0, UINT8 ubGeneration = 0); BOOLEAN SaveSmokeEffectsToSaveGameFile( HWFILE hFile ); BOOLEAN LoadSmokeEffectsFromLoadGameFile( HWFILE hFile ); - BOOLEAN SaveSmokeEffectsToMapTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ); BOOLEAN LoadSmokeEffectsFromMapTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ );