diff --git a/GameVersion.cpp b/GameVersion.cpp index 02109eae..6ebbab93 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -55,8 +55,8 @@ #endif -CHAR8 czVersionNumber[16] = { "Build 21.06.27" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 21.07.13" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; -CHAR16 zRevisionNumber[16] = { L"Revision 9113" }; +CHAR16 zRevisionNumber[16] = { L"Revision 9141" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index e2129e8a..1c9a1974 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -864,6 +864,7 @@ static int l_CreateCivilian( lua_State *L ); static int l_BuildFortification( lua_State *L ); static int l_RemoveFortification( lua_State *L ); +static int l_DestroyAndReplaceDecal( lua_State *L ); static int l_GetFact( lua_State *L ); static int l_SetFact( lua_State *L ); @@ -1762,6 +1763,7 @@ void IniFunction(lua_State *L, BOOLEAN bQuests ) lua_register( L, "BuildFortification", l_BuildFortification ); lua_register( L, "RemoveFortification", l_RemoveFortification ); + lua_register( L, "DestroyAndReplaceDecal", l_DestroyAndReplaceDecal ); lua_register(L, "GetFact", l_GetFact ); lua_register(L, "SetFact", l_SetFact ); @@ -13126,6 +13128,32 @@ static int l_RemoveFortification( lua_State *L ) return 0; } +static int l_DestroyAndReplaceDecal( lua_State *L ) +{ + if ( lua_gettop( L ) >= 3 ) + { + INT32 sGridNo = lua_tointeger( L, 1 ); + + size_t len = 0; + const char* str = lua_tolstring( L, 2, &len ); + + UINT8 index = lua_tointeger( L, 3 ); + + ApplyMapChangesToMapTempFile( TRUE ); + + RemoveAllStructsOfTypeRange( sGridNo, FIRSTWALLDECAL, FOURTHWALLDECAL ); + RemoveAllStructsOfTypeRange( sGridNo, FIFTHWALLDECAL, EIGTHWALLDECAL ); + RemoveAllStructsOfTypeRange( sGridNo, FIRSTDECORATIONS, FOURTHDECORATIONS ); + + + BuildStructFromName( sGridNo, 0, str, index ); + + ApplyMapChangesToMapTempFile( FALSE ); + } + + return 0; +} + static int l_GetFact( lua_State *L ) { if ( lua_gettop( L ) ) diff --git a/Tactical/Bullets.h b/Tactical/Bullets.h index 5f332b1e..db087445 100644 --- a/Tactical/Bullets.h +++ b/Tactical/Bullets.h @@ -18,6 +18,7 @@ #define BULLET_FLAG_TRACER 0x0100 #define BULLET_FLAG_ANTIMATERIEL 0x0200 // Flugente: bullet can destroy structures #define BULLET_FLAG_INFECTED 0x0400 // Flugente: bullet is infected +#define BULLET_FLAG_WHITESMOKE 0x0800 // Flugente: bullet leaves a white smoke trail (for fire extinguisher) //afp-start calculate line points between two point #define BULLET_TRACER_MAX_LENGTH 60 diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index d5ca4947..28d25768 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -7694,6 +7694,86 @@ UINT8 CheckBuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32 return 1; } +BOOLEAN BuildStructFromName( INT32 sGridNo, INT8 sLevel, const char* aStr, UINT8 usIndex ) +{ + INT16 sUseObjIndex = -1; + + // needs to be a valid location + if ( TileIsOutOfBounds( sGridNo ) ) + return FALSE; + + // if we want to build on a roof, a roof is required + if ( sLevel && !FlatRoofAboveGridNo( sGridNo ) ) + return FALSE; + + // don't build in water + if ( TERRAIN_IS_WATER( GetTerrainType( sGridNo ) ) ) + return FALSE; + + // do not build into people + if ( NOBODY != WhoIsThere2( sGridNo, sLevel ) ) + return FALSE; + + // search wether structure exists in the current tilesets. If not, well, too bad + for ( INT32 iType = 0; iType < giNumberOfTileTypes; ++iType ) + { + // if tileset is from the current tileset, check that + if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[iType][0] ) + { + if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[iType], aStr, 10 ) ) + { + sUseObjIndex = iType; + break; + } + } + // otherwise, check first tileset (GENERIC 1) + else if ( gTilesets[0].TileSurfaceFilenames[iType][0] ) + { + if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[iType], aStr, 10 ) ) + { + sUseObjIndex = iType; + break; + } + } + } + + if ( sUseObjIndex < 0 ) + return FALSE; + + // Check with Structure Database (aka ODB) if we can put the object here! + BOOLEAN fOkayToAdd = OkayToAddStructureToWorld( sGridNo, sLevel, gTileDatabase[( gTileTypeStartIndex[sUseObjIndex] + usIndex )].pDBStructureRef, INVALID_STRUCTURE_ID ); + if ( fOkayToAdd || ( gTileDatabase[( gTileTypeStartIndex[sUseObjIndex] + usIndex )].pDBStructureRef == NULL ) ) + { + // Remove old graphic + ApplyMapChangesToMapTempFile( TRUE ); + + //dnl Remove existing structure before adding the same, seems to solve problem with stacking but still need test to be sure that is not removed something what should stay + // Actual structure info is added by the functions below + if ( sLevel ) + { + RemoveOnRoofStruct( sGridNo, (UINT16)( gTileTypeStartIndex[sUseObjIndex] + usIndex ) ); + + AddOnRoofToTail( sGridNo, (UINT16)( gTileTypeStartIndex[sUseObjIndex] + usIndex ) ); + } + else + { + RemoveStruct( sGridNo, (UINT16)( gTileTypeStartIndex[sUseObjIndex] + usIndex ) ); + + AddStructToHead( sGridNo, (UINT16)( gTileTypeStartIndex[sUseObjIndex] + usIndex ) ); + } + + RecompileLocalMovementCosts( sGridNo ); + + // Turn off permanent changes.... + ApplyMapChangesToMapTempFile( FALSE ); + SetRenderFlags( RENDER_FLAG_FULL ); + + return TRUE; + } + + return FALSE; +} + UINT16 gusTempDragBuildSoldierID = NOBODY; BOOLEAN BuildStructDrag( INT32 sGridNo, INT8 sLevel, UINT32 uiTileType, UINT8 usIndex, UINT16 usSoldierID ) diff --git a/Tactical/Handle Items.h b/Tactical/Handle Items.h index bd96f98a..b9b20865 100644 --- a/Tactical/Handle Items.h +++ b/Tactical/Handle Items.h @@ -288,6 +288,8 @@ BOOLEAN RemoveFortification( INT32 sGridNo, SOLDIERTYPE *pSoldier, OBJECTTYPE *p UINT8 CheckBuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32 usStructureconstructindex ); BOOLEAN BuildFortification( INT32 sGridNo, INT8 sLevel, UINT8 usIndex, UINT32 usStructureconstructindex ); +BOOLEAN BuildStructFromName( INT32 sGridNo, INT8 sLevel, const char* aStr, UINT8 usIndex ); + BOOLEAN CanRemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureconstructindex ); BOOLEAN RemoveFortification( INT32 sGridNo, INT8 sLevel, UINT32 usStructureconstructindex ); diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index dfe3bd19..5f43bce5 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -779,6 +779,7 @@ extern OBJECTTYPE gTempObject; // extended flagmask to UINT64 #define EMPTY_BLOOD_BAG 0x0000000100000000 // this item is a empty blood bag #define MEDICAL_SPLINT 0x0000000200000000 // this item is a medical splint that can be applied to some diseases +#define FIREEXTINGUISHER 0x0000000400000000 // this item is a fire extinguisher, which results in a white trail of smoke when firing // ---------------------------------------------------------------- diff --git a/Tactical/Items.h b/Tactical/Items.h index ebb3d4cd..a2df8d46 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -30,6 +30,7 @@ enum EXPLOSV_FLASHBANG, EXPLOSV_SIGNAL_SMOKE, EXPLOSV_SMOKE_DEBRIS, + EXPLOSV_SMOKE_FIRERETARDANT, EXPLOSV_ANY_TYPE, }; diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 9c0a1cf5..bd01e092 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -1938,7 +1938,7 @@ INT32 LineOfSightTest( FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, // leaving a tile, check to see if it had gas in it // if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS) ) - if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS | MAPELEMENT_EXT_BURNABLEGAS | MAPELEMENT_EXT_DEBRIS_SMOKE) ) + if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS | MAPELEMENT_EXT_BURNABLEGAS | MAPELEMENT_EXT_DEBRIS_SMOKE | MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) ) { if ( (pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_DEBRIS_SMOKE) ) && !fSmell ) { @@ -3593,7 +3593,7 @@ INT32 HandleBulletStructureInteraction( BULLET * pBullet, STRUCTURE * pStructure *pfHit = FALSE; - if (pBullet->usFlags & BULLET_FLAG_KNIFE || pBullet->usFlags & BULLET_FLAG_MISSILE || pBullet->usFlags & BULLET_FLAG_TANK_CANNON || pBullet->usFlags & BULLET_FLAG_FLAME ) + if (pBullet->usFlags & BULLET_FLAG_KNIFE || pBullet->usFlags & BULLET_FLAG_MISSILE || pBullet->usFlags & BULLET_FLAG_TANK_CANNON || pBullet->usFlags & (BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE) ) { // stops! *pfHit = TRUE; @@ -3746,7 +3746,7 @@ INT32 CTGTHandleBulletStructureInteraction( BULLET * pBullet, STRUCTURE * pStruc INT32 iCurrImpact; INT32 iImpactReduction; - if (pBullet->usFlags & BULLET_FLAG_KNIFE || pBullet->usFlags & BULLET_FLAG_MISSILE || pBullet->usFlags & BULLET_FLAG_FLAME || pBullet->usFlags & BULLET_FLAG_TANK_CANNON ) + if (pBullet->usFlags & BULLET_FLAG_KNIFE || pBullet->usFlags & BULLET_FLAG_MISSILE || pBullet->usFlags & (BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE) || pBullet->usFlags & BULLET_FLAG_TANK_CANNON ) { // knife/rocket stops when it hits anything, and people block completely return( pBullet->iImpact ); @@ -4677,7 +4677,7 @@ INT8 FireBullet( UINT8 ubFirer, BULLET * pBullet, BOOLEAN fFake ) else { //afp-start //always a fast bullet - if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) ) + if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE /*| BULLET_FLAG_TRACER*/ ) ) pBullet->usClockTicksPerUpdate = (Weapon[ pBullet->pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pBullet->pFirer->inv[pBullet->pFirer->ubAttackingHand]) ) / 10; else if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS]) @@ -4824,6 +4824,11 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, usBulletFlags |= BULLET_FLAG_FLAME; ubSpreadIndex = 2; } + else if ( Item[usHandItem].usItemFlag & FIREEXTINGUISHER ) + { + usBulletFlags |= BULLET_FLAG_WHITESMOKE; + ubSpreadIndex = 2; + } // HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the // New Tracer System. else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) @@ -5318,6 +5323,11 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA usBulletFlags |= BULLET_FLAG_FLAME; ubSpreadIndex = 2; } + else if ( Item[usHandItem].usItemFlag & FIREEXTINGUISHER ) + { + usBulletFlags |= BULLET_FLAG_WHITESMOKE; + ubSpreadIndex = 2; + } // HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the // New Tracer System. else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) @@ -5999,6 +6009,11 @@ INT8 FireBulletGivenTargetTrapOnly( SOLDIERTYPE* pThrower, OBJECTTYPE* pObj, INT usBulletFlags |= BULLET_FLAG_FLAME; ubSpreadIndex = 2; } + else if ( Item[usItem].usItemFlag & FIREEXTINGUISHER ) + { + usBulletFlags |= BULLET_FLAG_WHITESMOKE; + ubSpreadIndex = 2; + } // Flugente: anti-materiel ammo if ( AmmoTypes[ammotype].ammoflag & AMMO_ANTIMATERIEL ) @@ -6579,6 +6594,11 @@ INT8 FireBulletGivenTarget_NoObjectNoSoldier( UINT16 usItem, UINT8 ammotype, UIN usBulletFlags |= BULLET_FLAG_FLAME; ubSpreadIndex = 2; } + else if ( Item[usItem].usItemFlag & FIREEXTINGUISHER ) + { + usBulletFlags |= BULLET_FLAG_WHITESMOKE; + ubSpreadIndex = 2; + } // Flugente: anti-materiel ammo if ( AmmoTypes[ammotype].ammoflag & AMMO_ANTIMATERIEL ) @@ -7451,7 +7471,7 @@ void MoveBullet( INT32 iBullet ) // HEADROCK HAM B2.5: Changed condition to read fTracer flag directly from bullet's struct. // This is for the New Tracer System. - if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER*/ ) ) + if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_WHITESMOKE /*| BULLET_FLAG_TRACER*/ ) ) || ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE))) { INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS; @@ -7460,7 +7480,7 @@ void MoveBullet( INT32 iBullet ) { bStepsPerMove = STEPS_FOR_BULLET_MOVE_SMALL_TRAILS; } - else if ( pBullet->usFlags & ( BULLET_FLAG_FLAME ) ) + else if ( pBullet->usFlags & ( BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE ) ) { bStepsPerMove = STEPS_FOR_BULLET_MOVE_FIRE_TRAILS; } @@ -7711,7 +7731,7 @@ void MoveBullet( INT32 iBullet ) if (fHitStructure) { // ATE: NOT if we are a special bullet like a LAW trail... - if (pStructure->fFlags & STRUCTURE_CORPSE && !( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT ) ) ) + if (pStructure->fFlags & STRUCTURE_CORPSE && !( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_WHITESMOKE ) ) ) { // ATE: In enemy territory here... ;) // Now that we have hit a corpse, make the bugger twich! @@ -7820,7 +7840,7 @@ void MoveBullet( INT32 iBullet ) // HEADROCK HAM B2.5: Changed condition to read fTracer flag directly from bullet's struct. // This is for the New Tracer System. - if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER */) ) + if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_WHITESMOKE /*| BULLET_FLAG_TRACER */) ) || ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE))) { INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS; @@ -7829,7 +7849,7 @@ void MoveBullet( INT32 iBullet ) { bStepsPerMove = STEPS_FOR_BULLET_MOVE_SMALL_TRAILS; } - else if ( pBullet->usFlags & ( BULLET_FLAG_FLAME ) ) + else if ( pBullet->usFlags & ( BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE ) ) { bStepsPerMove = STEPS_FOR_BULLET_MOVE_FIRE_TRAILS; } @@ -7876,7 +7896,7 @@ void MoveBullet( INT32 iBullet ) //pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2); pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * gGameCTHConstants.GRAVITY_COEFFICIENT); } - else if ( (pBullet->usFlags & BULLET_FLAG_FLAME) && (dDistanceMoved > pBullet->iRange) ) + else if ( (pBullet->usFlags & (BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE)) && (dDistanceMoved > pBullet->iRange) ) { //pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2); pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * (gGameCTHConstants.GRAVITY_COEFFICIENT / 2) ); @@ -7891,7 +7911,7 @@ void MoveBullet( INT32 iBullet ) // decrement is scaled down depending on how fast the bullet is (effective range) pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2); } - else if ( (pBullet->usFlags & BULLET_FLAG_FLAME) && ( pBullet->iLoop > pBullet->iRange ) ) + else if ( (pBullet->usFlags & (BULLET_FLAG_FLAME|BULLET_FLAG_WHITESMOKE) ) && ( pBullet->iLoop > pBullet->iRange ) ) { pBullet->qIncrZ -= INT32_TO_FIXEDPT( 100 ) / (pBullet->iRange * 2); } diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 08acc2de..86e4c798 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -2459,6 +2459,13 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE } } + if ( gpWorldLevelData[pSoldier->sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) + { + { + pExplosive = &( Explosive[Item[GetFirstExplosiveOfType( EXPLOSV_SMOKE_FIRERETARDANT )].ubClassIndex] ); + } + } + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pSoldier->flags.fHitByGasFlags: %d", pSoldier->flags.fHitByGasFlags ); //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Overhead pExplosive: %d", pExplosive->ubType ); diff --git a/Tactical/bullets.cpp b/Tactical/bullets.cpp index 3e376e3b..e9b8fda9 100644 --- a/Tactical/bullets.cpp +++ b/Tactical/bullets.cpp @@ -294,7 +294,7 @@ void UpdateBullets( ) { // ALRIGHTY, CHECK WHAT TYPE OF BULLET WE ARE - if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) ) + if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE /*| BULLET_FLAG_TRACER*/ ) ) { } else @@ -350,7 +350,7 @@ void UpdateBullets( ) } } // Are we a missle? - else if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT ) ) + else if ( gBullets[ uiCount ].usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_WHITESMOKE | BULLET_FLAG_CREATURE_SPIT ) ) { } /* @@ -474,7 +474,7 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q ANITILE_PARAMS AniParams; // If we are a small missle, don't show - if ( pBullet->usFlags & ( BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER*/ ) ) + if ( pBullet->usFlags & ( BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_WHITESMOKE /*| BULLET_FLAG_TRACER*/ ) ) { if ( pBullet->iLoop < 5 ) { @@ -532,6 +532,11 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q strcpy( AniParams.zCachedFile, "TILECACHE\\FLMTHR2.STI" ); AniParams.sDelay = (INT16)( 100 ); } + else if ( pBullet->usFlags & BULLET_FLAG_WHITESMOKE ) + { + strcpy( AniParams.zCachedFile, "TILECACHE\\white_smoke_trail.sti" ); + AniParams.sDelay = (INT16)( 100 ); + } //else if ( pBullet->usFlags & ( BULLET_FLAG_TRACER ) ) // HEADROCK HAM B2.5: Created new bullet flag that tells us whether this specific bullet is a tracer. // The condition now reads that flag and creates a lightshow only for tracer bullets. This flag is only diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index d93d3bd2..281aa5da 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -2261,7 +2261,7 @@ BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo ) BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo ) { // smoke - if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_SIGNAL_SMOKE | MAPELEMENT_EXT_DEBRIS_SMOKE) ) + if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_SIGNAL_SMOKE | MAPELEMENT_EXT_DEBRIS_SMOKE | MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) ) return TRUE; return InGas(pSoldier,sGridNo); diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index e23731c1..2d26a07c 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -2001,7 +2001,7 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN } } - else if ( pExplosive->ubType == EXPLOSV_SMOKE || pExplosive->ubType == EXPLOSV_SMOKE_DEBRIS )//dnl ch40 200909 + else if ( pExplosive->ubType == EXPLOSV_SMOKE || pExplosive->ubType == EXPLOSV_SMOKE_DEBRIS | pExplosive->ubType == EXPLOSV_SMOKE_FIRERETARDANT )//dnl ch40 200909 { // robots are unaffected by smoke if( AM_A_ROBOT(pSoldier) ) @@ -2108,6 +2108,7 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN break; case EXPLOSV_SMOKE://dnl ch40 200909 case EXPLOSV_SMOKE_DEBRIS: + case EXPLOSV_SMOKE_FIRERETARDANT: pSoldier->flags.fHitByGasFlags |= HIT_BY_SMOKEGAS; break; default: @@ -2262,6 +2263,12 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte bSmokeEffectType = DEBRIS_SMOKE_EFFECT; fBlastEffect = FALSE; break; + + case EXPLOSV_SMOKE_FIRERETARDANT: + fSmokeEffect = TRUE; + bSmokeEffectType = FIRERETARDANT_SMOKE_EFFECT; + fBlastEffect = FALSE; + break; } } @@ -2464,6 +2471,15 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte } else if ( fSmokeEffect ) { + // Flugente: if adding fire retardant, remove fire + if ( pExplosive->ubType == EXPLOSV_SMOKE_FIRERETARDANT ) + { + if ( gpWorldLevelData[sGridNo].ubExtFlags[bLevel] & MAPELEMENT_EXT_BURNABLEGAS ) + { + RemoveSmokeEffectFromTile( sGridNo, bLevel ); + } + } + // If tear gar, determine turns to spread..... if ( sSubsequent == ERASE_SPREAD_EFFECT ) { @@ -2945,7 +2961,15 @@ void SpreadEffect( INT32 sGridNo, UINT8 ubRadius, UINT16 usItem, UINT8 ubOwner, gfMPDebugOutputRandoms = true; #endif } - + + // Flugente: if tile has a fire retardant effect, don't create new fire + if ( Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_BURNABLEGAS ) + { + if ( gpWorldLevelData[sGridNo].ubExtFlags[bLevel] & MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) + { + return; + } + } INT32 uiNewSpot, uiTempSpot, uiBranchSpot, cnt, branchCnt; INT32 uiTempRange, ubBranchRange; @@ -2965,7 +2989,7 @@ void SpreadEffect( INT32 sGridNo, UINT8 ubRadius, UINT16 usItem, UINT8 ubOwner, case EXPLOSV_CREATUREGAS: case EXPLOSV_SIGNAL_SMOKE: case EXPLOSV_SMOKE_DEBRIS: - + case EXPLOSV_SMOKE_FIRERETARDANT: fSmokeEffect = TRUE; break; } diff --git a/TileEngine/SmokeEffects.cpp b/TileEngine/SmokeEffects.cpp index 5f3b5d08..798d8488 100644 --- a/TileEngine/SmokeEffects.cpp +++ b/TileEngine/SmokeEffects.cpp @@ -137,6 +137,10 @@ INT8 FromWorldFlagsToSmokeType( UINT16 ubWorldFlags ) { return(DEBRIS_SMOKE_EFFECT); } + else if ( ubWorldFlags & MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) + { + return FIRERETARDANT_SMOKE_EFFECT; + } return(NO_SMOKE_EFFECT); } @@ -180,6 +184,10 @@ UINT16 FromSmokeTypeToWorldFlags( INT8 bType ) return(MAPELEMENT_EXT_DEBRIS_SMOKE); break; + case FIRERETARDANT_SMOKE_EFFECT: + return MAPELEMENT_EXT_FIRERETARDANT_SMOKE; + break; + default: return( 0 ); @@ -288,6 +296,10 @@ INT32 NewSmokeEffect( INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, case EXPLOSV_SMOKE_DEBRIS: bSmokeEffectType = DEBRIS_SMOKE_EFFECT; break; + + case EXPLOSV_SMOKE_FIRERETARDANT: + bSmokeEffectType = FIRERETARDANT_SMOKE_EFFECT; + break; } pSmoke->ubDuration = (UINT8)Explosive[ Item[ usItem ].ubClassIndex ].ubDuration; @@ -395,6 +407,9 @@ INT32 NewSmokeEffect(INT32 sGridNo, UINT16 usItem, INT8 bLevel, UINT8 ubOwner, B case EXPLOSV_SMOKE_DEBRIS: bSmokeEffectType = DEBRIS_SMOKE_EFFECT; break; + case EXPLOSV_SMOKE_FIRERETARDANT: + bSmokeEffectType = FIRERETARDANT_SMOKE_EFFECT; + break; } // sevenfm: use custom duration/radius @@ -607,59 +622,19 @@ void AddSmokeEffectToTile( INT32 iSmokeEffectID, INT8 bType, INT32 sGridNo, INT8 break; case CREATURE_SMOKE_EFFECT: - - if ( !( gGameSettings.fOptions[ TOPTION_ANIMATE_SMOKE ] ) ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\spit_gas.STI" ); - } - else - { - if ( fDissipating ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\spit_gas.STI" ); - } - else - { - strcpy( AniParams.zCachedFile, "TILECACHE\\spit_gas.STI" ); - } - } + strcpy( AniParams.zCachedFile, "TILECACHE\\spit_gas.STI" ); break; case SIGNAL_SMOKE_EFFECT: - - if ( !( gGameSettings.fOptions[ TOPTION_ANIMATE_SMOKE ] ) ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\signal_gas.STI" ); - } - else - { - if ( fDissipating ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\signal_gas.STI" ); - } - else - { - strcpy( AniParams.zCachedFile, "TILECACHE\\signal_gas.STI" ); - } - } + strcpy( AniParams.zCachedFile, "TILECACHE\\signal_gas.STI" ); break; case DEBRIS_SMOKE_EFFECT: - if ( !(gGameSettings.fOptions[TOPTION_ANIMATE_SMOKE]) ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\debris_smoke.STI" ); - } - else - { - if ( fDissipating ) - { - strcpy( AniParams.zCachedFile, "TILECACHE\\debris_smoke.STI" ); - } - else - { - strcpy( AniParams.zCachedFile, "TILECACHE\\debris_smoke.STI" ); - } - } + strcpy( AniParams.zCachedFile, "TILECACHE\\debris_smoke.STI" ); + break; + + case FIRERETARDANT_SMOKE_EFFECT: + strcpy( AniParams.zCachedFile, "TILECACHE\\white_smoke.STI" ); break; } @@ -769,6 +744,15 @@ void DecaySmokeEffects( UINT32 uiTime ) } } + // Flugente: if tile has a fire retardant effect, don't create new fire + if ( Explosive[Item[pSmoke->usItem].ubClassIndex].ubType == EXPLOSV_BURNABLEGAS ) + { + if ( gpWorldLevelData[pSmoke->sGridNo].ubExtFlags[bLevel] & MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) + { + pSmoke->bAge = pSmoke->ubDuration + 1; + } + } + if ( fUpdate ) { pSmoke->uiTimeOfLastUpdate = uiTime; diff --git a/TileEngine/SmokeEffects.h b/TileEngine/SmokeEffects.h index c32f2cba..996a40d6 100644 --- a/TileEngine/SmokeEffects.h +++ b/TileEngine/SmokeEffects.h @@ -13,6 +13,7 @@ enum BURNABLEGAS_SMOKE_EFFECT, SIGNAL_SMOKE_EFFECT, // added by Flugente for artillery DEBRIS_SMOKE_EFFECT, // added by Flugente for collapsing roofs + FIRERETARDANT_SMOKE_EFFECT, // added by Flugente for fire extinguishers }; #define SMOKE_EFFECT_INDOORS 0x01 diff --git a/TileEngine/Tile Animation.cpp b/TileEngine/Tile Animation.cpp index 60b3e63b..7bc6a31d 100644 --- a/TileEngine/Tile Animation.cpp +++ b/TileEngine/Tile Animation.cpp @@ -560,8 +560,19 @@ void UpdateAniTiles( ) ubExpType = Explosive[ Item[ (UINT16)pNode->uiUserData ].ubClassIndex ].ubType; + // Flugente: if tile has a fire retardant effect, don't create new fire + if ( ubExpType == EXPLOSV_BURNABLEGAS ) + { + if ( gpWorldLevelData[pNode->sGridNo].ubExtFlags[gExplosionData[pNode->uiUserData3].Params.bLevel] & MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) + { + // don't add fire + return; + } + } + if ( ubExpType == EXPLOSV_TEARGAS || ubExpType == EXPLOSV_MUSTGAS || - ubExpType == EXPLOSV_SMOKE || ubExpType == EXPLOSV_BURNABLEGAS || ubExpType == EXPLOSV_SIGNAL_SMOKE || ubExpType == EXPLOSV_SMOKE_DEBRIS || ubExpType == EXPLOSV_CREATUREGAS) + ubExpType == EXPLOSV_SMOKE || ubExpType == EXPLOSV_BURNABLEGAS || ubExpType == EXPLOSV_SIGNAL_SMOKE || ubExpType == EXPLOSV_SMOKE_DEBRIS || ubExpType == EXPLOSV_CREATUREGAS || + ubExpType == EXPLOSV_SMOKE_FIRERETARDANT ) { // Do sound.... // PlayJA2Sample( AIR_ESCAPING_1, RATE_11025, SoundVolume( HIGHVOLUME, pNode->sGridNo ), 1, SoundDir( pNode->sGridNo ) ); diff --git a/TileEngine/worlddef.h b/TileEngine/worlddef.h index b956ed14..0d60208e 100644 --- a/TileEngine/worlddef.h +++ b/TileEngine/worlddef.h @@ -133,12 +133,13 @@ class SOLDIERTYPE; #define MAPELEMENT_EXT_CLIMBPOINT 0x0200 //0x200 #define MAPELEMENT_EXT_SIGNAL_SMOKE 0x0400 //0x400 // added by Flugente #define MAPELEMENT_EXT_DEBRIS_SMOKE 0x0800 //0x800 // added by Flugente +#define MAPELEMENT_EXT_FIRERETARDANT_SMOKE 0x1000 //0x800 // added by Flugente #define FIRST_LEVEL 0 #define SECOND_LEVEL 1 //#define ANY_SMOKE_EFFECT ( MAPELEMENT_EXT_CREATUREGAS | MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS ) -#define ANY_SMOKE_EFFECT ( MAPELEMENT_EXT_CREATUREGAS | MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS | MAPELEMENT_EXT_BURNABLEGAS | MAPELEMENT_EXT_SIGNAL_SMOKE | MAPELEMENT_EXT_DEBRIS_SMOKE ) +#define ANY_SMOKE_EFFECT ( MAPELEMENT_EXT_CREATUREGAS | MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS | MAPELEMENT_EXT_BURNABLEGAS | MAPELEMENT_EXT_SIGNAL_SMOKE | MAPELEMENT_EXT_DEBRIS_SMOKE | MAPELEMENT_EXT_FIRERETARDANT_SMOKE ) // WDS - Clean up inventory handling diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index ff8c850d..e2591279 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -298,6 +298,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "bloodbag" ) == 0 || strcmp(name, "emptybloodbag" ) == 0 || strcmp(name, "medicalsplint" ) == 0 || + strcmp(name, "fireextinguisher" ) == 0 || strcmp(name, "sFireResistance" ) == 0 || strcmp(name, "usAdministrationModifier" ) == 0)) { @@ -1543,6 +1544,13 @@ itemEndElementHandle(void *userData, const XML_Char *name) if ( (BOOLEAN)atol( pData->szCharData ) ) pData->curItem.usItemFlag |= MEDICAL_SPLINT; } + else if ( strcmp( name, "fireextinguisher" ) == 0 ) + { + pData->curElement = ELEMENT; + + if ( (BOOLEAN)atol( pData->szCharData ) ) + pData->curItem.usItemFlag |= FIREEXTINGUISHER; + } else if ( strcmp( name, "sFireResistance" ) == 0 ) { pData->curElement = ELEMENT; @@ -2192,6 +2200,7 @@ BOOLEAN WriteItemStats() if ( HasItemFlag( cnt, BLOOD_BAG) ) FilePrintf( hFile, "\t\t%d\r\n", 1 ); if ( HasItemFlag( cnt, EMPTY_BLOOD_BAG ) ) FilePrintf( hFile, "\t\t%d\r\n", 1 ); if ( HasItemFlag( cnt, MEDICAL_SPLINT ) ) FilePrintf( hFile, "\t\t%d\r\n", 1 ); + if ( HasItemFlag( cnt, FIREEXTINGUISHER ) ) FilePrintf( hFile, "\t\t%d\r\n", 1 ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usRiotShieldStrength ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usRiotShieldGraphic );