Files
source/Tactical/End Game.cpp
T
Wanne 91087ca8c0 ************************************************************
* Merged Source Code from Development Trunk: Revision 4063 *
************************************************************
- Source Code is merged from: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP
- This will be the Source for the Beta 2011 Test

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4064 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2011-01-18 09:11:09 +00:00

505 lines
14 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "PreBattle Interface.h"
#include "Intro.h"
#else
#include "Overhead.h"
#include "Boxing.h"
#include "Render Fun.h"
#include "Random.h"
#include "Worldman.h"
#include "Soldier Profile.h"
#include "NPC.h"
#include "Opplist.h"
#include "ai.h"
#include "Dialogue Control.h"
#include "Handle UI.h"
#include "Points.h"
#include "interface.h"
#include "end game.h"
#include "Intro.h"
#include "Exit Grids.h"
#include "strategicmap.h"
#include "Quests.h"
#include "SaveLoadMap.h"
#include "Sound Control.h"
#include "renderworld.h"
#include "Isometric Utils.h"
#include "Music Control.h"
#include "Soldier macros.h"
#include "qarray.h"
#include "los.h"
#include "Strategic AI.h"
#include "Squads.h"
#include "PreBattle Interface.h"
#include "Strategic Movement.h"
#include "strategic.h"
#include "Morale.h"
#include "Queen Command.h"
#include "Strategic Town Loyalty.h"
#include "Player Command.h"
#include "Campaign Types.h"
#include "Tactical Save.h"
#include "screenids.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
INT32 sStatueGridNos[] = { 13829, 13830, 13669, 13670 };
SOLDIERTYPE *gpKillerSoldier = NULL;
INT32 gsGridNo;
INT8 gbLevel;
// This function checks if our statue exists in the current sector at given gridno
BOOLEAN DoesO3SectorStatueExistHere( INT32 sGridNo )
{
INT32 cnt;
EXITGRID ExitGrid;
// First check current sector......
if ( gWorldSectorX == 3 && gWorldSectorY == MAP_ROW_O && gbWorldSectorZ == 0 )
{
// Check for exitence of and exit grid here...
// ( if it doesn't then the change has already taken place )
if ( !GetExitGrid( 13669, &ExitGrid ) )
{
for ( cnt = 0; cnt < 4; cnt++ )
{
if ( sStatueGridNos[ cnt ] == sGridNo )
{
return( TRUE );
}
}
}
}
return( FALSE );
}
// This function changes the graphic of the statue and adds the exit grid...
void ChangeO3SectorStatue( BOOLEAN fFromExplosion )
{
EXITGRID ExitGrid;
UINT16 usTileIndex;
INT16 sX, sY;
// Remove old graphic
ApplyMapChangesToMapTempFile( TRUE );
// Remove it!
// Get index for it...
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 5 ), &usTileIndex );
RemoveStruct( 13830, usTileIndex );
// Add new one...
if ( fFromExplosion )
{
// Use damaged peice
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 7 ), &usTileIndex );
}
else
{
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 8 ), &usTileIndex );
// Play sound...
PlayJA2Sample( OPEN_STATUE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
}
AddStructToHead( 13830, usTileIndex );
// Add exit grid
ExitGrid.ubGotoSectorX = 3;
ExitGrid.ubGotoSectorY = MAP_ROW_O;
ExitGrid.ubGotoSectorZ = 1;
ExitGrid.usGridNo = 13037; //dnl!!!
AddExitGridToWorld( 13669, &ExitGrid );
gpWorldLevelData[ 13669 ].uiFlags |= MAPELEMENT_REVEALED;
// Turn off permenant changes....
ApplyMapChangesToMapTempFile( FALSE );
// Re-render the world!
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
// FOR THE NEXT RENDER LOOP, RE-EVALUATE REDUNDENT TILES
InvalidateWorldRedundency( );
SetRenderFlags(RENDER_FLAG_FULL);
// Redo movement costs....
ConvertGridNoToXY( 13830, &sX, &sY );
RecompileLocalMovementCostsFromRadius( 13830, 5 );
}
void DeidrannaTimerCallback( void )
{
HandleDeidrannaDeath( gpKillerSoldier, gsGridNo, gbLevel );
}
void BeginHandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel )
{
gpKillerSoldier = pKillerSoldier;
gsGridNo = sGridNo;
gbLevel = bLevel;
// Lock the UI.....
gTacticalStatus.uiFlags |= ENGAGED_IN_CONV;
// Increment refrence count...
giNPCReferenceCount = 1;
gTacticalStatus.uiFlags |= IN_DEIDRANNA_ENDGAME;
SetCustomizableTimerCallbackAndDelay( 2000, DeidrannaTimerCallback, FALSE );
}
void HandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
UINT8 ubKillerSoldierID = NOBODY;
// Start victory music here...
SetMusicMode( MUSIC_TACTICAL_VICTORY );
if ( pKillerSoldier )
{
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLING_DEIDRANNA );
ubKillerSoldierID = pKillerSoldier->ubID;
}
// STEP 1 ) START ALL QUOTES GOING!
// OK - loop through all witnesses and see if they want to say something abou this...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
{
if ( cnt != ubKillerSoldierID )
{
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
{
if ( QuoteExp[ pTeamSoldier->ubProfile ].QuoteExpWitnessDeidrannaDeath )
{
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
TacticalCharacterDialogue( pTeamSoldier, QUOTE_KILLING_DEIDRANNA );
}
}
}
}
}
// Set fact that she is dead!
SetFactTrue( FACT_QUEEN_DEAD );
ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_QUEEN_DEAD, 0, 0 );
// AFTER LAST ONE IS DONE - PUT SPECIAL EVENT ON QUEUE TO BEGIN FADE< ETC
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, MULTIPURPOSE_SPECIAL_EVENT_DONE_KILLING_DEIDRANNA, 0,0,0,0 );
}
void DoneFadeInKilledQueen( void )
{
SOLDIERTYPE *pNPCSoldier;
// Locate gridno.....
// Run NPC script
pNPCSoldier = FindSoldierByProfileID( 136, FALSE );
if ( !pNPCSoldier )
{
return;
}
// Converse!
//InitiateConversation( pNPCSoldier, pSoldier, 0, 1 );
TriggerNPCRecordImmediately( pNPCSoldier->ubProfile, 6 );
}
void DoneFadeOutKilledQueen( void )
{
INT32 cnt;
SOLDIERTYPE *pSoldier, *pTeamSoldier;
// For one, loop through our current squad and move them over
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// look for all mercs on the same team,
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
{
// Are we in this sector, On the current squad?
if ( pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE && pSoldier->bInSector && pSoldier->bAssignment == CurrentSquad( ) )
{
gfTacticalTraversal = TRUE;
SetGroupSectorValue( 3, MAP_ROW_P, 0, pSoldier->ubGroupID );
// Set next sectore
pSoldier->sSectorX = 3;
pSoldier->sSectorY = MAP_ROW_P;
pSoldier->bSectorZ = 0;
// Set gridno
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
pSoldier->usStrategicInsertionData = 5687;//dnl!!!
// Set direction to face....
pSoldier->ubInsertionDirection = 100 + NORTHWEST;
}
}
// Kill all enemies in world.....
cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
// look for all mercs on the same team,
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++,pTeamSoldier++)
{
// Are we active and in sector.....
if ( pTeamSoldier->bActive )
{
// For sure for flag thet they are dead is not set
// Check for any more badguys
// ON THE STRAGETY LAYER KILL BAD GUYS!
if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) )
{
ProcessQueenCmdImplicationsOfDeath( pTeamSoldier );
}
}
}
// 'End' battle
ExitCombatMode();
gTacticalStatus.fLastBattleWon = TRUE;
// Set enemy presence to false
gTacticalStatus.fEnemyInSector = FALSE;
SetMusicMode( MUSIC_TACTICAL_VICTORY );
HandleMoraleEvent( NULL, MORALE_QUEEN_BATTLE_WON, 3, MAP_ROW_P, 0 );
HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_QUEEN_BATTLE_WON, 3, MAP_ROW_P, 0 );
SetMusicMode( MUSIC_TACTICAL_VICTORY );
SetThisSectorAsPlayerControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE );
// ATE: Force change of level set z to 1
gbWorldSectorZ = 1;
// Clear out dudes.......
SectorInfo[ SEC_P3 ].ubNumAdmins = 0;
SectorInfo[ SEC_P3 ].ubNumTroops = 0;
SectorInfo[ SEC_P3 ].ubNumElites = 0;
SectorInfo[ SEC_P3 ].ubAdminsInBattle = 0;
SectorInfo[ SEC_P3 ].ubTroopsInBattle = 0;
SectorInfo[ SEC_P3 ].ubElitesInBattle = 0;
// ATE: GEt rid of elliot in P3...
gMercProfiles[ ELLIOT ].sSectorX = 1;
ChangeNpcToDifferentSector( DEREK, 3, MAP_ROW_P, 0 );
ChangeNpcToDifferentSector( OLIVER, 3, MAP_ROW_P, 0 );
// OK, insertion data found, enter sector!
SetCurrentWorldSector( 3, MAP_ROW_P, 0 );
// OK, once down here, adjust the above map with crate info....
gfTacticalTraversal = FALSE;
gpTacticalTraversalGroup = NULL;
gpTacticalTraversalChosenSoldier = NULL;
gFadeInDoneCallback = DoneFadeInKilledQueen;
FadeInGameScreen( );
}
// Called after all player quotes are done....
void HandleDoneLastKilledQueenQuote( )
{
gFadeOutDoneCallback = DoneFadeOutKilledQueen;
FadeOutGameScreen( );
}
void EndQueenDeathEndgameBeginEndCimenatic( )
{
INT32 cnt;
SOLDIERTYPE *pSoldier;
// Start end cimimatic....
gTacticalStatus.uiFlags |= IN_ENDGAME_SEQUENCE;
// first thing is to loop through team and say end quote...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// look for all mercs on the same team,
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
{
// Are we in this sector, On the current squad?
if ( pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE && !AM_AN_EPC( pSoldier ) )
{
TacticalCharacterDialogue( pSoldier, QUOTE_END_GAME_COMMENT );
}
}
// Add queue event to proceed w/ smacker cimimatic
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, MULTIPURPOSE_SPECIAL_EVENT_TEAM_MEMBERS_DONE_TALKING, 0,0,0,0 );
}
void EndQueenDeathEndgame( )
{
// Unset flags...
gTacticalStatus.uiFlags &= (~ENGAGED_IN_CONV );
// Increment refrence count...
giNPCReferenceCount = 0;
gTacticalStatus.uiFlags &= (~IN_DEIDRANNA_ENDGAME);
}
void DoneFadeOutEndCinematic( void )
{
// DAVE PUT SMAKER STUFF HERE!!!!!!!!!!!!
// :)
gTacticalStatus.uiFlags &= (~IN_ENDGAME_SEQUENCE);
// For now, just quit the freaken game...
// InternalLeaveTacticalScreen( MAINMENU_SCREEN );
InternalLeaveTacticalScreen( INTRO_SCREEN );
// guiCurrentScreen = INTRO_SCREEN;
SetIntroType( INTRO_ENDING );
}
// OK, end death UI - fade to smaker....
void HandleDoneLastEndGameQuote( )
{
EndQueenDeathEndgame( );
gFadeOutDoneCallback = DoneFadeOutEndCinematic;
FadeOutGameScreen( );
}
void QueenBitchTimerCallback( void )
{
HandleQueenBitchDeath( gpKillerSoldier, gsGridNo, gbLevel );
}
void BeginHandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
gpKillerSoldier = pKillerSoldier;
gsGridNo = sGridNo;
gbLevel = bLevel;
// Lock the UI.....
gTacticalStatus.uiFlags |= ENGAGED_IN_CONV;
// Increment refrence count...
giNPCReferenceCount = 1;
// gTacticalStatus.uiFlags |= IN_DEIDRANNA_ENDGAME;
SetCustomizableTimerCallbackAndDelay( 3000, QueenBitchTimerCallback, FALSE );
// Kill all enemies in creature team.....
cnt = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID;
// look for all mercs on the same team,
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; cnt++,pTeamSoldier++)
{
// Are we active and ALIVE and in sector.....
if ( pTeamSoldier->bActive && pTeamSoldier->stats.bLife > 0 )
{
// For sure for flag thet they are dead is not set
// Check for any more badguys
// ON THE STRAGETY LAYER KILL BAD GUYS!
// HELLO! THESE ARE CREATURES! THEY CAN'T BE NEUTRAL!
//if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) )
{
// gTacticalStatus.ubAttackBusyCount++;
DebugAttackBusy( "Killing off a queen ally.\n");
pTeamSoldier->EVENT_SoldierGotHit( 0, 10000, 0, pTeamSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pTeamSoldier->bAimShotLocation, 0, NOWHERE );
}
}
}
}
void HandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT32 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
UINT8 ubKillerSoldierID = NOBODY;
// Start victory music here...
SetMusicMode( MUSIC_TACTICAL_VICTORY );
if ( pKillerSoldier )
{
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLING_QUEEN );
ubKillerSoldierID = pKillerSoldier->ubID;
}
// STEP 1 ) START ALL QUOTES GOING!
// OK - loop through all witnesses and see if they want to say something abou this...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
{
if ( cnt != ubKillerSoldierID )
{
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
{
if ( QuoteExp[ pTeamSoldier->ubProfile ].QuoteExpWitnessQueenBugDeath )
{
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
TacticalCharacterDialogue( pTeamSoldier, QUOTE_KILLING_QUEEN );
}
}
}
}
}
// Set fact that she is dead!
if ( CheckFact( FACT_QUEEN_DEAD, 0 ) )
{
EndQueenDeathEndgameBeginEndCimenatic( );
}
else
{
// Unset flags...
gTacticalStatus.uiFlags &= (~ENGAGED_IN_CONV );
// Increment refrence count...
giNPCReferenceCount = 0;
}
}