mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added missing #includes Added LUA scripting and console Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain Fixed signedness of many grid variables used in GetMouseMapPos calls Fixed enemy weapon choosing: Sometimes a mortar is chosen but later rejected, but the grenade class was not reset. Caused assertion failure Added checks so enemies don't try to chuck RPG grenades with their hands Now possible to shoot a someone in the head if he's in water Fixed InitSightArrays to also clear soldier interrupt duel points. This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called. Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have Removed early setting of muzzle flash. This would allow enemies to get an interrupt before you even fired. Fixed item dropping by AI. If AI tried to drop something while standing it would cause deadlock Change to greatly speed up closing the sector inventory window in an unloaded sector Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting Check builddefines.h for the conditional flags. Of greatest interest might be LUA_CONSOLE. This will cause the game to bring up a command console when run. However this console is severely lacking in many areas. If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated. The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus. LUA scripting is very limited, basically just proof of concept. There is one global variable, the Soldiers array. An array index gives you the soldier in that slot in the currently loaded sector. The soldier has a few things that can be accessed: name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
500 lines
11 KiB
C++
500 lines
11 KiB
C++
#include "builddefines.h"
|
|
|
|
#ifdef PRECOMPILEDHEADERS
|
|
#include "TileEngine All.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "wcheck.h"
|
|
#include "stdlib.h"
|
|
#include "debug.h"
|
|
#include "soldier control.h"
|
|
#include "weapons.h"
|
|
#include "handle items.h"
|
|
#include "worlddef.h"
|
|
#include "worldman.h"
|
|
#include "animation control.h"
|
|
#include "tile animation.h"
|
|
#include "handle items.h"
|
|
#include "lighteffects.h"
|
|
#include "message.h"
|
|
#include "isometric utils.h"
|
|
#include "renderworld.h"
|
|
#include "explosion control.h"
|
|
#include "Random.h"
|
|
#include "lighting.h"
|
|
#include "Game Clock.h"
|
|
#include "opplist.h"
|
|
#include "Campaign Types.h"
|
|
#include "Tactical Save.h"
|
|
#endif
|
|
|
|
#include "SaveLoadGame.h"
|
|
|
|
|
|
#define NUM_LIGHT_EFFECT_SLOTS 25
|
|
|
|
|
|
// 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 ) );
|
|
}
|
|
|
|
|
|
INT32 NewLightEffect( INT16 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 );
|
|
|
|
// 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!
|
|
return( pLight->iLight );
|
|
}
|
|
|
|
|
|
|
|
void RemoveLightEffectFromTile( INT16 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( INT16 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 fDelete = FALSE;
|
|
UINT16 usNumUpdates = 1;
|
|
|
|
// age all active tear gas clouds, deactivate those that are just dispersing
|
|
for ( cnt = 0; cnt < guiNumLightEffects; cnt++ )
|
|
{
|
|
pLight = &gLightEffectData[ cnt ];
|
|
|
|
fDelete = FALSE;
|
|
|
|
if ( pLight->fAllocated )
|
|
{
|
|
// ATE: Do this every so ofte, to acheive the effect we want...
|
|
if ( ( uiTime - pLight->uiTimeOfLastUpdate ) > 10 )
|
|
{
|
|
usNumUpdates = ( UINT16 ) ( ( uiTime - pLight->uiTimeOfLastUpdate ) / 10 );
|
|
|
|
pLight->uiTimeOfLastUpdate = uiTime;
|
|
|
|
for ( cnt2 = 0; cnt2 < usNumUpdates; cnt2++ )
|
|
{
|
|
pLight->bAge++;
|
|
|
|
if ( pLight->ubDuration <= 0 )
|
|
fDelete = TRUE;
|
|
// if this cloud remains effective (duration not reached)
|
|
if ( pLight->bAge < pLight->ubDuration)
|
|
{
|
|
// calculate the new cloud radius
|
|
// cloud expands by 1 every turn outdoors, and every other turn indoors
|
|
if ( ( pLight->bAge % 2 ) )
|
|
{
|
|
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 );
|
|
}
|
|
}
|
|
|
|
|
|
// 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( guiSaveGameVersion < 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;
|
|
UINT32 uiNumBytesWritten=0;
|
|
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++)
|
|
{
|
|
//Load the Light effect Data
|
|
FileRead( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( LIGHTEFFECT ) )
|
|
{
|
|
FileClose( hFile );
|
|
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;
|
|
}
|