mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- Magically appeared reinforcements for enemy and militia just turn after they are called from now could be delayed and randomized. Details: - Practically all enemy reinforcement which can populate available slots was always appeared next turn after they are called so now we have game settings under "Strategic Gameplay Settings" for fine tunning enemy and militia reinforce entry: MIN_DELAY_ENEMY_REINFORCEMENTS enemy reinforcement will arrive minimum this number of turns after they are called, if 0 then is disabled. RND_DELAY_ENEMY_REINFORCEMENTS additional random delay added to minimum when reinforcements will arrive after they are called. MIN_ENTER_ENEMY_REINFORCEMENTS minimum enemy units which will enter after above delay is over. RND_ENTER_ENEMY_REINFORCEMENTS additional random enemy units to appear after passing delay. MIN_DELAY_MILITIA_REINFORCEMENTS enemy reinforcement will arrive minimum this number of turns after they are called, if 0 then is disabled. RND_DELAY_MILITIA_REINFORCEMENTS additional random delay added to minimum when reinforcements will arrive after they are called. MIN_ENTER_MILITIA_REINFORCEMENTS minimum enemy units which will enter after above delay is over. RND_ENTER_MILITIA_REINFORCEMENTS additional random enemy units to appear after passing delay. - After first delay ends any other reinforcement appeared more frequently or if already arrive (but no free slot), they will pop up soon after slot is free. - Add option NO_REMOVE_RANDOM_SECTOR_ITEMS under "Strategic Gameplay Settings" to prevent permanent random removal of your sector items. - Add missing function DisplaySectorItemsInfo. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6386 3b4a5df2-a311-0410-b5c6-a8a6f20db521
3824 lines
81 KiB
C++
3824 lines
81 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"
|
|
#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;
|
|
|
|
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 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;
|
|
}
|
|
|
|
//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 )
|
|
{
|
|
if ( fHide )
|
|
{
|
|
SetRoofIndexFlagsFromTypeRange( iMapIndex, fType, fType, LEVELNODE_HIDDEN );
|
|
}
|
|
else
|
|
{
|
|
// ONLY UNHIDE IF NOT REAVEALED ALREADY
|
|
if ( !(gpWorldLevelData[ iMapIndex ].uiFlags & MAPELEMENT_REVEALED ) )
|
|
{
|
|
RemoveRoofIndexFlagsFromTypeRange( 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;
|
|
}
|
|
|
|
// 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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
// 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 )
|
|
{
|
|
MAP_ELEMENT * pMapElement;
|
|
|
|
if( TileIsOutOfBounds( sGridNo ) )
|
|
{
|
|
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 )
|
|
{
|
|
MAP_ELEMENT * pMapElement;
|
|
|
|
if( TileIsOutOfBounds( sGridNo ) )
|
|
{
|
|
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 )
|
|
{
|
|
return( DeepWater( sGridNo ) );
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
SetRenderFlags(RENDER_FLAG_FULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
//-------------------------------------------------------------------
|