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@8953 3b4a5df2-a311-0410-b5c6-a8a6f20db521
570 lines
13 KiB
C++
570 lines
13 KiB
C++
#include "builddefines.h"
|
|
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "TileEngine All.h"
|
|
#else
|
|
#include "debug.h"
|
|
#include "animation control.h"
|
|
#include "lighteffects.h"
|
|
#include "isometric utils.h"
|
|
#include "lighting.h"
|
|
#include "Game Clock.h"
|
|
#include "opplist.h"
|
|
#include "Tactical Save.h"
|
|
#endif
|
|
|
|
#include "SaveLoadGame.h"
|
|
#include "GameVersion.h" // added by Flugente
|
|
|
|
|
|
//forward declarations of common classes to eliminate includes
|
|
class OBJECTTYPE;
|
|
class SOLDIERTYPE;
|
|
|
|
|
|
#define NUM_LIGHT_EFFECT_SLOTS 500 // 25 // Flugente: raised to 500 - lets see what happens
|
|
|
|
|
|
// GLOBAL FOR LIGHT LISTING
|
|
LIGHTEFFECT gLightEffectData[ NUM_LIGHT_EFFECT_SLOTS ];
|
|
UINT32 guiNumLightEffects = 0;
|
|
|
|
|
|
INT32 GetFreeLightEffect( void );
|
|
void RecountLightEffects( void );
|
|
|
|
|
|
INT32 GetFreeLightEffect( void )
|
|
{
|
|
UINT32 uiCount;
|
|
|
|
for(uiCount=0; uiCount < guiNumLightEffects; uiCount++)
|
|
{
|
|
if(( gLightEffectData[uiCount].fAllocated==FALSE ) )
|
|
return( (INT32)uiCount );
|
|
}
|
|
|
|
if( guiNumLightEffects < NUM_LIGHT_EFFECT_SLOTS )
|
|
return( (INT32) guiNumLightEffects++ );
|
|
|
|
return( -1 );
|
|
}
|
|
|
|
void RecountLightEffects( void )
|
|
{
|
|
INT32 uiCount;
|
|
|
|
for(uiCount=guiNumLightEffects-1; (uiCount >=0) ; uiCount--)
|
|
{
|
|
if( ( gLightEffectData[uiCount].fAllocated ) )
|
|
{
|
|
guiNumLightEffects=(UINT32)(uiCount+1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void UpdateLightingSprite( LIGHTEFFECT *pLight )
|
|
{
|
|
CHAR8 LightName[20];
|
|
// Build light....
|
|
|
|
sprintf( LightName, "Light%d", pLight->bRadius );
|
|
|
|
// Delete old one if one exists...
|
|
if( pLight->iLight!=(-1) )
|
|
{
|
|
LightSpriteDestroy( pLight->iLight );
|
|
pLight->iLight = -1;
|
|
}
|
|
|
|
// Effect light.....
|
|
if( ( pLight->iLight = LightSpriteCreate( LightName, 0 ) )==(-1))
|
|
{
|
|
// Could not light!
|
|
return;
|
|
}
|
|
|
|
LightSpritePower( pLight->iLight, TRUE );
|
|
// LightSpriteFake( pLight->iLight );
|
|
LightSpritePosition( pLight->iLight, (INT16)( CenterX( pLight->sGridNo ) / CELL_X_SIZE ), (INT16)( CenterY( pLight->sGridNo ) / CELL_Y_SIZE ) );
|
|
}
|
|
|
|
// Flugente: create a pure light, worry about updating sight in other functions
|
|
INT32 NewLightEffectInternal( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius )
|
|
{
|
|
LIGHTEFFECT *pLight;
|
|
INT32 iLightIndex;
|
|
|
|
if( ( iLightIndex = GetFreeLightEffect() )==(-1) )
|
|
return(-1);
|
|
|
|
memset( &gLightEffectData[ iLightIndex ], 0, sizeof( LIGHTEFFECT ) );
|
|
|
|
pLight = &gLightEffectData[ iLightIndex ];
|
|
|
|
// Set some values...
|
|
pLight->sGridNo = sGridNo;
|
|
pLight->iLight = -1;
|
|
pLight->uiTimeOfLastUpdate = GetWorldTotalSeconds( );
|
|
|
|
pLight->ubDuration = ubDuration;
|
|
pLight->bRadius = ubStartRadius;
|
|
pLight->bAge = 0;
|
|
pLight->fAllocated = TRUE;
|
|
|
|
UpdateLightingSprite( pLight );
|
|
|
|
return iLightIndex;
|
|
}
|
|
|
|
INT32 NewLightEffect( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius )
|
|
{
|
|
INT32 iLightIndex = NewLightEffectInternal( sGridNo, ubDuration, ubStartRadius );
|
|
|
|
// Handle sight here....
|
|
AllTeamsLookForAll( FALSE );
|
|
|
|
//Play the breaklight sound
|
|
// PlayJA2Sample( BREAK_LIGHT_IGNITING, RATE_11025, SoundVolume( LOWVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
|
|
// MAdd: for some reason this crashes the game!
|
|
|
|
if ( iLightIndex > -1 )
|
|
{
|
|
LIGHTEFFECT *pLight = &gLightEffectData[ iLightIndex ];
|
|
return( pLight->iLight );
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
void RemoveLightEffectFromTile( INT32 sGridNo )
|
|
{
|
|
LIGHTEFFECT *pLight;
|
|
UINT32 cnt;
|
|
|
|
// Set to unallocated....
|
|
for ( cnt = 0; cnt < guiNumLightEffects; cnt++ )
|
|
{
|
|
pLight = &gLightEffectData[ cnt ];
|
|
|
|
if ( pLight->fAllocated )
|
|
{
|
|
if ( pLight->sGridNo == sGridNo )
|
|
{
|
|
pLight->fAllocated = FALSE;
|
|
|
|
// Remove light....
|
|
if( pLight->iLight != (-1) )
|
|
{
|
|
LightSpriteDestroy( pLight->iLight );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BOOLEAN IsLightEffectAtTile( INT32 sGridNo )
|
|
{
|
|
LIGHTEFFECT *pLight;
|
|
UINT32 cnt;
|
|
|
|
// Set to unallocated....
|
|
for ( cnt = 0; cnt < guiNumLightEffects; cnt++ )
|
|
{
|
|
pLight = &gLightEffectData[ cnt ];
|
|
|
|
if ( pLight->fAllocated )
|
|
{
|
|
if ( pLight->sGridNo == sGridNo )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void DecayLightEffects( UINT32 uiTime )
|
|
{
|
|
LIGHTEFFECT *pLight;
|
|
UINT32 cnt, cnt2;
|
|
BOOLEAN fUpdate = FALSE;
|
|
BOOLEAN fDelete = FALSE;
|
|
BOOLEAN fAnyUpdate = FALSE;
|
|
UINT16 usNumUpdates = 1;
|
|
|
|
// age all active light effects, deactivate those that are just dispersing
|
|
for ( cnt = 0; cnt < guiNumLightEffects; ++cnt )
|
|
{
|
|
pLight = &gLightEffectData[ cnt ];
|
|
|
|
fDelete = FALSE;
|
|
|
|
if ( pLight->fAllocated )
|
|
{
|
|
usNumUpdates = 1;
|
|
|
|
// Do things differently for combat /vs realtime
|
|
// always try to update during combat
|
|
if ( gTacticalStatus.uiFlags & INCOMBAT )
|
|
{
|
|
fUpdate = TRUE;
|
|
}
|
|
// ATE: Do this every so often, to achieve the effect we want...
|
|
else if ( (uiTime - pLight->uiTimeOfLastUpdate) >= 10 )
|
|
{
|
|
fUpdate = TRUE;
|
|
usNumUpdates = (UINT16)((uiTime - pLight->uiTimeOfLastUpdate) / 10);
|
|
}
|
|
|
|
if ( fUpdate )
|
|
{
|
|
pLight->uiTimeOfLastUpdate = uiTime;
|
|
|
|
for ( cnt2 = 0; cnt2 < usNumUpdates; ++cnt2 )
|
|
{
|
|
++pLight->bAge;
|
|
|
|
if ( pLight->ubDuration <= 0 )
|
|
fDelete = TRUE;
|
|
|
|
// if this light remains effective (duration not reached)
|
|
if ( pLight->bAge < pLight->ubDuration)
|
|
{
|
|
// calculate the new cloud radius
|
|
/*if ( ( pLight->bAge % 2 ) )
|
|
{
|
|
--pLight->bRadius;
|
|
}*/
|
|
if (pLight->ubDuration - pLight->bAge < pLight->bRadius)
|
|
{
|
|
pLight->bRadius--;
|
|
}
|
|
|
|
if ( pLight->bRadius == 0 )
|
|
{
|
|
// Delete...
|
|
fDelete = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
UpdateLightingSprite( pLight );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fDelete = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( fDelete )
|
|
{
|
|
pLight->fAllocated = FALSE;
|
|
|
|
if( pLight->iLight != (-1) )
|
|
{
|
|
LightSpriteDestroy( pLight->iLight );
|
|
}
|
|
}
|
|
|
|
// we have to update sight later on if any light was updated
|
|
fAnyUpdate = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fAnyUpdate )
|
|
{
|
|
// Handle sight here....
|
|
AllTeamsLookForAll( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN SaveLightEffectsToSaveGameFile( HWFILE hFile )
|
|
{
|
|
/*
|
|
UINT32 uiNumBytesWritten;
|
|
UINT32 uiNumberOfLights=0;
|
|
UINT32 uiCnt;
|
|
|
|
//loop through and count the number of active slots
|
|
for( uiCnt=0; uiCnt<guiNumLightEffects; uiCnt++)
|
|
{
|
|
if( gLightEffectData[ uiCnt ].fAllocated )
|
|
{
|
|
uiNumberOfLights++;
|
|
}
|
|
}
|
|
|
|
//Save the Number of Light Effects
|
|
FileWrite( hFile, &uiNumberOfLights, sizeof( UINT32 ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( UINT32 ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//if there are lights to save
|
|
if( uiNumberOfLights != 0 )
|
|
{
|
|
//loop through and save each active slot
|
|
for( uiCnt=0; uiCnt < guiNumLightEffects; uiCnt++)
|
|
{
|
|
if( gLightEffectData[ uiCnt ].fAllocated )
|
|
{
|
|
//Save the Light effect Data
|
|
FileWrite( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( LIGHTEFFECT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN LoadLightEffectsFromLoadGameFile( HWFILE hFile )
|
|
{
|
|
UINT32 uiNumBytesRead;
|
|
UINT32 uiCount;
|
|
|
|
//no longer need to load Light effects. They are now in temp files
|
|
if( guiCurrentSaveGameVersion < 76 )
|
|
{
|
|
memset( gLightEffectData, 0, sizeof( LIGHTEFFECT ) * NUM_LIGHT_EFFECT_SLOTS );
|
|
|
|
//Load the Number of Light Effects
|
|
FileRead( hFile, &guiNumLightEffects, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
//if there are lights saved.
|
|
if( guiNumLightEffects != 0 )
|
|
{
|
|
//loop through and apply the light effects to the map
|
|
for(uiCount=0; uiCount < guiNumLightEffects; uiCount++)
|
|
{
|
|
//Load the Light effect Data
|
|
FileRead( hFile, &gLightEffectData[ uiCount ], sizeof( LIGHTEFFECT ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( LIGHTEFFECT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//loop through and apply the light effects to the map
|
|
for(uiCount=0; uiCount < guiNumLightEffects; uiCount++)
|
|
{
|
|
if( gLightEffectData[uiCount].fAllocated )
|
|
UpdateLightingSprite( &( gLightEffectData[uiCount] ) );
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN SaveLightEffectsToMapTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
UINT32 uiNumLightEffects=0;
|
|
HWFILE hFile;
|
|
UINT32 uiNumBytesWritten=0;
|
|
CHAR8 zMapName[ 128 ];
|
|
UINT32 uiCnt;
|
|
|
|
//get the name of the map
|
|
GetMapTempFileName( SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//delete file the file.
|
|
FileDelete( zMapName );
|
|
|
|
//loop through and count the number of Light effects
|
|
for( uiCnt=0; uiCnt<guiNumLightEffects; uiCnt++)
|
|
{
|
|
if( gLightEffectData[ uiCnt ].fAllocated )
|
|
uiNumLightEffects++;
|
|
}
|
|
|
|
//if there are no Light effects
|
|
if( uiNumLightEffects == 0 )
|
|
{
|
|
//set the fact that there are no Light effects for this sector
|
|
ReSetSectorFlag( sMapX, sMapY, bMapZ, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
//Open the file for writing
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening map modification file
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//Save the Number of Light Effects
|
|
FileWrite( hFile, &uiNumLightEffects, sizeof( UINT32 ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( UINT32 ) )
|
|
{
|
|
//Close the file
|
|
FileClose( hFile );
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
//loop through and save the number of Light effects
|
|
for( uiCnt=0; uiCnt < guiNumLightEffects; uiCnt++)
|
|
{
|
|
//if the Light is active
|
|
if( gLightEffectData[ uiCnt ].fAllocated )
|
|
{
|
|
//Save the Light effect Data
|
|
FileWrite( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( LIGHTEFFECT ) )
|
|
{
|
|
//Close the file
|
|
FileClose( hFile );
|
|
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
//Close the file
|
|
FileClose( hFile );
|
|
|
|
SetSectorFlag( sMapX, sMapY, bMapZ, SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN LoadLightEffectsFromMapTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
|
{
|
|
UINT32 uiNumBytesRead;
|
|
UINT32 uiCount;
|
|
UINT32 uiCnt=0;
|
|
HWFILE hFile;
|
|
CHAR8 zMapName[ 128 ];
|
|
|
|
GetMapTempFileName( SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ );
|
|
|
|
//Open the file for reading, Create it if it doesnt exist
|
|
hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
|
|
if( hFile == 0 )
|
|
{
|
|
//Error opening file
|
|
return( FALSE );
|
|
}
|
|
|
|
//Clear out the old list
|
|
ResetLightEffects();
|
|
|
|
|
|
//Load the Number of Light Effects
|
|
FileRead( hFile, &guiNumLightEffects, sizeof( UINT32 ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( UINT32 ) )
|
|
{
|
|
FileClose( hFile );
|
|
return( FALSE );
|
|
}
|
|
|
|
//loop through and load the list
|
|
for( uiCnt=0; uiCnt<guiNumLightEffects;uiCnt++)
|
|
{
|
|
if(guiCurrentSaveGameVersion >= DYNAMIC_FLASHLIGHTS)
|
|
{
|
|
//Load the Light effect Data
|
|
FileRead( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( LIGHTEFFECT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UINT16 bla = sizeof( LIGHTEFFECT );
|
|
|
|
//Load the Light effect Data
|
|
FileRead( hFile, &gLightEffectData[ uiCnt ], LIGHTEFFECT_OLDSIZE, &uiNumBytesRead );
|
|
if( uiNumBytesRead != LIGHTEFFECT_OLDSIZE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//loop through and apply the light effects to the map
|
|
for(uiCount=0; uiCount < guiNumLightEffects; uiCount++)
|
|
{
|
|
if( gLightEffectData[uiCount].fAllocated )
|
|
UpdateLightingSprite( &( gLightEffectData[uiCount] ) );
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
void ResetLightEffects()
|
|
{
|
|
//Clear out the old list
|
|
memset( gLightEffectData, 0, sizeof( LIGHTEFFECT ) * NUM_LIGHT_EFFECT_SLOTS );
|
|
guiNumLightEffects = 0;
|
|
}
|
|
|
|
// Flugente: create and destroy light sources tied to a person
|
|
void CreatePersonalLight( INT32 sGridNo, UINT8 ubID )
|
|
{
|
|
INT32 iLightIndex = NewLightEffectInternal( sGridNo, 0, 1 );
|
|
|
|
if ( iLightIndex > -1 )
|
|
{
|
|
gLightEffectData[ iLightIndex ].ubOwner = ubID;
|
|
gLightEffectData[ iLightIndex ].flags |= LIGHTEFFECT_FLASHLIGHT;
|
|
}
|
|
}
|
|
|
|
void RemovePersonalLights( UINT8 ubID )
|
|
{
|
|
LIGHTEFFECT *pLight;
|
|
|
|
// Set to unallocated....
|
|
for ( UINT32 cnt = 0; cnt < guiNumLightEffects; ++cnt )
|
|
{
|
|
pLight = &gLightEffectData[ cnt ];
|
|
|
|
if ( pLight->iLight != (-1) && pLight->flags & LIGHTEFFECT_FLASHLIGHT && pLight->ubOwner == ubID && pLight->fAllocated )
|
|
{
|
|
pLight->fAllocated = FALSE;
|
|
pLight->flags &= ~LIGHTEFFECT_FLASHLIGHT;
|
|
|
|
LightSpriteDestroy( pLight->iLight );
|
|
}
|
|
}
|
|
}
|