- if a a roof collapses, any structures built on it (fans, sandbags) are destroyed

- if a a roof collapses, any corpses on it are moved to the floor

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7623 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2014-10-31 22:13:32 +00:00
parent faf345ac18
commit 8857e0772b
9 changed files with 304 additions and 17 deletions
+27 -1
View File
@@ -5934,6 +5934,32 @@ void RoofDestruction( INT32 sGridNo )
SoldierDropThroughRoof( pSoldier, soldierdropoffgridno );
}
// there can be non-roof structures on roofs. In order to collapse those, check for all structures who are above a certain height, and destroy them
STRUCTURE* pStruct = GetTallestStructureOnGridno( sGridNo, 1 );
while ( pStruct )
{
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
if ( pNode )
{
if ( RemoveOnRoofStruct( sGridNo, pNode->usIndex ) )
pStruct = GetTallestStructureOnGridno( sGridNo, 1 );
else
break;
}
else
break;
}
// very important: if applying changes to map files is turned on, adding corpses will corrupt the map (only noticeable if you reload it)
// for this reason we turn this off and on again
ApplyMapChangesToMapTempFile( FALSE );
// if there is a corpse here, drop that down as well
ShiftCorpse( sGridNo , 1);
ApplyMapChangesToMapTempFile( TRUE );
// play an animation of falling roof tiles
// if we merely collected the tiles that collapse and then call them all together, it would be possible to have animations for multi-tile collapses
static UINT16 usRoofCollapseExplosionIndex = 1727;
@@ -6016,7 +6042,7 @@ void HandleRoofDestruction( INT32 sGridNo, INT16 sDamage )
(*it).second = 0;
}
}
// Nodes might have been removed, and the roof might have degenerated into several networks
gridnoarmournetworkmap roofnetworkmap = GetConnectedRoofNetworks( floorarmourvector );
+43
View File
@@ -461,6 +461,22 @@ BOOLEAN LoadAllMapChangesFromMapTempFileAndApplyThem( )
++uiNumberOfElementsSavedBackToFile;
break;
case SLM_REMOVE_ONROOF:
if ( pMap->usImageType >= FIRSTTEXTURE && pMap->usImageType <= WIREFRAMES )
{
RemoveAllOnRoofsOfTypeRange( pMap->usGridNo, FIRSTTEXTURE, WIREFRAMES );
}
else
{
GetTileIndexFromTypeSubIndex( pMap->usImageType, pMap->usSubImageIndex, &usIndex );
RemoveOnRoofAdjustSavefile( pMap->usGridNo, usIndex );
}
// Save this struct back to the temp file
SaveModifiedMapStructToMapTempFile( pMap, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
//Since the element is being saved back to the temp file, increment the #
++uiNumberOfElementsSavedBackToFile;
break;
case SLM_REMOVE_TOPMOST:
break;
@@ -706,6 +722,33 @@ void RemoveRoofFromMapTempFile( INT32 uiMapIndex, UINT16 usIndex )
SaveModifiedMapStructToMapTempFile( &Map, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
}
void RemoveOnRoofFromMapTempFile( INT32 uiMapIndex, UINT16 usIndex )
{
MODIFY_MAP Map;
UINT32 uiType;
UINT16 usSubIndex;
if ( !gfApplyChangesToTempFile )
return;
if ( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
return;
GetTileType( usIndex, &uiType );
GetSubIndexFromTileIndex( usIndex, &usSubIndex );
memset( &Map, 0, sizeof(MODIFY_MAP) );
Map.usGridNo = uiMapIndex;
// Map.usIndex = usIndex;
Map.usImageType = (UINT16)uiType;
Map.usSubImageIndex = usSubIndex;
Map.ubType = SLM_REMOVE_ONROOF;
SaveModifiedMapStructToMapTempFile( &Map, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
}
void RemoveSavedStructFromMap( INT32 uiMapIndex, UINT16 usIndex )
{
+2 -1
View File
@@ -82,8 +82,9 @@ BOOLEAN LoadAllMapChangesFromMapTempFileAndApplyThem( );
void RemoveStructFromMapTempFile( INT32 uiMapIndex, UINT16 usIndex );
// Flugente: permanently remove roof tiles
// Flugente: permanently remove other tiles
void RemoveRoofFromMapTempFile( INT32 uiMapIndex, UINT16 usIndex );
void RemoveOnRoofFromMapTempFile( INT32 uiMapIndex, UINT16 usIndex );
void AddRemoveObjectToMapTempFile( INT32 uiMapIndex, UINT16 usIndex );
+38
View File
@@ -2460,6 +2460,44 @@ BOOLEAN FiniStructureDB( void )
return( TRUE );
}
STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel )
{
STRUCTURE* pCurrent = NULL;
STRUCTURE* pStruct = NULL;
INT8 bestheight = -1;
INT16 sDesiredLevel = STRUCTURE_ON_GROUND;
if ( bLevel )
sDesiredLevel = STRUCTURE_ON_ROOF;
pCurrent = gpWorldLevelData[sGridNo].pStructureHead;
while ( pCurrent != NULL )
{
// Check level!
if ( pCurrent->sCubeOffset == sDesiredLevel )
{
if ( pCurrent->fFlags & (STRUCTURE_CORPSE | STRUCTURE_PERSON | STRUCTURE_ROOF) )
{
// we are interested in building tiles, not people
pCurrent = pCurrent->pNext;
continue;
}
INT8 height = StructureHeight( pCurrent );
if ( height > bestheight )
{
bestheight = height;
pStruct = pCurrent;
}
}
pCurrent = pCurrent->pNext;
}
return pStruct;
}
INT8 GetBlockingStructureInfo( INT32 sGridNo, INT8 bDir, INT8 bNextDir, INT8 bLevel, INT8 *pStructHeight, STRUCTURE ** ppTallestStructure, BOOLEAN fWallsBlock )
{
+3
View File
@@ -82,6 +82,9 @@ void DebugStructurePage1( void );
BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructureFileRef, BOOLEAN fFromAnimation, INT16 sSTIStartIndex );
// Flugente: return the highest structure (no person, roof or corpse) on a gridno and level
STRUCTURE* GetTallestStructureOnGridno( INT32 sGridNo, INT8 bLevel );
// FUNCTIONS FOR DETERMINING STUFF THAT BLOCKS VIEW FOR TILE_bASED LOS
INT8 GetBlockingStructureInfo( INT32 sGridNo, INT8 bDir, INT8 bNextDir, INT8 bLevel, INT8 *pStructHeight, STRUCTURE ** ppTallestStructure, BOOLEAN fWallsBlock );
+159 -13
View File
@@ -1429,7 +1429,7 @@ BOOLEAN RemoveStruct( INT32 iMapIndex, UINT16 usIndex )
if ( pOldStruct == NULL )
{
// It's the head
gpWorldLevelData[ iMapIndex ].pStructHead = pStruct->pNext;
gpWorldLevelData[iMapIndex].pStructHead = pStruct->pNext;
}
else
{
@@ -1462,7 +1462,7 @@ BOOLEAN RemoveStruct( INT32 iMapIndex, UINT16 usIndex )
}
}
MemFree( pStruct );
guiLevelNodes--;
--guiLevelNodes;
return( TRUE );
}
@@ -1476,10 +1476,75 @@ BOOLEAN RemoveStruct( INT32 iMapIndex, UINT16 usIndex )
RemoveWorldFlagsFromNewNode( iMapIndex, usIndex );
return( FALSE );
}
// Flugente: permanently remove roof tiles
// same as RemoveStruct(...), except that this focuses on .pOnRoofHead instead of .pStructHead
BOOLEAN RemoveOnRoofStruct( INT32 iMapIndex, UINT16 usIndex )
{
LEVELNODE *pStruct = NULL;
LEVELNODE *pOldStruct = NULL;
pStruct = gpWorldLevelData[iMapIndex].pOnRoofHead;
// Look through all structs and remove index if found
while ( pStruct != NULL )
{
if ( pStruct->usIndex == usIndex )
{
// OK, set links
// Check for head or tail
if ( pOldStruct == NULL )
{
// It's the head
gpWorldLevelData[iMapIndex].pOnRoofHead = pStruct->pNext;
}
else
{
pOldStruct->pNext = pStruct->pNext;
}
//Check for special flag to stop burn-through on same-tile structs...
if ( pStruct->pStructureData != NULL )
{
// If we are NOT a wall and NOT multi-tiles, set mapelement flag...
//if ( !( pStruct->pStructureData->fFlags & STRUCTURE_WALLSTUFF ) && pStruct->pStructureData->pDBStructureRef->pDBStructure->ubNumberOfTiles == 1 )
//{
// UNSet flag...
// gpWorldLevelData[ iMapIndex ].ubExtFlags[0] &= ( ~MAPELEMENT_EXT_NOBURN_STRUCT );
//}
}
// Delete memory assosiated with item
DeleteStructureFromWorld( pStruct->pStructureData );
//If we have to, make sure to remove this node when we reload the map from a saved game
RemoveOnRoofFromMapTempFile( iMapIndex, usIndex );
if ( usIndex < giNumberOfTiles )
{
// Check flags for tiledat and set a shadow if we have a buddy
if ( !GridNoIndoors( iMapIndex ) && gTileDatabase[usIndex].uiFlags & HAS_SHADOW_BUDDY && gTileDatabase[usIndex].sBuddyNum != -1 )
{
RemoveShadow( iMapIndex, gTileDatabase[usIndex].sBuddyNum );
}
}
MemFree( pStruct );
--guiLevelNodes;
return(TRUE);
}
pOldStruct = pStruct;
pStruct = pStruct->pNext;
}
// Could not find it, return FALSE
RemoveWorldFlagsFromNewNode( iMapIndex, usIndex );
return(FALSE);
}
// Flugente: permanently remove structures
BOOLEAN RemoveRoofAdjustSavefile( INT32 iMapIndex, UINT16 usIndex )
{
LEVELNODE *pStruct = NULL;
@@ -1527,6 +1592,53 @@ BOOLEAN RemoveRoofAdjustSavefile( INT32 iMapIndex, UINT16 usIndex )
return(FALSE);
}
BOOLEAN RemoveOnRoofAdjustSavefile( INT32 iMapIndex, UINT16 usIndex )
{
LEVELNODE *pStruct = NULL;
LEVELNODE *pOldStruct = NULL;
pStruct = gpWorldLevelData[iMapIndex].pOnRoofHead;
// Look through all structs and remove index if found
while ( pStruct != NULL )
{
if ( pStruct->usIndex == usIndex )
{
// OK, set links
// Check for head or tail
if ( pOldStruct == NULL )
{
// It's the head
gpWorldLevelData[iMapIndex].pOnRoofHead = pStruct->pNext;
}
else
{
pOldStruct->pNext = pStruct->pNext;
}
// Delete memory assosiated with item
DeleteStructureFromWorld( pStruct->pStructureData );
//If we have to, make sure to remove this node when we reload the map from a saved game
RemoveOnRoofFromMapTempFile( iMapIndex, usIndex );
MemFree( pStruct );
--guiLevelNodes;
return(TRUE);
}
pOldStruct = pStruct;
pStruct = pStruct->pNext;
}
// Could not find it, return FALSE
RemoveWorldFlagsFromNewNode( iMapIndex, usIndex );
return(FALSE);
}
BOOLEAN RemoveStructFromLevelNode( INT32 iMapIndex, LEVELNODE *pNode )
{
@@ -1632,7 +1744,7 @@ BOOLEAN RemoveAllStructsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32
return fRetVal;
}
// Flugente: permanently remove roof tiles
// Flugente: permanently remove structures
BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
{
LEVELNODE *pStruct = NULL;
@@ -1672,6 +1784,45 @@ BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartT
return fRetVal;
}
BOOLEAN RemoveAllOnRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
{
LEVELNODE *pStruct = NULL;
LEVELNODE *pOldStruct = NULL;
UINT32 fTileType;
BOOLEAN fRetVal = FALSE;
LEVELNODE *pRoof = NULL;
LEVELNODE *pOldRoof = NULL;
pRoof = gpWorldLevelData[iMapIndex].pOnRoofHead;
// Look through all Roofs and Search for type
if ( pRoof != NULL )
{
if ( pRoof->usIndex != NO_TILE )
{
GetTileType( pRoof->usIndex, &fTileType );
// Advance to next
pOldRoof = pRoof;
pRoof = pRoof->pNext;
if ( fTileType >= fStartType && fTileType <= fEndType )
{
// Remove Item
if ( pOldRoof->usIndex < giNumberOfTiles )
{
RemoveOnRoofAdjustSavefile( iMapIndex, pOldRoof->usIndex );
fRetVal = TRUE;
}
}
}
}
return fRetVal;
}
//Kris: This was a serious problem. When saving the map and then reloading it, the structure
// information was invalid if you changed the types, etc. This is the bulletproof way.
BOOLEAN ReplaceStructIndex( INT32 iMapIndex, UINT16 usOldIndex, UINT16 usNewIndex )
@@ -2741,9 +2892,9 @@ void AdjustAllRoofShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
BOOLEAN RemoveAllRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
{
LEVELNODE *pRoof = NULL;
LEVELNODE *pOldRoof = NULL;
UINT32 fTileType;
BOOLEAN fRetVal = FALSE;
LEVELNODE *pOldRoof = NULL;
UINT32 fTileType;
BOOLEAN fRetVal = FALSE;
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
@@ -2751,10 +2902,8 @@ BOOLEAN RemoveAllRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fE
while( pRoof != NULL )
{
if ( pRoof->usIndex != NO_TILE )
{
GetTileType( pRoof->usIndex, &fTileType );
// Advance to next
@@ -2767,15 +2916,12 @@ BOOLEAN RemoveAllRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fE
RemoveRoof( iMapIndex, pOldRoof->usIndex );
fRetVal = TRUE;
}
}
}
// Could not find it, return FALSE
return fRetVal;
}
void RemoveRoofIndexFlagsFromTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags )
+5 -2
View File
@@ -69,9 +69,11 @@ BOOLEAN WaterTooDeepForAttacks( INT32 sGridNo );
// Structure manipulation routines
BOOLEAN RemoveStruct( INT32 iMapIndex, UINT16 usIndex );
BOOLEAN RemoveOnRoofStruct( INT32 iMapIndex, UINT16 usIndex );
// Flugente: permanently remove roof tiles
// Flugente: permanently remove structures
BOOLEAN RemoveRoofAdjustSavefile( INT32 iMapIndex, UINT16 usIndex );
BOOLEAN RemoveOnRoofAdjustSavefile( INT32 iMapIndex, UINT16 usIndex );
LEVELNODE *AddStructToTail( INT32 iMapIndex, UINT16 usIndex );
LEVELNODE *AddStructToTailCommon( INT32 iMapIndex, UINT16 usIndex, BOOLEAN fAddStructDBInfo );
@@ -81,8 +83,9 @@ BOOLEAN AddStructToHead( INT32 iMapIndex, UINT16 usIndex );
BOOLEAN TypeExistsInStructLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusStructIndex );
BOOLEAN RemoveAllStructsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType );
// Flugente: permanently remove roof tiles
// Flugente: permanently remove structures
BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType );
BOOLEAN RemoveAllOnRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType );
BOOLEAN AddWallToStructLayer( INT32 iMapIndex, UINT16 usIndex, BOOLEAN fReplace );
BOOLEAN ReplaceStructIndex( INT32 iMapIndex, UINT16 usOldIndex, UINT16 usNewIndex );