Files
source/Tactical/Ja25_Tactical.cpp
T

2027 lines
55 KiB
C++

#include "Items.h"
#include "Weapons.h"
#include "Soldier Control.h"
#include "Overhead.h"
#include "Handle UI.h"
#include "Animation Control.h"
#include "Isometric Utils.h"
#include "Animation Data.h"
#include "random.h"
#include "Campaign.h"
#include "Interface.h"
#include "Keys.h"
#include "Soldier Profile.h"
#include "SkillCheck.h"
#include "LOS.h"
#include "message.h"
#include "Text.h"
#include "MessageBoxScreen.h"
#include "ShopKeeper Interface.h"
#include "GameSettings.h"
#include "Auto Resolve.h"
#include "Interface Items.h"
#include "Campaign Types.h"
#include "strategicmap.h"
#include "Inventory Choosing.h"
#include "Soldier macros.h"
#include "Smell.h"
#include "lighting.h"
#include "Utilities.h"
#include "english.h"
#include "Debug Control.h"
#ifdef JA2UB
#include "worldman.h"
#include "Game Clock.h"
#include "Sound Control.h"
#include "Ja25 Strategic Ai.h"
#include "MapScreen Quotes.h"
#include "Ja25_Tactical.h"
#include "Dialogue Control.h"
#include "interface Dialogue.h"
#include "Quests.h"
#include "SaveLoadMap.h"
#include "renderworld.h"
#include "qarray.h"
#include "Soldier Init List.h"
#include "Soldier Control.h"
#include "End Game.h"
#include "structure.h"
#include "Explosion Control.h"
#include "ub_config.h"
#include "GameInitOptionsScreen.h"
//*******************************************************************
//
// Local Defines
//
//*******************************************************************
#define TCTL__DELAY_BETWEEN_ALARM_SOUNDS 4000
#define NUM_NEW_GUN_QUOTES 15
#define PGF__NUM_TURNS_TILL_START_FAN_BACK_UP_EASY 2
#define PGF__NUM_TURNS_TILL_START_FAN_BACK_UP_NORMAL 2
#define PGF__NUM_TURNS_TILL_START_FAN_BACK_UP_HARD 1
typedef struct
{
INT16 sItem;
BOOLEAN fHasBeenSaid;
} NEW_GUN_QUOTES_STRUCT;
//Morris items
//UINT32 MORRIS_INSTRUCTION_NOTE = 1362;
UINT8 Get3RandomQualifiedMercs( SoldierID *pSoldierId1, SoldierID *pSoldierId2, SoldierID *pSoldierId3 );
//*******************************************************************
//
// Global Variables
//
//*******************************************************************
NEW_GUN_QUOTES_STRUCT gNewGunQuotes[ NUM_NEW_GUN_QUOTES ];
//*******************************************************************
//
// Function Prototypes
//
//*******************************************************************
void StopPowerGenFan();
void SetNewGunQuoteToBePlayedForThisGun( INT32 iItemIndex );
BOOLEAN HasNewGunQuoteBeenPlayedForThisGun( INT32 iItemIndex );
BOOLEAN IsThisGunANewJa25Gun( INT32 iItemIndex );
BOOLEAN SaveNewGunQuotesArrayToSaveGameFile( HWFILE hFile );
BOOLEAN LoadNewGunQuotesArrayToSaveGameFile( HWFILE hFile );
void HandlePickingUpMorrisInstructionNote( SOLDIERTYPE *pSoldier, INT32 iIndex );
BOOLEAN IsSoldierAliveWithInitListGridNo( INT16 sInitListID );
void Ja25ScaleAllEnemiesByValue( INT8 bExpScaleValue );
INT8 JA25SecondHighestExpLevelOnPlayersTeam( );
INT8 JA25HighestExpLevelOnTeam( INT8 bTeam );
INT8 JA25SecondHighestExpLevelOnEnemiesTeam( );
INT8 CountNumberOfMercsOnSameTeamOfSameExpLevel( INT8 bTeam, INT8 bExpLevel );
BOOLEAN IsSoldierQualifiedGunCommenterMerc( SOLDIERTYPE *pSoldier );
UINT32 GetNumberOfTurnsPowerGenFanWillBeStoppedFor();
void HandleInitialEventsInHeliCrash();
BOOLEAN gfFirstTimeInGameHeliCrash = FALSE;
void HandleHowPlayerGotThroughFan();
//ppp
//*******************************************************************
//
// Functions
//
//*******************************************************************
BOOLEAN useOldJA2Inventory = TRUE;
//inshy: chenge index of items to 1.13 version. Now we dont need Items.xml in UB-113 folder
/*
UINT32 BARRETT_UB = 335;
UINT32 CALICO_960_UB = 69;
UINT32 PSG1_UB =334;
UINT32 L85_UB =331;
UINT32 TAR21_UB =332;
UINT32 VAL_SILENT_UB =333;
UINT32 MICRO_UZI_UB = 330;
UINT32 CALICO_950_UB = 67;
UINT32 CALICO_900_UB = 68;
UINT32 CLIP_CANNON_BALL = 1354;
UINT32 MERC_UMBRELLA = 1361;
UINT32 HAND_CANNON = 1352;
UINT32 HARTFORD_6_SHOOTER = 66;
UINT32 TEX_MOVIE_ATTACK_CLYDESDALES = 1356;
UINT32 TEX_MOVIE_WILD_EAST = 1357;
UINT32 TEX_MOVIE_HAVE_HONDA = 1358;
UINT32 LAPTOP_TRANSMITTER = 1355;
UINT32 CHE_GUEVARA_CANTEEN = 1359;
UINT32 MERC_WRISTWATCH = 1360;
UINT32 SAM_GARVER_COMBAT_KNIFE = 1353;
UINT32 MERC_UMBRELLA_OLD = 1361; //not used???
UINT32 MORRIS_INSTRUCTION_NOTE = 1362;
//inshy: chenge index of items to 1.13 version. Now we dont need Items.xml in UB-113 folder
UINT32 BARRETT_UB = 43;
UINT32 CALICO_960_UB = 44;
UINT32 PSG1_UB =45;
UINT32 L85_UB =46;
UINT32 TAR21_UB =47;
UINT32 VAL_SILENT_UB =48;
UINT32 MICRO_UZI_UB = 57;
UINT32 CALICO_950_UB = 66;
UINT32 CALICO_900_UB = 67;
UINT32 CLIP_CANNON_BALL = 115;
UINT32 MERC_UMBRELLA = 70;
UINT32 HAND_CANNON = 63;
UINT32 HARTFORD_6_SHOOTER = 68;
UINT32 TEX_MOVIE_ATTACK_CLYDESDALES = 328;
UINT32 TEX_MOVIE_WILD_EAST = 329;
UINT32 TEX_MOVIE_HAVE_HONDA = 330;
UINT32 LAPTOP_TRANSMITTER = 331;
UINT32 CHE_GUEVARA_CANTEEN = 332;
UINT32 MERC_WRISTWATCH = 333;
UINT32 SAM_GARVER_COMBAT_KNIFE = 69;
UINT32 MERC_UMBRELLA_OLD = 335;
UINT32 MORRIS_INSTRUCTION_NOTE = 336;
*/
UINT32 TEX_MOVIE_ATTACK_CLYDESDALES;
UINT32 TEX_MOVIE_WILD_EAST;
UINT32 TEX_MOVIE_HAVE_HONDA;
UINT32 LAPTOP_TRANSMITTER;
UINT32 CHE_GUEVARA_CANTEEN;
UINT32 MERC_WRISTWATCH;
UINT32 SAM_GARVER_COMBAT_KNIFE;
UINT32 MERC_UMBRELLA_OLD;
UINT32 MORRIS_INSTRUCTION_NOTE;
UINT32 HAND_CANNON;
UINT32 HARTFORD_6_SHOOTER;
UINT32 MERC_UMBRELLA;
UINT32 BARRETT_UB;
UINT32 CALICO_960_UB;
UINT32 PSG1_UB;
UINT32 L85_UB;
UINT32 TAR21_UB;
UINT32 VAL_SILENT_UB;
UINT32 MICRO_UZI_UB;
UINT32 CALICO_950_UB;
UINT32 CALICO_900_UB;
UINT32 CLIP_CANNON_BALL;
UINT8 MANUEL_UB;
UINT8 BIGGENS_UB;
UINT8 JOHN_K_UB;
UINT8 TEX_UB;
UINT8 GASTON_UB;
UINT8 STOGIE_UB;
UINT8 JERRY_MILO_UB;
UINT8 PGMALE4_UB;
UINT8 BETTY_UB;
UINT8 RAUL_UB;
UINT8 MORRIS_UB;
UINT8 RUDY_UB;
void Old_UB_Inventory ();
void New_UB_Inventory ();
void Old_UB_Inventory ()
{
BARRETT_UB = 43;
CALICO_960_UB = 44;
PSG1_UB =45;
L85_UB =46;
TAR21_UB =47;
VAL_SILENT_UB =48;
MICRO_UZI_UB = 57;
CALICO_950_UB = 66;
CALICO_900_UB = 67;
CLIP_CANNON_BALL = 115;
MERC_UMBRELLA = 70;
HAND_CANNON = 63;
HARTFORD_6_SHOOTER = 68;
TEX_MOVIE_ATTACK_CLYDESDALES = 328;
TEX_MOVIE_WILD_EAST = 329;
TEX_MOVIE_HAVE_HONDA = 330;
LAPTOP_TRANSMITTER = 331;
CHE_GUEVARA_CANTEEN = 332;
MERC_WRISTWATCH = 333;
SAM_GARVER_COMBAT_KNIFE = 69;
MERC_UMBRELLA_OLD = 335;
MORRIS_INSTRUCTION_NOTE = 336;
}
void New_UB_Inventory ()
{
//inshy: chenge index of items to 1.13 version. Now we dont need Items.xml in UB-113 folder
BARRETT_UB = 335;
CALICO_960_UB = 69;
PSG1_UB =334;
L85_UB =331;
TAR21_UB =332;
VAL_SILENT_UB =333;
MICRO_UZI_UB = 330;
CALICO_950_UB = 67;
CALICO_900_UB = 68;
CLIP_CANNON_BALL = 1354;
MERC_UMBRELLA = 1361;
HAND_CANNON = 1352;
HARTFORD_6_SHOOTER = 66;
TEX_MOVIE_ATTACK_CLYDESDALES = 1356;
TEX_MOVIE_WILD_EAST = 1357;
TEX_MOVIE_HAVE_HONDA = 1358;
LAPTOP_TRANSMITTER = 1355;
CHE_GUEVARA_CANTEEN = 1359;
MERC_WRISTWATCH = 1360;
SAM_GARVER_COMBAT_KNIFE = 1353;
MERC_UMBRELLA_OLD = 1361; //not used???
MORRIS_INSTRUCTION_NOTE = 1362;
}
//GridNo
UINT32 SWITCHINMORRISAREA_GRIDNO = 15231;
UINT32 SWITCHTOLAUNCHMISSLES_GRIDNO1 = 14268;
UINT32 SWITCHTOLAUNCHMISSLES_GRIDNO2 = 15708;
UINT32 RADIOLOCATORS_GRIDNO1 = 15070;
UINT32 RADIOLOCATORS_GRIDNO2 = 14744;
UINT32 POWERGENSECTOR_GRIDNO1 = 15100;
UINT32 POWERGENSECTOR_GRIDNO2 = 12220;
UINT32 POWERGENSECTOR_GRIDNO3 = 14155;
UINT32 POWERGENSECTOR_GRIDNO4 = 13980;
UINT32 POWERGENSECTOREXITGRID_SRC_GRIDNO = 10979;
UINT32 POWERGENSECTOREXITGRID_DST_GRIDNO = 19749;
UINT32 POWERGENFANSOUND_GRIDNO1 = 10979;
UINT32 POWERGENFANSOUND_GRIDNO2 = 19749;
UINT32 STARTFANBACKUPAGAIN_GRIDNO = 10980;
UINT32 STOPPOWERGENFAN_GRIDNO = 10980;
//L15-3
UINT32 SECTOR_LAUNCH_MISSLES_X = 15;
UINT32 SECTOR_LAUNCH_MISSLES_Y = 12;
UINT32 SECTOR_LAUNCH_MISSLES_Z = 3;
//J13-0
UINT32 SECTOR_FAN_X = 13;
UINT32 SECTOR_FAN_Y = 10;
UINT32 SECTOR_FAN_Z = 0;
//K14-1
UINT32 SECTOR_OPEN_GATE_IN_TUNNEL_X = 14;
UINT32 SECTOR_OPEN_GATE_IN_TUNNEL_Y = 11;
UINT32 SECTOR_OPEN_GATE_IN_TUNNEL_Z = 1;
// Destination sector for fan exitgrid
//J14-1
UINT32 EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_X = 14;
UINT32 EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Y = 10;
UINT32 EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Z = 1;
INT16 BETTY_BLOODCAT_SECTOR_X = 10;
INT16 BETTY_BLOODCAT_SECTOR_Y = 9;
INT8 BETTY_BLOODCAT_SECTOR_Z = 0;
void InitGridNoUB()
{
SWITCHINMORRISAREA_GRIDNO = gGameUBOptions.SwitchInMorrisAreaGridNo; //= 15231;
SWITCHTOLAUNCHMISSLES_GRIDNO1 = gGameUBOptions.SwitchToLaunchMisslesGridNo1; //= 14268;
SWITCHTOLAUNCHMISSLES_GRIDNO2 = gGameUBOptions.SwitchToLaunchMisslesGridNo2; //= 15708;
RADIOLOCATORS_GRIDNO1 = gGameUBOptions.RadioLocatorsGridNo1; //= 15070;
RADIOLOCATORS_GRIDNO2 = gGameUBOptions.RadioLocatorsGridNo2; //= 14744;
POWERGENSECTOR_GRIDNO1 = gGameUBOptions.PowergenSectorGridNo1; //= 15100;
POWERGENSECTOR_GRIDNO2 = gGameUBOptions.PowergenSectorGridNo2; //= 12220;
POWERGENSECTOR_GRIDNO3 = gGameUBOptions.PowergenSectorGridNo3; //= 14155;
POWERGENSECTOR_GRIDNO4 = gGameUBOptions.PowergenSectorGridNo4; //= 13980;
POWERGENSECTOREXITGRID_SRC_GRIDNO = gGameUBOptions.PowergenSectorExitgridSrcGridNo; //= 10979; // Exitgrid location in the sector it is created in
POWERGENSECTOREXITGRID_DST_GRIDNO = gGameUBOptions.PowergenSectorExitgridGridNo; // = 19749; // Exitgrid location in the destination sector
POWERGENFANSOUND_GRIDNO1 = gGameUBOptions.PowergenFanSoundGridNo1; //= 10979;
POWERGENFANSOUND_GRIDNO2 = gGameUBOptions.PowergenFanSoundGridNo2; //= 19749;
STARTFANBACKUPAGAIN_GRIDNO = gGameUBOptions.StartFanbackupAgainGridNo; //= 10980;
STOPPOWERGENFAN_GRIDNO = gGameUBOptions.StopPowergenFanGridNo; //= 10980;
//L15-3
SECTOR_LAUNCH_MISSLES_X = gGameUBOptions.SectorLaunchMisslesX; // 15;
SECTOR_LAUNCH_MISSLES_Y = gGameUBOptions.SectorLaunchMisslesY; // 12;
SECTOR_LAUNCH_MISSLES_Z = gGameUBOptions.SectorLaunchMisslesZ; //3;
//J13-0
SECTOR_FAN_X = gGameUBOptions.SectorFanX; //13;
SECTOR_FAN_Y = gGameUBOptions.SectorFanY; //10;
SECTOR_FAN_Z = gGameUBOptions.SectorFanZ; //0;
//K14-1
SECTOR_OPEN_GATE_IN_TUNNEL_X = gGameUBOptions.SectorOpenGateInTunnelX; //14;
SECTOR_OPEN_GATE_IN_TUNNEL_Y = gGameUBOptions.SectorOpenGateInTunnelY; //11;
SECTOR_OPEN_GATE_IN_TUNNEL_Z = gGameUBOptions.SectorOpenGateInTunnelZ; //1;
//J14-1
EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_X = gGameUBOptions.ExitForFanToPowerGenSectorX; //14;
EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Y = gGameUBOptions.ExitForFanToPowerGenSectorY; //10;
EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Z = gGameUBOptions.ExitForFanToPowerGenSectorZ; //1;
BETTY_BLOODCAT_SECTOR_X = gGameUBOptions.BettyBloodCatSectorX;
BETTY_BLOODCAT_SECTOR_Y = gGameUBOptions.BettyBloodCatSectorY;
BETTY_BLOODCAT_SECTOR_Z = gGameUBOptions.BettyBloodCatSectorZ;
MANUEL_UB = gGameUBOptions.ubMANUEL_UB;
BIGGENS_UB = gGameUBOptions.ubBIGGENS_UB;
JOHN_K_UB = gGameUBOptions.ubJOHN_K_UB;
TEX_UB = gGameUBOptions.ubTEX_UB;
GASTON_UB = gGameUBOptions.ubGASTON_UB;
STOGIE_UB = gGameUBOptions.ubSTOGIE_UB;
JERRY_MILO_UB = gGameUBOptions.ubJERRY_MILO_UB;
PGMALE4_UB = gGameUBOptions.ubPGMALE4_UB;
BETTY_UB = gGameUBOptions.ubBETTY_UB;
RAUL_UB = gGameUBOptions.ubRAUL_UB;
MORRIS_UB = gGameUBOptions.ubMORRIS_UB;
RUDY_UB = gGameUBOptions.ubRUDY_UB;
TEX_MOVIE_ATTACK_CLYDESDALES = gGameUBOptions.ubTEX_MOVIE_ATTACK_CLYDESDALES;
TEX_MOVIE_WILD_EAST = gGameUBOptions.ubTEX_MOVIE_WILD_EAST;
TEX_MOVIE_HAVE_HONDA = gGameUBOptions.ubTEX_MOVIE_HAVE_HONDA;
LAPTOP_TRANSMITTER = gGameUBOptions.ubLAPTOP_TRANSMITTER;
CHE_GUEVARA_CANTEEN = gGameUBOptions.ubCHE_GUEVARA_CANTEEN;
MERC_WRISTWATCH = gGameUBOptions.ubMERC_WRISTWATCH;
SAM_GARVER_COMBAT_KNIFE = gGameUBOptions.ubSAM_GARVER_COMBAT_KNIFE;
MERC_UMBRELLA_OLD = gGameUBOptions.ubMERC_UMBRELLA_OLD;
MORRIS_INSTRUCTION_NOTE = gGameUBOptions.ubMORRIS_INSTRUCTION_NOTE;
HAND_CANNON = gGameUBOptions.ubHAND_CANNON;
HARTFORD_6_SHOOTER = gGameUBOptions.ubHARTFORD_6_SHOOTER;
MERC_UMBRELLA = gGameUBOptions.ubMERC_UMBRELLA;
CLIP_CANNON_BALL = gGameUBOptions.ubCLIP_CANNON_BALL;
BARRETT_UB = gGameUBOptions.ubBARRETT_UB;
CALICO_960_UB = gGameUBOptions.ubCALICO_960_UB;
PSG1_UB = gGameUBOptions.ubPSG1_UB;
L85_UB = gGameUBOptions.ubL85_UB;
TAR21_UB = gGameUBOptions.ubTAR21_UB;
VAL_SILENT_UB = gGameUBOptions.ubVAL_SILENT_UB;
MICRO_UZI_UB = gGameUBOptions.ubMICRO_UZI_UB;
CALICO_950_UB = gGameUBOptions.ubCALICO_950_UB;
CALICO_900_UB = gGameUBOptions.ubCALICO_900_UB;
}
BOOLEAN IsSoldierQualifiedMerc( SOLDIERTYPE *pSoldier )
{
if( pSoldier->ubProfile == GASTON_UB || /// GASTON
pSoldier->ubProfile == STOGIE_UB || // STOGIE
pSoldier->ubProfile == TEX_UB ||// TEX ||
pSoldier->ubProfile == JOHN_K_UB || //JOHN_K ||
pSoldier->ubProfile == BIGGENS_UB || //BIGGENS ||
pSoldier->ubProfile == MANUEL_UB || //MANUEL ||
pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER
)
{
return( TRUE );
}
else
{
return( FALSE );
}
}
BOOLEAN IsSoldierQualifiedMercForSeeingPowerGenFan( SOLDIERTYPE *pSoldier )
{
if( pSoldier->ubProfile == MANUEL_UB ||//MANUEL ||
pSoldier->ubProfile == 53 || //PGCMale3
pSoldier->ubProfile == 55 || //PGCFem2
pSoldier->ubProfile == PGMALE4_UB //PGCMale4
)
{
return( TRUE );
}
else
{
return( FALSE );
}
}
BOOLEAN IsSoldierQualifiedGunCommenterMerc( SOLDIERTYPE *pSoldier )
{
if( pSoldier->ubProfile == GASTON_UB || // GASTON
pSoldier->ubProfile == STOGIE_UB || // STOGIE
pSoldier->ubProfile == TEX_UB || // TEX
pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER
)
{
return( TRUE );
}
else
{
return( FALSE );
}
}
BOOLEAN IsSoldierQualifiedInitialHireMerc( SOLDIERTYPE *pSoldier )
{
if( pSoldier->ubProfile == GASTON_UB || // GASTON
pSoldier->ubProfile == STOGIE_UB || // STOGIE
pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER
)
{
return( TRUE );
}
else
{
return( FALSE );
}
}
UINT8 GetNumSoldierIdAndProfileIdOfTheNewMercsOnPlayerTeam( SoldierID *pSoldierIdArray, UINT8 *pProfileIdArray )
{
SOLDIERTYPE *pSoldier=NULL;
UINT8 usNumMercsPresent=0;
if( pSoldierIdArray )
memset( pSoldierIdArray, NOBODY, NUM_MERCS_WITH_NEW_QUOTES );
if( pProfileIdArray )
memset( pProfileIdArray, NO_PROFILE, NUM_MERCS_WITH_NEW_QUOTES );
INT32 cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
//Check to see if Gaston, Stogie or the PGC is on the team
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt, ++pSoldier )
{
//if the merc is alive, in sector, etc...
//Note: cant do the OK_CONTROLLABLE_MERC() cause it does bInSector which is not set when EnterSector is finshed ( we need it then )
if( pSoldier->bActive &&
pSoldier->sSectorX == gWorldSectorX &&
pSoldier->sSectorY == gWorldSectorY &&
pSoldier->bSectorZ == gbWorldSectorZ &&
pSoldier->stats.bLife >= OKLIFE &&
!pSoldier->flags.fBetweenSectors )
{
//if the merc is one of the mercs we are looking for
if( IsSoldierQualifiedMerc( pSoldier ) )
{
//if we are to return an array of the mercs
if( pProfileIdArray != NULL )
{
//record the profile num of the merc
pProfileIdArray[ usNumMercsPresent ] = pSoldier->ubProfile;
}
//if we are to return an array of the mercs
if( pSoldierIdArray != NULL )
{
//record the soldier num of the merc
pSoldierIdArray[ usNumMercsPresent ] = pSoldier->ubID;
}
++usNumMercsPresent;
}
}
}
return usNumMercsPresent;
}
INT16 RandomProfileIdFromNewMercsOnPlayerTeam()
{
UINT8 usNumMercsPresent;
UINT8 ProfileIdArray[NUM_MERCS_WITH_NEW_QUOTES];
//Get the number and array of the new soldiers
usNumMercsPresent = GetNumSoldierIdAndProfileIdOfTheNewMercsOnPlayerTeam( NULL, ProfileIdArray );
Assert( usNumMercsPresent < NUM_MERCS_WITH_NEW_QUOTES );
if( usNumMercsPresent > 0 )
{
//return a random merc from the array
return( (INT16)(ProfileIdArray[ Random( usNumMercsPresent ) ]) );
}
else
{
return( -1 );
}
}
SoldierID RandomSoldierIdFromNewMercsOnPlayerTeam()
{
UINT8 usNumMercsPresent;
SoldierID SoldierIdArray[NUM_MERCS_WITH_NEW_QUOTES];
//Get the number and array of the new soldiers
usNumMercsPresent = GetNumSoldierIdAndProfileIdOfTheNewMercsOnPlayerTeam( SoldierIdArray, NULL );
Assert( usNumMercsPresent < NUM_MERCS_WITH_NEW_QUOTES );
if( usNumMercsPresent > 0 )
{
//return a random merc from the array
return( ( SoldierIdArray[ Random( usNumMercsPresent ) ] ));
}
else
{
return( NOBODY );
}
}
UINT8 RandomArrayOfQualifiedMercs( SoldierID *pRandomSoldierIdArray )
{
UINT8 usNumMercsPresent;
SoldierID SoldierIdArray[NUM_MERCS_WITH_NEW_QUOTES];
BOOLEAN UsedArray[NUM_MERCS_WITH_NEW_QUOTES];
BOOLEAN fFound=FALSE;
UINT8 ubRand;
memset( UsedArray, 0, NUM_MERCS_WITH_NEW_QUOTES );
memset( pRandomSoldierIdArray, NOBODY, NUM_MERCS_WITH_NEW_QUOTES );
//Get the number and array of the new soldiers
usNumMercsPresent = GetNumSoldierIdAndProfileIdOfTheNewMercsOnPlayerTeam( SoldierIdArray, NULL );
Assert( usNumMercsPresent < NUM_MERCS_WITH_NEW_QUOTES );
if( usNumMercsPresent > 0 )
{
//loop through all the available mercs
for( UINT8 ubCnt=0; ubCnt<usNumMercsPresent; ++ubCnt )
{
fFound = FALSE;
//loop
while( !fFound )
{
ubRand = Random( usNumMercsPresent );
if( !UsedArray[ ubRand ] )
{
UsedArray[ ubRand ] = TRUE;
pRandomSoldierIdArray[ubCnt] = SoldierIdArray[ubRand];
fFound = TRUE;
}
}
}
}
return( usNumMercsPresent );
}
UINT8 Get3RandomQualifiedMercs( SoldierID *pSoldierId1, SoldierID *pSoldierId2, SoldierID *pSoldierId3 )
{
UINT8 usNumMercs;
SoldierID RandomSoldierIdArray[ NUM_MERCS_WITH_NEW_QUOTES ];
UINT8 ubNumberDifMercsAssigned=0;
usNumMercs = RandomArrayOfQualifiedMercs( RandomSoldierIdArray );
if( usNumMercs == 0 )
{
return( 0 );
}
if( pSoldierId1 != NULL )
*pSoldierId1 = NOBODY;
if( pSoldierId2 != NULL )
*pSoldierId2 = NOBODY;
if( pSoldierId3 != NULL )
*pSoldierId3 = NOBODY;
if( usNumMercs >= 1 && pSoldierId1 != NULL )
{
*pSoldierId1 = RandomSoldierIdArray[ 0 ];
ubNumberDifMercsAssigned++;
}
if( usNumMercs >= 2 && pSoldierId2 != NULL )
{
*pSoldierId2 = RandomSoldierIdArray[ 1 ];
ubNumberDifMercsAssigned++;
}
else
{
*pSoldierId2 = RandomSoldierIdArray[ 0 ];
}
if( pSoldierId3 != NULL )
{
if( usNumMercs >= 3 )
{
*pSoldierId3 = RandomSoldierIdArray[ 2 ];
ubNumberDifMercsAssigned++;
}
else if( usNumMercs >= 2 )
{
if( Chance( 50 ) )
*pSoldierId3 = RandomSoldierIdArray[ 1 ];
else
*pSoldierId3 = RandomSoldierIdArray[ 0 ];
}
}
return( ubNumberDifMercsAssigned );
}
void HandleWhenCertainPercentageOfEnemiesDie()
{
UINT32 uiPercentEnemiesKilled;
UINT8 ubSectorID;
//if there isn't enemies in the sector
if( ( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) == 0 )
{
//get out
return;
}
uiPercentEnemiesKilled = (UINT32)( 100 * (UINT32)(gTacticalStatus.ubArmyGuysKilled + 1) / (UINT32)( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) );
ubSectorID = SECTOR( gWorldSectorX, gWorldSectorY );
switch( gbWorldSectorZ )
{
case 0:
switch( ubSectorID )
{
case SEC_K15:
//all enemies are dead and if the quote hasn't been said yet
if( uiPercentEnemiesKilled >= 100 && !( gJa25SaveStruct.uiJa25GeneralFlags & JA_GF__ALL_DEAD_TOP_LEVEL_OF_COMPLEX ) )
{
INT16 bProfile = RandomProfileIdFromNewMercsOnPlayerTeam();
if( bProfile != -1 )
DelayedMercQuote( (UINT16)bProfile, QUOTE_WONT_RENEW_CONTRACT_LAME_REFUSAL, GetWorldTotalSeconds() + 5 );
gJa25SaveStruct.uiJa25GeneralFlags |= JA_GF__ALL_DEAD_TOP_LEVEL_OF_COMPLEX;
}
break;
}
}
}
void StopPowerGenFan()
{
UINT16 usTileIndex;
SOLDIERTYPE *pSoldier=NULL;
// ATE: If destroyed, don't go into here
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector == PGF__BLOWN_UP )
{
return;
}
//If the fan is already stopped, or has been stopped in the past
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector == PGF__STOPPED ||
IsJa25GeneralFlagSet( JA_GF__POWER_GEN_FAN_HAS_BEEN_STOPPED ) )
{
//leave
return;
}
//if we are in turn based combat
if( !((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) )
{
return;
}
//Remember how the player got through
SetJa25GeneralFlag( JA_GF__POWER_GEN_FAN_HAS_BEEN_STOPPED );
gJa25SaveStruct.ubStateOfFanInPowerGenSector = PGF__STOPPED;
//Set the fact that player stopped the fan
SetFactTrue( FACT_FAN_STOPPPED );
//Is biggens on the team
pSoldier = FindSoldierByProfileID( BIGGENS_UB, TRUE ); // BIGGENS
if( pSoldier != NULL )
{
SetFactTrue( FACT_BIGGENS_ON_TEAM_AND_FAN_STOPPED );
}
//Turn off the power gen fan sound
HandleRemovingPowerGenFanSound();
//remember which turn the fan stopped on
gJa25SaveStruct.uiTurnPowerGenFanWentDown = gJa25SaveStruct.uiTacticalTurnCounter;
//
// Replace the Fan graphic
//
// Turn on permanent changes....
ApplyMapChangesToMapTempFile( TRUE );
//Add the exit grid to the power gen fan
AddExitGridForFanToPowerGenSector();
// Remove it!
// Get index for it...
GetTileIndexFromTypeSubIndex( FIFTHOSTRUCT, (INT8)( 1 ), &usTileIndex );
RemoveStruct( STOPPOWERGENFAN_GRIDNO, usTileIndex );
// Add the new one
// Get index for it...
GetTileIndexFromTypeSubIndex( FIFTHOSTRUCT, (INT8)( 7 ), &usTileIndex );
AddStructToHead( STOPPOWERGENFAN_GRIDNO, usTileIndex );
ApplyMapChangesToMapTempFile( FALSE );
//Recompile the movement costs since we have added a exit grid
RecompileLocalMovementCosts( STOPPOWERGENFAN_GRIDNO );
gpWorldLevelData[ STOPPOWERGENFAN_GRIDNO ].uiFlags |= MAPELEMENT_REVEALED;
// Re-render the world!
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
// FOR THE NEXT RENDER LOOP, RE-EVALUATE REDUNDENT TILES
SetRenderFlags(RENDER_FLAG_FULL);
}
void HandleStartingFanBackUp()
{
//if the fan has been stopped for the right amount of time
if( gJa25SaveStruct.uiTacticalTurnCounter == ( gJa25SaveStruct.uiTurnPowerGenFanWentDown + GetNumberOfTurnsPowerGenFanWillBeStoppedFor() ) )
{
//if it is stopped
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector == PGF__STOPPED )
{
StartFanBackUpAgain();
}
}
}
void StartFanBackUpAgain()
{
UINT16 usTileIndex;
// ATE: If destroyed, don't go into here
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector == PGF__BLOWN_UP )
{
return;
}
//Remember how the player got through
gJa25SaveStruct.ubStateOfFanInPowerGenSector = PGF__RUNNING_NORMALLY;
//Start the fan sound
HandleAddingPowerGenFanSound();
//
// Replace the Fan graphic
//
// Turn on permanent changes....
ApplyMapChangesToMapTempFile( TRUE );
// Remove it!
// Get index for it...
GetTileIndexFromTypeSubIndex( FIFTHOSTRUCT, (INT8)( 7 ), &usTileIndex );
RemoveStruct( STARTFANBACKUPAGAIN_GRIDNO, usTileIndex );
// Add the new one
// Get index for it...
GetTileIndexFromTypeSubIndex( FIFTHOSTRUCT, (INT8)( 1 ), &usTileIndex );
AddStructToHead( STARTFANBACKUPAGAIN_GRIDNO, usTileIndex );
ApplyMapChangesToMapTempFile( FALSE );
//Recompile the movement costs since we have added a exit grid
RecompileLocalMovementCosts( STARTFANBACKUPAGAIN_GRIDNO );
gpWorldLevelData[ STARTFANBACKUPAGAIN_GRIDNO ].uiFlags |= MAPELEMENT_REVEALED;
// Re-render the world!
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
//Remove the exit grid
RemoveExitGridFromWorld( POWERGENSECTOREXITGRID_SRC_GRIDNO );
// FOR THE NEXT RENDER LOOP, RE-EVALUATE REDUNDENT TILES
SetRenderFlags(RENDER_FLAG_FULL);
}
void HandlePowerGenAlarm()
{
static UINT32 uiLastTime=0;
static UINT32 uiAlarmCounter=0;
UINT32 uiCurTime=0;
//if its not the right sector J13-0
if( !( gWorldSectorX == SECTOR_FAN_X && gWorldSectorY == SECTOR_FAN_Y && gbWorldSectorZ == SECTOR_FAN_Z ) )
{
//leave
return;
}
//if the fan is not stopped
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector != PGF__STOPPED )
{
uiAlarmCounter = 0;
//leave
return;
}
uiCurTime = GetJA2Clock();
if( ( uiCurTime - uiLastTime ) >= TCTL__DELAY_BETWEEN_ALARM_SOUNDS )
{
uiAlarmCounter++;
PlayJA2SampleFromFile( "SOUNDS\\AlarmFan.wav", RATE_11025, MIDVOLUME, 1, MIDDLE );
uiLastTime = uiCurTime;
if( uiAlarmCounter == 2 && !IsJa25GeneralFlagSet( JA_GF__BIGGENS_SAID_QUOTE_117 ) )
{
//
// Have merc say the quote, if the conditions are right
//
if( gubFact[ FACT_PLAYER_KNOWS_ABOUT_FAN_STOPPING ] )
{
INT16 bID = RandomSoldierIdFromNewMercsOnPlayerTeam();
if( bID != -1 )
{
TacticalCharacterDialogue( &Menptr[ bID ], QUOTE_HATED_2_ON_TEAM_LONGTIMETOHATE );
}
}
else
{
SoldierID bSoldierId1, bSoldierId2, bSoldierId3;
Get3RandomQualifiedMercs( &bSoldierId1, &bSoldierId2, &bSoldierId3 );
if( bSoldierId1 != NOBODY && bSoldierId1->ubProfile != BIGGENS_UB ) //BIGGENS
{
TacticalCharacterDialogue( bSoldierId1, QUOTE_HATED_1_ON_TEAM_LONGTIMETOHATE );
}
else if( bSoldierId2 != NOBODY && bSoldierId2->ubProfile != BIGGENS_UB ) //BIGGENS
{
TacticalCharacterDialogue( bSoldierId2, QUOTE_HATED_1_ON_TEAM_LONGTIMETOHATE );
}
else if( bSoldierId3 != NOBODY && bSoldierId3->ubProfile != BIGGENS_UB ) // BIGGENS
{
TacticalCharacterDialogue( bSoldierId3, QUOTE_HATED_1_ON_TEAM_LONGTIMETOHATE );
}
}
}
}
}
void HandleAddingPowerGenFanSound()
{
UINT32 sGridNo;
//if its not already playing
if( gJa25SaveStruct.iPowerGenFanPositionSndID != -1 )
{
return;
}
if( gbWorldSectorZ == 0 )
sGridNo = POWERGENFANSOUND_GRIDNO1;
else
sGridNo = POWERGENFANSOUND_GRIDNO2;
//Create the new ambient fan sound
gJa25SaveStruct.iPowerGenFanPositionSndID = NewPositionSnd( sGridNo, POSITION_SOUND_STATIONATY_OBJECT, 0, POWER_GEN_FAN_SOUND, 30 );
SetPositionSndsInActive( );
SetPositionSndsActive( );
}
void HandleRemovingPowerGenFanSound()
{
//if there is an ambience sound playing
if( gJa25SaveStruct.iPowerGenFanPositionSndID != -1 )
{
//delete it
DeletePositionSnd( gJa25SaveStruct.iPowerGenFanPositionSndID );
gJa25SaveStruct.iPowerGenFanPositionSndID = -1;
}
}
void AddExitGridForFanToPowerGenSector()
{
EXITGRID ExitGrid;
memset( &ExitGrid, 0, sizeof( EXITGRID ) );
ExitGrid.ubGotoSectorX = EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_X; //14;
ExitGrid.ubGotoSectorY = EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Y; //MAP_ROW_J;
ExitGrid.ubGotoSectorZ = EXIT_FOR_FAN_TO_POWER_GEN_SECTOR_Z; //1;
ExitGrid.usGridNo = POWERGENSECTOREXITGRID_DST_GRIDNO;
//Add the exit grid when the fan is either stopped or blown up
AddExitGridToWorld( POWERGENSECTOREXITGRID_SRC_GRIDNO, &ExitGrid );
}
BOOLEAN HandlePlayerSayingQuoteWhenFailingToOpenGateInTunnel( SOLDIERTYPE *pSoldierAtDoor, BOOLEAN fSayQuoteOnlyOnce )
{
INT8 bSlot;
UINT32 cnt;
SOLDIERTYPE *pSoldier;
//is this the right sector K14-1
if( !( gWorldSectorX == SECTOR_OPEN_GATE_IN_TUNNEL_X && gWorldSectorY == SECTOR_OPEN_GATE_IN_TUNNEL_Y && gbWorldSectorZ == SECTOR_OPEN_GATE_IN_TUNNEL_Z ) )
{
//wrong door
return( FALSE );
}
//if the player has already said the quote
if( IsJa25GeneralFlagSet( JA_GF__PLAYER_SAID_GATE_LOCKED_QUOTE ) )
{
return( FALSE );
}
//
// look to see if anyone on the team has wire cutters
//
// loop throught the team and see if anyone in this sector has the wire cutter
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++)
{
//if the soldier is in the sector
if( pSoldier->bActive && pSoldier->bInSector && ( pSoldier->stats.bLife >= CONSCIOUSNESS ) &&
!( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !AM_A_ROBOT( pSoldier ) )
{
bSlot = FindObj( pSoldier, WIRECUTTERS );
if( bSlot != NO_SLOT )
{
//the merc has wire cutters
return( FALSE );
}
}
}
INT16 bID = RandomSoldierIdFromNewMercsOnPlayerTeam();
if( bID != -1 )
{
//have the merc say the quote about the tough gate
TacticalCharacterDialogue( &Menptr[ bID ], QUOTE_IMPATIENT_QUOTE );
}
//remeber we said the quote
if( fSayQuoteOnlyOnce )
{
SetJa25GeneralFlag( JA_GF__PLAYER_SAID_GATE_LOCKED_QUOTE );
}
return( TRUE );
}
void HandleHowPlayerGotThroughFan()
{
switch( gJa25SaveStruct.ubStateOfFanInPowerGenSector )
{
case PGF__STOPPED:
gJa25SaveStruct.ubHowPlayerGotThroughFan = PG__PLAYER_STOPPED_FAN_TO_GET_THROUGH;
break;
case PGF__BLOWN_UP:
gJa25SaveStruct.ubHowPlayerGotThroughFan = PG__PLAYER_BLEW_UP_FAN_TO_GET_THROUGH;
//If the player blew up the fan, then the enemies can hear it in the tunnel and prepare for it.
gJa25SaveStruct.uiJa25GeneralFlags |= JA_GF__DID_PLAYER_MAKE_SOUND_GOING_THROUGH_TUNNEL_GATE;
break;
}
}
/*
void RevealAllDroppedEnemyItems()
{
UINT32 uiCnt=0;
//loop through all the items
for(uiCnt=0; uiCnt<guiNumWorldItems; uiCnt++ )
{
//if the item exists AND the item was droppped from an enemy
if( gWorldItems[ uiCnt ].fExists && gWorldItems[ uiCnt ].usFlags & WORLD_ITEM_DROPPED_FROM_ENEMY )
{
gWorldItems[ uiCnt ].bVisible = VISIBLE;
}
}
// Make team look for items
AllSoldiersLookforItems( TRUE );
}
*/
void HandlePlayingQuoteWhenHiringNpc( UINT8 ubProfile )
{
if ( ubProfile == MANUEL_UB ) //MANUEL:
SayQuoteFromAllNewHiredMercButDoGastonLast( ubProfile, QUOTE_PRECEDENT_TO_REPEATING_ONESELF );
else if ( ubProfile == BIGGENS_UB ) //BIGGENS:
SayQuoteFromAllNewHiredMercButDoGastonLast( ubProfile, QUOTE_REFUSAL_TO_JOIN_LACK_OF_FUNDS );
else if ( ubProfile == JOHN_K_UB ) //JOHN_K:
{
SayQuoteFromAllNewHiredMercButDoGastonLast( ubProfile, QUOTE_DEPART_COMMET_CONTRACT_NOT_RENEWED_OR_TERMINATED_UNDER_48 );
//Delay John saying quote about town
DelayedMercQuote( JOHN_K_UB, QUOTE_HATED_2_ON_TEAM, GetWorldTotalSeconds() + 5 + Random( 10 ) );
}
else if ( ubProfile == TEX_UB ) //TEX:
SayQuoteFromAllNewHiredMercButDoGastonLast( ubProfile, QUOTE_DEATH_RATE_RENEWAL );
}
BOOLEAN SayQuoteFromAllNewHiredMercButDoGastonLast( UINT8 ubProfile, UINT32 uiQuoteNum )
{
UINT8 usNumMercsPresent;
SoldierID SoldierIdArray[NUM_MERCS_WITH_NEW_QUOTES];
SOLDIERTYPE *pSoldier=NULL;
//Get an array of the mercs on the team
usNumMercsPresent = GetNumSoldierIdAndProfileIdOfTheNewMercsOnPlayerTeam( SoldierIdArray, NULL );
if( !usNumMercsPresent )
{
return( FALSE );
}
for ( UINT8 iCnt=0; iCnt<usNumMercsPresent; ++iCnt )
{
//Do Gaston and the newly hired RPC last
if( Menptr[ SoldierIdArray[ iCnt ] ].ubProfile == GASTON_UB || Menptr[ SoldierIdArray[ iCnt ] ].ubProfile == ubProfile) // GASTON
{
continue;
}
TacticalCharacterDialogue( &Menptr[ SoldierIdArray[ iCnt ] ], (UINT16)uiQuoteNum );
}
//if Gaston is on the team, say his quote
pSoldier = FindSoldierByProfileID( GASTON_UB, TRUE ); // GASTON
if( pSoldier &&
pSoldier->sSectorX == gWorldSectorX &&
pSoldier->sSectorY == gWorldSectorY &&
pSoldier->bSectorZ == gbWorldSectorZ )
{
TacticalCharacterDialogue( pSoldier, (UINT16)uiQuoteNum );
}
//Say the quote of the newly hired person
pSoldier = FindSoldierByProfileID( ubProfile, TRUE );
if( pSoldier )
{
TacticalCharacterDialogue( pSoldier, (UINT16)uiQuoteNum );
}
return( TRUE );
}
//returns false if a new merc is not going to handle saying the new quote
BOOLEAN HandleNewGunComment( SOLDIERTYPE *pSoldier, INT32 iItemIndex, BOOLEAN fFromGround )
{
BOOLEAN fNewMerc = IsSoldierQualifiedGunCommenterMerc( pSoldier );
if( !fFromGround )
{
//if this is morris's note, handle it
HandlePickingUpMorrisInstructionNote( pSoldier, iItemIndex );
}
//if the quote has already been said
if( HasNewGunQuoteBeenPlayedForThisGun( iItemIndex ) )
{
//get out
return( TRUE );
}
//if we are not in tactical or map screen,
if( guiCurrentScreen != GAME_SCREEN && guiCurrentScreen != MAP_SCREEN )
{
//only remeber that we have picked up the gun at some point
SetNewGunQuoteToBePlayedForThisGun( iItemIndex );
return( FALSE );
}
//if the soldier is a NOT new merc AND this item is from the ground AND the merc didnt say this quote recently
if( !fNewMerc && fFromGround && ( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_FOUND_SOMETHING_NICE ) == 0 )
{
//if the merc can say it
if( QuoteExp_GotGunOrUsedGun[ pSoldier->ubProfile ] == QUOTE_FOUND_SOMETHING_SPECIAL )
{
//Have the merc say his cool item quote
TacticalCharacterDialogue( pSoldier, QUOTE_FOUND_SOMETHING_SPECIAL );
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_FOUND_SOMETHING_NICE;
}
}
//if it is a new merc
if( fNewMerc )
{
//if the item is the hand cannon
if( iItemIndex == HAND_CANNON ) //4498
{
//say the new gun quote
TacticalCharacterDialogue( pSoldier, QUOTE_PRECEDENT_TO_REPEATING_ONESELF_RENEW );
}
else
{
//say the new gun quote
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_1_ON_TEAM_WONT_RENEW );
}
//rememeber we have played the quote
SetNewGunQuoteToBePlayedForThisGun( iItemIndex );
}
return( TRUE );
}
BOOLEAN SaveJa25TacticalInfoToSaveGame( HWFILE hFile )
{
if( !SaveNewGunQuotesArrayToSaveGameFile( hFile ) )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN LoadJa25TacticalInfoFromSavedGame( HWFILE hFile )
{
if( !LoadNewGunQuotesArrayToSaveGameFile( hFile ) )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN SaveNewGunQuotesArrayToSaveGameFile( HWFILE hFile )
{
UINT32 uiNumBytesWritten;
UINT32 uiSize = sizeof( NEW_GUN_QUOTES_STRUCT ) * NUM_NEW_GUN_QUOTES;
FileWrite( hFile, &gNewGunQuotes, uiSize, &uiNumBytesWritten );
if( uiNumBytesWritten != uiSize )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN LoadNewGunQuotesArrayToSaveGameFile( HWFILE hFile )
{
UINT32 uiNumBytesRead;
UINT32 uiSize = sizeof( NEW_GUN_QUOTES_STRUCT ) * NUM_NEW_GUN_QUOTES;
FileRead( hFile, &gNewGunQuotes, uiSize, &uiNumBytesRead );
if( uiNumBytesRead != uiSize )
{
return( FALSE );
}
InitNewGunArray();
return( TRUE );
}
void InitNewGunArray()
{
INT32 iCnt=0;
gNewGunQuotes[iCnt++].sItem = BARRETT_UB;
gNewGunQuotes[iCnt++].sItem = CALICO_960_UB;
gNewGunQuotes[iCnt++].sItem = PSG1_UB;
gNewGunQuotes[iCnt++].sItem = L85_UB;
gNewGunQuotes[iCnt++].sItem = TAR21_UB;
gNewGunQuotes[iCnt++].sItem = VAL_SILENT_UB;
gNewGunQuotes[iCnt++].sItem = MICRO_UZI_UB;
gNewGunQuotes[iCnt++].sItem = HAND_CANNON;
gNewGunQuotes[iCnt++].sItem = CALICO_950_UB;
gNewGunQuotes[iCnt++].sItem = CALICO_900_UB;
}
BOOLEAN IsThisGunANewJa25Gun( INT32 iItemIndex )
{
//if this gun ISNT a new gun
if( !( iItemIndex == BARRETT_UB ||
iItemIndex == CALICO_960_UB ||
iItemIndex == PSG1_UB ||
iItemIndex == L85_UB ||
iItemIndex == TAR21_UB ||
iItemIndex == VAL_SILENT_UB ||
iItemIndex == MICRO_UZI_UB ||
iItemIndex == HAND_CANNON ||
iItemIndex == CALICO_950_UB ||
iItemIndex == CALICO_900_UB ) )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN HasNewGunQuoteBeenPlayedForThisGun( INT32 iItemIndex )
{
INT32 iCnt;
for( iCnt=0; iCnt<NUM_NEW_GUN_QUOTES; iCnt++)
{
//if this is the item
if( gNewGunQuotes[ iCnt ].sItem == iItemIndex )
{
//return wether it has been said
return( gNewGunQuotes[ iCnt ].fHasBeenSaid );
}
}
return( TRUE );
}
void SetNewGunQuoteToBePlayedForThisGun( INT32 iItemIndex )
{
INT32 iCnt;
for( iCnt=0; iCnt<NUM_NEW_GUN_QUOTES; iCnt++)
{
//if this is the item
if( gNewGunQuotes[ iCnt ].sItem == iItemIndex )
{
gNewGunQuotes[ iCnt ].fHasBeenSaid = TRUE;
return;
}
}
}
void HandlePickingUpMorrisInstructionNote( SOLDIERTYPE *pSoldier, INT32 iIndex )
{
if( iIndex != MORRIS_INSTRUCTION_NOTE )
{
return;
}
/*
//if the note has already been picked up by a new merc, or the not ehas been displayed
if( gJa25SaveStruct.ubMorrisNoteState == MN__PICKED_UP_BY_NEW_MERC ||
gJa25SaveStruct.ubMorrisNoteState == MN__FINISHED )
{
return;
}
*/
INT16 bID = RandomSoldierIdFromNewMercsOnPlayerTeam();
//if this is a qualified merc on the team
if( IsSoldierQualifiedMerc( pSoldier ) )
{
//Remember we said the quote
gJa25SaveStruct.ubMorrisNoteState = MN__PICKED_UP_BY_NEW_MERC;
//Delaying the merc to say the note
DelayedMercQuote( pSoldier->ubProfile, DQ__NEW_MERC_SAY_NOTE_QUOTES, GetWorldTotalSeconds()+1 );
}
//else if there is a new merc on the team
else if( bID != -1 )
{
UINT32 uiTime=0;
if( gJa25SaveStruct.ubMorrisNoteState == MN__PICKED_UP_BY_OLD_MERC_SAID_QUOTE_ALREADY )
{
return;
}
//the merc is not a new merc
gJa25SaveStruct.ubMorrisNoteState = MN__PICKED_UP_BY_OLD_MERC_SAID_QUOTE_ALREADY;
TacticalCharacterDialogue( &Menptr[ bID ], QUOTE_RENEWING_CAUSE_BUDDY_1_ON_TEAM );
gJa25SaveStruct.bNewMercProfileIDForSayingMorrisNote = bID;
//if we are in turnbased combat
if( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
{
uiTime = GetWorldTotalSeconds() + 3;
}
else
{
uiTime = GetWorldTotalSeconds() + 10;
}
DelayedMercQuote( NOBODY, DQ__MORRIS_NOTE_NEW_MERC_DELAY, uiTime );
}
else
{
//
// Create a merc popup box that will display a message telling player what to do
//
gJa25SaveStruct.bNewMercProfileIDForSayingMorrisNote = pSoldier->ubProfile;
DelayedMercQuote( pSoldier->ubProfile, DQ__MORRIS_NOTE_DISPLAY_NOTE_1, GetWorldTotalSeconds() + 1 );
gJa25SaveStruct.ubMorrisNoteState = MN__FINISHED;
}
}
void HandleDeathInPowerGenSector( SOLDIERTYPE *pSoldier )
{
//if this is NOT the power gen sector J13
if( gWorldSectorX != SECTOR_FAN_X || gWorldSectorY != SECTOR_FAN_Y || gbWorldSectorZ != SECTOR_FAN_Z )
{
return;
}
else
{
BOOLEAN fFoundValidEnemy=FALSE;
UINT8 ubNumFlagedEnemiesInSector=0;
UINT32 sRandomSlotGridNo;
UINT8 uiCnt;
//SOLDIERINITNODE *pInitListSoldier;
#define NUM_ENEMIES_SLOTS 4
UINT32 sEnemyPlacementGridNo[ NUM_ENEMIES_SLOTS ]=
{
POWERGENSECTOR_GRIDNO1,
POWERGENSECTOR_GRIDNO2,
POWERGENSECTOR_GRIDNO3,
POWERGENSECTOR_GRIDNO4,
};
//
// Count number of Flaged guys still left
//
for( uiCnt=0; uiCnt<NUM_ENEMIES_SLOTS; uiCnt++ )
{
//Choose a random ID
sRandomSlotGridNo = sEnemyPlacementGridNo[ uiCnt ];
//is this soldier still alive
if( IsSoldierAliveWithInitListGridNo( sRandomSlotGridNo ) )
{
ubNumFlagedEnemiesInSector++;
}
}
/*
//
// Chooose a random slot ID for the enemy
//
for( uiCnt=0; uiCnt<50; uiCnt++ )
{
//Choose a random ID
sRandomSlotGridNo = sEnemyPlacementGridNo[ Random( NUM_ENEMIES_SLOTS ) ];
//is this soldier still alive
if( IsSoldierAliveWithInitListGridNo( sRandomSlotGridNo ) )
{
pInitListSoldier = FindSoldierInitNodeWithID( pSoldier->ubID );
//is this the same soldier
if( pInitListSoldier && pInitListSoldier->pBasicPlacement->usStartingGridNo == sRandomSlotGridNo )
{
fFoundValidEnemy = TRUE;
}
//we are done,
break;
}
}
*/
// if we found an enemy, or this is the 2nd last enemy in the sector
if( fFoundValidEnemy || ubNumFlagedEnemiesInSector <= 2 )
{
StopPowerGenFan();
}
}
}
BOOLEAN IsSoldierAliveWithInitListGridNo( INT16 sInitListGridNo )
{
SOLDIERINITNODE *curr;
curr = gSoldierInitHead;
while( curr )
{
if( curr->pBasicPlacement->usStartingGridNo == sInitListGridNo && curr->pSoldier != NULL )
{
if ( curr->pSoldier->stats.bLife >= OKLIFE )
{
return( TRUE );
}
}
curr = curr->next;
}
return( FALSE );
}
#define JA25__MAX_EXP_DECREASE (-2)
#define JA25__MIN_EXP_LEVEL_AFTER_CHANGE (2)
void HandleJa25EnemyExpLevelModifier( )
{
INT8 bPlayerExpLevel=0;
INT8 bEnemyExpLevel=0;
INT8 bDifference=0;
if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
{
return;
}
//if there are no enemies
if( NumEnemyInSector() == 0 )
{
//get out
return;
}
switch( gGameOptions.ubDifficultyLevel )
{
case DIF_LEVEL_EASY:
//Get the 2nd highest player exp level
bPlayerExpLevel = JA25SecondHighestExpLevelOnPlayersTeam( );
//get the enemies exp level
bEnemyExpLevel = JA25SecondHighestExpLevelOnEnemiesTeam( );
//get the difference b/n the 2
bDifference = bPlayerExpLevel - bEnemyExpLevel;
//if the players exp level is less then enemies
if( bDifference < 0 )
{
//if the difference
if( bDifference < JA25__MAX_EXP_DECREASE )
{
bDifference = JA25__MAX_EXP_DECREASE;
}
//Degrade all the enemies exp levels by difference
Ja25ScaleAllEnemiesByValue( bDifference );
}
break;
case DIF_LEVEL_MEDIUM:
//if the player imported the save
if( gJa25SaveStruct.fImportCharactersFromOldJa2Save )
{
//Get the 2nd highest player exp level
bPlayerExpLevel = JA25SecondHighestExpLevelOnPlayersTeam( );
//get the best enemies exp level
bEnemyExpLevel = JA25HighestExpLevelOnTeam( ENEMY_TEAM );
//get the difference b/n the 2
bDifference = bPlayerExpLevel - bEnemyExpLevel;
//if the players exp level is greater then enemies
if( bDifference > 0 )
{
//Upgrade all the enemies exp levels by difference
Ja25ScaleAllEnemiesByValue( bDifference );
}
}
break;
case DIF_LEVEL_HARD:
//Get the highest player exp level
bPlayerExpLevel = JA25HighestExpLevelOnTeam( OUR_TEAM );
//get the best enemies exp level
bEnemyExpLevel = JA25HighestExpLevelOnTeam( ENEMY_TEAM );
//get the difference b/n the 2
bDifference = bPlayerExpLevel - bEnemyExpLevel;
//if the players exp level is greater then enemies
if( bDifference > 0 )
{
//if the player imported the save
if( gJa25SaveStruct.fImportCharactersFromOldJa2Save )
{
//Upgrade all the enemies exp levels by difference
Ja25ScaleAllEnemiesByValue( bDifference );
}
else
{
//Upgrade all the enemies exp levels by 1
Ja25ScaleAllEnemiesByValue( 1 );
}
}
break;
default:
//Get the 2nd highest player exp level
bPlayerExpLevel = JA25SecondHighestExpLevelOnPlayersTeam( );
//get the enemies exp level
bEnemyExpLevel = JA25SecondHighestExpLevelOnEnemiesTeam( );
//get the difference b/n the 2
bDifference = bPlayerExpLevel - bEnemyExpLevel;
//if the players exp level is less then enemies
if( bDifference < 0 )
{
//if the difference
if( bDifference < JA25__MAX_EXP_DECREASE )
{
bDifference = JA25__MAX_EXP_DECREASE;
}
//Degrade all the enemies exp levels by difference
Ja25ScaleAllEnemiesByValue( bDifference );
}
break;
}
}
INT8 JA25HighestExpLevelOnTeam( INT8 bTeam )
{
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
INT8 bHighestExpLevel=0;
cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; cnt++, pSoldier++)
{
if( pSoldier->bActive )
{
if( bHighestExpLevel < pSoldier->stats.bExpLevel )
{
bHighestExpLevel = pSoldier->stats.bExpLevel;
}
}
}
return( bHighestExpLevel );
}
INT8 JA25SecondHighestExpLevelOnPlayersTeam( )
{
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
INT8 bHighestExpLevel=0;
INT8 b2ndHighestExpLevel=0;
INT8 bNumber=0;
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++, pSoldier++)
{
if( pSoldier->bActive )
{
if( bHighestExpLevel < pSoldier->stats.bExpLevel )
{
bHighestExpLevel = pSoldier->stats.bExpLevel;
}
else if( b2ndHighestExpLevel < pSoldier->stats.bExpLevel )
{
b2ndHighestExpLevel = pSoldier->stats.bExpLevel;
}
}
}
//Count number of people on team with same EXP level
bNumber = CountNumberOfMercsOnSameTeamOfSameExpLevel( OUR_TEAM, bHighestExpLevel );
//if there are more then 2 mercs on the team with the same high exp level
if( bNumber >= 2 )
{
//use the highest exp level
b2ndHighestExpLevel = bHighestExpLevel;
}
else
{
//else we are to only decuct 1 exp level from the main guy so there isnt a HUGE descrepincy b/n 1 super merc
//and a bunch of low level losers on a team
b2ndHighestExpLevel = bHighestExpLevel - 1;
}
return( b2ndHighestExpLevel );
}
INT8 JA25SecondHighestExpLevelOnEnemiesTeam( )
{
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
INT8 bHighestExpLevel=0;
INT8 b2ndHighestExpLevel=0;
INT8 bNumber=0;
//Get the highest exp level on the enemy team
bHighestExpLevel = JA25HighestExpLevelOnTeam( ENEMY_TEAM );
//Count number of people on team with same EXP level
bNumber = CountNumberOfMercsOnSameTeamOfSameExpLevel( ENEMY_TEAM, bHighestExpLevel );
//if there are more then 2 enemies at the high exp level
if( bNumber > 2 )
{
//use the highest value
b2ndHighestExpLevel = bHighestExpLevel;
}
else
{
//otherwise loop through and determine the second highest exp level
cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++, pSoldier++)
{
if( pSoldier->bActive )
{
//if the exp level is less then the highest
if( pSoldier->stats.bExpLevel < bHighestExpLevel )
{
//is this a new second highest level
if( b2ndHighestExpLevel < pSoldier->stats.bExpLevel )
{
b2ndHighestExpLevel = pSoldier->stats.bExpLevel;
}
}
}
}
}
return( b2ndHighestExpLevel );
}
void Ja25ScaleAllEnemiesByValue( INT8 bExpScaleValue )
{
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
INT8 bNewExpLevel=0;
cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++, pSoldier++)
{
if( pSoldier->bActive )
{
bNewExpLevel = pSoldier->stats.bExpLevel + bExpScaleValue;
if( bNewExpLevel > 10 )
{
bNewExpLevel = 10;
}
//else if the new value will bring it below 1
else if( bNewExpLevel < 1 )
{
bNewExpLevel = 1;
}
//if the enemy originally had a higher exp level AND will now go below set level
else if( pSoldier->stats.bExpLevel > JA25__MIN_EXP_LEVEL_AFTER_CHANGE && bNewExpLevel < JA25__MIN_EXP_LEVEL_AFTER_CHANGE )
{
bNewExpLevel = JA25__MIN_EXP_LEVEL_AFTER_CHANGE;
}
pSoldier->stats.bExpLevel = bNewExpLevel;
}
}
}
INT8 CountNumberOfMercsOnSameTeamOfSameExpLevel( INT8 bTeam, INT8 bExpLevel )
{
INT8 bNumber=0;
SOLDIERTYPE *pSoldier=NULL;
INT32 cnt;
cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; cnt++, pSoldier++)
{
if( pSoldier->bActive )
{
if( bExpLevel == pSoldier->stats.bExpLevel )
{
bNumber++;
}
}
}
return( bNumber );
}
INT8 RandomSoldierIdForAnyMercInSector()
{
UINT8 SoldierIdArray[18];
UINT8 ubNumMercsInSector=0;
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
UINT8 ubCount=0;
ubNumMercsInSector = PlayerMercsInSector( (UINT8)gWorldSectorX, (UINT8)gWorldSectorY, gbWorldSectorZ );
if( ubNumMercsInSector == 0 )
{
return( -1 );
}
memset( SoldierIdArray, 0, 18 );
//loop through the merc array and fill in the soldier id
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++)
{
//if the soldier is in the sector
if( pSoldier->bActive && pSoldier->bInSector && ( pSoldier->stats.bLife >= CONSCIOUSNESS ) &&
!( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !AM_A_ROBOT( pSoldier ) )
{
SoldierIdArray[ ubCount++ ] = cnt;
}
}
return( SoldierIdArray[ Random( ubCount ) ] );
}
void HandleFanStartingAtEndOfCombat()
{
//if its not the right sector
if( !( gWorldSectorX == SECTOR_FAN_X && gWorldSectorY == SECTOR_FAN_Y && gbWorldSectorZ == SECTOR_FAN_Z ) )
{
//leave
return;
}
//if the fan is not stopped
if( gJa25SaveStruct.ubStateOfFanInPowerGenSector != PGF__STOPPED )
{
//leave
return;
}
StartFanBackUpAgain();
}
void HandleInitialEventsInHeliCrash()
{
SOLDIERTYPE *pSoldier=NULL;
INT32 cnt;
//first, loop through all the mercs and injure them
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++)
{
//if the merc is alive
if( pSoldier->bActive )
{
pSoldier->stats.bLife -= ( 3 + Random( 5 ) );
pSoldier->sBreathRed = ( 15 + Random( 15 ) ) * 100;
pSoldier->bActionPoints = 0;
}
}
/*
#ifdef JA2TESTVERSION
//Add a smoke effect behind the heli
NewSmokeEffect( 15102, SMOKE_GRENADE, 0, NOBODY );
#endif
*/
}
UINT32 GetNumberOfTurnsPowerGenFanWillBeStoppedFor()
{
return( zDiffSetting[gGameOptions.ubDifficultyLevel].iGetNumberOfTurnsPowerGenFanWillBeStoppedFor );
}
void DisplayCommanderMorrisNote( SOLDIERTYPE *pSoldier )
{
CHAR16 zString[1024];
if( gJa25SaveStruct.ubDisplayCommanderMorrisNote == DMN__FINISHED )
{
return;
}
if( pSoldier == NULL )
{
return;
}
//if it si the first part of the note to be displayed
if( gJa25SaveStruct.ubDisplayCommanderMorrisNote == DMN__NOT_TO_DISPLAY_IT )
{
gJa25SaveStruct.ubDisplayCommanderMorrisNote = DMN__DISPLAY_PART_1;
swprintf( zString, zNewTacticalMessages[ TCTL_MSG__END_GAME_POPUP_TXT_1 ], pSoldier->GetName() );
}
//if it si the second part of the note to be displayed
else if( gJa25SaveStruct.ubDisplayCommanderMorrisNote == DMN__DISPLAY_PART_1 )
{
gJa25SaveStruct.ubDisplayCommanderMorrisNote = DMN__DISPLAY_PART_2;
swprintf( zString, zNewTacticalMessages[ TCTL_MSG__END_GAME_POPUP_TXT_2 ], pSoldier->GetName(), pSoldier->GetName() );
}
//Display it
ExecuteTacticalTextBox( 110, zString );
}
void HandleCommanderMorrisNewMercWantsNoteDelayedSpeech()
{
//if the note has already been picked up by a new merc, or the note has been displayed
if( gJa25SaveStruct.ubMorrisNoteState == MN__PICKED_UP_BY_NEW_MERC ||
gJa25SaveStruct.ubMorrisNoteState == MN__FINISHED )
{
return;
}
//if the original merc who said the quote is valid
INT16 bID = gJa25SaveStruct.bNewMercProfileIDForSayingMorrisNote;
if( bID != -1 && IsSoldierQualifiedMerc( &Menptr[ bID ] ) )
{
}
else
{
bID = RandomSoldierIdFromNewMercsOnPlayerTeam();
if( bID != -1 )
{
gJa25SaveStruct.bNewMercProfileIDForSayingMorrisNote = bID;
}
else
{
return;
}
}
TacticalCharacterDialogue( &Menptr[ bID ], QUOTE_RENEWING_CAUSE_BUDDY_1_ON_TEAM );
}
void HandleShowingRadioLocatorsInMorrisArea()
{
//Reveal the switch in Morris area
HandleOpenControlPanelToRevealSwitchInMorrisArea();
//control panel locater
BeginMultiPurposeLocator( RADIOLOCATORS_GRIDNO1, 0, TRUE );
//if we are not in combat
if( !((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) )
{
DelayedMercQuote( RADIOLOCATORS_GRIDNO2, DQ__SHOW_RADIO_LOCATOR, GetWorldTotalSeconds() + 3 );
}
}
void HandleNewMercSayingContentsOfMorrisNote( SOLDIERTYPE *pSoldier )
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_LEAVING_ALSUCO_SOON );
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE );
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_JERRY_MILO, JM_SE__SHOW_RADIO_LOCATOR, 0, 0, 0, DIALOGUE_TACTICAL_UI );
}
void HandlePlayerHittingSwitchToLaunchMissles()
{
INT32 cnt;
SOLDIERTYPE *pSoldier=NULL;
//
// The player Just won the game, remeber this
//
gGameSettings.fPlayerFinishedTheGame = TRUE;
SaveGameSettings();
SaveFeatureFlags();
//Update the quest log
InternalEndQuest( QUEST_DESTROY_MISSLES, -1, -1, TRUE );
//lock the interface
guiPendingOverrideEvent = LU_BEGINUILOCK;
HandleTacticalUI( );
//
// Loop through all the mercs in the sector and make them run to the elevator
//
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pSoldier++)
{
// if the soldier was in the complex
if( pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE && pSoldier->bInSector &&
pSoldier->sSectorX == SECTOR_LAUNCH_MISSLES_X && pSoldier->sSectorY == SECTOR_LAUNCH_MISSLES_Y && pSoldier->bSectorZ == SECTOR_LAUNCH_MISSLES_Z )
{
if( PythSpacesAway( pSoldier->sGridNo, SWITCHTOLAUNCHMISSLES_GRIDNO1 ) < PythSpacesAway( pSoldier->sGridNo, SWITCHTOLAUNCHMISSLES_GRIDNO2 ) )
pSoldier->EVENT_InternalGetNewSoldierPath( SWITCHTOLAUNCHMISSLES_GRIDNO1, RUNNING, TRUE, TRUE );
else
pSoldier->EVENT_InternalGetNewSoldierPath( SWITCHTOLAUNCHMISSLES_GRIDNO2, RUNNING, TRUE, TRUE );
}
}
//Start a timer so we can fade out
DelayedMercQuote( NOBODY, DQ__FADE_OUT_TO_END_GAME_CINEMATIC, GetWorldTotalSeconds()+2 );
}
void HandleFadingOutToEndGameCinematics()
{
gFadeOutDoneCallback = DoneFadeOutEndCinematic;
FadeOutGameScreen( );
// UnLock UI!
guiPendingOverrideEvent = LU_ENDUILOCK;
HandleTacticalUI( );
}
void HandleOpenControlPanelToRevealSwitchInMorrisArea()
{
//if the note has already been picked up by a new merc, or the note has been displayed
if( gJa25SaveStruct.ubMorrisNoteState == MN__PICKED_UP_BY_NEW_MERC ||
gJa25SaveStruct.ubMorrisNoteState == MN__FINISHED )
{
STRUCTURE * pStructure;
INT32 iItemIndex;
ITEM_POOL * pItemPool;
// first, find the switch item and turn off its trap level
if ( ItemTypeExistsAtLocation( SWITCHINMORRISAREA_GRIDNO, SWITCH, 0, &iItemIndex ) )
{
//gWorldItems[ iItemIndex ]->data.bTrap = 0;
gWorldItems[ iItemIndex ].object[0]->data.bTrap = 0;
GetItemPool( SWITCHINMORRISAREA_GRIDNO, &pItemPool, 0 );
if ( pItemPool )
{
SetItemPoolVisibilityOn( pItemPool, ANY_VISIBILITY_VALUE, FALSE );
}
}
//Open up the Control Panel so the switch is visibile
pStructure = FindStructure( SWITCHINMORRISAREA_GRIDNO, STRUCTURE_GENERIC );
if( pStructure == NULL )
{
return;
}
if( SwapStructureForPartnerForcingGraphicalChange( SWITCHINMORRISAREA_GRIDNO, pStructure ) == NULL )
{
//an error occured
return;
}
}
}
#endif