1591 lines
44 KiB
C++
1591 lines
44 KiB
C++
|
/*
|
||
|
** Command & Conquer Renegade(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** Confidential - Westwood Studios ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : Commando *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Commando/combatgmode.cpp $*
|
||
|
* *
|
||
|
* $Author:: Steve_t $*
|
||
|
* *
|
||
|
* $Modtime:: 2/23/02 2:04p $*
|
||
|
* *
|
||
|
* $Revision:: 267 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "combatgmode.h"
|
||
|
#include "level.h"
|
||
|
#include "input.h"
|
||
|
#include "cnetwork.h"
|
||
|
#include "AudibleSound.H"
|
||
|
#include "debug.h"
|
||
|
#include "registry.h"
|
||
|
#include "_globals.h"
|
||
|
#include "console.h"
|
||
|
#include "radar.h"
|
||
|
#include "spawn.h"
|
||
|
#include "ccamera.h"
|
||
|
#include "scorescreen.h"
|
||
|
#include "devoptions.h"
|
||
|
#include "useroptions.h"
|
||
|
#include "systemsettings.h"
|
||
|
#include "gameobjmanager.h"
|
||
|
#include "building.h"
|
||
|
#include "saveloadstatus.h"
|
||
|
#include "playertype.h"
|
||
|
#include "bitpackids.h"
|
||
|
#include "vehicle.h"
|
||
|
#include "doors.h"
|
||
|
#include "elevator.h"
|
||
|
#include "msgloop.h"
|
||
|
#include "assetmgr.h"
|
||
|
#include "font3d.h"
|
||
|
#include "wwprofile.h"
|
||
|
#include "gametype.h"
|
||
|
#include "messagewindow.h"
|
||
|
#include "objectives.h"
|
||
|
#include "multihud.h"
|
||
|
#include "textureloader.h"
|
||
|
#include "wolgmode.h"
|
||
|
#include "renegadedialogmgr.h"
|
||
|
#include "textdisplay.h"
|
||
|
#include "playermanager.h"
|
||
|
#include "teammanager.h"
|
||
|
#include "consolefunction.h"
|
||
|
#include "overlay.h"
|
||
|
#include "gameinitmgr.h"
|
||
|
#include "campaign.h"
|
||
|
#include "diaglog.h"
|
||
|
#include "god.h"
|
||
|
#include "sbbomanager.h"
|
||
|
#include "savegame.h"
|
||
|
#include "commandosaveload.h"
|
||
|
#include "dlgmpingamechat.h"
|
||
|
#include "loadingevent.h"
|
||
|
#include "cheatmgr.h"
|
||
|
#include "menubackdrop.h"
|
||
|
#include "translatedb.h"
|
||
|
#include "thread.h"
|
||
|
#include "dlgcncteaminfo.h"
|
||
|
#include "dlgcncbattleinfo.h"
|
||
|
#include "bandwidthgraph.h"
|
||
|
#include "suicideevent.h"
|
||
|
#include "assetstatus.h"
|
||
|
#include "stylemgr.h"
|
||
|
#include "gametype.h"
|
||
|
#include "wwmemlog.h"
|
||
|
#include "directinput.h"
|
||
|
#include "cncmodesettings.h"
|
||
|
#include "announceevent.h"
|
||
|
#include "fastallocator.h"
|
||
|
#include "dlgcncserverinfo.h"
|
||
|
#include "radiocommanddisplay.h"
|
||
|
#include "hudinfo.h"
|
||
|
#include "string_ids.h"
|
||
|
#include "radiocommanddisplay.h"
|
||
|
#include "consolemode.h"
|
||
|
#include "specialbuilds.h"
|
||
|
#include <wwlib\realcrc.h>
|
||
|
#include "demosupport.h"
|
||
|
#include "natter.h"
|
||
|
#include "gamespyadmin.h"
|
||
|
#include "dialogtests.h"
|
||
|
#include "dialogmgr.h"
|
||
|
#include "GameSpy_QnR.h"
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
extern bool g_is_loading;
|
||
|
bool g_b_core_restart;//TSS081401
|
||
|
bool g_client_quit = false;
|
||
|
|
||
|
AudibleSoundClass * CombatGameModeClass::BackgroundMusic = NULL;
|
||
|
int CombatGameModeClass::IsHudShown = true;
|
||
|
static int ForceGod = false;
|
||
|
static bool ForceGodPending = true;
|
||
|
static int DefaultToFirstPerson = true;
|
||
|
static bool PendingCampaignContinue = false;
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
class CombatGameMiscHandlerClass : public CombatMiscHandlerClass {
|
||
|
public:
|
||
|
virtual void Mission_Complete( bool success );
|
||
|
virtual void Star_Killed( void );
|
||
|
};
|
||
|
|
||
|
CombatGameMiscHandlerClass GameMiscHandler;
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
static void Combat_To_Menu (RenegadeDialogMgrClass::LOCATION location)
|
||
|
{
|
||
|
//
|
||
|
// Remember: Combat and Menu are not mutually exclusive.
|
||
|
// Therefore this function may be called when menu is already active.
|
||
|
//
|
||
|
if (!GameModeManager::Find("Menu")->Is_Active()) {
|
||
|
|
||
|
//
|
||
|
// Do not suspend Combat in Multiplayer game!
|
||
|
//
|
||
|
if (IS_SOLOPLAY) {
|
||
|
GameModeManager::Find( "Combat" )->Suspend(); // suspend Combat Mode
|
||
|
}
|
||
|
|
||
|
//if (IS_SOLOPLAY) {
|
||
|
if (IS_MISSION) {
|
||
|
RenegadeDialogMgrClass::Goto_Location (location);
|
||
|
} else {
|
||
|
RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_CNC_REFERENCE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
static void Start_In_Game_Help(void)
|
||
|
{
|
||
|
//
|
||
|
// Remember: Combat and Menu are not mutually exclusive.
|
||
|
// Therefore this function may be called when menu is already active.
|
||
|
//
|
||
|
if (!GameModeManager::Find("Menu")->Is_Active()) {
|
||
|
|
||
|
//
|
||
|
// Do not suspend Combat in Multiplayer game!
|
||
|
//
|
||
|
if (IS_SOLOPLAY) {
|
||
|
GameModeManager::Find( "Combat" )->Suspend(); // suspend Combat Mode
|
||
|
}
|
||
|
|
||
|
RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_IN_GAME_HELP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CombatGameModeClass::Combat_Keyboard( void )
|
||
|
{
|
||
|
WWPROFILE( "Combat_Keyboard" );
|
||
|
|
||
|
#ifdef ATI_DEMO_HACK
|
||
|
// HACK: Make double-ESC exit back to desktop
|
||
|
static unsigned esc_pressed_time=0x7ffff;
|
||
|
if ( Input::Get_State( INPUT_FUNCTION_MENU_TOGGLE ) ) {
|
||
|
unsigned current_time=WW3D::Get_Sync_Time();
|
||
|
if ((current_time-esc_pressed_time)<5000) {
|
||
|
cDevOptions::QuickFullExit.Set(true);
|
||
|
esc_pressed_time=0x7ffff;
|
||
|
}
|
||
|
else {
|
||
|
Get_Text_Display()->Print_System( "Press ESC again to exit to desktop...\n" );
|
||
|
}
|
||
|
esc_pressed_time=current_time;
|
||
|
}
|
||
|
|
||
|
|
||
|
// HACK: In ATI demo toggle the statistics display using TAB
|
||
|
if ( Input::Get_State( INPUT_FUNCTION_EVA_MISSION_OBJECTIVES_TOGGLE ) ) {
|
||
|
if (StatisticsDisplayManager::Is_Current_Display( "fps" )) {
|
||
|
StatisticsDisplayManager::Set_Display( "off" );
|
||
|
}
|
||
|
else {
|
||
|
StatisticsDisplayManager::Set_Display( "fps" );
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
bool to_menu=Input::Get_State( INPUT_FUNCTION_MENU_TOGGLE );
|
||
|
// If game doesn't have a focus and combat is active, suspend combat by entering menu
|
||
|
if (!GameInFocus) {
|
||
|
if (IS_SOLOPLAY && COMBAT_CAMERA && !COMBAT_CAMERA->Is_In_Cinematic() ) {
|
||
|
to_menu|=GameModeManager::Find( "Combat" )->Is_Active();
|
||
|
}
|
||
|
}
|
||
|
if ( to_menu ) {
|
||
|
Combat_To_Menu( RenegadeDialogMgrClass::LOC_ENCYCLOPEDIA );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Handle the in-game EVA mission objectives window
|
||
|
//
|
||
|
if ( IS_MISSION && Input::Get_State( INPUT_FUNCTION_EVA_MISSION_OBJECTIVES_TOGGLE ) ) {
|
||
|
if ( ObjectiveManager::Is_Viewer_Displayed() ) {
|
||
|
ObjectiveManager::Page_Down_Viewer();
|
||
|
} else {
|
||
|
ObjectiveManager::Display_Viewer( true );
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if ( Input::Get_State( INPUT_FUNCTION_HELP_SCREEN ) ) {
|
||
|
Start_In_Game_Help();
|
||
|
}
|
||
|
|
||
|
if ( IS_SOLOPLAY && Input::Get_State( INPUT_FUNCTION_EVA_OBJECTIVES_SCREEN ) ) {
|
||
|
Combat_To_Menu( RenegadeDialogMgrClass::LOC_OBJECTIVES );
|
||
|
}
|
||
|
|
||
|
if ( IS_SOLOPLAY && Input::Get_State( INPUT_FUNCTION_EVA_MAP_SCREEN ) ) {
|
||
|
Combat_To_Menu( RenegadeDialogMgrClass::LOC_MAP );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Display the server info screen
|
||
|
//
|
||
|
if (!IS_MISSION && Input::Get_State( INPUT_FUNCTION_SERVER_INFO_TOGGLE )) {
|
||
|
START_DIALOG (CNCServerInfoDialogClass);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Display the team information page
|
||
|
//
|
||
|
if (!IS_MISSION && cNetwork::I_Am_Client() && COMBAT_STAR != NULL) {
|
||
|
if (Input::Get_State( INPUT_FUNCTION_TEAM_INFO_TOGGLE )) {
|
||
|
START_DIALOG (CNCTeamInfoDialogClass);
|
||
|
} else if (Input::Get_State( INPUT_FUNCTION_BATTLE_INFO_TOGGLE )) {
|
||
|
START_DIALOG (CNCBattleInfoDialogClass);
|
||
|
}/* else if (Input::Get_State( INPUT_FUNCTION_SERVER_INFO_TOGGLE )) {
|
||
|
START_DIALOG (CNCServerInfoDialogClass);
|
||
|
}*/
|
||
|
|
||
|
// Handle radio commands
|
||
|
for (int radioCmdIndex = INPUT_FUNCTION_RADIO_CMD_01; radioCmdIndex <= INPUT_FUNCTION_RADIO_CMD_30; ++radioCmdIndex) {
|
||
|
if (Input::Get_State((InputFunction)radioCmdIndex)) {
|
||
|
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
|
||
|
|
||
|
if (cncDef) {
|
||
|
int radioCmdNum = (radioCmdIndex - INPUT_FUNCTION_RADIO_CMD_01);
|
||
|
int radioCmd = cncDef->Get_Radio_Command(radioCmdNum);
|
||
|
|
||
|
if (radioCmd) {
|
||
|
CSAnnouncement* announce = new CSAnnouncement;
|
||
|
assert(announce != NULL);
|
||
|
announce->Init(cNetwork::Get_My_Team_Number(), radioCmd, ANNOUNCEMENT_TEAM, radioCmdNum);
|
||
|
RadioCommandDisplayClass::Reset_Display_Timer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!IS_MISSION && Input::Get_State( INPUT_FUNCTION_EVA_MISSION_OBJECTIVES_TOGGLE )) {
|
||
|
//MultiHUDClass::Toggle_Verbose_Lists();
|
||
|
MultiHUDClass::Next_Playerlist_Format();
|
||
|
}
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
if ( Input::Get_State( INPUT_FUNCTION_QUICK_FULL_EXIT ) ) {
|
||
|
cDevOptions::QuickFullExit.Set(true);
|
||
|
WWDEBUG_SAY(("Quick full exit requested by keypress.\n"));
|
||
|
}
|
||
|
if (cDevOptions::QuickFullExit.Is_True()) {
|
||
|
|
||
|
GameInitMgrClass::End_Game();
|
||
|
|
||
|
GameInitMgrClass::End_Client_Server();
|
||
|
|
||
|
extern void Stop_Main_Loop (int exitCode);
|
||
|
Stop_Main_Loop (EXIT_SUCCESS);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if ( (The_Game() != NULL &&
|
||
|
(Input::Get_State(INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE) ||
|
||
|
(Input::Get_State(INPUT_FUNCTION_BEGIN_TEAM_MESSAGE) && cNetwork::I_Am_Client()))) &&
|
||
|
!IS_MISSION)
|
||
|
{
|
||
|
MPIngameChatPopupClass * p_dialog = new MPIngameChatPopupClass;
|
||
|
WWASSERT(p_dialog != NULL);
|
||
|
|
||
|
//
|
||
|
// Configure the dialog
|
||
|
//
|
||
|
if (Input::Get_State(INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE)) {
|
||
|
p_dialog->Set_Default_Type(TEXT_MESSAGE_PUBLIC);
|
||
|
} else {
|
||
|
p_dialog->Set_Default_Type(TEXT_MESSAGE_TEAM);
|
||
|
}
|
||
|
|
||
|
p_dialog->Start_Dialog();
|
||
|
REF_PTR_RELEASE (p_dialog);
|
||
|
}
|
||
|
|
||
|
if ( Input::Get_State( INPUT_FUNCTION_QUICKSAVE )) {
|
||
|
// Only for singeplay
|
||
|
if ( IS_MISSION ) {
|
||
|
Quick_Save();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** called when the mode is activated
|
||
|
*/
|
||
|
void CombatGameModeClass::Init()
|
||
|
{
|
||
|
Debug_Say(("CombatGameModeClass::Init\n"));
|
||
|
|
||
|
if (!IS_MISSION) {
|
||
|
MultiHUDClass::Init();
|
||
|
}
|
||
|
|
||
|
PendingCampaignContinue = false;
|
||
|
|
||
|
//
|
||
|
// Initialize the radio command display window
|
||
|
//
|
||
|
RadioCommandDisplayClass::Initialize ();
|
||
|
|
||
|
//
|
||
|
// Notify combat about the state of the CameraLockedToTurret user option.
|
||
|
//
|
||
|
VehicleGameObj::Set_Camera_Locked_To_Turret(cUserOptions::CameraLockedToTurret.Get());
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** called when the mode is deactivated
|
||
|
*/
|
||
|
void CombatGameModeClass::Shutdown()
|
||
|
{
|
||
|
Debug_Say(("CombatGameModeClass::Shutdown\n"));
|
||
|
|
||
|
Core_Shutdown();
|
||
|
|
||
|
//
|
||
|
// Shutdown the radio command display window
|
||
|
//
|
||
|
RadioCommandDisplayClass::Shutdown ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
class LoadingScreenClass
|
||
|
{
|
||
|
MenuBackDropClass backdrop;
|
||
|
Render2DSentenceClass backdropText;
|
||
|
Render2DSentenceClass backdropText2; // The BIG text
|
||
|
float LoadTime;
|
||
|
float LoadPercentage;
|
||
|
float LoadPercentageDrawn;
|
||
|
float LoadPercentageClamp;
|
||
|
float LoadPercentageRate;
|
||
|
|
||
|
public:
|
||
|
LoadingScreenClass()
|
||
|
{
|
||
|
int color = 0xFFFFFFFF;
|
||
|
|
||
|
WWMEMLOG(MEM_GAMEDATA);
|
||
|
|
||
|
backdropText.Set_Texture_Size_Hint( 256 );
|
||
|
backdropText2.Set_Texture_Size_Hint( 256 );
|
||
|
|
||
|
LoadTime = 0.001f;
|
||
|
LoadPercentage = 0;
|
||
|
LoadPercentageDrawn = 0;
|
||
|
LoadPercentageRate = 0;
|
||
|
|
||
|
FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
|
||
|
backdropText.Set_Font( font );
|
||
|
|
||
|
font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_BIG_TXT );
|
||
|
backdropText2.Set_Font( font );
|
||
|
|
||
|
// Parse Descriptions
|
||
|
int count = CampaignManager::Get_Backdrop_Description_Count();
|
||
|
for ( int i = 0; i < count; i++ ) {
|
||
|
const char * read = CampaignManager::Get_Backdrop_Description( i );
|
||
|
// Debug_Say(( "Parse %s\n", read ));
|
||
|
StringClass desc = read;
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
while ( desc.Get_Length() && desc[desc.Get_Length()-1]<=' ' ) desc.Erase(desc.Get_Length()-1, 1 );
|
||
|
|
||
|
// Parse Big Translated Text
|
||
|
if ( ::strnicmp( "Text2", desc, 5 ) == 0 ) {
|
||
|
desc.Erase( 0, 5 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float x,y;
|
||
|
::sscanf( desc, "%f,%f,", &x, &y );
|
||
|
const char * str = ::strchr( desc, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
str = ::strchr( str+1, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
WideStringClass wide_str = TranslateDBClass::Get_String( str+1 );
|
||
|
backdropText2.Build_Sentence( wide_str );
|
||
|
// Scale
|
||
|
x *= Render2DClass::Get_Screen_Resolution().Right / 640.0f;
|
||
|
y *= Render2DClass::Get_Screen_Resolution().Bottom / 480.0f;
|
||
|
backdropText2.Set_Location( Vector2( (int)x, (int)y ) );
|
||
|
backdropText2.Draw_Sentence( color );
|
||
|
color=0xFFFFFFFF;
|
||
|
backdropText2.Set_Wrapping_Width( 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Parse Translated Text
|
||
|
if ( ::strnicmp( "Text", desc, 4 ) == 0 ) {
|
||
|
desc.Erase( 0, 4 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float x,y;
|
||
|
::sscanf( desc, "%f,%f,", &x, &y );
|
||
|
const char * str = ::strchr( desc, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
str = ::strchr( str+1, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
WideStringClass wide_str = TranslateDBClass::Get_String( str+1 );
|
||
|
backdropText.Build_Sentence( wide_str );
|
||
|
// Scale
|
||
|
x *= Render2DClass::Get_Screen_Resolution().Right / 640.0f;
|
||
|
y *= Render2DClass::Get_Screen_Resolution().Bottom / 480.0f;
|
||
|
backdropText.Set_Location( Vector2( (int)x, (int)y ) );
|
||
|
backdropText.Draw_Sentence( color );
|
||
|
color=0xFFFFFFFF;
|
||
|
backdropText.Set_Wrapping_Width( 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set Big Wrapping Width
|
||
|
if ( ::strnicmp( "Wrap2", desc, 5 ) == 0 ) {
|
||
|
desc.Erase( 0, 5 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float w;
|
||
|
::sscanf( desc, "%f,", &w );
|
||
|
// Scale
|
||
|
w *= Render2DClass::Get_Screen_Resolution().Right / 640.0f;
|
||
|
backdropText2.Set_Wrapping_Width( w );
|
||
|
}
|
||
|
|
||
|
// Set Wrapping Width
|
||
|
if ( ::strnicmp( "Wrap", desc, 4 ) == 0 ) {
|
||
|
desc.Erase( 0, 4 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float w;
|
||
|
::sscanf( desc, "%f,", &w );
|
||
|
// Scale
|
||
|
w *= Render2DClass::Get_Screen_Resolution().Right / 640.0f;
|
||
|
backdropText.Set_Wrapping_Width( w );
|
||
|
}
|
||
|
|
||
|
// Parse test Text
|
||
|
if ( ::strnicmp( "Test", desc, 4 ) == 0 ) {
|
||
|
desc.Erase( 0, 4 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float x,y;
|
||
|
::sscanf( desc, "%f,%f,", &x, &y );
|
||
|
const char * str = ::strchr( desc, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
str = ::strchr( str+1, ',' );
|
||
|
if ( str != NULL ) {
|
||
|
WideStringClass wide_str;
|
||
|
wide_str.Convert_From( str+1 );
|
||
|
backdropText.Build_Sentence( wide_str );
|
||
|
// Scale
|
||
|
x *= Render2DClass::Get_Screen_Resolution().Right / 640.0f;
|
||
|
y *= Render2DClass::Get_Screen_Resolution().Bottom / 480.0f;
|
||
|
backdropText.Set_Location( Vector2( (int)x, (int)y ) );
|
||
|
backdropText.Draw_Sentence( color );
|
||
|
color=0xFFFFFFFF;
|
||
|
backdropText.Set_Wrapping_Width( 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Parse back model
|
||
|
if ( ::strnicmp( "Model", desc, 5 ) == 0 ) {
|
||
|
desc.Erase( 0, 5 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
|
||
|
backdrop.Set_Model(desc);
|
||
|
StringClass anim_name;
|
||
|
anim_name.Format( "%s.%s", desc, desc );
|
||
|
backdrop.Set_Animation( anim_name );
|
||
|
backdrop.Set_Animation_Percentage( 0 );
|
||
|
}
|
||
|
|
||
|
if ( ::strnicmp( "Color", desc, 5 ) == 0 ) {
|
||
|
desc.Erase( 0, 5 );
|
||
|
while ( desc.Get_Length() && desc[0] <= ' ' ) desc.Erase( 0, 1 );
|
||
|
float r,g,b;
|
||
|
::sscanf( desc, "%f,%f,%f", &r, &g, &b );
|
||
|
|
||
|
Vector3 c( r/255.0f, g/255.0f, b/255.0f );
|
||
|
color = c.Convert_To_ARGB();
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
SaveLoadStatus::Reset_Status_Count();
|
||
|
}
|
||
|
|
||
|
~LoadingScreenClass()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
float Get_Predicted_Percentage( int state )
|
||
|
{
|
||
|
switch( state )
|
||
|
{
|
||
|
#define TOTAL (18.0f)
|
||
|
case 0: return 0.1f / TOTAL;
|
||
|
case 1: return 0.2f / TOTAL;
|
||
|
case 2: return 0.3f / TOTAL;
|
||
|
case 3: return 0.7f / TOTAL;
|
||
|
case 4: return 3.8f / TOTAL;
|
||
|
case 5: return 15.5f / TOTAL;
|
||
|
case 6: return 17.6f / TOTAL;
|
||
|
default: return 1.0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void Render(bool update_network = false)
|
||
|
{
|
||
|
TimeManager::Update_Frame_Time();
|
||
|
LoadTime += TimeManager::Get_Frame_Seconds();
|
||
|
|
||
|
WW3D::Begin_Render( true, true, Vector3(0.0f,0.0f,0.0f), update_network ? &cNetwork::Update : NULL);
|
||
|
|
||
|
backdrop.Render();
|
||
|
backdropText.Render();
|
||
|
backdropText2.Render();
|
||
|
|
||
|
static int last_count = -1;
|
||
|
static int _last_percent_drawn = -1;
|
||
|
if ( last_count != CombatManager::Get_Load_Progress() ) {
|
||
|
last_count = CombatManager::Get_Load_Progress();
|
||
|
Debug_Say(( " ****** Status Count %d at %f\n", last_count, LoadTime ));
|
||
|
LoadPercentage = Get_Predicted_Percentage( last_count );
|
||
|
LoadPercentageRate = LoadPercentage / LoadTime;
|
||
|
LoadPercentageClamp = Get_Predicted_Percentage( last_count+1 );
|
||
|
}
|
||
|
|
||
|
LoadPercentage += LoadPercentageRate * TimeManager::Get_Frame_Seconds();
|
||
|
LoadPercentage = WWMath::Clamp( LoadPercentage, 0, LoadPercentageClamp );
|
||
|
LoadPercentageDrawn += ( LoadPercentage - LoadPercentageDrawn ) * 0.1f;
|
||
|
backdrop.Set_Animation_Percentage( LoadPercentageDrawn );
|
||
|
if (ConsoleBox.Is_Exclusive() && _last_percent_drawn != LoadPercentageDrawn) {
|
||
|
_last_percent_drawn = LoadPercentageDrawn;
|
||
|
ConsoleBox.Print("Load %d%% complete\r", (int)(LoadPercentageDrawn * 100.0f));
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
StringClass txt=SaveLoadStatus::Get_Status_Text(0);
|
||
|
txt=SaveLoadStatus::Get_Status_Text(1);
|
||
|
#endif
|
||
|
|
||
|
WW3D::End_Render();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#define LOADTIME_NETWORK_UPDATE if (!IS_SOLOPLAY) cNetwork::Update()
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void CombatGameModeClass::Load_Level( void )
|
||
|
{
|
||
|
WWLOG_PREPARE_TIME_AND_MEMORY("CombatGameModeClass::Load_Level");
|
||
|
WWMEMLOG(MEM_GAMEDATA);
|
||
|
Debug_Say(("CombatGameModeClass::Load_Level\n"));
|
||
|
|
||
|
ConsoleBox.Print("Loading level %s\n", The_Game()->Get_Map_Name());
|
||
|
|
||
|
CombatManager::Set_Load_Progress(0);
|
||
|
LoadingScreenClass loading_screen; // Try moving this to very start of loading
|
||
|
loading_screen.Render(true);
|
||
|
|
||
|
// Hack load reg for default first person. Is dont again later.
|
||
|
Load_Registry_Keys();
|
||
|
WWLOG_INTERMEDIATE("Load_REgistry_Keys");
|
||
|
|
||
|
// Flush out current level
|
||
|
INIT_STATUS("Release current level");
|
||
|
LevelManager::Release_Level();
|
||
|
WWLOG_INTERMEDIATE("Releasing old level");
|
||
|
|
||
|
if (!ConsoleBox.Is_Exclusive()) {
|
||
|
WW3D::_Invalidate_Textures();
|
||
|
WWLOG_INTERMEDIATE("WW3D::_Invalidate_Textures()");
|
||
|
AssetStatusClass::Peek_Instance()->Enable_Load_On_Demand_Reporting(false);
|
||
|
}
|
||
|
|
||
|
// LoadingScreenClass loading_screen;
|
||
|
// loading_screen.Render(true);
|
||
|
|
||
|
PendingCampaignContinue = false;
|
||
|
g_is_loading = true;
|
||
|
|
||
|
//
|
||
|
// Stop the network layer from processing packets. This is needed in case a packet import or export accesses the datasafe
|
||
|
// from the main thread while the loader thread is loading stuff into the datasafe. This won't shut off packet acks so no-one
|
||
|
// will be disconnected as a result of this.
|
||
|
//
|
||
|
if (cNetwork::PServerConnection) {
|
||
|
cNetwork::PServerConnection->Allow_Packet_Processing(false);
|
||
|
}
|
||
|
|
||
|
if (!IS_SOLOPLAY && cNetwork::PClientConnection != NULL) {
|
||
|
cNetwork::PClientConnection->Allow_Extra_Timeout_For_Loading();
|
||
|
}
|
||
|
|
||
|
CombatManager::Pre_Load_Level(ConsoleBox.Is_Exclusive() ? false : true);
|
||
|
|
||
|
INIT_STATUS("Apply system settings");
|
||
|
SystemSettings::Apply_All();
|
||
|
|
||
|
CombatManager::Set_Combat_Misc_Handler( &GameMiscHandler );
|
||
|
|
||
|
// Flush out current level
|
||
|
// INIT_STATUS("Release current level");
|
||
|
// LevelManager::Release_Level();
|
||
|
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
StringClass map_name(The_Game()->Get_Map_Name(),true);
|
||
|
WWASSERT( !map_name.Is_Empty() );
|
||
|
|
||
|
bool preload_assets = true;
|
||
|
#ifdef WWDEBUG
|
||
|
preload_assets = cDevOptions::PreloadAssets.Get();
|
||
|
#endif
|
||
|
|
||
|
DIAG_LOG(( "LOAD", "%s", map_name ));
|
||
|
|
||
|
NetworkObjectMgrClass::Set_Is_Level_Loading (true);
|
||
|
|
||
|
TextureLoader::Suspend_Texture_Load();
|
||
|
|
||
|
CombatManager::Load_Level_Threaded( map_name, preload_assets );
|
||
|
|
||
|
WWLOG_INTERMEDIATE("Level load preprocessing");
|
||
|
|
||
|
while (!CombatManager::Is_Load_Level_Complete() ) {
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
ThreadClass::Sleep_Ms(50);
|
||
|
}
|
||
|
WWLOG_INTERMEDIATE("Threaded level load");
|
||
|
|
||
|
GenericDataSafeClass::Set_Preferred_Thread(GetCurrentThreadId());
|
||
|
TextureLoader::Continue_Texture_Load();
|
||
|
WWLOG_INTERMEDIATE("TextureLoader::Continue_Texture_Load()");
|
||
|
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
|
||
|
// Post load processing ----------------------------------------------------
|
||
|
INIT_STATUS("Post_Load_Processing");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
SaveLoadSystemClass::Post_Load_Processing(IS_SOLOPLAY ? NULL : &cNetwork::Update);
|
||
|
NetworkObjectMgrClass::Set_Is_Level_Loading (false);
|
||
|
WWLOG_INTERMEDIATE("SaveLoadSystemClass::Post_Load_Processing(&cNetwork::Update)");
|
||
|
|
||
|
INIT_STATUS("Post_Load_Level");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
CombatManager::Post_Load_Level();
|
||
|
WWLOG_INTERMEDIATE("CombatManager::Post_Load_Level()");
|
||
|
|
||
|
INIT_STATUS("Post_Load_Id_Uniqueness_Check");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
Post_Load_Id_Uniqueness_Check();
|
||
|
WWLOG_INTERMEDIATE("Post_Load_Id_Uniqueness_Check()");
|
||
|
|
||
|
INIT_STATUS("Post_Load_Dynamic_Object_Filtering");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
Post_Load_Dynamic_Object_Filtering();
|
||
|
WWLOG_INTERMEDIATE("Post_Load_Dynamic_Object_Filtering()");
|
||
|
|
||
|
// Spawn point validation --------------------------------------------------
|
||
|
INIT_STATUS("Spawn_Point_Validation");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
Spawn_Point_Validation();
|
||
|
WWLOG_INTERMEDIATE("Spawn_Point_Validation()");
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
//DefinitionMgrClass::List_Available_Definitions();
|
||
|
|
||
|
INIT_STATUS("Compute world size");
|
||
|
Compute_World_Size();
|
||
|
WWLOG_INTERMEDIATE("Compute_World_Size()");
|
||
|
|
||
|
//
|
||
|
// Set precision for other stuff
|
||
|
// This stuff should be placed elsewhere... when there are a few
|
||
|
// more of them.
|
||
|
//
|
||
|
ControlClass::Set_Precision();
|
||
|
//SoldierGameObj::Set_Precision();
|
||
|
HumanStateClass::Set_Precision();
|
||
|
VehicleGameObj::Set_Precision();
|
||
|
DoorPhysClass::Set_Precision();
|
||
|
ElevatorPhysClass::Set_Precision();
|
||
|
DefenseObjectClass::Set_Precision();
|
||
|
BuildingGameObj::Set_Precision();
|
||
|
|
||
|
// Override background color if this is a dedicated server
|
||
|
if (cNetwork::I_Am_Only_Server()) {
|
||
|
GameModeManager::Set_Background_Color( Vector3( 0.0f, 0.0f, 0.4f ) );
|
||
|
}
|
||
|
|
||
|
INIT_STATUS("Registry keys");
|
||
|
Load_Registry_Keys();
|
||
|
Save_Registry_Keys();
|
||
|
WWLOG_INTERMEDIATE("SaveLoadRegistry");
|
||
|
|
||
|
// Radar init --------------------------------------------------------------
|
||
|
INIT_STATUS("Init radar class"); // Init the radar after the game is loaded (so we have the global settings
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
RadarManager::Init();
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
RadarManager::Set_Radar_Mode(The_Game()->Get_Radar_Mode());
|
||
|
WWLOG_INTERMEDIATE("Init Radar");
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
const bool is_reloaded = true;
|
||
|
The_Game()->Reset_Game(is_reloaded);
|
||
|
WWLOG_INTERMEDIATE("The_Game()->Reset_Game(is_reloaded)");
|
||
|
|
||
|
// Buildings init ----------------------------------------------------------
|
||
|
// After the level loads, the buildings collect all of their components
|
||
|
INIT_STATUS("Init_Buildings");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
GameObjManager::Init_Buildings();
|
||
|
WWLOG_INTERMEDIATE("GameObjManager::Init_Buildings()");
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
// Update texture loader ---------------------------------------------------
|
||
|
// This is needed here as we want to apply all textures that may have changed
|
||
|
// during the game loading before the game actually starts.
|
||
|
INIT_STATUS("Init_Textures");
|
||
|
loading_screen.Render(true);
|
||
|
Windows_Message_Handler();
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
TextureLoader::Update(IS_SOLOPLAY ? NULL : &cNetwork::Update);
|
||
|
WWLOG_INTERMEDIATE("TextureLoader::Update(&cNetwork::Update)");
|
||
|
// -------------------------------------------------------------------------
|
||
|
|
||
|
// Notify the game of "game start"
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
The_Game()->On_Game_Begin();
|
||
|
WWLOG_INTERMEDIATE("The_Game()->On_Game_Begin()");
|
||
|
|
||
|
ForceGodPending = ForceGod != 0;
|
||
|
|
||
|
/* if ( GameModeManager::Find( "Overlay3D" ) ) {
|
||
|
((Overlay3DGameModeClass*)GameModeManager::Find( "Overlay3D" ))->Start_Intro();
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
LOADTIME_NETWORK_UPDATE;
|
||
|
AssetStatusClass::Peek_Instance()->Enable_Load_On_Demand_Reporting(true);
|
||
|
g_is_loading = false;
|
||
|
|
||
|
ConsoleBox.Print("Load %d%% complete\n", 100);
|
||
|
ConsoleBox.Print("Level loaded OK\n");
|
||
|
|
||
|
GameSpyQnR.Init();
|
||
|
|
||
|
//
|
||
|
// Re-enable packet processing.
|
||
|
//
|
||
|
if (cNetwork::PServerConnection) {
|
||
|
cNetwork::PServerConnection->Allow_Packet_Processing(true);
|
||
|
}
|
||
|
|
||
|
if (!ConsoleBox.Is_Exclusive()) {
|
||
|
unsigned ffheap=FastAllocatorGeneral::Get_Allocator()->Get_Total_Heap_Size();
|
||
|
unsigned ffuse=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size();
|
||
|
unsigned actualuse=FastAllocatorGeneral::Get_Allocator()->Get_Total_Actual_Memory_Usage();
|
||
|
unsigned count=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count();
|
||
|
StringClass working_string(0,true);
|
||
|
working_string.Format(
|
||
|
"\nMalloc count: %d\n"
|
||
|
"Free count: %d\n"
|
||
|
"FF Heap: %d.%3.3d.%3.3d (%d Mb)\n"
|
||
|
"FF Use: %d.%3.3d.%3.3d (%d Mb)\n"
|
||
|
"Actual Use: %d.%3.3d.%3.3d (%d Mb)\n"
|
||
|
"FF Count: %d\n"
|
||
|
,
|
||
|
WW3D::Get_Last_Frame_Memory_Allocation_Count(),
|
||
|
WW3D::Get_Last_Frame_Memory_Free_Count(),
|
||
|
ffheap/(1000*1000),(ffheap/1000)%1000,ffheap%1000, ffheap/(1024*1024),
|
||
|
ffuse/(1000*1000),(ffuse/10000)%1000,ffuse%1000, ffuse/(1024*1024),
|
||
|
actualuse/(1000*1000),(actualuse/1000)%1000,actualuse%1000, actualuse/(1024*1024),
|
||
|
count);
|
||
|
WWDEBUG_SAY((working_string));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CombatGameModeClass::Core_Shutdown()
|
||
|
{
|
||
|
Debug_Say(("CombatGameModeClass::Core_Shutdown\n"));
|
||
|
|
||
|
//
|
||
|
// Switch to the in-game sound page to ensure all those sounds get freed
|
||
|
// as we're shutting down the level.
|
||
|
//
|
||
|
WWAudioClass::Get_Instance ()->Push_Active_Sound_Page (WWAudioClass::PAGE_PRIMARY);
|
||
|
|
||
|
MultiHUDClass::Shutdown();
|
||
|
//cPlayerManager::Shutdown();
|
||
|
//cTeamManager::Shutdown();
|
||
|
|
||
|
// Shutdown the sound library
|
||
|
if (BackgroundMusic != NULL) {
|
||
|
BackgroundMusic->Stop ();
|
||
|
BackgroundMusic->Release_Ref ();
|
||
|
BackgroundMusic = NULL;
|
||
|
}
|
||
|
|
||
|
if (IS_MISSION) {
|
||
|
//
|
||
|
// Keep the GOD manager from offering a respawn when the star is gone
|
||
|
//
|
||
|
cGod::Exit();
|
||
|
}
|
||
|
|
||
|
CombatManager::Unload_Level();
|
||
|
|
||
|
LevelManager::Release_Level();
|
||
|
|
||
|
RadarManager::Shutdown();
|
||
|
|
||
|
//
|
||
|
// Restore the current sound page
|
||
|
//
|
||
|
WWAudioClass::Get_Instance ()->Pop_Active_Sound_Page ();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CombatGameModeClass::Post_Load_Id_Uniqueness_Check(void)
|
||
|
{
|
||
|
bool list_ids = false;
|
||
|
|
||
|
//
|
||
|
// Make sure no 2 phys objects have the same id.
|
||
|
//
|
||
|
|
||
|
// Debug_Say(("Testing id uniqueness for physical objects:\n"));
|
||
|
|
||
|
int phys_obj_count = 0;
|
||
|
SLNode<BaseGameObj> * objnode;
|
||
|
for (objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
|
||
|
WWASSERT(objnode->Data() != NULL);
|
||
|
PhysicalGameObj * p_phys_obj = objnode->Data()->As_PhysicalGameObj();
|
||
|
if (p_phys_obj != NULL) {
|
||
|
|
||
|
phys_obj_count++;
|
||
|
|
||
|
if (list_ids) {
|
||
|
Debug_Say((" Object %d, model %s\n",
|
||
|
p_phys_obj->Get_ID(),
|
||
|
p_phys_obj->Peek_Model()->Get_Name()));
|
||
|
}
|
||
|
|
||
|
SLNode<BaseGameObj> * objnode2;
|
||
|
for (objnode2 = GameObjManager::Get_Game_Obj_List()->Head(); objnode2; objnode2 = objnode2->Next()) {
|
||
|
WWASSERT(objnode2->Data() != NULL);
|
||
|
PhysicalGameObj * p_phys_obj_2 = objnode2->Data()->As_PhysicalGameObj();
|
||
|
if (p_phys_obj_2 != NULL &&
|
||
|
p_phys_obj_2->Get_ID() == p_phys_obj->Get_ID()) {
|
||
|
|
||
|
//WWASSERT(p_phys_obj_2 == p_phys_obj);
|
||
|
if (p_phys_obj_2 != p_phys_obj) {
|
||
|
Debug_Say(("Level file error: Two phys objects found with id %d.\n",
|
||
|
p_phys_obj_2->Get_ID()));
|
||
|
DIE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Debug_Say((" %d unique physical objects were loaded.\n", phys_obj_count));
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Make sure no 2 static objects have the same id.
|
||
|
//
|
||
|
// Debug_Say(("Testing id uniqueness for static objects:\n"));
|
||
|
|
||
|
WWASSERT(COMBAT_SCENE != NULL);
|
||
|
int static_obj_count = 0;
|
||
|
RefPhysListIterator iter_1 = COMBAT_SCENE->Get_Static_Object_Iterator();
|
||
|
for (iter_1.First(); !iter_1.Is_Done(); iter_1.Next()) {
|
||
|
|
||
|
//StaticPhysClass * p_obj_1 = (StaticPhysClass *) iter_1.Peek_Obj();
|
||
|
PhysClass * p_obj_1 = iter_1.Peek_Obj();
|
||
|
WWASSERT(p_obj_1 != NULL);
|
||
|
int object_id_1 = p_obj_1->Get_ID();
|
||
|
|
||
|
static_obj_count++;
|
||
|
|
||
|
if (list_ids) {
|
||
|
//Debug_Say((" Object %d\n", object_id_1));
|
||
|
Debug_Say((" Object %d, model %s\n",
|
||
|
p_obj_1->Get_ID(),
|
||
|
p_obj_1->Peek_Model()->Get_Name()));
|
||
|
}
|
||
|
|
||
|
RefPhysListIterator iter_2 = COMBAT_SCENE->Get_Static_Object_Iterator();
|
||
|
for (iter_2.First(); !iter_2.Is_Done(); iter_2.Next()) {
|
||
|
//StaticPhysClass * p_obj_2 = (StaticPhysClass *) iter_2.Peek_Obj();
|
||
|
PhysClass * p_obj_2 = iter_2.Peek_Obj();
|
||
|
WWASSERT(p_obj_2 != NULL);
|
||
|
int object_id_2 = p_obj_2->Get_ID();
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// DO NOT DISABLE THIS
|
||
|
//
|
||
|
//
|
||
|
if (object_id_1 == object_id_2 && p_obj_1 != p_obj_2) {
|
||
|
Debug_Say(("Fatal level file error: Two static objects found with id %d.\n",
|
||
|
object_id_1));
|
||
|
DIE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Debug_Say((" %d unique static objects were loaded.\n", static_obj_count));
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CombatGameModeClass::Post_Load_Dynamic_Object_Filtering(void)
|
||
|
{
|
||
|
//
|
||
|
// Look through the soldiers and remove any that aren't
|
||
|
// appropriate for this particular game type.
|
||
|
//
|
||
|
//
|
||
|
// Any commando's that are tagged as having human players must be removed.
|
||
|
// The player id field is not valid...
|
||
|
// The exception is the commando belonging to the first player.
|
||
|
//
|
||
|
// Remove any soldiers with invalid player types for this game.
|
||
|
//
|
||
|
// Remove any grunts unless this is a mission.
|
||
|
//
|
||
|
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
|
||
|
SLNode<SmartGameObj> * objnode;
|
||
|
for (objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
|
||
|
SmartGameObj * p_smart_obj = objnode->Data();
|
||
|
WWASSERT(p_smart_obj != NULL);
|
||
|
|
||
|
if (p_smart_obj->As_SoldierGameObj() != NULL) {
|
||
|
|
||
|
if (p_smart_obj->Has_Player() && (p_smart_obj->Get_Control_Owner() > 1 ||
|
||
|
(!cNetwork::I_Am_Client()))) {
|
||
|
Debug_Say(("* Removing loaded soldier belonging to another player.\n"));
|
||
|
p_smart_obj->Set_Delete_Pending();
|
||
|
}
|
||
|
|
||
|
if (!p_smart_obj->Is_Delete_Pending() &&
|
||
|
!The_Game()->Is_Valid_Player_Type(p_smart_obj->Get_Player_Type())) {
|
||
|
Debug_Say(("* Removing loaded soldier due to invalid playertype for this game.\n"));
|
||
|
p_smart_obj->Set_Delete_Pending();
|
||
|
}
|
||
|
|
||
|
if (!p_smart_obj->Is_Delete_Pending() && !p_smart_obj->Has_Player() &&
|
||
|
!IS_SOLOPLAY) {
|
||
|
Debug_Say(("* Removing loaded soldier grunt in non-mission game (id = %d).\n",
|
||
|
p_smart_obj->Get_ID()));
|
||
|
p_smart_obj->Set_Delete_Pending();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CombatGameModeClass::Compute_World_Size(void)
|
||
|
{
|
||
|
//
|
||
|
// Tell networking system about the size of the world, to be used
|
||
|
// in filtering.
|
||
|
//
|
||
|
Vector3 min;
|
||
|
Vector3 max;
|
||
|
WWASSERT(PhysicsSceneClass::Get_Instance() != NULL);
|
||
|
PhysicsSceneClass::Get_Instance()->Get_Level_Extents(min, max);
|
||
|
//Debug_Say(("World extends from (%5.2f, %5.2f, %5.2f) to (%5.2f, %5.2f, %5.2f)\n",
|
||
|
// min.X, min.Y, min.Z, max.X, max.Y, max.Z));
|
||
|
|
||
|
Vector3 longest_distance = max - min;
|
||
|
//Debug_Say(("Longest distance is %5.2fm\n", longest_distance.Length()));
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
The_Game()->Set_Maximum_World_Distance(longest_distance.Length());
|
||
|
|
||
|
double margin = 1; // comfort zone
|
||
|
|
||
|
//
|
||
|
// Also, set encoding precision for positional information
|
||
|
//
|
||
|
cEncoderList::Set_Precision(BITPACK_WORLD_POSITION_X,
|
||
|
min.X - margin, max.X + margin, 0.2);
|
||
|
cEncoderList::Set_Precision(BITPACK_WORLD_POSITION_Y,
|
||
|
min.Y - margin, max.Y + margin, 0.2);
|
||
|
cEncoderList::Set_Precision(BITPACK_WORLD_POSITION_Z,
|
||
|
min.Z - margin, max.Z + margin, 0.2);
|
||
|
cEncoderList::Set_Precision(BITPACK_BUILDING_RADIUS,
|
||
|
0.0, 50.0, 0.1);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
#define ADD_CASE(exp) case exp: return #exp; break;
|
||
|
static LPCSTR Playertype_To_String(int player_type)
|
||
|
{
|
||
|
switch (player_type) {
|
||
|
ADD_CASE(PLAYERTYPE_MUTANT);
|
||
|
ADD_CASE(PLAYERTYPE_NEUTRAL);
|
||
|
ADD_CASE(PLAYERTYPE_RENEGADE);
|
||
|
ADD_CASE(PLAYERTYPE_NOD);
|
||
|
ADD_CASE(PLAYERTYPE_GDI);
|
||
|
|
||
|
default:
|
||
|
DIE;
|
||
|
return "ERROR"; // to avoid compiler warning
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CombatGameModeClass::Spawn_Point_Validation(void)
|
||
|
{
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
|
||
|
bool is_spawners_valid = true;
|
||
|
|
||
|
for (int spawn_type = PLAYERTYPE_RENEGADE; spawn_type <= PLAYERTYPE_LAST; spawn_type++) {
|
||
|
|
||
|
if ( !SpawnManager::Spawner_Exists( spawn_type ) ) {
|
||
|
Debug_Say((" Error: No spawn point(s) of type %s found.\n",
|
||
|
Playertype_To_String(spawn_type)));
|
||
|
is_spawners_valid = false;
|
||
|
} else {
|
||
|
Debug_Say((" Spawn point(s) of type %s found.\n",
|
||
|
Playertype_To_String(spawn_type)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!IS_SOLOPLAY) {
|
||
|
WWASSERT(is_spawners_valid);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void CombatGameModeClass::Core_Restart(void)
|
||
|
{
|
||
|
Debug_Say(("CombatGameModeClass::Core_Restart\n"));
|
||
|
|
||
|
Core_Shutdown();
|
||
|
|
||
|
GameModeManager::Safely_Deactivate();
|
||
|
|
||
|
INIT_STATUS("Reloading...");
|
||
|
|
||
|
if ( IS_MISSION ) {
|
||
|
#ifndef MULTIPLAYERDEMO
|
||
|
StringClass new_name;
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
|
||
|
new_name = CombatManager::Get_Last_LSD_Name();
|
||
|
|
||
|
// convert .LSD to .MIX
|
||
|
if ( new_name.Get_Length() > 4 &&
|
||
|
::stricmp( &new_name[new_name.Get_Length() - 4], ".LSD" ) == 0 ) {
|
||
|
new_name.Erase( new_name.Get_Length() - 4, 4 );
|
||
|
new_name += ".MIX";
|
||
|
}
|
||
|
|
||
|
The_Game()->Set_Map_Name( new_name );
|
||
|
#endif // !MULTIPLAYERDEMO
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Reset the timer system if we are a dedicated server and there is no-one in the game.
|
||
|
// ST - 1/30/2002 12:44PM
|
||
|
//
|
||
|
if (The_Game() && The_Game()->IsDedicated.Is_True()) {
|
||
|
if (cNetwork::PServerConnection && cNetwork::PServerConnection->Get_Num_RHosts() == 0) {
|
||
|
GameModeClass *game_mode = GameModeManager::Find("LAN");
|
||
|
|
||
|
//
|
||
|
// Don't do this if the NAT thread is busy since it uses timers extensively.
|
||
|
//
|
||
|
if ((game_mode && game_mode->Is_Active()) || WOLNATInterface.Is_NAT_Thread_Busy() == false) {
|
||
|
//
|
||
|
// Danger! Danger!
|
||
|
// This could cause code that uses time deltas to fail. Hopefully there isn't any code doing that right now.
|
||
|
//
|
||
|
SystemTime.Reset();
|
||
|
TimeManager::Reset();
|
||
|
GenericDataSafeClass::Reset_Timers();
|
||
|
|
||
|
GameModeClass* game_mode = GameModeManager::Find("WOL");
|
||
|
|
||
|
if (game_mode && game_mode->Is_Active()) {
|
||
|
WolGameModeClass* wol_game = reinterpret_cast<WolGameModeClass*>(game_mode);
|
||
|
wol_game->System_Timer_Reset();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Reset packet optimizer bandwidth stats.
|
||
|
//
|
||
|
PacketManager.Reset_Stats();
|
||
|
|
||
|
Load_Level();
|
||
|
|
||
|
#ifdef WW3D_COMPILE_WITH_DX8__
|
||
|
DX8MeshRendererContainerClass::Invalidate_All();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void CombatGameModeClass::Load_Registry_Keys(void)
|
||
|
{
|
||
|
RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_OPTIONS );
|
||
|
WWASSERT( registry );
|
||
|
if ( registry->Is_Valid() ) {
|
||
|
IsHudShown = registry->Get_Int( "IsHudShown", IsHudShown );
|
||
|
ForceGod = registry->Get_Int( "ForceGod", ForceGod );
|
||
|
|
||
|
//TSS
|
||
|
DefaultToFirstPerson = registry->Get_Int( "DefaultToFirstPerson", DefaultToFirstPerson );
|
||
|
CombatManager::Set_First_Person_Default(DefaultToFirstPerson == TRUE);
|
||
|
}
|
||
|
delete registry;
|
||
|
}
|
||
|
|
||
|
void CombatGameModeClass::Save_Registry_Keys(void)
|
||
|
{
|
||
|
RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_OPTIONS );
|
||
|
WWASSERT( registry );
|
||
|
if ( registry->Is_Valid() ) {
|
||
|
registry->Set_Int( "IsHudShown", IsHudShown );
|
||
|
registry->Set_Int( "ForceGod", ForceGod );
|
||
|
|
||
|
//TSS
|
||
|
DefaultToFirstPerson = CombatManager::Get_First_Person_Default();
|
||
|
registry->Set_Int( "DefaultToFirstPerson", DefaultToFirstPerson );
|
||
|
}
|
||
|
delete registry;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** called each time through the main loop when active
|
||
|
*/
|
||
|
void CombatGameModeClass::Think()
|
||
|
{
|
||
|
WWPROFILE( "Combat Think" );
|
||
|
|
||
|
if ( !Is_Active() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Combat_Keyboard();
|
||
|
|
||
|
//
|
||
|
// Test again to see if we are active, because quick exit may inactivate us.
|
||
|
//
|
||
|
if ( !Is_Active() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CombatManager::Generate_Control();
|
||
|
|
||
|
//
|
||
|
// Network Update needs to be between input and think
|
||
|
//
|
||
|
|
||
|
float time_1;
|
||
|
{
|
||
|
WWMeasureItClass net_upd_time_s(&time_1);
|
||
|
cNetwork::Update();
|
||
|
}
|
||
|
|
||
|
float time_2;
|
||
|
{
|
||
|
WWMeasureItClass combat_think_time_s(&time_2);
|
||
|
CombatManager::Think();
|
||
|
}
|
||
|
|
||
|
if (cNetwork::I_Am_Server())
|
||
|
{
|
||
|
WWPROFILE( "cSbboManager stuff" );
|
||
|
cSbboManager::Increment_Accum_Time_S_Net_Update(time_1);
|
||
|
cSbboManager::Increment_Accum_Time_S_Combat_Think(time_2);
|
||
|
cSbboManager::Think();
|
||
|
}
|
||
|
|
||
|
DEMO_SECURITY_CHECK;
|
||
|
|
||
|
if ( COMBAT_STAR ) {
|
||
|
WWPROFILE( "Stuff 1" );
|
||
|
Vector3 pos;
|
||
|
COMBAT_STAR->Get_Position( &pos );
|
||
|
float facing = COMBAT_STAR->Get_Facing();
|
||
|
Get_Console()->Set_Player_Position( pos, facing );
|
||
|
|
||
|
if ( ForceGodPending ) {
|
||
|
ForceGodPending = false;
|
||
|
ConsoleFunctionManager::Parse_Input( "God" );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
MultiHUDClass::Think();
|
||
|
cPlayerManager::Think();
|
||
|
cTeamManager::Think();
|
||
|
|
||
|
if ( PendingCampaignContinue ) {
|
||
|
WWPROFILE( "Stuff 2" );
|
||
|
PendingCampaignContinue = false;
|
||
|
Debug_Say(( "Handle Pending Campaign Continue\n" ));
|
||
|
CampaignManager::Continue();
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef MULTIPLAYERDEMO
|
||
|
//
|
||
|
// Security check. Randomly every few minutes, check to see if a special
|
||
|
// MP demo object (id 100277) exists. If it doesn't, assume someone has hacked in
|
||
|
// a different map. Bail.
|
||
|
//
|
||
|
if ((::rand() % 10131 == 939) && (NetworkObjectMgrClass::Find_Object(100277) == NULL)) {
|
||
|
WWDEBUG_SAY(("MP DEMO OBJECT NOT FOUND... BAILING.\n"));
|
||
|
Suspend();
|
||
|
GameInitMgrClass::End_Game();
|
||
|
extern void Stop_Main_Loop (int);
|
||
|
Stop_Main_Loop(EXIT_SUCCESS);
|
||
|
}
|
||
|
#endif // MULTIPLAYERDEMO
|
||
|
|
||
|
|
||
|
if (g_b_core_restart) {
|
||
|
WWPROFILE( "g_b_core_restart" );
|
||
|
|
||
|
g_b_core_restart = false;
|
||
|
|
||
|
//Core_Restart();
|
||
|
|
||
|
cPlayer * p_me = cNetwork::Get_My_Player_Object();
|
||
|
|
||
|
if (p_me != NULL) {// && cNetwork::I_Am_Only_Client()) {
|
||
|
|
||
|
p_me->Set_Is_In_Game(false);
|
||
|
cLoadingEvent * p_loading_1 = new cLoadingEvent;
|
||
|
p_loading_1->Init(true);
|
||
|
|
||
|
Core_Restart();
|
||
|
|
||
|
p_me->Set_Is_In_Game(true);
|
||
|
cLoadingEvent * p_loading_2 = new cLoadingEvent;
|
||
|
p_loading_2->Init(false);
|
||
|
|
||
|
} else {
|
||
|
Core_Restart();
|
||
|
}
|
||
|
|
||
|
if (!IS_MISSION) {
|
||
|
MultiHUDClass::Init();
|
||
|
}
|
||
|
|
||
|
cNetwork::Enable_Waiting_Players();
|
||
|
|
||
|
/*
|
||
|
#if(0)
|
||
|
WWDEBUG_SAY(("****** CombatGameModeClass::Think On_Game_Begin()\n"));
|
||
|
WWASSERT(The_Game() != NULL);
|
||
|
|
||
|
// The_Game()->On_Game_End();
|
||
|
The_Game()->Reset_Game(false);
|
||
|
The_Game()->On_Game_Begin();//TSS091201
|
||
|
#endif
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
// Autosave, after one run throught main loop
|
||
|
if ( CombatManager::Is_Autosave_Requested() ) {
|
||
|
WWPROFILE( "Autosaving" );
|
||
|
Debug_Say(( "Autosaving\n" ));
|
||
|
int time=TIMEGETTIME();
|
||
|
CombatManager::Request_Autosave( false );
|
||
|
SaveGameManager::Set_Description( TRANSLATE( IDS_SAVE_AUTOSAVE ) );
|
||
|
SaveGameManager::Save_Game( "save\\autosave.sav", &_CommandoSaveLoad, NULL );
|
||
|
time=TIMEGETTIME()-time;
|
||
|
Debug_Say(( "Autosaving Complete, took %d.%2.2d seconds\n",time/1000,(time/10)%100 ));
|
||
|
}
|
||
|
|
||
|
//TSS090401
|
||
|
if (g_client_quit)
|
||
|
{
|
||
|
WWPROFILE( "g_client_quit" );
|
||
|
|
||
|
//
|
||
|
// This becomes true when the connection to the server breaks
|
||
|
//
|
||
|
g_client_quit = false;
|
||
|
|
||
|
Suspend();
|
||
|
GameInitMgrClass::End_Game();
|
||
|
|
||
|
//GAMESPY
|
||
|
if (cGameSpyAdmin::Get_Is_Launched_From_Gamespy())
|
||
|
{
|
||
|
#ifdef MULTIPLAYERDEMO
|
||
|
DialogMgrClass::Flush_Dialogs ();
|
||
|
START_DIALOG (SplashOutroMenuDialogClass);
|
||
|
#else
|
||
|
extern void Stop_Main_Loop (int);
|
||
|
Stop_Main_Loop(EXIT_SUCCESS);
|
||
|
#endif // MULTIPLAYERDEMO
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GameInitMgrClass::Display_End_Game_Menu();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CombatGameModeClass::Render()
|
||
|
{
|
||
|
if ( !Is_Active() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (cNetwork::I_Am_Client()) {
|
||
|
|
||
|
/*
|
||
|
** In multi-play, only render the combatmanager when we have a valid camera and the menu is not active
|
||
|
*/
|
||
|
bool menu_active = false;
|
||
|
GameModeClass * menu_mode = GameModeManager::Find( "Menu" ); // Activate the main menu
|
||
|
if ((menu_mode != NULL) && (menu_mode->Get_State() == GAME_MODE_ACTIVE)) {
|
||
|
menu_active = true;
|
||
|
}
|
||
|
|
||
|
if ( COMBAT_CAMERA && COMBAT_CAMERA->Is_Valid() && (menu_active == false)) {
|
||
|
CombatManager::Render();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MultiHUDClass::Render();
|
||
|
cBandwidthGraph::Render();
|
||
|
cPlayerManager::Render();
|
||
|
cTeamManager::Render();
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
The_Game()->Render();
|
||
|
RadioCommandDisplayClass::Render ();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CombatGameModeClass::Toggle_Multi_Hud(void)
|
||
|
{
|
||
|
MultiHUDClass::Toggle();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------
|
||
|
|
||
|
void CombatGameMiscHandlerClass::Mission_Complete( bool success )
|
||
|
{
|
||
|
if (IS_MISSION) {
|
||
|
if ( success ) {
|
||
|
PendingCampaignContinue = true;
|
||
|
} else {
|
||
|
cGod::Mission_Failed();
|
||
|
}
|
||
|
#if 0
|
||
|
GameModeManager::Find("Combat")->Suspend();
|
||
|
// GameModeManager::Find("Combat")->Deactivate();
|
||
|
// GameModeManager::Find("ScoreScreen")->Activate();
|
||
|
// ((ScoreScreenGameModeClass*)GameModeManager::Find("ScoreScreen"))->Set_Success( success );
|
||
|
|
||
|
if ( GameModeManager::Find( "Overlay3D" ) ) {
|
||
|
((Overlay3DGameModeClass*)GameModeManager::Find( "Overlay3D" ))->Start_End_Screen();
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CombatGameMiscHandlerClass::Star_Killed( void )
|
||
|
{
|
||
|
cGod::Star_Killed();
|
||
|
}
|
||
|
|
||
|
void CombatGameModeClass::Resume(void)
|
||
|
{
|
||
|
//
|
||
|
// Show the message window (if necessary)
|
||
|
//
|
||
|
if ( CombatManager::Get_Message_Window () != NULL &&
|
||
|
CombatManager::Get_Message_Window ()->Has_Data ())
|
||
|
{
|
||
|
CombatManager::Get_Message_Window ()->Force_Display (true);
|
||
|
}
|
||
|
|
||
|
GameMajorModeClass::Resume();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
void CombatGameModeClass::Suspend(void)
|
||
|
{
|
||
|
//
|
||
|
// Hide the message window
|
||
|
//
|
||
|
if (CombatManager::Get_Message_Window () != NULL) {
|
||
|
CombatManager::Get_Message_Window ()->Force_Display (false);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Hide the objective viewer
|
||
|
//
|
||
|
ObjectiveManager::Display_Viewer (false);
|
||
|
|
||
|
GameMajorModeClass::Suspend();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
void CombatGameModeClass::Quick_Save( void )
|
||
|
{
|
||
|
bool saveA = true;
|
||
|
|
||
|
RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_OPTIONS );
|
||
|
WWASSERT( registry );
|
||
|
if ( registry->Is_Valid() ) {
|
||
|
saveA = registry->Get_Bool( "QuicksaveA", saveA );
|
||
|
}
|
||
|
|
||
|
#define SAVEGAME_NAME_A "save\\quicksaveA.sav"
|
||
|
#define SAVEGAME_NAME_B "save\\quicksaveB.sav"
|
||
|
|
||
|
// Check for a missing file
|
||
|
if ( !cMiscUtil::File_Exists(SAVEGAME_NAME_B) ) {
|
||
|
saveA = false;
|
||
|
}
|
||
|
if ( !cMiscUtil::File_Exists(SAVEGAME_NAME_A) ) {
|
||
|
saveA = true;
|
||
|
}
|
||
|
|
||
|
if ( saveA ) {
|
||
|
SaveGameManager::Set_Description( TRANSLATE(IDS_SAVE_QUICKSAVE_A) );
|
||
|
SaveGameManager::Save_Game( SAVEGAME_NAME_A, &_CommandoSaveLoad, NULL );
|
||
|
Debug_Say(( "Quicksaved A\n" ));
|
||
|
} else {
|
||
|
SaveGameManager::Set_Description( TRANSLATE(IDS_SAVE_QUICKSAVE_B) );
|
||
|
SaveGameManager::Save_Game( SAVEGAME_NAME_B, &_CommandoSaveLoad, NULL );
|
||
|
Debug_Say(( "Quicksaved B\n" ));
|
||
|
}
|
||
|
saveA = !saveA;
|
||
|
|
||
|
if ( registry->Is_Valid() ) {
|
||
|
registry->Set_Bool( "QuicksaveA", saveA );
|
||
|
}
|
||
|
delete registry;
|
||
|
|
||
|
// Display "Quick Saved"
|
||
|
HUDInfo::Set_HUD_Help_Text( TRANSLATE( IDS_M00DSGN_DSGN1017I1DSGN_TXT ), Vector3( 0,1,0 ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**/
|
||
|
/*
|
||
|
if (::rand() % 10131 == 939)) {
|
||
|
bool bail = true;
|
||
|
|
||
|
ScriptableGameObj * p_obj = GameObjManager::Find_ScriptableGameObj(100277);
|
||
|
if (p_obj != NULL && p_obj->Get_Definition().Get_Name()) {
|
||
|
bail = false;
|
||
|
}
|
||
|
|
||
|
if (bail) {
|
||
|
Suspend();
|
||
|
GameInitMgrClass::End_Game();
|
||
|
extern void Stop_Main_Loop (int);
|
||
|
Stop_Main_Loop(EXIT_SUCCESS);
|
||
|
}
|
||
|
}
|
||
|
*/
|