Files
source/Tactical/Merc Entering.cpp
T

814 lines
15 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "Tactical 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 "rotting corpses.h"
#include "tile cache.h"
#include "isometric utils.h"
#include "animation control.h"
#include "utilities.h"
#include "game clock.h"
#include "soldier create.h"
#include "renderworld.h"
#include "tile animation.h"
#include "merc entering.h"
#include "sound control.h"
#include "strategic.h"
#include "strategicmap.h"
#include "Handle UI.h"
#include "squads.h"
#include "english.h"
#include "cursors.h"
#include "cursor control.h"
#endif
#define MAX_MERC_IN_HELI 20
#define MAX_HELI_SCRIPT 30
#define ME_SCRIPT_DELAY 100
#define NUM_PER_HELI_RUN 6
enum
{
HELI_APPROACH,
HELI_MOVETO,
HELI_BEGINDROP,
HELI_DROP,
HELI_ENDDROP,
HELI_MOVEAWAY,
HELI_EXIT,
NUM_HELI_STATES
} HeliStateEnums;
enum
{
HELI_REST,
HELI_MOVE_DOWN,
HELI_MOVE_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVEY,
HELI_MOVELARGERY,
HELI_HANDLE_DROP,
HELI_SHOW_HELI,
HELI_GOTO_BEGINDROP,
HELI_GOTO_DROP,
HELI_GOTO_EXIT,
HELI_GOTO_MOVETO,
HELI_GOTO_MOVEAWAY,
HELI_DONE,
} HeliCodes;
UINT8 ubHeliScripts[ NUM_HELI_STATES ][ MAX_HELI_SCRIPT ] =
{
// HELI_APPROACH
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_GOTO_MOVETO,
// MOVE TO
HELI_SHOW_HELI,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_GOTO_BEGINDROP,
// HELI_BEGIN_DROP
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_GOTO_DROP,
// Heli Begin Drop
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_GOTO_DROP,
// HELI END DROP
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_GOTO_MOVEAWAY,
// MOVE AWAY
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_GOTO_EXIT,
// HELI EXIT
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_DONE,
};
BOOLEAN gfHandleHeli = FALSE;
UINT8 gusHeliSeats[ MAX_MERC_IN_HELI ];
INT8 gbNumHeliSeatsOccupied = 0;
BOOLEAN gfFirstGuyDown = FALSE;
UINT32 uiSoundSample;
INT16 gsGridNoSweetSpot;
INT16 gsHeliXPos;
INT16 gsHeliYPos;
FLOAT gdHeliZPos;
INT16 gsHeliScript;
UINT8 gubHeliState;
UINT32 guiHeliLastUpdate;
INT8 gbCurDrop;
INT8 gbExitCount;
INT8 gbHeliRound;
BOOLEAN fFadingHeliIn = FALSE;
BOOLEAN fFadingHeliOut = FALSE;
BOOLEAN gfIngagedInDrop = FALSE;
ANITILE *gpHeli;
BOOLEAN gfFirstHeliRun;
void HandleFirstHeliDropOfGame( );
void ResetHeliSeats( )
{
gbNumHeliSeatsOccupied = 0;
}
void AddMercToHeli( UINT8 ubID )
{
INT32 cnt;
if ( gbNumHeliSeatsOccupied < MAX_MERC_IN_HELI )
{
// Check if it already exists!
for ( cnt = 0; cnt < gbNumHeliSeatsOccupied; cnt++ )
{
if ( gusHeliSeats[ cnt ] == ubID )
{
return;
}
}
gusHeliSeats[ gbNumHeliSeatsOccupied ] = ubID;
gbNumHeliSeatsOccupied++;
}
}
void StartHelicopterRun( INT16 sGridNoSweetSpot )
{
INT16 sX, sY;
gsGridNoSweetSpot = sGridNoSweetSpot;
if ( gbNumHeliSeatsOccupied == 0 )
{
return;
}
InterruptTime();
PauseGame();
LockPauseState( 20 );
ConvertGridNoToCenterCellXY( sGridNoSweetSpot, &sX, &sY );
gsHeliXPos = sX - ( 2 * CELL_X_SIZE );
gsHeliYPos = sY - ( 10 * CELL_Y_SIZE );
//gsHeliXPos = sX - ( 3 * CELL_X_SIZE );
//gsHeliYPos = sY + ( 4 * CELL_Y_SIZE );
gdHeliZPos = 0;
gsHeliScript = 0;
gbCurDrop = 0;
gbExitCount = 0;
gbHeliRound = 1;
gubHeliState = HELI_APPROACH;
guiHeliLastUpdate = GetJA2Clock( );
// Start sound
uiSoundSample = PlayJA2Sample( HELI_1, RATE_11025, 0, 10000, MIDDLEPAN );
fFadingHeliIn = TRUE;
gfHandleHeli = TRUE;
gfFirstGuyDown = TRUE;
guiPendingOverrideEvent = LU_BEGINUILOCK;
}
void HandleHeliDrop( )
{
UINT8 ubScriptCode;
UINT32 uiClock;
//INT16 sWorldX, sWorldY;
INT32 iVol;
INT32 cnt;
ANITILE_PARAMS AniParams;
if ( gfHandleHeli )
{
if ( gCurrentUIMode != LOCKUI_MODE )
{
guiPendingOverrideEvent = LU_BEGINUILOCK;
}
if ( _KeyDown( ESC ) )
{
// Loop through all mercs not yet placed
for ( cnt = gbCurDrop; cnt < gbNumHeliSeatsOccupied; cnt++ )
{
// Add merc to sector
MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
UpdateMercInSector( MercPtrs[ gusHeliSeats[ cnt ] ], 9, 1, 0 );
// Check for merc arrives quotes...
HandleMercArrivesQuotes( MercPtrs[ gusHeliSeats[ cnt ] ] );
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[ MERC_HAS_ARRIVED_STR ], MercPtrs[ gusHeliSeats[ cnt ] ]->name );
}
// Remove heli
DeleteAniTile( gpHeli );
RebuildCurrentSquad( );
// Remove sound
if( uiSoundSample!=NO_SAMPLE )
{
SoundStop( uiSoundSample );
}
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
UnLockPauseState();
UnPauseGame();
// Select our first guy
SelectSoldier( gusHeliSeats[ 0 ], FALSE, TRUE );
//guiCurrentEvent = LU_ENDUILOCK;
//gCurrentUIMode = LOCKUI_MODE;
guiPendingOverrideEvent = LU_ENDUILOCK;
//UIHandleLUIEndLock( NULL );
HandleFirstHeliDropOfGame( );
return;
}
gfIgnoreScrolling = TRUE;
uiClock = GetJA2Clock( );
if ( ( uiClock - guiHeliLastUpdate ) > ME_SCRIPT_DELAY )
{
guiHeliLastUpdate = uiClock;
if(fFadingHeliIn)
{
if( uiSoundSample!=NO_SAMPLE )
{
iVol=SoundGetVolume( uiSoundSample );
iVol=__min( HIGHVOLUME, iVol+5);
SoundSetVolume(uiSoundSample, iVol);
if(iVol==HIGHVOLUME)
fFadingHeliIn=FALSE;
}
else
{
fFadingHeliIn=FALSE;
}
}
else if(fFadingHeliOut)
{
if( uiSoundSample!=NO_SAMPLE )
{
iVol=SoundGetVolume(uiSoundSample);
iVol=__max( 0, iVol-5);
SoundSetVolume(uiSoundSample, iVol);
if(iVol==0)
{
// Stop sound
SoundStop( uiSoundSample );
fFadingHeliOut=FALSE;
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
guiPendingOverrideEvent = LU_ENDUILOCK;
UnLockPauseState();
UnPauseGame();
RebuildCurrentSquad( );
HandleFirstHeliDropOfGame( );
}
}
else
{
fFadingHeliOut=FALSE;
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
guiPendingOverrideEvent = LU_ENDUILOCK;
UnLockPauseState();
UnPauseGame();
RebuildCurrentSquad( );
HandleFirstHeliDropOfGame( );
}
}
if ( gsHeliScript == MAX_HELI_SCRIPT )
{
return;
}
ubScriptCode = ubHeliScripts[ gubHeliState ][ gsHeliScript ];
// Switch on mode...
if ( gubHeliState == HELI_DROP )
{
if ( !gfIngagedInDrop )
{
INT8 bEndVal;
bEndVal = ( gbHeliRound * NUM_PER_HELI_RUN );
if ( bEndVal > gbNumHeliSeatsOccupied )
{
bEndVal = gbNumHeliSeatsOccupied;
}
// OK, Check if we have anybody left to send!
if ( gbCurDrop < bEndVal )
{
//sWorldX = CenterX( gsGridNoSweetSpot );
//sWorldY = CenterY( gsGridNoSweetSpot );
EVENT_InitNewSoldierAnim( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], HELIDROP, 0 , FALSE );
// Change insertion code
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
UpdateMercInSector( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], 9, 1, 0 );
//EVENT_SetSoldierPosition( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], sWorldX, sWorldY );
// IF the first guy down, set squad!
if ( gfFirstGuyDown )
{
gfFirstGuyDown = FALSE;
SetCurrentSquad( MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->bAssignment, TRUE );
}
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[ MERC_HAS_ARRIVED_STR ], MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->name );
gbCurDrop++;
gfIngagedInDrop = TRUE;
}
else
{
if( gbExitCount == 0 )
{
gbExitCount = 2;
}
else
{
gbExitCount--;
if ( gbExitCount == 1 )
{
// Goto leave
gsHeliScript = -1;
gubHeliState = HELI_ENDDROP;
}
}
}
}
}
switch( ubScriptCode )
{
case HELI_REST:
break;
case HELI_MOVE_DOWN:
gdHeliZPos -= 1;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVE_UP:
gdHeliZPos += 1;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVESMALL_DOWN:
gdHeliZPos -= 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVESMALL_UP:
gdHeliZPos += 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVEY:
gpHeli->sRelativeY += 4;
break;
case HELI_MOVELARGERY:
gpHeli->sRelativeY += 6;
break;
case HELI_GOTO_BEGINDROP:
gsHeliScript = -1;
gubHeliState = HELI_BEGINDROP;
break;
case HELI_SHOW_HELI:
// Start animation
memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
AniParams.sGridNo = gsGridNoSweetSpot;
AniParams.ubLevelID = ANI_SHADOW_LEVEL;
AniParams.sDelay = 90;
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_LOOPING;
AniParams.sX = gsHeliXPos;
AniParams.sY = gsHeliYPos;
AniParams.sZ = (INT16)gdHeliZPos;
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH.STI" );
gpHeli = CreateAnimationTile( &AniParams );
break;
case HELI_GOTO_DROP:
// Goto drop animation
gdHeliZPos -= 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
gsHeliScript = -1;
gubHeliState = HELI_DROP;
break;
case HELI_GOTO_MOVETO:
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_MOVETO;
break;
case HELI_GOTO_MOVEAWAY:
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_MOVEAWAY;
break;
case HELI_GOTO_EXIT:
if ( gbCurDrop < gbNumHeliSeatsOccupied )
{
// Start another run......
INT16 sX, sY;
ConvertGridNoToCenterCellXY( gsGridNoSweetSpot, &sX, &sY );
gsHeliXPos = sX - ( 2 * CELL_X_SIZE );
gsHeliYPos = sY - ( 10 * CELL_Y_SIZE );
gdHeliZPos = 0;
gsHeliScript = 0;
gbExitCount = 0;
gubHeliState = HELI_APPROACH;
gbHeliRound++;
// Ahh, but still delete the heli!
DeleteAniTile( gpHeli );
gpHeli = NULL;
}
else
{
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_EXIT;
// Delete helicopter image!
DeleteAniTile( gpHeli );
gpHeli = NULL;
gfIgnoreScrolling = FALSE;
// Select our first guy
SelectSoldier( gusHeliSeats[ 0 ], FALSE, TRUE );
}
break;
case HELI_DONE:
// End
fFadingHeliOut = TRUE;
break;
}
gsHeliScript++;
}
}
}
void BeginMercEntering( SOLDIERTYPE *pSoldier, INT16 sGridNo )
{
ResetHeliSeats( );
AddMercToHeli( pSoldier->ubID );
StartHelicopterRun( sGridNo );
// Make sure AI does nothing.....
PauseAIUntilManuallyUnpaused();
}
void HandleFirstHeliDropOfGame( )
{
// Are we in the first heli drop?
if ( gfFirstHeliRun )
{
SyncStrategicTurnTimes();
// Call people to area
CallAvailableEnemiesTo( gsGridNoSweetSpot );
// Say quote.....
SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE );
// Start music
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
gfFirstHeliRun = FALSE;
}
// Send message to turn on ai again....
CharacterDialogueWithSpecialEvent( 0, 0, 0 , DIALOGUE_TACTICAL_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_ENABLE_AI ,0, 0 );
}