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 );