mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8936 3b4a5df2-a311-0410-b5c6-a8a6f20db521
4342 lines
94 KiB
C++
4342 lines
94 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "TileEngine All.h"
|
|
#else
|
|
#include "worlddef.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "wcheck.h"
|
|
#include "stdlib.h"
|
|
#include "video.h"
|
|
#include "debug.h"
|
|
#include "worldman.h"
|
|
#include "lighting.h"
|
|
#include "renderworld.h"
|
|
#include "overhead.h"
|
|
#include "ai.h"
|
|
#include "animation control.h"
|
|
#include "isometric utils.h"
|
|
#include "Font Control.h"
|
|
#include "message.h"
|
|
#include "tile cache.h"
|
|
#include "SaveLoadMap.h"
|
|
#include "random.h"
|
|
#include "render fun.h"
|
|
#include "GameSettings.h"
|
|
// sevenfm
|
|
#include "PATHAI.H"
|
|
#endif
|
|
|
|
extern BOOLEAN gfBasement;
|
|
|
|
UINT32 guiLNCount[9];
|
|
static CHAR16 gzLevelString[9][15] =
|
|
{
|
|
L"",
|
|
L"Land %d",
|
|
L"Object %d",
|
|
L"Struct %d",
|
|
L"Shadow %d",
|
|
L"Merc %d",
|
|
L"Roof %d",
|
|
L"Onroof %d",
|
|
L"Topmost %d",
|
|
};
|
|
|
|
// World management routines ( specific Double Linked list functions
|
|
void SetIndexLevelNodeFlags( LEVELNODE *pStartNode, UINT32 uiFlags, UINT16 usIndex );
|
|
void RemoveIndexLevelNodeFlags( LEVELNODE *pStartNode, UINT32 uiFlags, UINT16 usIndex );
|
|
|
|
void SetWorldFlagsFromNewNode( INT32 sGridNo, UINT16 usIndex );
|
|
void RemoveWorldFlagsFromNewNode( INT32 sGridNo, UINT16 usIndex );
|
|
|
|
BOOLEAN RemoveLandEx( INT32 iMapIndex, UINT16 usIndex );
|
|
|
|
UINT32 guiLevelNodes = 0;
|
|
|
|
// LEVEL NODE MANIPLULATION FUNCTIONS
|
|
BOOLEAN CreateLevelNode( LEVELNODE **ppNode )
|
|
{
|
|
*ppNode = (LEVELNODE *)MemAlloc( sizeof( LEVELNODE ) );
|
|
CHECKF( *ppNode != NULL );
|
|
|
|
// Clear all values
|
|
memset( *ppNode, 0, sizeof( LEVELNODE ) );
|
|
|
|
// Set default values
|
|
(*ppNode)->ubShadeLevel = LightGetAmbient();
|
|
(*ppNode)->ubNaturalShadeLevel = LightGetAmbient();
|
|
(*ppNode)->pSoldier = NULL;
|
|
(*ppNode)->pNext = NULL;
|
|
(*ppNode)->sRelativeX = 0;
|
|
(*ppNode)->sRelativeY = 0;
|
|
|
|
guiLevelNodes++;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
void CountLevelNodes( void )
|
|
{
|
|
INT32 uiLoop, uiLoop2;
|
|
LEVELNODE * pLN;
|
|
MAP_ELEMENT * pME;
|
|
|
|
for (uiLoop2 = 0; uiLoop2 < 9; uiLoop2++)
|
|
{
|
|
guiLNCount[uiLoop2] = 0;
|
|
}
|
|
|
|
for (uiLoop = 0; uiLoop < WORLD_MAX; uiLoop++)
|
|
{
|
|
pME = &(gpWorldLevelData[uiLoop]);
|
|
// start at 1 to skip land head ptr; 0 stores total
|
|
for (uiLoop2 = 1; uiLoop2 < 9; uiLoop2++)
|
|
{
|
|
pLN = pME->pLevelNodes[uiLoop2];
|
|
while( pLN != NULL )
|
|
{
|
|
guiLNCount[uiLoop2]++;
|
|
guiLNCount[0]++;
|
|
pLN = pLN->pNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define LINE_HEIGHT 20
|
|
void DebugLevelNodePage( void )
|
|
{
|
|
UINT32 uiLoop;
|
|
|
|
SetFont( LARGEFONT1 );
|
|
gprintf( 0, 0, L"DEBUG LEVELNODES PAGE 1 OF 1" );
|
|
|
|
for (uiLoop = 1; uiLoop < 9; uiLoop++)
|
|
{
|
|
gprintf( 0, LINE_HEIGHT * (uiLoop + 1), gzLevelString[uiLoop], guiLNCount[uiLoop] );
|
|
}
|
|
gprintf( 0, LINE_HEIGHT * 12, L"%d land nodes in excess of world max", guiLNCount[1] - WORLD_MAX);
|
|
gprintf( 0, LINE_HEIGHT * 13, L"Total # levelnodes %d, %d bytes each", guiLNCount[0], sizeof( LEVELNODE ) );
|
|
gprintf( 0, LINE_HEIGHT * 14, L"Total memory for levelnodes %d", guiLNCount[0] * sizeof( LEVELNODE ) );
|
|
}
|
|
|
|
BOOLEAN TypeExistsInLevel( LEVELNODE *pStartNode, UINT32 fType, UINT16 *pusIndex )
|
|
{
|
|
UINT32 fTileType;
|
|
|
|
// Look through all objects and Search for type
|
|
while( pStartNode != NULL )
|
|
{
|
|
|
|
if ( pStartNode->usIndex != NO_TILE && pStartNode->usIndex < giNumberOfTiles )
|
|
{
|
|
GetTileType( pStartNode->usIndex, &fTileType );
|
|
|
|
if ( fTileType == fType )
|
|
{
|
|
*pusIndex = pStartNode->usIndex;
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
pStartNode = pStartNode->pNext;
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// SHADE LEVEL MANIPULATION FOR NODES
|
|
void SetLevelShadeLevel( LEVELNODE *pStartNode, UINT8 ubShadeLevel )
|
|
{
|
|
// Look through all objects and Search for type
|
|
while( pStartNode != NULL )
|
|
{
|
|
pStartNode->ubShadeLevel = ubShadeLevel;
|
|
|
|
// Advance to next
|
|
pStartNode = pStartNode->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void AdjustLevelShadeLevel( LEVELNODE *pStartNode, INT8 bShadeDiff )
|
|
{
|
|
// Look through all objects and Search for type
|
|
while( pStartNode != NULL )
|
|
{
|
|
pStartNode->ubShadeLevel += bShadeDiff;
|
|
|
|
if ( pStartNode->ubShadeLevel > MAX_SHADE_LEVEL )
|
|
{
|
|
pStartNode->ubShadeLevel = MAX_SHADE_LEVEL;
|
|
}
|
|
|
|
if ( pStartNode->ubShadeLevel < MIN_SHADE_LEVEL )
|
|
{
|
|
pStartNode->ubShadeLevel = MIN_SHADE_LEVEL;
|
|
}
|
|
|
|
// Advance to next
|
|
pStartNode = pStartNode->pNext;
|
|
|
|
}
|
|
}
|
|
|
|
void SetIndexLevelNodeFlags( LEVELNODE *pStartNode, UINT32 uiFlags, UINT16 usIndex )
|
|
{
|
|
// Look through all objects and Search for type
|
|
while( pStartNode != NULL )
|
|
{
|
|
if ( pStartNode->usIndex == usIndex )
|
|
{
|
|
pStartNode->uiFlags |= uiFlags;
|
|
break;
|
|
}
|
|
|
|
// Advance to next
|
|
pStartNode = pStartNode->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void RemoveIndexLevelNodeFlags( LEVELNODE *pStartNode, UINT32 uiFlags, UINT16 usIndex )
|
|
{
|
|
// Look through all objects and Search for type
|
|
while( pStartNode != NULL )
|
|
{
|
|
if ( pStartNode->usIndex == usIndex )
|
|
{
|
|
pStartNode->uiFlags &= (~uiFlags);
|
|
break;
|
|
}
|
|
|
|
// Advance to next
|
|
pStartNode = pStartNode->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First for object layer
|
|
// #################################################################
|
|
|
|
LEVELNODE *AddObjectToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
LEVELNODE *pNextObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pObject == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextObject ) != FALSE );
|
|
pNextObject->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pObjectHead = pNextObject;
|
|
}
|
|
else
|
|
{
|
|
while( pObject != NULL )
|
|
{
|
|
|
|
if ( pObject->pNext == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextObject ) != FALSE );
|
|
pObject->pNext = pNextObject;
|
|
|
|
pNextObject->pNext = NULL;
|
|
pNextObject->usIndex = usIndex;
|
|
|
|
break;
|
|
}
|
|
|
|
pObject = pObject->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//CheckForAndAddTileCacheStructInfo( pNextObject, (INT16)iMapIndex, usIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_OBJECTS );
|
|
return( pNextObject );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AddObjectToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
LEVELNODE *pNextObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
CHECKF( CreateLevelNode( &pNextObject ) != FALSE );
|
|
|
|
pNextObject->pNext = pObject;
|
|
pNextObject->usIndex = usIndex;
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pObjectHead = pNextObject;
|
|
|
|
//CheckForAndAddTileCacheStructInfo( pNextObject, (INT16)iMapIndex, usIndex );
|
|
|
|
// If it's NOT the first head
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_OBJECTS );
|
|
|
|
//Add the object to the map temp file, if we have to
|
|
AddObjectToMapTempFile( iMapIndex, usIndex );
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveObject( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
LEVELNODE *pOldObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
// Look through all objects and remove index if found
|
|
|
|
while( pObject != NULL )
|
|
{
|
|
if ( pObject->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldObject == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pObjectHead = pObject->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldObject->pNext = pObject->pNext;
|
|
}
|
|
|
|
CheckForAndDeleteTileCacheStructInfo( pObject, usIndex );
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pObject );
|
|
guiLevelNodes--;
|
|
|
|
//Add the index to the maps temp file so we can remove it after reloading the map
|
|
AddRemoveObjectToMapTempFile( iMapIndex, usIndex );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldObject = pObject;
|
|
pObject = pObject->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeRangeExistsInObjectLayer( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT16 *pusObjectIndex )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
LEVELNODE *pOldObject = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pObject != NULL )
|
|
{
|
|
// Advance to next
|
|
pOldObject = pObject;
|
|
pObject = pObject->pNext;
|
|
|
|
if ( pOldObject->usIndex != NO_TILE && pOldObject->usIndex < giNumberOfTiles )
|
|
{
|
|
GetTileType( pOldObject->usIndex, &fTileType );
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
*pusObjectIndex = pOldObject->usIndex;
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeExistsInObjectLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusObjectIndex )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
return( TypeExistsInLevel( pObject, fType, pusObjectIndex ) );
|
|
}
|
|
|
|
|
|
void SetAllObjectShadeLevels( INT32 iMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
SetLevelShadeLevel( pObject, ubShadeLevel );
|
|
|
|
}
|
|
|
|
|
|
void AdjustAllObjectShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
|
|
{
|
|
LEVELNODE *pObject = NULL;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
AdjustLevelShadeLevel( pObject, bShadeDiff );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN RemoveAllObjectsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
|
|
LEVELNODE *pObject = NULL;
|
|
LEVELNODE *pOldObject = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
if( iMapIndex < 0 )
|
|
return fRetVal;
|
|
|
|
pObject = gpWorldLevelData[ iMapIndex ].pObjectHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pObject != NULL )
|
|
{
|
|
// Advance to next
|
|
pOldObject = pObject;
|
|
pObject = pObject->pNext;
|
|
|
|
if ( pOldObject->usIndex != NO_TILE && pOldObject->usIndex < giNumberOfTiles )
|
|
{
|
|
|
|
GetTileType( pOldObject->usIndex, &fTileType );
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
// Remove Item
|
|
RemoveObject( iMapIndex, pOldObject->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
// #######################################################
|
|
// Land Peice Layer
|
|
// #######################################################
|
|
|
|
LEVELNODE *AddLandToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pNextLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pLand == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextLand ) != FALSE );
|
|
pNextLand->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pLandHead = pNextLand;
|
|
|
|
}
|
|
else
|
|
{
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
if ( pLand->pNext == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextLand ) != FALSE );
|
|
pLand->pNext = pNextLand;
|
|
|
|
pNextLand->pNext = NULL;
|
|
pNextLand->pPrevNode = pLand;
|
|
pNextLand->usIndex = usIndex;
|
|
|
|
break;
|
|
}
|
|
|
|
pLand = pLand->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_LAND );
|
|
return( pNextLand );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AddLandToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pNextLand = NULL;
|
|
TILE_ELEMENT TileElem;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Allocate head
|
|
CHECKF( CreateLevelNode( &pNextLand ) != FALSE );
|
|
|
|
pNextLand->pNext = pLand;
|
|
pNextLand->pPrevNode = NULL;
|
|
pNextLand->usIndex = usIndex;
|
|
pNextLand->ubShadeLevel = LightGetAmbient();
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
// Get tile element
|
|
TileElem = gTileDatabase[ usIndex ];
|
|
|
|
// Check for full tile
|
|
if ( TileElem.ubFullTile )
|
|
{
|
|
gpWorldLevelData[ iMapIndex ].pLandStart = pNextLand;
|
|
}
|
|
}
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pLandHead = pNextLand;
|
|
|
|
// If it's NOT the first head
|
|
if ( pLand != NULL )
|
|
{
|
|
pLand->pPrevNode = pNextLand;
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_LAND );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveLand( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
|
|
RemoveLandEx( iMapIndex, usIndex );
|
|
|
|
AdjustForFullTile( iMapIndex );
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveLandEx( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all Lands and remove index if found
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
if ( pLand->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pLand->pPrevNode == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pLandHead = pLand->pNext;
|
|
}
|
|
else
|
|
{
|
|
pLand->pPrevNode->pNext = pLand->pNext;
|
|
}
|
|
|
|
// Check for tail
|
|
if ( pLand->pNext == NULL )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pLand->pNext->pPrevNode = pLand->pPrevNode;
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pLand );
|
|
guiLevelNodes--;
|
|
|
|
break;
|
|
|
|
}
|
|
pLand = pLand->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AdjustForFullTile( INT32 iMapIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
TILE_ELEMENT TileElem;
|
|
// UINT32 iType;
|
|
// UINT16 iNewIndex;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all Lands and remove index if found
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
if ( pLand->usIndex < giNumberOfTiles )
|
|
{
|
|
// If this is a full tile, set new full tile
|
|
TileElem = gTileDatabase[ pLand->usIndex ];
|
|
|
|
// Check for full tile
|
|
if ( TileElem.ubFullTile )
|
|
{
|
|
gpWorldLevelData[ iMapIndex ].pLandStart = pLand;
|
|
return( TRUE );
|
|
}
|
|
}
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
}
|
|
|
|
// Could not find a full tile
|
|
// Set to tail, and convert it to a full tile!
|
|
// Add a land peice to tail from basic land
|
|
{
|
|
UINT16 NewIndex;
|
|
LEVELNODE *pNewNode;
|
|
|
|
NewIndex = (UINT16)(Random( 10 ) );
|
|
|
|
// Adjust for type
|
|
NewIndex += gTileTypeStartIndex[ gCurrentBackground ];
|
|
|
|
pNewNode = AddLandToTail( iMapIndex, NewIndex );
|
|
|
|
gpWorldLevelData[ iMapIndex ].pLandStart = pNewNode;
|
|
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN ReplaceLandIndex( INT32 iMapIndex, UINT16 usOldIndex, UINT16 usNewIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all Lands and remove index if found
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
if ( pLand->usIndex == usOldIndex )
|
|
{
|
|
// OK, set new index value
|
|
pLand->usIndex = usNewIndex;
|
|
|
|
AdjustForFullTile( iMapIndex );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
// Advance
|
|
pLand = pLand->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeExistsInLandLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusLandIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
return( TypeExistsInLevel( pLand, fType, pusLandIndex ) );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeRangeExistsInLandLayer( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT16 *pusLandIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
if ( pLand->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pLand->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
*pusLandIndex = pOldLand->usIndex;
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeRangeExistsInLandHead( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT16 *pusLandIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
if ( pLand->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pLand->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
*pusLandIndex = pOldLand->usIndex;
|
|
return( TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
BOOLEAN TypeRangeExistsInStructLayer( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT16 *pusStructIndex )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pStruct->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
*pusStructIndex = pOldStruct->usIndex;
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveAllLandsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
if ( pLand->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pLand->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
// Remove Item
|
|
RemoveLand( iMapIndex, pOldLand->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
|
|
void SetAllLandShadeLevels( INT32 iMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
SetLevelShadeLevel( pLand, ubShadeLevel );
|
|
|
|
}
|
|
|
|
|
|
void AdjustAllLandShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all objects and Search for type
|
|
AdjustLevelShadeLevel( pLand, bShadeDiff );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN DeleteAllLandLayers( INT32 iMapIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
// Remove Item
|
|
RemoveLandEx( iMapIndex, pOldLand->usIndex );
|
|
|
|
}
|
|
|
|
// Set world data values
|
|
gpWorldLevelData[ iMapIndex ].pLandHead = NULL;
|
|
gpWorldLevelData[ iMapIndex ].pLandStart = NULL;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN InsertLandIndexAtLevel( INT32 iMapIndex, UINT16 usIndex, UINT8 ubLevel )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pNextLand = NULL;
|
|
UINT8 level = 0;
|
|
BOOLEAN CanInsert = FALSE;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
|
|
// If we want to insert at head;
|
|
if ( ubLevel == 0 )
|
|
{
|
|
AddLandToHead( iMapIndex, usIndex );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// Allocate memory for new item
|
|
CHECKF( CreateLevelNode( &pNextLand ) != FALSE );
|
|
pNextLand->usIndex = usIndex;
|
|
|
|
// Move to index before insertion
|
|
while( pLand != NULL )
|
|
{
|
|
if ( level == (ubLevel-1) )
|
|
{
|
|
CanInsert = TRUE;
|
|
break;
|
|
}
|
|
|
|
pLand = pLand->pNext;
|
|
level++;
|
|
|
|
}
|
|
|
|
// Check if level has been macthed
|
|
if ( !CanInsert )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Set links, according to position!
|
|
pNextLand->pPrevNode = pLand;
|
|
pNextLand->pNext = pLand->pNext;
|
|
pLand->pNext = pNextLand;
|
|
|
|
// Check for tail
|
|
if ( pNextLand->pNext == NULL )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNextLand->pNext->pPrevNode = pNextLand;
|
|
}
|
|
|
|
AdjustForFullTile( iMapIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_LAND );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN RemoveHigherLandLevels( INT32 iMapIndex, UINT32 fSrcType, UINT32 **puiHigherTypes, UINT8 *pubNumHigherTypes )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
UINT32 fTileType;
|
|
UINT8 ubSrcLogHeight;
|
|
|
|
*pubNumHigherTypes = 0;
|
|
*puiHigherTypes = NULL;
|
|
|
|
// Start at tail and up
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
//GEt tail
|
|
while( pLand != NULL )
|
|
{
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
}
|
|
|
|
pLand = pOldLand;
|
|
|
|
// Get src height
|
|
GetTileTypeLogicalHeight( fSrcType, &ubSrcLogHeight );
|
|
|
|
// Look through all objects and Search for height
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
GetTileType( pLand->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pPrevNode;
|
|
|
|
if ( gTileTypeLogicalHeight[ fTileType ] > ubSrcLogHeight )
|
|
{
|
|
// Remove Item
|
|
SetLandIndex( iMapIndex, pOldLand->usIndex, fTileType, TRUE );
|
|
|
|
(*pubNumHigherTypes)++;
|
|
|
|
*puiHigherTypes = (UINT32 *) MemRealloc( *puiHigherTypes, (*pubNumHigherTypes) * sizeof( UINT32 ) );
|
|
|
|
(*puiHigherTypes)[ (*pubNumHigherTypes)-1 ] = fTileType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Adjust full tile sets
|
|
AdjustForFullTile( iMapIndex );
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN SetLowerLandLevels( INT32 iMapIndex, UINT32 fSrcType, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pLand = NULL;
|
|
LEVELNODE *pOldLand = NULL;
|
|
UINT32 fTileType;
|
|
UINT8 ubSrcLogHeight;
|
|
UINT16 NewTile;
|
|
|
|
pLand = gpWorldLevelData[ iMapIndex ].pLandHead;
|
|
|
|
// Get src height
|
|
GetTileTypeLogicalHeight( fSrcType, &ubSrcLogHeight );
|
|
|
|
// Look through all objects and Search for height
|
|
while( pLand != NULL )
|
|
{
|
|
|
|
GetTileType( pLand->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldLand = pLand;
|
|
pLand = pLand->pNext;
|
|
|
|
if ( gTileTypeLogicalHeight[ fTileType ] < ubSrcLogHeight )
|
|
{
|
|
// Set item
|
|
GetTileIndexFromTypeSubIndex( fTileType, usIndex, &NewTile );
|
|
|
|
// Set as normal
|
|
SetLandIndex( iMapIndex, NewTile, fTileType, FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Adjust full tile sets
|
|
AdjustForFullTile( iMapIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_LAND );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
// Struct layer
|
|
// #################################################################
|
|
|
|
LEVELNODE *AddStructToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
return(AddStructToTailCommon( iMapIndex, usIndex, TRUE ));
|
|
}
|
|
|
|
LEVELNODE *ForceStructToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
return(AddStructToTailCommon( iMapIndex, usIndex, FALSE ));
|
|
}
|
|
|
|
LEVELNODE *AddStructToTailCommon( INT32 iMapIndex, UINT16 usIndex, BOOLEAN fAddStructDBInfo )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pTailStruct = NULL;
|
|
LEVELNODE *pNextStruct = NULL;
|
|
DB_STRUCTURE * pDBStructure;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Do we have an empty list?
|
|
if ( pStruct == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextStruct ) != FALSE );
|
|
|
|
if ( fAddStructDBInfo )
|
|
{
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 0, gTileDatabase[usIndex].pDBStructureRef, pNextStruct ) == FALSE)
|
|
{
|
|
MemFree( pNextStruct );
|
|
guiLevelNodes--;
|
|
return( NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// pNextStruct->pStructureData = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
pNextStruct->usIndex = usIndex;
|
|
|
|
pNextStruct->pNext = NULL;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pStructHead = pNextStruct;
|
|
}
|
|
else
|
|
{
|
|
// MOVE TO TAIL
|
|
while ( pStruct != NULL )
|
|
{
|
|
pTailStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
}
|
|
|
|
CHECKN( CreateLevelNode( &pNextStruct ) != FALSE );
|
|
|
|
if ( fAddStructDBInfo )
|
|
{
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 0, gTileDatabase[usIndex].pDBStructureRef, pNextStruct ) == FALSE)
|
|
{
|
|
MemFree( pNextStruct );
|
|
guiLevelNodes--;
|
|
return( NULL );
|
|
}
|
|
else
|
|
{
|
|
// pNextStruct->pStructureData = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pNextStruct->usIndex = usIndex;
|
|
|
|
pNextStruct->pNext = NULL;
|
|
pTailStruct->pNext = pNextStruct;
|
|
}
|
|
|
|
// Check flags for tiledat and set a shadow if we have a buddy
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if ( !GridNoIndoors( iMapIndex ) && gTileDatabase[ usIndex ].uiFlags & HAS_SHADOW_BUDDY && gTileDatabase[ usIndex ].sBuddyNum != -1 )
|
|
{
|
|
AddShadowToHead( iMapIndex, gTileDatabase[ usIndex ].sBuddyNum );
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead->uiFlags |= LEVELNODE_BUDDYSHADOW;
|
|
}
|
|
|
|
//Check for special flag to stop burn-through on same-tile structs...
|
|
if ( gTileDatabase[ usIndex ].pDBStructureRef != NULL )
|
|
{
|
|
pDBStructure = gTileDatabase[ usIndex ].pDBStructureRef->pDBStructure;
|
|
|
|
// Default to off....
|
|
gpWorldLevelData[ iMapIndex ].ubExtFlags[0] &= (~MAPELEMENT_EXT_NOBURN_STRUCT);
|
|
|
|
// If we are NOT a wall and NOT multi-tiles, set mapelement flag...
|
|
if ( !FindStructure( iMapIndex, STRUCTURE_WALLSTUFF ) && pDBStructure->ubNumberOfTiles == 1 )
|
|
{
|
|
// Set flag...
|
|
gpWorldLevelData[ iMapIndex ].ubExtFlags[0] |= MAPELEMENT_EXT_NOBURN_STRUCT;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Add the structure the maps temp file
|
|
AddStructToMapTempFile( iMapIndex, usIndex );
|
|
|
|
//CheckForAndAddTileCacheStructInfo( pNextStruct, (INT16)iMapIndex, usIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_STRUCTURES );
|
|
|
|
return( pNextStruct );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN AddStructToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pNextStruct = NULL;
|
|
DB_STRUCTURE * pDBStructure;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
CHECKF( CreateLevelNode( &pNextStruct ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 0, gTileDatabase[usIndex].pDBStructureRef, pNextStruct ) == FALSE)
|
|
{
|
|
MemFree( pNextStruct );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
pNextStruct->pNext = pStruct;
|
|
pNextStruct->usIndex = usIndex;
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pStructHead = pNextStruct;
|
|
|
|
SetWorldFlagsFromNewNode( iMapIndex, pNextStruct->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 )
|
|
{
|
|
AddShadowToHead( iMapIndex, gTileDatabase[ usIndex ].sBuddyNum );
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead->uiFlags |= LEVELNODE_BUDDYSHADOW;
|
|
}
|
|
|
|
//Check for special flag to stop burn-through on same-tile structs...
|
|
if ( gTileDatabase[ usIndex ].pDBStructureRef != NULL )
|
|
{
|
|
pDBStructure = gTileDatabase[ usIndex ].pDBStructureRef->pDBStructure;
|
|
|
|
// Default to off....
|
|
gpWorldLevelData[ iMapIndex ].ubExtFlags[0] &= (~MAPELEMENT_EXT_NOBURN_STRUCT);
|
|
|
|
// If we are NOT a wall and NOT multi-tiles, set mapelement flag...
|
|
if ( !!FindStructure( iMapIndex, STRUCTURE_WALLSTUFF ) && pDBStructure->ubNumberOfTiles == 1 )
|
|
{
|
|
// Set flag...
|
|
gpWorldLevelData[ iMapIndex ].ubExtFlags[0] |= MAPELEMENT_EXT_NOBURN_STRUCT;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//Add the structure the maps temp file
|
|
AddStructToMapTempFile( iMapIndex, usIndex );
|
|
|
|
//CheckForAndAddTileCacheStructInfo( pNextStruct, (INT16)iMapIndex, usIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_STRUCTURES );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN InsertStructIndex( INT32 iMapIndex, UINT16 usIndex, UINT8 ubLevel )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pNextStruct = NULL;
|
|
UINT8 level = 0;
|
|
BOOLEAN CanInsert = FALSE;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// If we want to insert at head;
|
|
if ( ubLevel == 0 )
|
|
{
|
|
return( AddStructToHead( iMapIndex, usIndex ) );
|
|
}
|
|
|
|
|
|
// Allocate memory for new item
|
|
CHECKF( CreateLevelNode( &pNextStruct ) != FALSE );
|
|
|
|
pNextStruct->usIndex = usIndex;
|
|
|
|
// Move to index before insertion
|
|
while( pStruct != NULL )
|
|
{
|
|
if ( level == (ubLevel-1) )
|
|
{
|
|
CanInsert = TRUE;
|
|
break;
|
|
}
|
|
|
|
pStruct = pStruct->pNext;
|
|
level++;
|
|
|
|
}
|
|
|
|
// Check if level has been macthed
|
|
if ( !CanInsert )
|
|
{
|
|
MemFree( pNextStruct );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 0, gTileDatabase[usIndex].pDBStructureRef, pNextStruct ) == FALSE)
|
|
{
|
|
MemFree( pNextStruct );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set links, according to position!
|
|
pNextStruct->pNext = pStruct->pNext;
|
|
pStruct->pNext = pNextStruct;
|
|
|
|
//CheckForAndAddTileCacheStructInfo( pNextStruct, (INT16)iMapIndex, usIndex );
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_STRUCTURES );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN RemoveStructFromTail( INT32 iMapIndex )
|
|
{
|
|
return(RemoveStructFromTailCommon( iMapIndex, TRUE ));
|
|
}
|
|
|
|
BOOLEAN ForceRemoveStructFromTail( INT32 iMapIndex )
|
|
{
|
|
return(RemoveStructFromTailCommon( iMapIndex, FALSE ));
|
|
}
|
|
|
|
BOOLEAN RemoveStructFromTailCommon( INT32 iMapIndex, BOOLEAN fRemoveStructDBInfo )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pPrevStruct = NULL;
|
|
UINT16 usIndex;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// GOTO TAIL
|
|
while( pStruct != NULL )
|
|
{
|
|
// AT THE TAIL
|
|
if ( pStruct->pNext == NULL )
|
|
{
|
|
if ( pPrevStruct != NULL )
|
|
{
|
|
pPrevStruct->pNext = pStruct->pNext;
|
|
}
|
|
else
|
|
gpWorldLevelData[ iMapIndex ].pStructHead = pPrevStruct;
|
|
|
|
if ( fRemoveStructDBInfo )
|
|
{
|
|
//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 );
|
|
//}
|
|
}
|
|
|
|
DeleteStructureFromWorld( pStruct->pStructureData );
|
|
}
|
|
|
|
usIndex = pStruct->usIndex;
|
|
|
|
//If we have to, make sure to remove this node when we reload the map from a saved game
|
|
RemoveStructFromMapTempFile( iMapIndex, usIndex );
|
|
|
|
|
|
MemFree( pStruct );
|
|
guiLevelNodes--;
|
|
|
|
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 );
|
|
}
|
|
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
pPrevStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN RemoveStruct( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// 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].pStructHead = 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
|
|
RemoveStructFromMapTempFile( 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 );
|
|
}
|
|
|
|
BOOLEAN FindStruct(INT32 sSpot, INT8 bLevel, UINT16 usIndex)
|
|
{
|
|
if (TileIsOutOfBounds(sSpot))
|
|
return FALSE;
|
|
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
|
|
if (bLevel == 0)
|
|
{
|
|
pStruct = gpWorldLevelData[sSpot].pStructHead;
|
|
}
|
|
else
|
|
{
|
|
pStruct = gpWorldLevelData[sSpot].pOnRoofHead;
|
|
}
|
|
|
|
// Look through all structs
|
|
while (pStruct != NULL)
|
|
{
|
|
if (pStruct->usIndex == usIndex)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN FindStructFlag(INT32 sSpot, INT8 bLevel, UINT32 uiFlag)
|
|
{
|
|
if (bLevel > 0)
|
|
return FALSE;
|
|
|
|
if (TileIsOutOfBounds(sSpot))
|
|
return FALSE;
|
|
|
|
STRUCTURE * pStructure;
|
|
|
|
pStructure = FindStructure(sSpot, uiFlag);
|
|
|
|
if (pStructure)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// 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;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[iMapIndex].pRoofHead;
|
|
|
|
// 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].pRoofHead = 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
|
|
RemoveRoofFromMapTempFile( iMapIndex, usIndex );
|
|
|
|
MemFree( pStruct );
|
|
--guiLevelNodes;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
RemoveWorldFlagsFromNewNode( iMapIndex, 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 )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT16 usIndex;
|
|
|
|
usIndex = pNode->usIndex;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Look through all structs and remove index if found
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
if ( pStruct == pNode )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldStruct == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pStructHead = 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
|
|
RemoveStructFromMapTempFile( iMapIndex, usIndex );
|
|
|
|
if ( pNode->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 );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveAllStructsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 fTileType;
|
|
UINT16 usIndex;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Look through all structs and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pStruct->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
usIndex = pOldStruct->usIndex;
|
|
|
|
// Remove Item
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
RemoveStruct( iMapIndex, pOldStruct->usIndex );
|
|
fRetVal = TRUE;
|
|
if ( !GridNoIndoors( iMapIndex ) && gTileDatabase[ usIndex ].uiFlags & HAS_SHADOW_BUDDY && gTileDatabase[ usIndex ].sBuddyNum != -1 )
|
|
{
|
|
RemoveShadow( iMapIndex, gTileDatabase[ usIndex ].sBuddyNum );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
// Flugente: permanently remove structures
|
|
BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( 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].pRoofHead;
|
|
|
|
// 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 )
|
|
{
|
|
RemoveRoofAdjustSavefile( iMapIndex, pOldRoof->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 )
|
|
{
|
|
RemoveStruct( iMapIndex, usOldIndex );
|
|
AddWallToStructLayer( iMapIndex, usNewIndex, FALSE );
|
|
return TRUE;
|
|
// LEVELNODE *pStruct = NULL;
|
|
// pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
// Look through all Structs and remove index if found
|
|
// while( pStruct != NULL )
|
|
// {
|
|
// if ( pStruct->usIndex == usOldIndex )
|
|
// {
|
|
// // OK, set new index value
|
|
// pStruct->usIndex = usNewIndex;
|
|
// AdjustForFullTile( iMapIndex );
|
|
// return( TRUE );
|
|
// }
|
|
// // Advance
|
|
// pStruct = pStruct->pNext;
|
|
// }
|
|
// // Could not find it, return FALSE
|
|
// return( FALSE );
|
|
}
|
|
|
|
// When adding, put in order such that it's drawn before any walls of a
|
|
// lesser orientation value
|
|
BOOLEAN AddWallToStructLayer( INT32 iMapIndex, UINT16 usIndex, BOOLEAN fReplace )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
UINT16 usCheckWallOrient;
|
|
UINT16 usWallOrientation;
|
|
BOOLEAN fInsertFound = FALSE;
|
|
BOOLEAN fRoofFound = FALSE;
|
|
UINT8 ubRoofLevel=0;
|
|
UINT32 uiCheckType;
|
|
UINT8 ubLevel = 0;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
|
|
// Get orientation of peice we want to add
|
|
GetWallOrientation( usIndex, &usWallOrientation );
|
|
|
|
// Look through all objects and Search for orientation
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
GetWallOrientation( pStruct->usIndex, &usCheckWallOrient );
|
|
//OLD CASE
|
|
//if ( usCheckWallOrient > usWallOrientation )
|
|
//Kris:
|
|
//New case -- If placing a new wall which is at right angles to the current wall, then
|
|
//we insert it.
|
|
if( usCheckWallOrient > usWallOrientation )
|
|
{
|
|
if( (usWallOrientation == INSIDE_TOP_RIGHT || usWallOrientation == OUTSIDE_TOP_RIGHT) &&
|
|
(usCheckWallOrient == INSIDE_TOP_LEFT || usCheckWallOrient == OUTSIDE_TOP_LEFT ) ||
|
|
(usWallOrientation == INSIDE_TOP_LEFT || usWallOrientation == OUTSIDE_TOP_LEFT) &&
|
|
(usCheckWallOrient == INSIDE_TOP_RIGHT || usCheckWallOrient == OUTSIDE_TOP_RIGHT ) )
|
|
{
|
|
fInsertFound = TRUE;
|
|
}
|
|
}
|
|
|
|
GetTileType( pStruct->usIndex, &uiCheckType );
|
|
|
|
// if ( uiCheckType >= FIRSTFLOOR && uiCheckType <= LASTFLOOR )
|
|
if ( uiCheckType >= FIRSTROOF && uiCheckType <= LASTROOF )
|
|
{
|
|
fRoofFound = TRUE;
|
|
ubRoofLevel = ubLevel;
|
|
}
|
|
|
|
//OLD CHECK
|
|
// Check if it's the same orientation
|
|
//if ( usCheckWallOrient == usWallOrientation )
|
|
//Kris:
|
|
//New check -- we want to check for walls being parallel to each other. If so, then
|
|
//we we want to replace it. This is because of an existing problem with say, INSIDE_TOP_LEFT
|
|
//and OUTSIDE_TOP_LEFT walls coexisting.
|
|
if( (usWallOrientation == INSIDE_TOP_RIGHT || usWallOrientation == OUTSIDE_TOP_RIGHT) &&
|
|
(usCheckWallOrient == INSIDE_TOP_RIGHT || usCheckWallOrient == OUTSIDE_TOP_RIGHT ) ||
|
|
(usWallOrientation == INSIDE_TOP_LEFT || usWallOrientation == OUTSIDE_TOP_LEFT) &&
|
|
(usCheckWallOrient == INSIDE_TOP_LEFT || usCheckWallOrient == OUTSIDE_TOP_LEFT ) )
|
|
{
|
|
// Same, if replace, replace here
|
|
if ( fReplace )
|
|
{
|
|
return( ReplaceStructIndex( iMapIndex, pStruct->usIndex, usIndex ) );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
// Advance to next
|
|
pStruct = pStruct->pNext;
|
|
|
|
ubLevel++;
|
|
|
|
}
|
|
|
|
// Check if we found an insert position, otherwise set to head
|
|
if ( fInsertFound )
|
|
{
|
|
// Insert struct at head
|
|
AddStructToHead( iMapIndex, usIndex );
|
|
}
|
|
else
|
|
{
|
|
// Make sure it's ALWAYS after the roof ( if any )
|
|
if ( fRoofFound )
|
|
{
|
|
InsertStructIndex( iMapIndex, usIndex, ubRoofLevel );
|
|
}
|
|
else
|
|
{
|
|
AddStructToTail( iMapIndex, usIndex );
|
|
}
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_STRUCTURES );
|
|
// Could not find it, return FALSE
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN TypeExistsInStructLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusStructIndex )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
return( TypeExistsInLevel( pStruct, fType, pusStructIndex ) );
|
|
}
|
|
|
|
|
|
void SetAllStructShadeLevels( INT32 iMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
SetLevelShadeLevel( pStruct, ubShadeLevel );
|
|
|
|
}
|
|
|
|
|
|
void AdjustAllStructShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
AdjustLevelShadeLevel( pStruct, bShadeDiff );
|
|
|
|
}
|
|
|
|
|
|
void SetStructIndexFlagsFromTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Look through all structs and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pStruct->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
pOldStruct->uiFlags |= uiFlags;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOLEAN HideStructOfGivenType(INT32 iMapIndex, UINT32 fType, BOOLEAN fHide)//dnl ch80 011213
|
|
{
|
|
if(fHide)
|
|
{
|
|
/*
|
|
if(fType >= FIRSTONROOF && fType <= LASTONROOF)
|
|
SetOnRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
else
|
|
SetRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
*/
|
|
|
|
// Buggler: set all tiles to their proper roof index flags
|
|
if(fType >= FIRSTROOF && fType <= SECONDSLANTROOF)
|
|
SetRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
else
|
|
SetOnRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
}
|
|
else
|
|
{
|
|
// ONLY UNHIDE IF NOT REVEALED ALREADY
|
|
if(!(gpWorldLevelData[iMapIndex].uiFlags & MAPELEMENT_REVEALED))
|
|
{
|
|
/*
|
|
if(fType >= FIRSTONROOF && fType <= LASTONROOF)
|
|
RemoveOnRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
else
|
|
RemoveRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
*/
|
|
|
|
if(fType >= FIRSTROOF && fType <= SECONDSLANTROOF)
|
|
RemoveRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
else
|
|
RemoveOnRoofIndexFlagsFromTypeRange(iMapIndex, fType, fType, LEVELNODE_HIDDEN);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
void RemoveStructIndexFlagsFromTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pStructHead;
|
|
|
|
// Look through all structs and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pStruct->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
pOldStruct->uiFlags &= ( ~uiFlags );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Shadow layer
|
|
// #################################################################
|
|
|
|
BOOLEAN AddShadowToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pNextShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pShadow == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pShadow ) != FALSE );
|
|
pShadow->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead = pShadow;
|
|
|
|
}
|
|
else
|
|
{
|
|
while( pShadow != NULL )
|
|
{
|
|
|
|
if ( pShadow->pNext == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextShadow ) != FALSE );
|
|
pShadow->pNext = pNextShadow;
|
|
pNextShadow->pNext = NULL;
|
|
pNextShadow->usIndex = usIndex;
|
|
break;
|
|
}
|
|
|
|
pShadow = pShadow->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_SHADOWS );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
//Kris: identical shadows can exist in the same gridno, though it makes no sense
|
|
// because it actually renders the shadows darker than the others. This is an
|
|
// undesirable effect with walls and buildings so I added this function to make
|
|
// sure there isn't already a shadow before placing it.
|
|
void AddExclusiveShadow( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pShadow;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
while( pShadow )
|
|
{
|
|
if( pShadow->usIndex == usIndex )
|
|
return;
|
|
pShadow = pShadow->pNext;
|
|
}
|
|
AddShadowToHead( iMapIndex, usIndex );
|
|
}
|
|
|
|
BOOLEAN AddShadowToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pShadow;
|
|
LEVELNODE *pNextShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Allocate head
|
|
CHECKF( CreateLevelNode( &pNextShadow ) != FALSE );
|
|
pNextShadow->pNext = pShadow;
|
|
pNextShadow->usIndex = usIndex;
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead = pNextShadow;
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_SHADOWS );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveShadow( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pOldShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Look through all shadows and remove index if found
|
|
|
|
while( pShadow != NULL )
|
|
{
|
|
if ( pShadow->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldShadow == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead = pShadow->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldShadow->pNext = pShadow->pNext;
|
|
}
|
|
#if 0//#ifdef JA2EDITOR//dnl ch80 011213 //dnl ch86 190214
|
|
if(pShadow->uiFlags & LEVELNODE_EXITGRID && pShadow->pExitGridInfo)
|
|
memset(pShadow->pExitGridInfo, 0, sizeof(EXITGRID));
|
|
#endif
|
|
// Delete memory assosiated with item
|
|
MemFree( pShadow );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldShadow = pShadow;
|
|
pShadow = pShadow->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveShadowFromLevelNode( INT32 iMapIndex, LEVELNODE *pNode )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pOldShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Look through all shadows and remove index if found
|
|
|
|
while( pShadow != NULL )
|
|
{
|
|
if ( pShadow == pNode )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldShadow == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead = pShadow->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldShadow->pNext = pShadow->pNext;
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pShadow );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldShadow = pShadow;
|
|
pShadow = pShadow->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveStructShadowPartner( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pOldShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Look through all shadows and remove index if found
|
|
|
|
while( pShadow != NULL )
|
|
{
|
|
if ( pShadow->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldShadow == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pShadowHead = pShadow->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldShadow->pNext = pShadow->pNext;
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pShadow );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldShadow = pShadow;
|
|
pShadow = pShadow->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveAllShadowsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pOldShadow = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Look through all shadows and Search for type
|
|
|
|
while( pShadow != NULL )
|
|
{
|
|
|
|
if ( pShadow->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pShadow->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldShadow = pShadow;
|
|
pShadow = pShadow->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
// Remove Item
|
|
RemoveShadow( iMapIndex, pOldShadow->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
BOOLEAN RemoveAllShadows( INT32 iMapIndex )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
LEVELNODE *pOldShadow = NULL;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
// Look through all shadows and Search for type
|
|
|
|
while( pShadow != NULL )
|
|
{
|
|
|
|
if ( pShadow->usIndex != NO_TILE )
|
|
{
|
|
|
|
// Advance to next
|
|
pOldShadow = pShadow;
|
|
pShadow = pShadow->pNext;
|
|
|
|
// Remove Item
|
|
RemoveShadow( iMapIndex, pOldShadow->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
BOOLEAN TypeExistsInShadowLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusShadowIndex )
|
|
{
|
|
LEVELNODE *pShadow = NULL;
|
|
|
|
pShadow = gpWorldLevelData[ iMapIndex ].pShadowHead;
|
|
|
|
return( TypeExistsInLevel( pShadow, fType, pusShadowIndex ) );
|
|
}
|
|
|
|
|
|
// Merc layer
|
|
// #################################################################
|
|
|
|
|
|
BOOLEAN AddMercToHead( INT32 iMapIndex, SOLDIERTYPE *pSoldier, BOOLEAN fAddStructInfo )
|
|
{
|
|
LEVELNODE *pMerc = NULL;
|
|
LEVELNODE *pNextMerc = NULL;
|
|
|
|
pMerc = gpWorldLevelData[ iMapIndex ].pMercHead;
|
|
|
|
// Allocate head
|
|
CHECKF( CreateLevelNode( &pNextMerc ) != FALSE );
|
|
pNextMerc->pNext = pMerc;
|
|
pNextMerc->pSoldier = pSoldier;
|
|
pNextMerc->uiFlags |= LEVELNODE_SOLDIER;
|
|
|
|
// Add structure info if we want
|
|
if ( fAddStructInfo )
|
|
{
|
|
// Set soldier's levelnode
|
|
pSoldier->pLevelNode = pNextMerc;
|
|
|
|
AddMercStructureInfo( iMapIndex, pSoldier );
|
|
}
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pMercHead = pNextMerc;
|
|
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_MERCS | TILES_DYNAMIC_STRUCT_MERCS | TILES_DYNAMIC_HIGHMERCS );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AddMercStructureInfo( INT32 sGridNo, SOLDIERTYPE *pSoldier )
|
|
{
|
|
UINT16 usAnimSurface;
|
|
|
|
// Get surface data
|
|
usAnimSurface = GetSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
|
|
|
|
AddMercStructureInfoFromAnimSurface( sGridNo, pSoldier, usAnimSurface, pSoldier->usAnimState );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN AddMercStructureInfoFromAnimSurface( INT32 sGridNo, SOLDIERTYPE *pSoldier, UINT16 usAnimSurface, UINT16 usAnimState )
|
|
{
|
|
STRUCTURE_FILE_REF *pStructureFileRef;
|
|
BOOLEAN fReturn;
|
|
|
|
// Turn off multi tile flag...
|
|
pSoldier->flags.uiStatusFlags &= ( ~SOLDIER_MULTITILE );
|
|
|
|
if ( pSoldier->pLevelNode == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( usAnimSurface == INVALID_ANIMATION_SURFACE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Remove existing structs
|
|
DeleteStructureFromWorld( pSoldier->pLevelNode->pStructureData );
|
|
pSoldier->pLevelNode->pStructureData = NULL;
|
|
|
|
pStructureFileRef = GetAnimationStructureRef( pSoldier->ubID, usAnimSurface, usAnimState );
|
|
|
|
// Now check if we are multi-tiled!
|
|
if ( pStructureFileRef != NULL )
|
|
{
|
|
if ( pSoldier->ubBodyType == QUEENMONSTER )
|
|
{
|
|
// Queen uses onely one direction....
|
|
fReturn = AddStructureToWorld( sGridNo, pSoldier->pathing.bLevel, &( pStructureFileRef->pDBStructureRef[ 0 ] ), pSoldier->pLevelNode );
|
|
}
|
|
else
|
|
{
|
|
fReturn = AddStructureToWorld( sGridNo, pSoldier->pathing.bLevel, &( pStructureFileRef->pDBStructureRef[ gOneCDirection[ pSoldier->ubDirection ] ] ), pSoldier->pLevelNode );
|
|
}
|
|
/*
|
|
if ( fReturn == FALSE )
|
|
{
|
|
// try to add default
|
|
ScreenMsg( MSG_FONT_YELLOW, MSG_DEBUG, L"FAILED: add struct info for merc: %d, at %d direction %d, trying default instead", pSoldier->ubID, sGridNo, pSoldier->ubDirection );
|
|
|
|
pStructureFileRef = GetDefaultStructureRef( pSoldier->ubID );
|
|
if ( pStructureFileRef )
|
|
{
|
|
fReturn = AddStructureToWorld( sGridNo, pSoldier->bLevel, &( pStructureFileRef->pDBStructureRef[ gOneCDirection[ pSoldier->ubDirection ] ] ), pSoldier->pLevelNode );
|
|
}
|
|
}
|
|
*/
|
|
|
|
if ( fReturn == FALSE )
|
|
{
|
|
|
|
// Debug msg
|
|
ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"FAILED: add struct info for merc %d (%s), at %d direction %d", pSoldier->ubID, pSoldier->name, sGridNo, pSoldier->ubDirection );
|
|
|
|
if ( pStructureFileRef->pDBStructureRef[ gOneCDirection[ pSoldier->ubDirection ] ].pDBStructure->ubNumberOfTiles > 1 )
|
|
{
|
|
// If we have more than one tile
|
|
pSoldier->flags.uiStatusFlags |= SOLDIER_MULTITILE_Z;
|
|
}
|
|
|
|
|
|
return( FALSE );
|
|
}
|
|
else
|
|
{
|
|
// Turn on if we are multi-tiled
|
|
if ( pSoldier->pLevelNode->pStructureData->pDBStructureRef->pDBStructure->ubNumberOfTiles > 1 )
|
|
{
|
|
// If we have more than one tile
|
|
pSoldier->flags.uiStatusFlags |= SOLDIER_MULTITILE_Z;
|
|
}
|
|
else
|
|
{
|
|
//pSoldier->uiStatusFlags |= SOLDIER_MULTITILE_NZ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN OKToAddMercToWorld( SOLDIERTYPE *pSoldier, INT8 bDirection )
|
|
{
|
|
UINT16 usAnimSurface;
|
|
STRUCTURE_FILE_REF *pStructFileRef;
|
|
UINT16 usOKToAddStructID;
|
|
|
|
// 0verhaul: Reinserting this check. If a soldier is sitting or standing on a grid and another soldier is lying prone
|
|
// across that grid but has the structure, this call will not allow the current soldier to turn. Since we are talking
|
|
// about the soldier whose turn it is, this is not a good thing because it will lead to deadlock.
|
|
if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE ||
|
|
pSoldier->usAnimState == CRAWLING)
|
|
{
|
|
// Get surface data
|
|
usAnimSurface = GetSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
|
|
if ( usAnimSurface == INVALID_ANIMATION_SURFACE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pStructFileRef = GetAnimationStructureRef( pSoldier->ubID, usAnimSurface, pSoldier->usAnimState );
|
|
|
|
// Now check if we have multi-tile info!
|
|
if ( pStructFileRef != NULL )
|
|
{
|
|
//Try adding struct to this location, if we can it's good!
|
|
if ( pSoldier->pLevelNode && pSoldier->pLevelNode->pStructureData != NULL )
|
|
{
|
|
usOKToAddStructID = pSoldier->pLevelNode->pStructureData->usStructureID;
|
|
}
|
|
else
|
|
{
|
|
usOKToAddStructID = INVALID_STRUCTURE_ID;
|
|
}
|
|
|
|
if ( !OkayToAddStructureToWorld( pSoldier->sGridNo, pSoldier->pathing.bLevel, &(pStructFileRef->pDBStructureRef[gOneCDirection[ bDirection ]]), usOKToAddStructID ))
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN UpdateMercStructureInfo( SOLDIERTYPE *pSoldier )
|
|
{
|
|
// Remove strucute info!
|
|
if ( pSoldier->pLevelNode == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//DeleteStructureFromWorld( pSoldier->pLevelNode->pStructureData );
|
|
|
|
// Add new one!
|
|
return( AddMercStructureInfo( pSoldier->sGridNo, pSoldier ) );
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveMerc( INT32 iMapIndex, SOLDIERTYPE *pSoldier, BOOLEAN fPlaceHolder )
|
|
{
|
|
LEVELNODE *pMerc = NULL;
|
|
LEVELNODE *pOldMerc = NULL;
|
|
BOOLEAN fMercFound;
|
|
|
|
if ( TileIsOutOfBounds( iMapIndex ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pMerc = gpWorldLevelData[ iMapIndex ].pMercHead;
|
|
|
|
// Look through all mercs and remove index if found
|
|
|
|
while( pMerc != NULL )
|
|
{
|
|
fMercFound = FALSE;
|
|
|
|
if ( pMerc->pSoldier == pSoldier )
|
|
{
|
|
// If it's a placeholder, check!
|
|
if ( fPlaceHolder )
|
|
{
|
|
if ( ( pMerc->uiFlags & LEVELNODE_MERCPLACEHOLDER ) )
|
|
{
|
|
fMercFound = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !( pMerc->uiFlags & LEVELNODE_MERCPLACEHOLDER ) )
|
|
{
|
|
fMercFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fMercFound )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldMerc == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pMercHead = pMerc->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldMerc->pNext = pMerc->pNext;
|
|
}
|
|
|
|
if ( !fPlaceHolder )
|
|
{
|
|
// Set level node to NULL
|
|
pSoldier->pLevelNode = NULL;
|
|
|
|
// Remove strucute info!
|
|
DeleteStructureFromWorld( pMerc->pStructureData );
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pMerc );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
pOldMerc = pMerc;
|
|
pMerc = pMerc->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
// Roof layer
|
|
// #################################################################
|
|
|
|
LEVELNODE *AddRoofToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pNextRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pRoof == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pRoof ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pRoof ) == FALSE)
|
|
{
|
|
MemFree( pRoof );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
pRoof->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pRoofHead = pRoof;
|
|
|
|
pNextRoof = pRoof;
|
|
}
|
|
else
|
|
{
|
|
while( pRoof != NULL )
|
|
{
|
|
|
|
if ( pRoof->pNext == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextRoof ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pNextRoof ) == FALSE)
|
|
{
|
|
MemFree( pNextRoof );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
pRoof->pNext = pNextRoof;
|
|
|
|
pNextRoof->pNext = NULL;
|
|
pNextRoof->usIndex = usIndex;
|
|
|
|
break;
|
|
}
|
|
|
|
pRoof = pRoof->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_ROOF );
|
|
|
|
return( pNextRoof );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AddRoofToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pNextRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
CHECKF( CreateLevelNode( &pNextRoof ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pNextRoof ) == FALSE)
|
|
{
|
|
MemFree( pNextRoof );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
pNextRoof->pNext = pRoof;
|
|
pNextRoof->usIndex = usIndex;
|
|
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pRoofHead = pNextRoof;
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_ROOF );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveRoof( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and remove index if found
|
|
|
|
while( pRoof != NULL )
|
|
{
|
|
if ( pRoof->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldRoof == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pRoofHead = pRoof->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldRoof->pNext = pRoof->pNext;
|
|
}
|
|
// Delete memory assosiated with item
|
|
DeleteStructureFromWorld( pRoof->pStructureData );
|
|
MemFree( pRoof );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldRoof = pRoof;
|
|
pRoof = pRoof->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeExistsInRoofLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusRoofIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
return( TypeExistsInLevel( pRoof, fType, pusRoofIndex ) );
|
|
}
|
|
|
|
|
|
BOOLEAN TypeRangeExistsInRoofLayer( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT16 *pusRoofIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pRoof != NULL )
|
|
{
|
|
if ( pRoof->usIndex != NO_TILE )
|
|
{
|
|
GetTileType( pRoof->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldRoof = pRoof;
|
|
pRoof = pRoof->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
*pusRoofIndex = pOldRoof->usIndex;
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN IndexExistsInRoofLayer( INT32 sGridNo, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ sGridNo ].pRoofHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pRoof != NULL )
|
|
{
|
|
if ( pRoof->usIndex == usIndex )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
pRoof = pRoof->pNext;
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SetAllRoofShadeLevels( INT32 iMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
SetLevelShadeLevel( pRoof, ubShadeLevel );
|
|
|
|
}
|
|
|
|
|
|
void AdjustAllRoofShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
AdjustLevelShadeLevel( pRoof, bShadeDiff );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN RemoveAllRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and Search for type
|
|
|
|
while( 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
|
|
RemoveRoof( iMapIndex, pOldRoof->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
void RemoveRoofIndexFlagsFromTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and Search for type
|
|
|
|
while( pRoof != NULL )
|
|
{
|
|
|
|
if ( pRoof->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pRoof->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldRoof = pRoof;
|
|
pRoof = pRoof->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
pOldRoof->uiFlags &= ( ~uiFlags );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void SetRoofIndexFlagsFromTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pRoof = NULL;
|
|
LEVELNODE *pOldRoof = NULL;
|
|
UINT32 fTileType;
|
|
|
|
pRoof = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and Search for type
|
|
|
|
while( pRoof != NULL )
|
|
{
|
|
|
|
if ( pRoof->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pRoof->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldRoof = pRoof;
|
|
pRoof = pRoof->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
pOldRoof->uiFlags |= uiFlags;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// OnRoof layer
|
|
// #################################################################
|
|
|
|
LEVELNODE *AddOnRoofToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
LEVELNODE *pNextOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pOnRoof == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pOnRoof ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pOnRoof ) == FALSE)
|
|
{
|
|
MemFree( pOnRoof );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
pOnRoof->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pOnRoofHead = pOnRoof;
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_ONROOF );
|
|
return( pOnRoof );
|
|
|
|
}
|
|
else
|
|
{
|
|
while( pOnRoof != NULL )
|
|
{
|
|
|
|
if ( pOnRoof->pNext == NULL )
|
|
{
|
|
CHECKF( CreateLevelNode( &pNextOnRoof ) != FALSE );
|
|
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pNextOnRoof ) == FALSE)
|
|
{
|
|
MemFree( pNextOnRoof );
|
|
guiLevelNodes--;
|
|
return( NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
pOnRoof->pNext = pNextOnRoof;
|
|
|
|
pNextOnRoof->pNext = NULL;
|
|
pNextOnRoof->usIndex = usIndex;
|
|
break;
|
|
}
|
|
|
|
pOnRoof = pOnRoof->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_ONROOF );
|
|
return( pNextOnRoof );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN AddOnRoofToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
LEVELNODE *pNextOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
CHECKF( CreateLevelNode( &pNextOnRoof ) != FALSE );
|
|
if ( usIndex < giNumberOfTiles )
|
|
{
|
|
if (gTileDatabase[usIndex].pDBStructureRef != NULL)
|
|
{
|
|
if (AddStructureToWorld( iMapIndex, 1, gTileDatabase[usIndex].pDBStructureRef, pNextOnRoof ) == FALSE)
|
|
{
|
|
MemFree( pNextOnRoof );
|
|
guiLevelNodes--;
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
pNextOnRoof->pNext = pOnRoof;
|
|
pNextOnRoof->usIndex = usIndex;
|
|
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pOnRoofHead = pNextOnRoof;
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_ONROOF );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveOnRoof( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
LEVELNODE *pOldOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
// Look through all OnRoofs and remove index if found
|
|
|
|
while( pOnRoof != NULL )
|
|
{
|
|
if ( pOnRoof->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldOnRoof == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pOnRoofHead = pOnRoof->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldOnRoof->pNext = pOnRoof->pNext;
|
|
}
|
|
|
|
// REMOVE ONROOF!
|
|
MemFree( pOnRoof );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldOnRoof = pOnRoof;
|
|
pOnRoof = pOnRoof->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveOnRoofFromLevelNode( INT32 iMapIndex, LEVELNODE *pNode )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
LEVELNODE *pOldOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
// Look through all OnRoofs and remove index if found
|
|
|
|
while( pOnRoof != NULL )
|
|
{
|
|
if ( pOnRoof == pNode )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldOnRoof == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pOnRoofHead = pOnRoof->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldOnRoof->pNext = pOnRoof->pNext;
|
|
}
|
|
|
|
// REMOVE ONROOF!
|
|
MemFree( pOnRoof );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldOnRoof = pOnRoof;
|
|
pOnRoof = pOnRoof->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN TypeExistsInOnRoofLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusOnRoofIndex )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
return( TypeExistsInLevel( pOnRoof, fType, pusOnRoofIndex ) );
|
|
}
|
|
|
|
|
|
void SetAllOnRoofShadeLevels( INT32 iMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
SetLevelShadeLevel( pOnRoof, ubShadeLevel );
|
|
|
|
}
|
|
|
|
|
|
void AdjustAllOnRoofShadeLevels( INT32 iMapIndex, INT8 bShadeDiff )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
AdjustLevelShadeLevel( pOnRoof, bShadeDiff );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN RemoveAllOnRoofsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pOnRoof = NULL;
|
|
LEVELNODE *pOldOnRoof = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
if( iMapIndex < 0 )
|
|
return fRetVal;
|
|
|
|
pOnRoof = gpWorldLevelData[ iMapIndex ].pOnRoofHead;
|
|
|
|
// Look through all OnRoofs and Search for type
|
|
|
|
while( pOnRoof != NULL )
|
|
{
|
|
|
|
if ( pOnRoof->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileType( pOnRoof->usIndex, &fTileType );
|
|
|
|
// Advance to next
|
|
pOldOnRoof = pOnRoof;
|
|
pOnRoof = pOnRoof->pNext;
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
// Remove Item
|
|
RemoveOnRoof( iMapIndex, pOldOnRoof->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
void RemoveOnRoofIndexFlagsFromTypeRange(INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags)//dnl ch80 011213
|
|
{
|
|
LEVELNODE *pOnRoof, *pOldOnRoof;
|
|
UINT32 fTileType;
|
|
|
|
pOnRoof = gpWorldLevelData[iMapIndex].pOnRoofHead;
|
|
while(pOnRoof && pOnRoof->usIndex != NO_TILE)
|
|
{
|
|
GetTileType(pOnRoof->usIndex, &fTileType);
|
|
pOldOnRoof = pOnRoof;
|
|
pOnRoof = pOnRoof->pNext;
|
|
if(fTileType >= fStartType && fTileType <= fEndType)
|
|
pOldOnRoof->uiFlags &= (~uiFlags);
|
|
}
|
|
}
|
|
|
|
void SetOnRoofIndexFlagsFromTypeRange(INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32 uiFlags)//dnl ch80 011213
|
|
{
|
|
LEVELNODE *pOnRoof, *pOldOnRoof;
|
|
UINT32 fTileType;
|
|
|
|
pOnRoof = gpWorldLevelData[iMapIndex].pOnRoofHead;
|
|
while(pOnRoof && pOnRoof->usIndex != NO_TILE)
|
|
{
|
|
GetTileType(pOnRoof->usIndex, &fTileType);
|
|
pOldOnRoof = pOnRoof;
|
|
pOnRoof = pOnRoof->pNext;
|
|
if(fTileType >= fStartType && fTileType <= fEndType)
|
|
pOldOnRoof->uiFlags |= uiFlags;
|
|
}
|
|
}
|
|
|
|
// Topmost layer
|
|
// #################################################################
|
|
|
|
LEVELNODE *AddTopmostToTail( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
LEVELNODE *pNextTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
// If we're at the head, set here
|
|
if ( pTopmost == NULL )
|
|
{
|
|
CHECKN( CreateLevelNode( &pNextTopmost ) != FALSE );
|
|
pNextTopmost->usIndex = usIndex;
|
|
|
|
gpWorldLevelData[ iMapIndex ].pTopmostHead = pNextTopmost;
|
|
|
|
}
|
|
else
|
|
{
|
|
while( pTopmost != NULL )
|
|
{
|
|
|
|
if ( pTopmost->pNext == NULL )
|
|
{
|
|
CHECKN( CreateLevelNode( &pNextTopmost ) != FALSE );
|
|
pTopmost->pNext = pNextTopmost;
|
|
pNextTopmost->pNext = NULL;
|
|
pNextTopmost->usIndex = usIndex;
|
|
|
|
break;
|
|
}
|
|
|
|
pTopmost = pTopmost->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_TOPMOST );
|
|
return( pNextTopmost );
|
|
|
|
}
|
|
|
|
BOOLEAN AddUIElem( INT32 iMapIndex, UINT16 usIndex, INT8 sRelativeX, INT8 sRelativeY, LEVELNODE **ppNewNode )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
|
|
pTopmost = AddTopmostToTail( iMapIndex, usIndex );
|
|
|
|
CHECKF( pTopmost != NULL );
|
|
|
|
// Set flags
|
|
pTopmost->uiFlags |= LEVELNODE_USERELPOS;
|
|
pTopmost->sRelativeX = sRelativeX;
|
|
pTopmost->sRelativeY = sRelativeY;
|
|
|
|
if ( ppNewNode != NULL )
|
|
{
|
|
*ppNewNode = pTopmost;
|
|
}
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_TOPMOST );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void RemoveUIElem( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
RemoveTopmost( iMapIndex, usIndex );
|
|
}
|
|
|
|
|
|
BOOLEAN AddTopmostToHead( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
LEVELNODE *pNextTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
// Allocate head
|
|
CHECKF( CreateLevelNode( &pNextTopmost ) != FALSE );
|
|
pNextTopmost->pNext = pTopmost;
|
|
pNextTopmost->usIndex = usIndex;
|
|
|
|
// Set head
|
|
gpWorldLevelData[ iMapIndex ].pTopmostHead = pNextTopmost;
|
|
|
|
ResetSpecificLayerOptimizing( TILES_DYNAMIC_TOPMOST );
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveTopmost( INT32 iMapIndex, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
LEVELNODE *pOldTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
// Look through all topmosts and remove index if found
|
|
|
|
while( pTopmost != NULL )
|
|
{
|
|
if ( pTopmost->usIndex == usIndex )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldTopmost == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pTopmostHead = pTopmost->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldTopmost->pNext = pTopmost->pNext;
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pTopmost );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldTopmost = pTopmost;
|
|
pTopmost = pTopmost->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveTopmostFromLevelNode( INT32 iMapIndex, LEVELNODE *pNode )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
LEVELNODE *pOldTopmost = NULL;
|
|
UINT16 usIndex;
|
|
|
|
usIndex = pNode->usIndex;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
// Look through all topmosts and remove index if found
|
|
|
|
while( pTopmost != NULL )
|
|
{
|
|
if ( pTopmost == pNode )
|
|
{
|
|
// OK, set links
|
|
// Check for head or tail
|
|
if ( pOldTopmost == NULL )
|
|
{
|
|
// It's the head
|
|
gpWorldLevelData[ iMapIndex ].pTopmostHead = pTopmost->pNext;
|
|
}
|
|
else
|
|
{
|
|
pOldTopmost->pNext = pTopmost->pNext;
|
|
}
|
|
|
|
// Delete memory assosiated with item
|
|
MemFree( pTopmost );
|
|
guiLevelNodes--;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
pOldTopmost = pTopmost;
|
|
pTopmost = pTopmost->pNext;
|
|
|
|
}
|
|
|
|
// Could not find it, return FALSE
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN RemoveAllTopmostsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
LEVELNODE *pOldTopmost = NULL;
|
|
UINT32 fTileType;
|
|
BOOLEAN fRetVal = FALSE;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
// Look through all topmosts and Search for type
|
|
|
|
while( pTopmost != NULL )
|
|
{
|
|
// Advance to next
|
|
pOldTopmost = pTopmost;
|
|
pTopmost = pTopmost->pNext;
|
|
|
|
if ( pOldTopmost->usIndex != NO_TILE && pOldTopmost->usIndex < giNumberOfTiles )
|
|
{
|
|
GetTileType( pOldTopmost->usIndex, &fTileType );
|
|
|
|
if ( fTileType >= fStartType && fTileType <= fEndType )
|
|
{
|
|
// Remove Item
|
|
RemoveTopmost( iMapIndex, pOldTopmost->usIndex );
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return fRetVal;
|
|
}
|
|
|
|
BOOLEAN TypeExistsInTopmostLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusTopmostIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
return( TypeExistsInLevel( pTopmost, fType, pusTopmostIndex ) );
|
|
}
|
|
|
|
|
|
void SetTopmostFlags( INT32 iMapIndex, UINT32 uiFlags, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
SetIndexLevelNodeFlags( pTopmost, uiFlags, usIndex );
|
|
}
|
|
|
|
void RemoveTopmostFlags( INT32 iMapIndex, UINT32 uiFlags, UINT16 usIndex )
|
|
{
|
|
LEVELNODE *pTopmost = NULL;
|
|
|
|
pTopmost = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
|
|
RemoveIndexLevelNodeFlags( pTopmost, uiFlags, usIndex );
|
|
}
|
|
|
|
|
|
BOOLEAN SetMapElementShadeLevel( INT32 uiMapIndex, UINT8 ubShadeLevel )
|
|
{
|
|
SetAllLandShadeLevels( uiMapIndex, ubShadeLevel );
|
|
SetAllObjectShadeLevels( uiMapIndex, ubShadeLevel );
|
|
SetAllStructShadeLevels( uiMapIndex, ubShadeLevel );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN IsHeigherLevel( INT32 sGridNo )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
pStructure = FindStructure( sGridNo, STRUCTURE_NORMAL_ROOF );
|
|
|
|
if ( pStructure != NULL )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsLowerLevel( INT32 sGridNo )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
pStructure = FindStructure( sGridNo, STRUCTURE_NORMAL_ROOF );
|
|
|
|
if ( pStructure == NULL )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsRoofVisible( INT32 sMapPos )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
if ( !gfBasement )
|
|
{
|
|
pStructure = FindStructure( sMapPos, STRUCTURE_ROOF );
|
|
|
|
if ( pStructure != NULL )
|
|
{
|
|
if ( !( gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//if ( InARoom( sMapPos, &ubRoom ) )
|
|
{
|
|
//if ( !( gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN IsRoofVisible2( INT32 sMapPos )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
if ( !gfBasement )
|
|
{
|
|
pStructure = FindStructure( sMapPos, STRUCTURE_ROOF );
|
|
|
|
if ( pStructure != NULL )
|
|
{
|
|
if ( !( gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//if ( InARoom( sMapPos, &ubRoom ) )
|
|
{
|
|
if ( !( gpWorldLevelData[ sMapPos ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
UINT8 WhoIsThere2( INT32 sGridNo, INT8 bLevel )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
if ( !GridNoOnVisibleWorldTile( sGridNo ) )
|
|
{
|
|
return( NOBODY );
|
|
}
|
|
|
|
|
|
if ( gpWorldLevelData[ sGridNo ].pStructureHead != NULL )
|
|
{
|
|
|
|
pStructure = gpWorldLevelData[ sGridNo ].pStructureHead;
|
|
|
|
while ( pStructure )
|
|
{
|
|
// person must either have their pSoldier->sGridNo here or be non-passable
|
|
if ( (pStructure->fFlags & STRUCTURE_PERSON) && ( !(pStructure->fFlags & STRUCTURE_PASSABLE) || MercPtrs[ pStructure->usStructureID ]->sGridNo == sGridNo) )
|
|
{
|
|
if ( ( bLevel == 0 && pStructure->sCubeOffset == 0 ) || (bLevel > 0 && pStructure->sCubeOffset > 0) )
|
|
{
|
|
// found a person, on the right level!
|
|
// structure ID and merc ID are identical for merc structures
|
|
return( (UINT8) pStructure->usStructureID );
|
|
}
|
|
}
|
|
pStructure = pStructure->pNext;
|
|
}
|
|
|
|
}
|
|
|
|
return( (UINT8)NOBODY );
|
|
}
|
|
|
|
UINT8 GetTerrainType( INT32 sGridNo )
|
|
{
|
|
return( gpWorldLevelData[sGridNo].ubTerrainID );
|
|
/*
|
|
LEVELNODE *pNode;
|
|
|
|
|
|
// Check if we have anything in object layer which has a terrain modifier
|
|
pNode = gpWorldLevelData[ sGridNo ].pObjectHead;
|
|
|
|
if ( pNode != NULL )
|
|
{
|
|
if ( gTileDatabase[ pNode->usIndex ].ubTerrainID != NO_TERRAIN )
|
|
{
|
|
return( gTileDatabase[ pNode->usIndex ].ubTerrainID );
|
|
}
|
|
}
|
|
|
|
// Now try terrain!
|
|
pNode = gpWorldLevelData[ sGridNo ].pLandHead;
|
|
|
|
return( gTileDatabase[ pNode->usIndex ].ubTerrainID );
|
|
*/
|
|
}
|
|
|
|
BOOLEAN Water( INT32 sGridNo, BOOLEAN bLevel )
|
|
{
|
|
MAP_ELEMENT * pMapElement;
|
|
|
|
if( TileIsOutOfBounds( sGridNo ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// sevenfm: check bridge
|
|
if( bLevel )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pMapElement = &(gpWorldLevelData[sGridNo]);
|
|
if ( TERRAIN_IS_WATER( pMapElement->ubTerrainID) )
|
|
{
|
|
// check for a bridge! otherwise...
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
BOOLEAN DeepWater( INT32 sGridNo, BOOLEAN bLevel )
|
|
{
|
|
MAP_ELEMENT * pMapElement;
|
|
|
|
if( TileIsOutOfBounds( sGridNo ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// sevenfm: check bridge
|
|
if( bLevel )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pMapElement = &(gpWorldLevelData[sGridNo]);
|
|
|
|
if (TERRAIN_IS_DEEP_WATER( pMapElement->ubTerrainID) )
|
|
{
|
|
// check for a bridge! otherwise...
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
BOOLEAN WaterTooDeepForAttacks( INT32 sGridNo, BOOLEAN bLevel )
|
|
{
|
|
return( DeepWater( sGridNo, bLevel ) );
|
|
}
|
|
|
|
void SetStructAframeFlags( INT32 iMapIndex, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 uiTileFlags;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and Search for type
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileFlags( pStruct->usIndex, &uiTileFlags );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( uiTileFlags & AFRAME_TILE )
|
|
{
|
|
pOldStruct->uiFlags |= uiFlags;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void RemoveStructAframeFlags( INT32 iMapIndex, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
LEVELNODE *pOldStruct = NULL;
|
|
UINT32 uiTileFlags;
|
|
|
|
pStruct = gpWorldLevelData[ iMapIndex ].pRoofHead;
|
|
|
|
// Look through all Roofs and Search for type
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
if ( pStruct->usIndex != NO_TILE )
|
|
{
|
|
|
|
GetTileFlags( pStruct->usIndex, &uiTileFlags );
|
|
|
|
// Advance to next
|
|
pOldStruct = pStruct;
|
|
pStruct = pStruct->pNext;
|
|
|
|
if ( uiTileFlags & AFRAME_TILE )
|
|
{
|
|
pOldStruct->uiFlags &= ( ~uiFlags );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LEVELNODE * FindLevelNodeBasedOnStructure( INT32 sGridNo, STRUCTURE * pStructure )
|
|
{
|
|
LEVELNODE * pLevelNode;
|
|
|
|
//ATE: First look on the struct layer.....
|
|
pLevelNode = gpWorldLevelData[sGridNo].pStructHead;
|
|
while( pLevelNode != NULL )
|
|
{
|
|
if (pLevelNode->pStructureData == pStructure)
|
|
{
|
|
return( pLevelNode );
|
|
}
|
|
pLevelNode = pLevelNode->pNext;
|
|
}
|
|
|
|
// Next the roof layer....
|
|
pLevelNode = gpWorldLevelData[sGridNo].pRoofHead;
|
|
while( pLevelNode != NULL )
|
|
{
|
|
if (pLevelNode->pStructureData == pStructure)
|
|
{
|
|
return( pLevelNode );
|
|
}
|
|
pLevelNode = pLevelNode->pNext;
|
|
}
|
|
|
|
// Then the object layer....
|
|
pLevelNode = gpWorldLevelData[sGridNo].pObjectHead;
|
|
while( pLevelNode != NULL )
|
|
{
|
|
if (pLevelNode->pStructureData == pStructure)
|
|
{
|
|
return( pLevelNode );
|
|
}
|
|
pLevelNode = pLevelNode->pNext;
|
|
}
|
|
|
|
// Finally the onroof layer....
|
|
pLevelNode = gpWorldLevelData[sGridNo].pOnRoofHead;
|
|
while( pLevelNode != NULL )
|
|
{
|
|
if (pLevelNode->pStructureData == pStructure)
|
|
{
|
|
return( pLevelNode );
|
|
}
|
|
pLevelNode = pLevelNode->pNext;
|
|
}
|
|
|
|
// WANNE: Removed the assertion, because it can happen on custom maps.
|
|
// It is not a big deal, if the node cannot be found.
|
|
// Assert here if it cannot be found....
|
|
//AssertMsg( 0, "FindLevelNodeBasedOnStruct failed.");
|
|
|
|
return( NULL );
|
|
}
|
|
|
|
// WANNE: Old JA2 vanilla version to find the shadow tile
|
|
/*
|
|
LEVELNODE * FindShadow( INT32 sGridNo, UINT16 usStructIndex )
|
|
{
|
|
LEVELNODE * pLevelNode;
|
|
UINT16 usShadowIndex;
|
|
|
|
if (usStructIndex < FIRSTOSTRUCT1 || usStructIndex >= FIRSTSHADOW1)
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
usShadowIndex = usStructIndex - FIRSTOSTRUCT1 + FIRSTSHADOW1;
|
|
|
|
pLevelNode = gpWorldLevelData[sGridNo].pShadowHead;
|
|
while( pLevelNode != NULL )
|
|
{
|
|
if (pLevelNode->usIndex == usShadowIndex)
|
|
{
|
|
break;
|
|
}
|
|
pLevelNode = pLevelNode->pNext;
|
|
}
|
|
return( pLevelNode );
|
|
}
|
|
*/
|
|
|
|
// WANNE: Improved v1.13 version to find the shadow tile. (by Realist)
|
|
// This should fix the bug, finding and swapping shadows when swapping structures
|
|
// e.g: When curring a fence tile, the shadow tile was not swapped. Now it should be fixed.
|
|
LEVELNODE* FindShadow(INT32 sGridNo, UINT16 usStructIndex)
|
|
{
|
|
TILE_ELEMENT const * const te = &gTileDatabase[usStructIndex];
|
|
if (te->uiFlags & HAS_SHADOW_BUDDY && te->sBuddyNum != -1)
|
|
{
|
|
LEVELNODE* pLevelNode;
|
|
for (pLevelNode = gpWorldLevelData[sGridNo].pShadowHead; pLevelNode != NULL; pLevelNode = pLevelNode->pNext)
|
|
{
|
|
if (pLevelNode->usIndex == te->sBuddyNum)
|
|
{
|
|
return pLevelNode;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void WorldHideTrees()
|
|
{
|
|
LEVELNODE *pNode;
|
|
BOOLEAN fRerender = FALSE;
|
|
UINT32 fTileFlags;
|
|
INT32 cnt;
|
|
|
|
for (cnt = 0; cnt < WORLD_MAX; cnt++)
|
|
{
|
|
pNode = gpWorldLevelData[cnt].pStructHead;
|
|
while (pNode != NULL)
|
|
{
|
|
GetTileFlags(pNode->usIndex, &fTileFlags);
|
|
|
|
if (fTileFlags & FULL3D_TILE)
|
|
{
|
|
if (!(pNode->uiFlags & LEVELNODE_REVEALTREES))
|
|
{
|
|
pNode->uiFlags |= (LEVELNODE_REVEALTREES);
|
|
}
|
|
|
|
fRerender = TRUE;
|
|
}
|
|
pNode = pNode->pNext;
|
|
}
|
|
}
|
|
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
}
|
|
|
|
|
|
void WorldShowTrees()
|
|
{
|
|
LEVELNODE *pNode;
|
|
BOOLEAN fRerender = FALSE;
|
|
UINT32 fTileFlags;
|
|
INT32 cnt;
|
|
|
|
for (cnt = 0; cnt < WORLD_MAX; cnt++)
|
|
{
|
|
pNode = gpWorldLevelData[cnt].pStructHead;
|
|
while (pNode != NULL)
|
|
{
|
|
GetTileFlags(pNode->usIndex, &fTileFlags);
|
|
|
|
if (fTileFlags & FULL3D_TILE)
|
|
{
|
|
|
|
if ((pNode->uiFlags & LEVELNODE_REVEALTREES))
|
|
{
|
|
pNode->uiFlags &= (~(LEVELNODE_REVEALTREES));
|
|
}
|
|
|
|
fRerender = TRUE;
|
|
}
|
|
pNode = pNode->pNext;
|
|
}
|
|
}
|
|
|
|
// sevenfm: also update smart tree tops
|
|
if (gGameSettings.fOptions[TOPTION_SMART_TREE_TOPS])
|
|
UpdateTreeVisibility();
|
|
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
}
|
|
|
|
void UpdateTreeVisibility()
|
|
{
|
|
if (!gGameSettings.fOptions[TOPTION_SMART_TREE_TOPS] || !gGameSettings.fOptions[TOPTION_TOGGLE_TREE_TOPS])
|
|
return;
|
|
|
|
LEVELNODE *pNode;
|
|
BOOLEAN fRerender = FALSE;
|
|
BOOLEAN fHidden = FALSE;
|
|
UINT32 fTileFlags;
|
|
INT32 cnt;
|
|
|
|
SOLDIERTYPE *pOpponent;
|
|
STRUCTURE *pStructureData;
|
|
INT32 sSpot;
|
|
BOOLEAN fHideTree;
|
|
INT32 usMouseSpot;
|
|
|
|
//Get the gridno the cursor is at
|
|
GetMouseMapPos(&usMouseSpot);
|
|
|
|
// first show all trees
|
|
for (cnt = 0; cnt < WORLD_MAX; cnt++)
|
|
{
|
|
pNode = gpWorldLevelData[cnt].pStructHead;
|
|
while (pNode != NULL)
|
|
{
|
|
GetTileFlags(pNode->usIndex, &fTileFlags);
|
|
|
|
if (fTileFlags & FULL3D_TILE)
|
|
{
|
|
if ((pNode->uiFlags & LEVELNODE_REVEALTREES))
|
|
{
|
|
pNode->uiFlags &= ~(LEVELNODE_REVEALTREES);
|
|
fRerender = TRUE;
|
|
}
|
|
}
|
|
pNode = pNode->pNext;
|
|
}
|
|
}
|
|
|
|
// now show all trees except trees near visible soldiers
|
|
for (cnt = 0; cnt < WORLD_MAX; cnt++)
|
|
{
|
|
pNode = gpWorldLevelData[cnt].pStructHead;
|
|
|
|
while (pNode != NULL)
|
|
{
|
|
pStructureData = pNode->pStructureData;
|
|
if (pStructureData)
|
|
sSpot = pNode->pStructureData->sGridNo;
|
|
//sSpot = pNode->pStructureData->sBaseGridNo;
|
|
else
|
|
sSpot = NOWHERE;
|
|
|
|
fHideTree = FALSE;
|
|
|
|
// check trees near cursor position
|
|
if (!TileIsOutOfBounds(usMouseSpot) &&
|
|
(PythSpacesAway(sSpot, usMouseSpot) <= 2 && AIDirection(sSpot, usMouseSpot) == 0 ||
|
|
PythSpacesAway(sSpot, usMouseSpot) <= 5 && AIDirection(sSpot, usMouseSpot) == 7 ||
|
|
PythSpacesAway(sSpot, usMouseSpot) <= 2 && AIDirection(sSpot, usMouseSpot) == 6))
|
|
{
|
|
fHideTree = TRUE;
|
|
}
|
|
|
|
// find visible soldier near spot
|
|
if (!TileIsOutOfBounds(sSpot) && !fHideTree)
|
|
{
|
|
for (UINT8 uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
|
|
{
|
|
pOpponent = MercSlots[uiLoop];
|
|
|
|
if (pOpponent &&
|
|
pOpponent->bVisible != -1 &&
|
|
!TileIsOutOfBounds(pOpponent->sGridNo) &&
|
|
(PythSpacesAway(sSpot, pOpponent->sGridNo) <= 2 && AIDirection(sSpot, pOpponent->sGridNo) == 0 ||
|
|
PythSpacesAway(sSpot, pOpponent->sGridNo) <= 5 && AIDirection(sSpot, pOpponent->sGridNo) == 7 ||
|
|
PythSpacesAway(sSpot, pOpponent->sGridNo) <= 2 && AIDirection(sSpot, pOpponent->sGridNo) == 6))
|
|
{
|
|
fHideTree = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fHideTree)
|
|
{
|
|
GetTileFlags(pNode->usIndex, &fTileFlags);
|
|
|
|
if (fTileFlags & FULL3D_TILE)
|
|
{
|
|
if (!(pNode->uiFlags & LEVELNODE_REVEALTREES))
|
|
{
|
|
pNode->uiFlags |= (LEVELNODE_REVEALTREES);
|
|
fRerender = TRUE;
|
|
fHidden = TRUE;
|
|
}
|
|
}
|
|
}
|
|
pNode = pNode->pNext;
|
|
}
|
|
}
|
|
|
|
if (fRerender)
|
|
{
|
|
SetRenderFlags(RENDER_FLAG_FULL);
|
|
if (fHidden)
|
|
{
|
|
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
|
|
//gTacticalStatus.uiFlags &= (~NOHIDE_REDUNDENCY);
|
|
InvalidateWorldRedundency();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SetWorldFlagsFromNewNode( INT32 sGridNo, UINT16 usIndex )
|
|
{
|
|
|
|
}
|
|
|
|
void RemoveWorldFlagsFromNewNode( INT32 sGridNo, UINT16 usIndex )
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void SetWallLevelnodeFlags( INT32 sGridNo, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ sGridNo ].pStructHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
|
|
if ( pStruct->pStructureData != NULL )
|
|
{
|
|
// See if we are a wall!
|
|
if ( pStruct->pStructureData->fFlags & STRUCTURE_WALLSTUFF )
|
|
{
|
|
pStruct->uiFlags |= uiFlags;
|
|
}
|
|
}
|
|
// Advance to next
|
|
pStruct = pStruct->pNext;
|
|
|
|
}
|
|
}
|
|
|
|
void RemoveWallLevelnodeFlags( INT32 sGridNo, UINT32 uiFlags )
|
|
{
|
|
LEVELNODE *pStruct = NULL;
|
|
|
|
pStruct = gpWorldLevelData[ sGridNo ].pStructHead;
|
|
|
|
// Look through all objects and Search for type
|
|
|
|
while( pStruct != NULL )
|
|
{
|
|
if ( pStruct->pStructureData != NULL )
|
|
{
|
|
// See if we are a wall!
|
|
if ( pStruct->pStructureData->fFlags & STRUCTURE_WALLSTUFF )
|
|
{
|
|
pStruct->uiFlags &= (~uiFlags);
|
|
}
|
|
}
|
|
// Advance to next
|
|
pStruct = pStruct->pNext;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SetTreeTopStateForMap()
|
|
{
|
|
if ( !gGameSettings.fOptions[ TOPTION_TOGGLE_TREE_TOPS ] )
|
|
{
|
|
WorldHideTrees( );
|
|
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
|
|
}
|
|
else
|
|
{
|
|
WorldShowTrees( );
|
|
gTacticalStatus.uiFlags &= (~NOHIDE_REDUNDENCY);
|
|
}
|
|
|
|
// FOR THE NEXT RENDER LOOP, RE-EVALUATE REDUNDENT TILES
|
|
InvalidateWorldRedundency( );
|
|
}
|
|
|
|
|
|
|
|
//--------------------legion 2 Jazz---------------------------------------------------------------
|
|
BOOLEAN IsOknoLevel( INT32 sGridNo )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
pStructure = FindStructure( sGridNo, STRUCTURE_WALLNWINDOW );
|
|
|
|
if ( pStructure != NULL && !( pStructure->fFlags & STRUCTURE_OPEN ))
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
BOOLEAN IsLegionLevel( INT32 sGridNo )
|
|
{
|
|
STRUCTURE * pStructure;
|
|
|
|
pStructure = FindStructure( sGridNo, STRUCTURE_FENCE );
|
|
|
|
if ( pStructure != NULL )//&& !( pStructure->fFlags & STRUCTURE_OPEN ))
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
//-------------------------------------------------------------------
|
|
|
|
// sevenfm: check adjacent tiles
|
|
BOOLEAN FindNotDeepWaterNearby(INT32 sSpot, BOOLEAN bLevel)
|
|
{
|
|
UINT8 ubMovementCost;
|
|
INT32 sTempGridNo;
|
|
UINT8 ubDirection;
|
|
|
|
// check adjacent reachable tiles
|
|
for (ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ubDirection++)
|
|
{
|
|
sTempGridNo = NewGridNo(sSpot, DirectionInc(ubDirection));
|
|
ubMovementCost = gubWorldMovementCosts[sTempGridNo][ubDirection][bLevel];
|
|
|
|
if (ubMovementCost < TRAVELCOST_BLOCKED &&
|
|
!DeepWater(sTempGridNo, bLevel))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN FindNotWaterNearby(INT32 sSpot, BOOLEAN bLevel)
|
|
{
|
|
UINT8 ubMovementCost;
|
|
INT32 sTempGridNo;
|
|
UINT8 ubDirection;
|
|
|
|
// check adjacent reachable tiles
|
|
for (ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ubDirection++)
|
|
{
|
|
sTempGridNo = NewGridNo(sSpot, DirectionInc(ubDirection));
|
|
ubMovementCost = gubWorldMovementCosts[sTempGridNo][ubDirection][bLevel];
|
|
|
|
if (ubMovementCost < TRAVELCOST_BLOCKED &&
|
|
!Water(sTempGridNo, bLevel))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|