Files
FC1/CryGame/Game.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1953 lines
51 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Game source code
//
// File: Game.cpp
//
// History:
// -August 02,2001: Create by Alberto Demichelis
// -Sep 24,2001 : Modified by Petar Kotevski
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <IStreamEngine.h>
#include <ICryPak.h>
#include "Game.h"
#include "XNetwork.h"
#include "XServer.h"
#include "XClient.h"
#include "UIHud.h"
#include "WeaponSystemEx.h"
#include "WeaponClass.h"
#include "XVehicleSystem.h"
#include "PlayerSystem.h"
#include "XServer.h"
#include "XSystemBase.h"
#include "UISystem.h"
#include "Flock.h"
#include "EntityClassRegistry.h"
#include "ScriptObjectGame.h"
#include "ScriptObjectInput.h"
#include "ScriptObjectLanguage.h"
#include "ScriptObjectPlayer.h"
#include "ScriptObjectSpectator.h" // CScriptObjectSpectator
#include "ScriptObjectAdvCamSystem.h" // CScriptObjectAdvCamSystem
#include "ScriptObjectSynched2DTable.h" // CScriptObjectSynched2DTable
#include "ScriptObjectVehicle.h"
#include "ScriptObjectRenderer.h"
#include "ScriptObjectStream.h"
#include "ScriptObjectWeaponClass.h"
#include "ScriptObjectAI.h"
#include "ScriptObjectUI.h"
#include "ScriptObjectBoids.h"
#include "ScriptTimerMgr.h"
#include "IngameDialog.h"
#include <IEntitySystem.h>
#include <ISound.h>
#include "TagPoint.h"
//#include "XPath.h"
#include "XPlayer.h"
#include "XVehicle.h"
#include <IMovieSystem.h>
#include "CMovieUser.h"
#include "TimeDemoRecorder.h"
#include "GameMods.h"
#ifdef WIN32
#include <winioctl.h>
#include <tchar.h>
typedef std::basic_string< TCHAR > tstring;
typedef std::vector< TCHAR > tvector;
#endif
//////////////////////////////////////////////////////////////////////////
// Pointer to Global ISystem.
static ISystem* gISystem = 0;
ISystem* GetISystem()
{
return gISystem;
}
//////////////////////////////////////////////////////////////////////////////////////////////
// DLL Interface
//////////////////////////////////////////////////////////////////////
// interface of the DLL
IGame* CreateGameInstance()
{
CXGame *pGame = new CXGame();
return pGame;
}
//////////////////////////////////////////////////////////////////////////////////////////////
// CTagPointManager
class CTagPointManager : public ITagPointManager
{
public:
CTagPointManager( IGame *pGame ) { m_pGame = (CXGame*) pGame; };
virtual ~CTagPointManager() {};
// This function creates a tag point in the game world
virtual ITagPoint *CreateTagPoint(const string &name, const Vec3 &pos, const Vec3 &angles)
{
return m_pGame->CreateTagPoint( name, pos, angles );
};
// Retrieves a tag point by name
virtual ITagPoint *GetTagPoint(const string &name)
{
return m_pGame->GetTagPoint( name );
}
// Deletes a tag point from the game
virtual void RemoveTagPoint(ITagPoint *pPoint)
{
m_pGame->RemoveTagPoint( pPoint );
}
virtual void AddRespawnPoint(ITagPoint *pPoint)
{
m_pGame->AddRespawnPoint( pPoint );
}
virtual void RemoveRespawnPoint(ITagPoint *pPoint)
{
m_pGame->RemoveRespawnPoint( pPoint );
}
private:
CXGame *m_pGame;
};
//////////////////////////////////////////////////////////////////////////////////////////////
// CXGame
//!constructor
CXGame::CXGame()
{
m_pTimeDemoRecorder = NULL;
m_pScriptObjectGame = NULL;
m_pScriptTimerMgr = NULL;
m_pScriptSystem = NULL;
m_pServer = NULL;
m_pClient = NULL;
m_pLog = NULL;
m_pServerSnooper = NULL;
m_pNETServerSnooper = 0;
m_pRConSystem = 0;
m_pWeaponSystemEx = NULL;
m_mapTagPoints.clear();
m_bMenuInitialized = false;
m_pCurrentUI = 0;
m_pIActionMapManager=NULL;
m_pIngameDialogMgr = new CIngameDialogMgr();
m_pUISystem = 0;
mp_model = 0;
#if !defined(LINUX)
// to avoid all references to movie user in this file
m_pMovieUser = new CMovieUser(this);
#endif
m_nPlayerIconTexId = -1;
m_nVehicleIconTexId = -1;
m_nBuildingIconTexId = -1;
m_nUnknownIconTexId = -1;
m_bMenuOverlay = false;
m_bUIOverlay = false;
m_bUIExclusiveInput = false;
m_bHideLocalPlayer = false;
m_pCVarCheatMode=NULL;
m_fTimeGran=m_fFixedStep=m_fTimeGran2FixedStep=m_frFixedStep = 0;
m_iFixedStep2TimeGran = 0;
g_language=0;
g_playerprofile=0;
g_serverprofile=0;
m_tPlayerPersistentData.m_bDataSaved=false;
m_fFadingStartTime=-1.0f;
cv_game_physics_quality=NULL;
m_bMapLoadedFromCheckpoint=false;
m_bSynchronizing = false;
//m_fTimeToSaveThumbnail = 0;
m_pGameMods = NULL;
m_bLastDoLateSwitch = 0;
m_bLastCDAuthentication = 0;
m_bAllowQuicksave = true;
m_sGameName = "FarCry";
m_pTagPointManager = new CTagPointManager( this );
m_nDEBUG_TIMING = 0;
m_fDEBUG_STARTTIMER = 0;
}
//////////////////////////////////////////////////////////////////////
//!destructor
CXGame::~CXGame()
{
m_pScriptSystem->BeginCall("Shutdown");
m_pScriptSystem->PushFuncParam(0);
m_pScriptSystem->EndCall();
if (m_pIngameDialogMgr)
delete m_pIngameDialogMgr;
m_pIngameDialogMgr=NULL;
#if !defined(LINUX)
if (m_pMovieUser)
{
if (m_pSystem)
{
IMovieSystem *pMovieSystem=m_pSystem->GetIMovieSystem();
if (pMovieSystem)
{
if (pMovieSystem->GetUser()==m_pMovieUser)
pMovieSystem->SetUser(NULL);
}
}
delete m_pMovieUser;
}
#endif
m_pMovieUser=NULL;
// shutdown the client if there is one
ShutdownClient();
// shutdown the server if there is one
ShutdownServer();
if (m_pUISystem)
{
m_pUISystem->Release();
}
SAFE_DELETE(m_pUISystem);
CScriptObjectUI::ReleaseTemplate();
CScriptObjectPlayer::ReleaseTemplate();
CScriptObjectFireParam::ReleaseTemplate();
CScriptObjectWeaponClass::ReleaseTemplate();
CScriptObjectVehicle::ReleaseTemplate();
CScriptObjectSpectator::ReleaseTemplate();
CScriptObjectAdvCamSystem::ReleaseTemplate();
CScriptObjectSynched2DTable::ReleaseTemplate();
CScriptObjectBoids::ReleaseTemplate();
CScriptObjectRenderer::ReleaseTemplate();
CScriptObjectGame::ReleaseTemplate();
CScriptObjectInput::ReleaseTemplate();
CScriptObjectLanguage::ReleaseTemplate();
CScriptObjectAI::ReleaseTemplate();
CScriptObjectServer::ReleaseTemplate();
CScriptObjectServerSlot::ReleaseTemplate();
CScriptObjectClient::ReleaseTemplate();
CScriptObjectStream::ReleaseTemplate();
cl_scope_flare->Release();
cl_ThirdPersonRange->Release();
cl_ThirdPersonOffs->Release();
cl_ThirdPersonOffsAngHor->Release();
cl_ThirdPersonOffsAngVert->Release();
cl_display_hud->Release();
cl_motiontracker->Release();
cl_hud_pickup_icons->Release();
cl_msg_notification->Release();
cl_hud_name->Release();
ai_num_of_bots->Release();
p_name->Release();
p_model->Release();
mp_model->Release();
p_color->Release();
p_always_run->Release();
g_language->Release();
g_playerprofile->Release();
g_serverprofile->Release();
g_GC_Frequence->Release();
p_speed_run->Release();
p_sprint_scale->Release();
p_sprint_decoy->Release();
p_sprint_restore_run->Release();
p_sprint_restore_idle->Release();
p_speed_walk->Release();
p_speed_crouch->Release();
p_speed_prone->Release();
p_jump_force->Release();
p_jump_run_time->Release();
p_jump_walk_time->Release();
// p_lean->Release();
p_lean_offset->Release();
p_bob_pitch->Release();
p_bob_roll->Release();
p_bob_length->Release();
p_bob_weapon->Release();
p_bob_fcoeff->Release();
p_weapon_switch->Release();
cv_game_physics_quality->Release();
m_jump_vel->Release();
m_jump_arc->Release();
b_camera->Release();
// f_update->Release();
// f_draw->Release();
// f_drawDbg->Release();
sv_timeout->Release();
cl_timeout->Release();
cl_loadtimeout->Release();
g_LevelName->Release();
g_GameType->Release();
g_LeftHanded->Release();
p_DeadBody->Release();
p_HitImpulse->Release();
p_RotateHead->Release();
a_DrawArea->Release();
a_LogArea->Release();
m_pCVarCheatMode->Release();
pl_JumpNegativeImpulse->Release();
if (m_pRenderer && (m_nPlayerIconTexId>=0))
m_pRenderer->RemoveTexture(m_nPlayerIconTexId);
if (m_pRenderer && (m_nVehicleIconTexId>=0))
m_pRenderer->RemoveTexture(m_nVehicleIconTexId);
if (m_pRenderer && (m_nBuildingIconTexId>=0))
m_pRenderer->RemoveTexture(m_nBuildingIconTexId);
if (m_pRenderer && (m_nUnknownIconTexId>=0))
m_pRenderer->RemoveTexture(m_nUnknownIconTexId);
SAFE_DELETE(m_pUIHud);
SAFE_DELETE(m_pWeaponSystemEx);
SAFE_DELETE(m_pVehicleSystem);
SAFE_DELETE(m_pPlayerSystem);
SAFE_DELETE(m_pFlockManager);
CScriptObjectPlayer::ReleaseTemplate();
//shutdown script stuff
SAFE_DELETE(m_pScriptObjectGame);
SAFE_DELETE(m_pScriptObjectInput);
SAFE_DELETE(m_pScriptObjectBoids);
SAFE_DELETE(m_pScriptObjectLanguage);
SAFE_DELETE(m_pScriptObjectAI);
// Release the action map
SAFE_RELEASE(m_pIActionMapManager);
SAFE_DELETE(m_pScriptTimerMgr);
// release the tags
if (!m_mapTagPoints.empty())
{
TagPointMap::iterator ti;
for (ti=m_mapTagPoints.begin();ti!=m_mapTagPoints.end();ti++)
delete ti->second;
}
SAFE_RELEASE(m_pServerSnooper);
SAFE_RELEASE(m_pNETServerSnooper);
SAFE_RELEASE(m_pRConSystem);
SAFE_DELETE(m_pTimeDemoRecorder);
SAFE_DELETE(m_pGameMods);
delete m_pTagPointManager;
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::InitClassRegistry()
{
m_EntityClassRegistry.Init( m_pSystem );
CPlayerSystem *pPlayerSystem = GetPlayerSystem();
CVehicleSystem *pVehicleSystem = GetVehicleSystem();
CWeaponSystemEx *pWeaponSystemEx = GetWeaponSystemEx(); // m10
assert( pPlayerSystem );
assert( pVehicleSystem );
assert( pWeaponSystemEx );
// Enumerate entity classes.
EntityClass *entCls = NULL;
m_EntityClassRegistry.MoveFirst();
do {
entCls = m_EntityClassRegistry.Next();
if (entCls)
{
const char* entity_type = entCls->strGameType.c_str();
EntityClassId ClassId = entCls->ClassId;
if(strcmp("Player",entity_type)==0)
pPlayerSystem->AddPlayerClass(ClassId);
if(strcmp("Vehicle",entity_type)==0)
pVehicleSystem->AddVehicleClass(ClassId);
if(strcmp("Projectile",entity_type)==0)
{
// cannot be loaded at that point - other scripts must be loaded before
pWeaponSystemEx->AddProjectileClass(ClassId);
}
}
} while (entCls);
return true;
}
//////////////////////////////////////////////////////////////////////////
void CXGame::SoftReset()
{
m_pLog->Log("Soft Reset Begin");
//allow to reload scripts with(LoadScript)
m_pScriptSystem->SetGlobalToNull("_localplayer");
if(m_pScriptSystem)
m_pScriptSystem->UnloadScripts();
std::vector<string> vLoadedWeapons;
for (int i = 0; i != m_pWeaponSystemEx->GetNumWeaponClasses(); ++i)
vLoadedWeapons.push_back(m_pWeaponSystemEx->GetWeaponClass(i)->GetName());
m_pWeaponSystemEx->Reset();
#if !defined(LINUX)
if (m_pSystem->GetIMovieSystem())
m_pSystem->GetIMovieSystem()->StopAllSequences();
#endif
m_pScriptObjectGame->Reset();
m_pScriptSystem->ForceGarbageCollection();
//m_p3DEngine->ClearRenderResources();
m_iLastCmdIdx = 0;
m_pWeaponSystemEx->Init(this);
for (std::vector<string>::iterator i = vLoadedWeapons.begin(); i != vLoadedWeapons.end(); ++i)
AddWeapon((*i).c_str());
//if (GetMyPlayer())
// GetMyPlayer()->SetNeedUpdate(true);
if (m_pCurrentUI)
{
m_pCurrentUI->Reset();
m_pCurrentUI->Init(m_pScriptSystem);
}
m_pLog->Log("Soft Reset End");
}
//////////////////////////////////////////////////////////////////////
//!reset the game before a level reloading
//!this function allow the reloading of all scripts
//!and wipe out all textures from the 3dengine
void CXGame::Reset()
{
m_pEntitySystem->Reset();
// Unload all music.
if (m_pSystem->GetIMusicSystem())
m_pSystem->GetIMusicSystem()->Unload();
//allow to reload scripts with(LoadScript)
m_pScriptSystem->SetGlobalToNull("_localplayer");
if(m_pScriptSystem)
m_pScriptSystem->UnloadScripts();
m_pWeaponSystemEx->Reset();
m_XSurfaceMgr.Reset();
m_XAreaMgr.Clear();
ClearTagPoints();
#if !defined(LINUX)
if (m_pSystem->GetIMovieSystem())
m_pSystem->GetIMovieSystem()->Reset(false);
#endif
m_pScriptObjectGame->Reset();
m_pScriptSystem->ForceGarbageCollection();
m_p3DEngine->ClearRenderResources();
// Must reset all timers.
m_pScriptTimerMgr->Reset();
//clen up the input buffer
if (m_pSystem->GetIInput())
{
m_pSystem->GetIInput()->Update(true);
m_pSystem->GetIInput()->Update(true);
}
if (m_pIActionMapManager)
m_pIActionMapManager->Reset();
m_iLastCmdIdx = 0;
//////////////////////////////////////////////////////////////////////////
// Reset UI.
//////////////////////////////////////////////////////////////////////////
if (m_pUISystem)
{
m_pUISystem->UnloadAllModels();
m_pUISystem->StopAllVideo();
m_p3DEngine->Enable(1);
//m_pSystem->GetILog()->Log("UISystem: Enabled 3D Engine!");
}
if (m_pCurrentUI)
m_pCurrentUI->Reset();
if (m_pUIHud)
m_pUIHud->Reset();
if (GetMyPlayer())
GetMyPlayer()->SetNeedUpdate(true);
}
IXSystem *CXGame::GetXSystem(){return m_pServer?m_pServer->m_pISystem:m_pClient?m_pClient->m_pISystem:NULL;}
//////////////////////////////////////////////////////////////////////
//! Initialize the game. This must be called before calling other functions of this class.
bool CXGame::Init(struct ISystem *pSystem,bool bDedicatedSrv,bool bInEditor,const char *szGameMod)
{
// Setup the system and 3D Engine pointers
m_pSystem = pSystem;
m_pGameMods = new CGameMods(this);
gISystem = pSystem;
m_bDedicatedServer=bDedicatedSrv;
m_XAreaMgr.Init( pSystem );
m_bEditor=bInEditor;
m_bRelaunch=false;
m_bMovieSystemPaused = false;
m_bIsLoadingLevelFromFile=false;
m_bOK = false;
m_bUpdateRet = true;
m_pClient = NULL;
m_pServer = NULL;
m_pSystem->GetILog()->Log("Game Initialization");
#if !defined(LINUX)
IMovieSystem *pMovieSystem=m_pSystem->GetIMovieSystem();
if (pMovieSystem)
pMovieSystem->SetUser(m_pMovieUser);
#endif
if (!m_pTimeDemoRecorder)
m_pTimeDemoRecorder = new CTimeDemoRecorder(pSystem);
m_pUIHud = NULL;
m_pNetwork= m_pSystem->GetINetwork();
m_pLog= m_pSystem->GetILog();
m_p3DEngine = m_pSystem->GetI3DEngine();
m_pRenderer = m_pSystem->GetIRenderer();
m_pScriptSystem=pSystem->GetIScriptSystem();
m_pEntitySystem=m_pSystem->GetIEntitySystem();
// Register game rendering callback.
//[Timur] m_p3DEngine->SetRenderCallback( OnRenderCallback,this );
// init subsystems
#ifndef _XBOX
m_pServerSnooper=m_pNetwork->CreateServerSnooper(this);
m_pNETServerSnooper=m_pNetwork->CreateNETServerSnooper(this);
m_pRConSystem=m_pNetwork->CreateRConSystem();
#endif
m_pWeaponSystemEx = new CWeaponSystemEx();
m_pVehicleSystem = new CVehicleSystem();
m_pPlayerSystem = new CPlayerSystem();
m_pFlockManager = new CFlockManager(m_pSystem);
CScriptObjectUI::InitializeTemplate(m_pScriptSystem);
// init is not necessary for now, but add here if it later is
m_pScriptObjectGame=new CScriptObjectGame;
CScriptObjectGame::InitializeTemplate(m_pScriptSystem);
m_pScriptObjectInput=new CScriptObjectInput;
CScriptObjectInput::InitializeTemplate(m_pScriptSystem);
m_pScriptObjectLanguage=new CScriptObjectLanguage;
CScriptObjectLanguage::InitializeTemplate(m_pScriptSystem);
m_pScriptObjectBoids = new CScriptObjectBoids;
CScriptObjectBoids::InitializeTemplate(m_pScriptSystem);
m_pScriptObjectAI = new CScriptObjectAI;
CScriptObjectAI::InitializeTemplate(m_pScriptSystem);
CScriptObjectServer::InitializeTemplate(m_pScriptSystem);
CScriptObjectPlayer::InitializeTemplate(m_pScriptSystem);
CScriptObjectFireParam::InitializeTemplate(m_pScriptSystem);
CScriptObjectWeaponClass::InitializeTemplate(m_pScriptSystem);
CScriptObjectVehicle::InitializeTemplate(m_pScriptSystem);
CScriptObjectSpectator::InitializeTemplate(m_pScriptSystem);
CScriptObjectAdvCamSystem::InitializeTemplate(m_pScriptSystem);
CScriptObjectSynched2DTable::InitializeTemplate(m_pScriptSystem);
CScriptObjectRenderer::InitializeTemplate(m_pScriptSystem);
m_pScriptObjectGame->Init(m_pScriptSystem, this);
m_pScriptObjectInput->Init(m_pScriptSystem,this,m_pSystem);
m_pScriptObjectBoids->Init(m_pScriptSystem,m_pSystem,m_pFlockManager);
m_pScriptObjectLanguage->Init(m_pScriptSystem,&m_StringTableMgr);
m_pScriptObjectAI->Init(m_pScriptSystem,m_pSystem,this);
CScriptObjectServerSlot::InitializeTemplate(m_pScriptSystem);
CScriptObjectClient::InitializeTemplate(m_pScriptSystem);
CScriptObjectStream::InitializeTemplate(m_pScriptSystem);
m_pScriptTimerMgr=new CScriptTimerMgr(m_pScriptSystem,m_pSystem->GetIEntitySystem(),this);
// making some constants accessable to the script
m_pScriptSystem->SetGlobalValue("FireActivation_OnPress",ePressing);
m_pScriptSystem->SetGlobalValue("FireActivation_OnRelease",eReleasing);
m_pScriptSystem->SetGlobalValue("FireActivation_OnHold",eHolding);
m_pScriptSystem->SetGlobalValue("ENTITYTYPE_PLAYER", ENTITYTYPE_PLAYER);
m_pScriptSystem->SetGlobalValue("ENTITYTYPE_WAYPOINT", ENTITYTYPE_WAYPOINT);
m_pScriptSystem->SetGlobalValue("ENTITYTYPE_OWNTEAM", ENTITYTYPE_OWNTEAM);
/* m_pScriptSystem->SetGlobalValue("CMD_GO", CMD_GO);
m_pScriptSystem->SetGlobalValue("CMD_ATTACK", CMD_ATTACK);
m_pScriptSystem->SetGlobalValue("CMD_DEFEND", CMD_DEFEND);
m_pScriptSystem->SetGlobalValue("CMD_COVER", CMD_COVER);
m_pScriptSystem->SetGlobalValue("CMD_BARRAGEFIRE", CMD_BARRAGEFIRE);*/
InitConsoleVars();
if (szGameMod && szGameMod[0])
{
// apply the mod without restarting as the game just started!
GetModsInterface()->SetCurrentMod(szGameMod,false);
}
InitClassRegistry();
// execute the "main"-script (to pre-load other scripts, etc.)
m_pScriptSystem->ExecuteFile("scripts/main.lua");
m_pScriptSystem->BeginCall("Init");
m_pScriptSystem->PushFuncParam(0);
m_pScriptSystem->EndCall();
// initialize the surface-manager
m_XSurfaceMgr.Init(m_pScriptSystem,m_p3DEngine,GetSystem()->GetIPhysicalWorld());
// init key-bindings
if(!m_bDedicatedServer)
InitInputMap();
// create various console-commands/variables
InitConsoleCommands();
// loading the main language-string-table
if (!m_StringTableMgr.Load(GetSystem(),*m_pScriptObjectLanguage,g_language->GetString()))
m_pLog->Log("cannot load language file [%s]",g_language->GetString());
// creating HUD interface
m_pLog->Log("Initializing UI");
m_pUIHud = new CUIHud(this,m_pSystem);
LoadConfiguration("","game.cfg");
//////////////////////////////////////////////////////////////////////////
// Materials
// load materials (once before all, this info stays till we quit the game - no need to load material later)
// first load normal materials
m_XSurfaceMgr.LoadMaterials("scripts/materials");
if(!m_bDedicatedServer)
{
m_pSystem->GetIConsole()->ShowConsole(0);
if (!bInEditor)
{
//-------------------------------------------------------------------------------------------------
m_pUISystem = new CUISystem;
if (m_pUISystem)
{
m_pUISystem->Create(this, m_pSystem, m_pScriptSystem, "Scripts/MenuScreens/UISystem.lua", 1);
}
else
{
m_pLog->Log("Failed to create UI System!");
}
//-------------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------
if (m_pUISystem)
{
m_bMenuOverlay = 1;
}
//-------------------------------------------------------------------------------------------------
}
else
m_pSystem->GetIConsole()->ShowConsole(true);
// load textures used as icons by the mini-map
if (m_pRenderer)
{
ITexPic *pPic;
pPic=m_pRenderer->EF_LoadTexture("gui/map_player", FT_NOREMOVE, 0, eTT_Base);
if (pPic && pPic->IsTextureLoaded())
m_nPlayerIconTexId=pPic->GetTextureID();
pPic=m_pRenderer->EF_LoadTexture("gui/map_vehicle", FT_NOREMOVE, 0, eTT_Base);
if (pPic && pPic->IsTextureLoaded())
m_nVehicleIconTexId=pPic->GetTextureID();
pPic=m_pRenderer->EF_LoadTexture("gui/map_building", FT_NOREMOVE, 0, eTT_Base);
if (pPic && pPic->IsTextureLoaded())
m_nBuildingIconTexId=pPic->GetTextureID();
pPic=m_pRenderer->EF_LoadTexture("gui/map_unknown", FT_NOREMOVE, 0, eTT_Base);
if (pPic && pPic->IsTextureLoaded())
m_nUnknownIconTexId=pPic->GetTextureID();
}
if(!bInEditor)
m_pEntitySystem->SetDynamicEntityIdMode(true);
#if !defined(_XBOX) && !defined(PS2) && !defined(LINUX)
SetCursor(NULL);
#endif
//////////////////////////////////////////////////////////////////////////
DevModeInit();
m_bOK = true;
e_deformable_terrain = NULL;
return (true);
}
//////////////////////////////////////////////////////////////////////
//! game-mainloop
bool CXGame::Run(bool &bRelaunch)
{
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF);
if(m_bDedicatedServer)
{
return Update();
}
else
{
//static float fLastFrame=0;
m_bRelaunch=false;
while(1)
{
if (!Update())
break;
}
bRelaunch=m_bRelaunch;
}
return true;
}
#if !defined(_XBOX) && !defined(PS2) && !defined(LINUX)
#include <Mmsystem.h>
#include ".\game.h"
#pragma comment (lib , "Winmm.lib")
#else
#define GetCurrentTime() ((unsigned int)(GetSystem()->GetITimer()->GetCurrTime() * 1000.f))
#endif
//////////////////////////////////////////////////////////////////////////
bool CXGame::IsInPause(IProcess *pProcess)
{
bool bPause = (m_bMenuOverlay && (!IsMultiplayer()));
//check if the game is in pause or in menu mode
if ((pProcess->GetFlags() & PROC_MENU) && !IsMultiplayer())
bPause=true;
return (bPause);
}
//////////////////////////////////////////////////////////////////////
//! update all game and children
bool CXGame::Update()
{
if (!m_nDEBUG_TIMING)
{
m_fDEBUG_STARTTIMER = m_pSystem->GetITimer()->GetAsyncCurTime();
m_nDEBUG_TIMING = 1;
}
if (!m_bEditor)
{
if (!m_bMenuOverlay || !m_pUISystem || m_pUISystem->GetScriptObjectUI()->CanRenderGame())
{
m_p3DEngine->Enable(1);
}
else
{
m_p3DEngine->Enable(0);
}
}
bool bRenderFrame = (!m_pSystem->GetViewCamera().GetPos().IsZero() || m_bMenuOverlay || m_bUIOverlay)
&& g_Render->GetIVal() != 0;
//////////////////////////////////////////////////////////////////////////
// Start Profiling frame
m_pSystem->GetIProfileSystem()->StartFrame();
//////////////////////////////////////////////////////////////////////////
FUNCTION_PROFILER( m_pSystem,PROFILE_GAME );
ITimer *pTimer=m_pSystem->GetITimer();
pTimer->MeasureTime("EnterGameUp");
//Timur[10/2/2002]
// Cannot Run Without System.
assert( m_pSystem );
float maxFPS=g_maxfps->GetFVal();
if(maxFPS>0)
{
// float extraTime = pTimer->GetAsyncCurTime() + 1.0f/maxFPS - pTimer->GetFrameTime();
// while(extraTime - pTimer->GetAsyncCurTime() > 0)
// ;
DWORD extraTime = (DWORD)((1.0f/maxFPS - pTimer->GetFrameTime())*1000.0f);
#if !defined(LINUX)
if(extraTime>0&&extraTime<300)//thread sleep not process sleep
Sleep(extraTime);
#endif
}
PhysicsVars *pVars = m_pSystem->GetIPhysicalWorld()->GetPhysVars();
float fTimeGran=pVars->timeGranularity, fFixedStep=g_MP_fixed_timestep->GetFVal();
if (fTimeGran!=m_fTimeGran || fFixedStep!=m_fFixedStep)
{
m_fTimeGran = fTimeGran; m_fFixedStep = fFixedStep;
if (fFixedStep>0)
{
m_fTimeGran2FixedStep = fTimeGran/fFixedStep;
m_iFixedStep2TimeGran = (int)(fFixedStep/fTimeGran+0.5f);
m_frFixedStep = 1.0f/fFixedStep;
}
else
m_iFixedStep2TimeGran = 0;
m_frTimeGran = 1.0f/fTimeGran;
}
pVars->bMultiplayer = IsMultiplayer() ? 1:0;
//check what is the current process
//bool bPause=false;
IProcess *pProcess=m_pSystem->GetIProcess();
if (!pProcess)
return false;
bool bPause=IsInPause(pProcess);
if (m_bIsLoadingLevelFromFile)
bPause=false;
#if !defined(LINUX)
// Pauses or unpauses movie system.
if (bPause != m_bMovieSystemPaused)
{
m_bMovieSystemPaused = bPause;
if (bPause)
m_pSystem->GetIMovieSystem()->Pause();
else
m_pSystem->GetIMovieSystem()->Resume();
}
#endif
// [marco] check current sound and vis areas
// for music etc.
CheckSoundVisAreas();
//int nStartGC=m_pScriptSystem->GetCGCount();
pTimer->MeasureTime("SomeStuff");
// update system
int nPauseMode=0;
if (bPause)
nPauseMode=1;
// TODO: Add pause mode for a cutscene currently playing (pausemode 2)
if (IsMultiplayer()) {
pe_params_flags pf; pf.flagsOR = pef_update;
for(ListOfPlayers::iterator pl=m_DeadPlayers.begin(); pl!=m_DeadPlayers.end(); pl++)
if ((*pl)->GetEntity() && (*pl)->GetEntity()->GetPhysics())
(*pl)->GetEntity()->GetPhysics()->SetParams(&pf);
}
if (!m_pSystem->Update(IsMultiplayer() ? ESYSUPDATE_MULTIPLAYER:0, nPauseMode)) //Update returns false when quitting
return (false);
if (IsMultiplayer()) {
pe_params_flags pf; pf.flagsAND = ~pef_update;
for(ListOfPlayers::iterator pl=m_DeadPlayers.begin(); pl!=m_DeadPlayers.end(); pl++)
if ((*pl)->GetEntity() && (*pl)->GetEntity()->GetPhysics())
(*pl)->GetEntity()->GetPhysics()->SetParams(&pf);
}
pTimer->MeasureTime("SysUpdate");
// [marco] after system update, retrigger areas if necessary
if (!bPause)
RetriggerAreas();
if (!bPause || (m_pClient && !m_pClient->IsConnected()))
{ // network start
FRAME_PROFILER( "GameUpdate:Client",m_pSystem,PROFILE_GAME );
// update client
if (m_pClient)
{
m_pClient->UpdateClientNetwork();
pTimer->MeasureTime("Net");
assert(m_pClient);
m_pClient->Update();
if(m_pClient->DestructIfMarked()) // to make sure the client is only released in one place - here
m_pClient=0;
}
pTimer->MeasureTime("ClServ Up");
////////UPDATE THE NETWORK
// [Anton] moved from after the rendering, so that the server has access to the most recent physics data
// update server
if (m_pServer)
{
FRAME_PROFILER( "GameUpdate:Server",m_pSystem,PROFILE_GAME );
m_pServer->Update();
}
pTimer->MeasureTime("EndServUp");
}
m_pNetwork->UpdateNetwork(); // used to update things like the UBI.com services
DWORD dwCurrentTimeInMS=GetCurrentTime();
if (!m_pSystem->IsDedicated())
{
if(m_pServerSnooper)
m_pServerSnooper->Update(dwCurrentTimeInMS);
if(m_pNETServerSnooper)
m_pNETServerSnooper->Update(dwCurrentTimeInMS);
}
if(m_pRConSystem)
{
if (m_pClient)
m_pRConSystem->Update( dwCurrentTimeInMS,m_pClient->GetNetworkClient() );
else
m_pRConSystem->Update(dwCurrentTimeInMS);
}
// network end
// system rendering
if (bRenderFrame)
{
// render begin must be always called anyway to clear buffer, draw buttons etc.
// even in menu mode
m_pSystem->RenderBegin();
m_pSystem->Render();
pTimer->MeasureTime("3SysRend");
}
// update the HUD
if (m_pCurrentUI && !bPause && m_pClient && m_pClient->m_bDisplayHud)
{
FRAME_PROFILER( "GameUpdate:HUD",m_pSystem,PROFILE_GAME );
// update hud itself
if(!m_pCurrentUI->Update())
m_bUpdateRet = false;
// update ingame-dialog-manager
if (m_pIngameDialogMgr)
m_pIngameDialogMgr->Update();
pTimer->MeasureTime("HUD Up");
}
if (m_pUISystem && m_pUISystem->IsEnabled())
{
FRAME_PROFILER("GameUpdate:UI", m_pSystem, PROFILE_GAME);
if (m_bMenuOverlay || m_bUIOverlay)
{
m_pUISystem->Update();
m_pUISystem->Draw();
}
}
if(a_DrawArea->GetIVal())
{
m_XAreaMgr.DrawAreas( m_pSystem );
pTimer->MeasureTime("XAreaDraw");
}
// print time profiling results
#ifndef PS2
pTimer->MeasureTime((const char*)-1);
#else
pTimer->MeasureTime("Time");
#endif
pTimer->MeasureTime("3TimeProf");
//NETWORK DEBUGGING
if(m_pClient && m_pClient->cl_netstats->GetIVal()!=0)
{
m_pClient->DrawNetStats();
}
if(m_pServer && m_pServer->sv_netstats->GetIVal()!=0)
{
m_pServer->DrawNetStats(m_pRenderer);
}
pTimer->MeasureTime("NetStats");
// end of frame
if (bRenderFrame)
{
// same thing as for render begin
if (m_pTimeDemoRecorder)
m_pTimeDemoRecorder->RenderInfo();
m_pSystem->RenderEnd();
}
pTimer->MeasureTime("3Rend Up");
// get messages from process
//char *szProcessMessage = m_pSystem->GetIProcess()->GetPMessage();
// process messages from process
{
if (m_fFadingStartTime>0)
{
if (((m_pSystem->GetITimer()->GetCurrTime())-m_fFadingStartTime)>1.5f)
{
m_fFadingStartTime=-1;
SendMessage(m_szLoadMsg);
}
}
while(!m_qMessages.empty())
{
string smsg=m_qMessages.front();
m_qMessages.pop();
ProcessPMessages(smsg.c_str());
}
// the messages can switch the game to menu or viceversa
bPause=IsInPause(pProcess);
}
//update script timers
if(m_pScriptTimerMgr)
m_pScriptTimerMgr->Update( (unsigned long)(pTimer->GetCurrTime()*1000) );
pTimer->MeasureTime("ScrTimerUp");
if(g_GC_Frequence->GetFVal()>0)
{
// Change Script Garbage collection frequency.
m_pSystem->SetGCFrequency(g_GC_Frequence->GetFVal());
}
//////////////////////////////////////////////////////////////////////////
// Special update function for developers mode.
//////////////////////////////////////////////////////////////////////////
if (IsDevModeEnable())
DevModeUpdate();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
pTimer->MeasureTime("EndGameUp");
//////////////////////////////////////////////////////////////////////////
// End Profiling Frame
m_pSystem->GetIProfileSystem()->EndFrame();
//////////////////////////////////////////////////////////////////////////
return (m_bUpdateRet);
}
void CXGame::UpdateDuringLoading()
{
/* // to find areas where the function should be called more often
{
static DWORD dwTime=GetTickCount();
DWORD dwNewTime=GetTickCount();
DWORD dwRelative = dwNewTime-dwTime;
if(dwRelative>1000)
m_pSystem->GetILog()->Log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UpdateDuringLoading %d",dwRelative);
else
m_pSystem->GetILog()->Log("UpdateDuringLoading %d",dwRelative);
dwTime=dwNewTime;
}
*/
if(m_pServer)
m_pServer->UpdateXServerNetwork();
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::ParseLevelName(const char *szMsg,char *szLevelName,char *szMissionName)
{
const char *szPtr=szMsg;
char *szDest;
// get level & mission-name
szPtr=szMsg+11; //skip "StartLevel "
//find the level name
memset(szLevelName,0,32);
szDest=szLevelName;
while ((*szPtr) && (*szPtr!=' '))
*szDest++=*szPtr++;
//find the mission name
memset(szMissionName,0,32);
if (*szPtr) //if not eos
{
szPtr++; //skip space
szDest=szMissionName;
while (*szPtr)
*szDest++=*szPtr++;
}
return (true);
}
//////////////////////////////////////////////////////////////////////
//Process the process messages
//it is needed for example to perform actions that must be done
//the next frame
void CXGame::ProcessPMessages(const char *szMsg)
{
if (!szMsg)
return;
if ((stricmp(szMsg,"EndDemo") == 0) || (stricmp(szMsg,"EndDemoQuit") == 0)) // used for demos (e3, magazine demos)
{
ITexPic * pPic = m_pRenderer->EF_LoadTexture("Textures/end_screen.dds", FT_NORESIZE, 0, eTT_Base);
int img = -1;
if (pPic)
{
img = pPic->GetTextureID();
}
GetSystem()->GetIRenderer()->BeginFrame();
//GetSystem()->GetIRenderer()->Draw2dImage(0,0,(float)(GetSystem()->GetIRenderer()->GetWidth()),(float)(GetSystem()->GetIRenderer()->GetHeight()),img,0,1.0f,1.0f,0);
// hack! hardcoded to fix the incorrect d3d9 renderer matrix
GetSystem()->GetIRenderer()->SetState(GS_NODEPTHTEST);
GetSystem()->GetIRenderer()->Draw2dImage(0,0,(float)(800),(float)(600),img,0,1.0f,1.0f,0);
GetSystem()->GetIRenderer()->Update();
float time = GetSystem()->GetITimer()->GetCurrTime();
// wait a bit and then quit the game
while((GetSystem()->GetITimer()->GetCurrTime()-time) < 7)
{
GetSystem()->GetITimer()->Update();
}
if (stricmp(szMsg,"EndDemoQuit") == 0)
{
m_bUpdateRet = false;
}
else
{
this->SendMessage("Switch");
}
return;
}
else
if (stricmp(szMsg,"Quit-Yes") == 0) // quit message
{
m_bUpdateRet = false;
return;
}
else
if (stricmp(szMsg,"Relaunch") == 0) // relaunch message
{
m_bRelaunch = true;
m_bUpdateRet = false;
return;
}
else
if (stricmp(szMsg,"Switch")==0) // switch process (menu <> game)
{
//clear the current message
// ::OutputDebugString("###############switch#############\n");
//m_pSystem->GetIProcess()->SetPMessage("");
if(m_bEditor) return; // we are probably in the editor?
if (m_bMenuOverlay) // we're in menu-mode; switch to game
{
//check if a game is currently running before switching to
//the 3d-engine
CPlayer *pPlayer = 0;
if (GetMyPlayer())
{
GetMyPlayer()->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void **)&pPlayer);
}
// there must be a client for us to be able to go out of the menu
// if this is a singleplayer game, and the player is alive, we can go back to game
// otherwise, if this is not multiplayer game and the player is dead, it is locked in the menu
// also, the client must not be loading, or waiting to connect
if (m_pClient && m_pClient->IsConnected() && m_pUISystem->GetScriptObjectUI()->CanSwitch(0))
{
if (IsMultiplayer() || (!pPlayer || pPlayer->m_stats.health > 0))
{
MenuOff();
}
}
}
else if (m_pUISystem->GetScriptObjectUI()->CanSwitch(1))
{
// ::OutputDebugString("->menu\n");
// quit if menu disabled (usefull during development)
ICVar * pCvarNoMenu = m_pSystem->GetIConsole()->CreateVariable("g_NoMenu","0",0);
if(pCvarNoMenu && pCvarNoMenu->GetIVal())
{
m_pSystem->Quit();
return;
}
MenuOn();
}
}
else if (stricmp(szMsg, "EndCutScene")==0)
{
if (m_bMenuOverlay) // we're in menu-mode; switch to game
{
if (m_pClient)
{
MenuOff();
}
else if(!IsMultiplayer())
{
// there's no game, so lets quit...
// exit from game-must be prompted with "Are you Sure?"
m_pSystem->Quit();
}
}
}
else if (stricmp(szMsg,"LoadLastCheckPoint")==0)
{
// the loading funciotn calls game->update 20 times(??)
// and the script menu system allows to click the reload
// button again during game->update, so be sure that the game isn't
// loading already
if (!m_bIsLoadingLevelFromFile)
{
LoadLatest();
}
}
else if (strnicmp(szMsg,"StartLevelFade",14)==0) // start a level with fade out
{
if (!m_bEditor)
{
ICVar *g_LevelStated = GetISystem()->GetIConsole()->GetCVar("g_LevelStated");
if (g_LevelStated && g_LevelStated->GetIVal() && m_pClient && m_pClient->IsConnected())
{
HSCRIPTFUNCTION pfnDisplayLevelStats = m_pScriptSystem->GetFunctionPtr("Game", "DisplayTimeZone");
if (pfnDisplayLevelStats)
{
m_pScriptSystem->BeginCall(pfnDisplayLevelStats);
m_pScriptSystem->PushFuncParam(GetScriptObject());
m_pScriptSystem->EndCall();
m_pScriptSystem->ReleaseFunc(pfnDisplayLevelStats);
}
}
else
{
m_p3DEngine->ResetScreenFx();
m_p3DEngine->SetScreenFx("ScreenFade",1);
float fFadeTime=1.5f;
m_p3DEngine->SetScreenFxParam("ScreenFade","ScreenFadeTime", &fFadeTime);
m_fFadingStartTime=m_pSystem->GetITimer()->GetCurrTime();
AllowQuicksave(false);
sprintf(m_szLoadMsg,"StartLevel%s",szMsg+14); // skip levelfade
// disable input handling during fading to load
m_pSystem->GetIInput()->EnableEventPosting(0);
}
}
else
m_pSystem->GetILog()->Log("Skipping Load Level in editor (%s)",szMsg);
}
else if (strnicmp(szMsg,"StartLevel",10)==0) // start a level
{
if (!m_bEditor)
{
ICVar *g_LevelStated = GetISystem()->GetIConsole()->GetCVar("g_LevelStated");
if (g_LevelStated && g_LevelStated->GetIVal() && m_pClient && m_pClient->IsConnected())
{
HSCRIPTFUNCTION pfnDisplayLevelStats = m_pScriptSystem->GetFunctionPtr("Game", "DisplayTimeZone");
if (pfnDisplayLevelStats)
{
m_pScriptSystem->BeginCall(pfnDisplayLevelStats);
m_pScriptSystem->PushFuncParam(GetScriptObject());
m_pScriptSystem->EndCall();
m_pScriptSystem->ReleaseFunc(pfnDisplayLevelStats);
}
}
else
{
char szLevelName[32];
char szMissionName[32];
m_p3DEngine->ResetScreenFx();
// always disable cryvision at start
m_p3DEngine->SetScreenFx("NightVision",0);
// reset fading in case someone will load a level
// while the current one is fading out
m_fFadingStartTime=-1;
m_p3DEngine->SetScreenFx("ScreenFade",0);
ParseLevelName(szMsg,szLevelName,szMissionName);
bool listen = false;
if (strcmp(szMissionName, "listen")==0)
{
szMissionName[0] = 0;
//strcpy( szMissionName,"" );
listen = true;
};
// disable input handling during load
m_pSystem->GetIInput()->EnableEventPosting(0);
m_pSystem->GetIInput()->GetIKeyboard()->ClearKeyState();
LoadLevelCS(false, szLevelName, szMissionName, listen);
// finished loading, reenable input handling
m_pSystem->GetIInput()->EnableEventPosting(1);
m_pSystem->GetIInput()->GetIKeyboard()->ClearKeyState();
}
}
else
m_pSystem->GetILog()->Log("Skipping Load Level in editor (%s)",szMsg);
}
else
if (strnicmp(szMsg,"SaveGame", 8)==0) // save current game
{
if(!m_bEditor)
{
//clear the current message
// m_pSystem->GetIProcess()->SetPMessage("");
const char *sname="quicksave";
if(strlen(szMsg)>8) {
sname=szMsg+9;
}
Save(sname, NULL, NULL);
}
}
else
if (strnicmp(szMsg,"LoadGame", 8)==0) // load game
{
if(!m_bEditor)
{
m_p3DEngine->ResetScreenFx();
//clear the current message
// m_pSystem->GetIProcess()->SetPMessage("");
const char *sname="quicksave";
if(strlen(szMsg)>8)
{
sname=szMsg+9;
}
// disable input handling during load
m_pSystem->GetIInput()->EnableEventPosting(0);
//m_pSystem->GetIInput()->GetIKeyboard()->ClearKeyState();
// get out of all the areas localplayer is in - on load it will be retrigererd
IEntity *pIMyPlayer = GetMyPlayer();
if( pIMyPlayer )
{
IEntityContainer *pIContainer = pIMyPlayer->GetContainer();
if (pIContainer)
{
CPlayer *pPlayer = NULL;
if (pIContainer->QueryContainerInterface(CIT_IPLAYER, (void**)&pPlayer))
m_XAreaMgr.ExitAllAreas( pPlayer->m_AreaUser );
}
}
if (Load(sname))
{
//if loaded successfull, switch to 3d engine
if(m_pClient)
{
m_pSystem->SetIProcess(m_p3DEngine);
m_pSystem->GetIProcess()->SetFlags(PROC_3DENGINE);
}
}
// finished loading, reenable input
m_pSystem->GetIInput()->EnableEventPosting(1);
//m_pSystem->GetIInput()->GetIKeyboard()->ClearKeyState();
}
}
// else
// if (stricmp(szMsg,"ConnectTo")==0)
// {
// }
}
//////////////////////////////////////////////////////////////////////////
/*! Load a level on the local machine (connecting with a local client)
@param dedicated if true the local client will not be created
@param keepclient if true the current client server connection will be kept
@param szMapName name of the level that has to be loaded
@param szMissionName name of the mission that has to be loaded
@param listen allow external clients to connect
*/
//////////////////////////////////////////////////////////////////////////
void CXGame::LoadLevelCS(bool keepclient, const char *szMapName, const char *szMissionName, bool listen)
{
// need to reset timers as well
m_pScriptTimerMgr->Reset();
if (m_pUISystem)
{
m_pUISystem->GetScriptObjectUI()->OnSwitch(0);
m_pUISystem->StopAllVideo();
m_p3DEngine->Enable(1);
m_pSystem->GetILog()->Log("UISystem: Enabled 3D Engine!");
}
#if !defined(LINUX)
if (m_pSystem->GetIMovieSystem())
m_pSystem->GetIMovieSystem()->StopAllCutScenes();
//m_lstPlayedCutScenes.clear();
#endif
bool bDedicated=GetSystem()->IsDedicated();
string strGameType = g_GameType->GetString();
AutoSuspendTimeQuota AutoSuspender(GetSystem()->GetStreamEngine());
assert( szMissionName != 0 );
string sLevelFolder = szMapName;
if (sLevelFolder.find('\\') == string::npos && sLevelFolder.find('/') == string::npos)
{
// This is just a map name, not a folder.
sLevelFolder = GetLevelsFolder() + "/" + sLevelFolder;
}
IConsole *pConsole=GetSystem()->GetIConsole();
IInput *pInput=GetSystem()->GetIInput(); // might be 0 (e.g. dedicated server)
if(pInput)
pInput->SetMouseExclusive(false);
//if(!*szMissionName) szMissionName = "Multiplayer";
if (!IsMultiplayer())
{
m_pSystem->GetIConsole()->Clear();
m_pSystem->GetIConsole()->SetScrollMax(600);
m_pSystem->GetIConsole()->ShowConsole(true);
string sLoadingScreenTexture = string("levels/") + string(szMapName) + string("/loadscreen_") + string(szMapName) + ".dds";
m_pSystem->GetIConsole()->SetLoadingImage(sLoadingScreenTexture.c_str());
m_pSystem->GetIConsole()->ResetProgressBar(0x7fffffff);
m_pSystem->GetILog()->UpdateLoadingScreen(""); // just to draw the console
}
if (m_pClient && !keepclient)
{
ShutdownClient();
}
// start server
if((!m_pServer || !keepclient) && !StartupServer(listen))
{
m_pLog->LogToConsole("Unable to load the level %s,%s [startup server failed]", sLevelFolder.c_str(),szMissionName);
if(pInput)
pInput->SetMouseExclusive(true);
LoadingError("@LoadLevelError");
return;
}
bool bNeedClient = !bDedicated && ((keepclient && !m_pClient) || !keepclient);
//create local client(must be before the level is loaded)
if(bNeedClient)
{
if(!StartupLocalClient())
{
m_pLog->LogToConsole("Unable to load the level %s,mission %s [startup client failed]", sLevelFolder.c_str(),szMissionName);
if(pInput)
pInput->SetMouseExclusive(true);
LoadingError("@LoadLevelError");
return;
}
}
const char *szMission = szMissionName;
if (!*szMissionName)
szMission=strGameType.c_str();
// KIRILL lets reset - they will be spawned anyway
m_pSystem->GetAISystem()->Reset();
// refresh the current server info for incoming queries during loading
m_pServer->GetServerInfo();
// load the level
if(!m_pServer->m_pISystem->LoadLevel( sLevelFolder.c_str(),szMission,false))
{
m_pLog->LogToConsole("Unable to load the level %s,mission %s \n", sLevelFolder.c_str(),szMissionName);
if (pInput)
pInput->SetMouseExclusive(true);
LoadingError("@LoadLevelError");
return;
}
// start and connect a local client
if(bNeedClient)
{
if(m_pClient)
{
if (IsMultiplayer() && m_pServer->m_pIServer->GetServerType()!=eMPST_LAN)
m_pClient->XConnect("127.0.0.1",false,true);
else
m_pClient->XConnect("127.0.0.1");
}
}
if(m_pClient)
m_pClient->OnMapChanged();
if(m_pServer)
m_pServer->OnMapChanged();
if(pInput)
pInput->SetMouseExclusive(true);
AllowQuicksave(true);
};
//////////////////////////////////////////////////////////////////////////
bool CXGame::GetLevelMissions( const char *szLevelDir,std::vector<string> &missions )
{
string sLevelPath = szLevelDir;
if (!szLevelDir || sLevelPath.empty())
return false;
string sEPath = sLevelPath+string("/levelinfo.xml");
string sPaks = sLevelPath + "/*.pak";
//GetSystem()->GetIPak()->OpenPacks(sPaks.c_str());
OpenPacks(sPaks.c_str());
XmlNodeRef root = GetSystem()->LoadXmlFile( sEPath.c_str() );
bool bResult = false;
if (root)
{
XmlNodeRef missionsNode = root->findChild( "Missions" );
if (missionsNode)
{
// we found a mission node - the level is valid
bResult = true;
for (int i = 0; i < missionsNode->getChildCount(); i++)
{
XmlNodeRef missionNode = missionsNode->getChild(i);
if (missionNode->isTag( "Mission" ))
{
const char *sMissionName = missionNode->getAttr( "Name" );
if (sMissionName)
missions.push_back( sMissionName );
}
}
}
}
//GetSystem()->GetIPak()->
ClosePacks(sPaks.c_str());
return bResult;
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::IsMultiplayer()
{
// cannot be in multiplayer when in editor
if (m_bEditor)
return false;
bool bServer=IsServer();
bool bClient=IsClient();
if(!bServer && !bClient)
return false;
return !bServer || !bClient || m_pServer->m_bListen;
};
//////////////////////////////////////////////////////////////////////////
void CXGame::ResetState(void)
{
// m_PlayersWithLighs.clear();
m_pSystem->GetIEntitySystem()->ResetEntities();
if (GetMyPlayer())
{
m_XAreaMgr.ReTriggerArea(GetMyPlayer(), GetMyPlayer()->GetPos(),false);
GetMyPlayer()->SetNeedUpdate(true);
}
m_pSystem->GetIInput()->Update(1); // flush the keyboard buffers
m_pSystem->GetIInput()->Update(1); // flush the keyboard buffers
m_pSystem->GetIInput()->GetIKeyboard()->ClearKeyState();
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::ConstrainToSandbox(IEntity *pEntity)
{
bool bPosChanged = false;
if (IsMultiplayer())
{
Vec3 vPos, vBounds[2]={Vec3(0,0,0),Vec3(0,0,0)};
IPhysicalEntity *pPhysEnt = pEntity->GetPhysics();
if (pPhysEnt)
{
pe_status_pos sp;
pPhysEnt->GetStatus(&sp);
vPos = sp.pos;
}
else
vPos=pEntity->GetPos();
vBounds[1].x = vBounds[1].y = (float)m_p3DEngine->GetTerrainSize();
vBounds[0].z = -100; vBounds[1].z = 500;
for(int i=0;i<3;i++)
if (!inrange(vPos[i], vBounds[0][i],vBounds[1][i]))
{
vPos[i] = vBounds[isneg((vBounds[0][i]+vBounds[1][i])*0.5f-vPos[i])][i];
bPosChanged = true;
}
if (bPosChanged)
{
if (pPhysEnt)
{
pe_params_pos pp;
pp.pos = vPos;
pPhysEnt->SetParams(&pp);
}
else
pEntity->SetPos(vPos);
}
}
return bPosChanged;
}
//////////////////////////////////////////////////////////////////////////
void CXGame::GotoMenu(bool bTriggerOnSwitch)
{
if(m_bEditor)
return;
if(!m_pUISystem) // e.g. dedicated server
return;
if (!IsInMenu())
{
DeleteMessage("Switch");
SendMessage("Switch");
}
else if (bTriggerOnSwitch)
{
m_pUISystem->GetScriptObjectUI()->OnSwitch(1);
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::GotoGame(bool bTriggerOnSwitch)
{
if (m_bEditor)
{
return;
}
if (IsInMenu())
{
DeleteMessage("Switch");
SendMessage("Switch");
}
else if (bTriggerOnSwitch)
{
m_pUISystem->GetScriptObjectUI()->OnSwitch(0);
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::MenuOn()
{
// stop sounds and timers affected by game pause
m_pSystem->GetISoundSystem()->Pause(true,true);
m_pScriptTimerMgr->Pause(true);
if (m_pSystem->GetIMusicSystem())
{
m_pSystem->GetIMusicSystem()->Pause(true);
//m_pSystem->GetIMusicSystem()->Silence();
}
if (m_pUISystem && m_pUISystem->IsEnabled())
{
m_pSystem->GetIInput()->AddEventListener(m_pUISystem);
m_pSystem->GetIInput()->ClearKeyState();
m_pUISystem->GetScriptObjectUI()->OnSwitch(1);
}
m_bMenuOverlay = 1;
if (!m_bEditor)
{
if (m_pUISystem->GetScriptObjectUI()->CanRenderGame())
{
m_pSystem->GetILog()->Log("UISystem: Enabled 3D Engine!");
m_p3DEngine->Enable(1);
}
else
{
m_pSystem->GetILog()->Log("UISystem: Disabled 3D Engine!");
m_p3DEngine->Enable(0);
}
}
_SmartScriptObject pClientStuff(m_pScriptSystem, true);
if(m_pScriptSystem->GetGlobalValue("ClientStuff",pClientStuff))
{
m_pScriptSystem->BeginCall("ClientStuff","OnPauseGame");
m_pScriptSystem->PushFuncParam(pClientStuff);
m_pScriptSystem->EndCall();
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::MenuOff()
{
// resume sounds and timers affected by game pause
m_pSystem->GetISoundSystem()->Pause(false);
m_pSystem->GetIMusicSystem()->Pause(false);
m_pScriptTimerMgr->Pause(false);
if (m_pUISystem && m_pUISystem->IsEnabled())
{
m_pSystem->GetIInput()->RemoveEventListener(m_pUISystem);
m_pSystem->GetIInput()->ClearKeyState();
m_pUISystem->GetScriptObjectUI()->OnSwitch(0);
if (GetMyPlayer())
m_XAreaMgr.ReTriggerArea(GetMyPlayer(), GetMyPlayer()->GetPos(),false);
// m_XAreaMgr.ReTriggerArea(GetMyPlayer(), m_pSystem->GetISoundSystem()->GetListenerPos(),false);
}
m_bMenuOverlay = 0;
m_pSystem->SetIProcess(m_p3DEngine);
m_pSystem->GetIProcess()->SetFlags(PROC_3DENGINE);
if (!m_bEditor)
{
m_pSystem->GetILog()->Log("UISystem: Enabled 3D Engine!");
m_p3DEngine->Enable(1);
}
_SmartScriptObject pClientStuff(m_pScriptSystem, true);
if(m_pScriptSystem->GetGlobalValue("ClientStuff",pClientStuff))
{
m_pScriptSystem->BeginCall("ClientStuff","OnResumeGame");
m_pScriptSystem->PushFuncParam(pClientStuff);
m_pScriptSystem->EndCall();
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::DeleteMessage(const char *szMessage)
{
StringQueue NewQueue;
while(!m_qMessages.empty())
{
string qMessage = m_qMessages.front();
m_qMessages.pop();
if (qMessage != szMessage)
{
NewQueue.push(qMessage);
}
}
m_qMessages = NewQueue;
}
//////////////////////////////////////////////////////////////////////////
IScriptObject *CXGame::GetScriptObject()
{
if (!m_pScriptObjectGame)
{
return 0;
}
return m_pScriptObjectGame->GetScriptObject();
}
void CXGame::PlaySubtitle(ISound * pSound)
{
#if !defined(LINUX)
if (m_pMovieUser)
m_pMovieUser->PlaySubtitles(pSound);
#endif
}
vector2f CXGame::GetSubtitleSize(const string &szMessage, float sizex, float sizey, const string &szFontName, const string &szFontEffect)
{
IFFont *pFont = m_pSystem->GetICryFont()->GetFont(szFontName.c_str());
pFont->Reset();
pFont->SetEffect(szFontEffect.c_str());
pFont->SetSize(vector2f(sizex, sizey));
wstring szwString;
m_StringTableMgr.Localize(szMessage, szwString);
return pFont->GetTextSizeW(szwString.c_str());
}
void CXGame::WriteSubtitle(const string &szMessage, float x, float y, float sizex, float sizey, const color4f &cColor, const string &szFontName, const string &szFontEffect)
{
IFFont *pFont = m_pSystem->GetICryFont()->GetFont(szFontName.c_str());
pFont->Reset();
pFont->SetEffect(szFontEffect.c_str());
pFont->SetSize(vector2f(sizex, sizey));
pFont->SetColor(cColor);
wstring szwString;
m_StringTableMgr.Localize(szMessage, szwString);
pFont->DrawStringW(x, y, szwString.c_str());
}
//////////////////////////////////////////////////////////////////////////
IGameMods* CXGame::GetModsInterface()
{
return m_pGameMods;
};
//////////////////////////////////////////////////////////////////////////
void CXGame::LoadingError(const char *szError)
{
m_pRenderer->ClearColorBuffer(Vec3(0,0,0));
GetSystem()->GetIConsole()->ResetProgressBar(0);
m_pSystem->GetIConsole()->ShowConsole(false);
m_pSystem->GetIConsole()->SetScrollMax(600/2);
m_pScriptSystem->BeginCall("Game", "OnLoadingError");
m_pScriptSystem->PushFuncParam(GetScriptObject());
m_pScriptSystem->PushFuncParam(szError);
m_pScriptSystem->EndCall();
}
//-------------------------------------------------------------------------------------------------
bool CXGame::GetCDPath(string &szCDPath)
{
bool bRet( false );
#ifdef WIN32
DWORD nBufferSize( GetLogicalDriveStrings( 0, 0 ) );
if( 0 < nBufferSize )
{
// get list of all available logical drives
tvector rawDriveLetters( nBufferSize + 1 );
GetLogicalDriveStrings( nBufferSize, &rawDriveLetters[ 0 ] );
// quickly scan all drives
tvector::size_type i( 0 );
while( true )
{
// check if current drive is cd/dvd drive
if( DRIVE_CDROM == GetDriveType( &rawDriveLetters[ i ] ) )
{
// get volume name
tvector cdVolumeName( MAX_VOLUME_ID_SIZE + 1 );
if( FALSE != GetVolumeInformation( &rawDriveLetters[ i ],
&cdVolumeName[ 0 ], (DWORD) cdVolumeName.size(), 0, 0, 0, 0, 0 ) )
{
// check volume name to verify it's Far Cry's game cd/dvd
tstring cdVolumeLabel( &cdVolumeName[ 0 ] );
tstring farCryDisk1Label( _T( "FARCRY_1" ) );
if( cdVolumeLabel == farCryDisk1Label )
{
// found Far Cry's game cd/dvd, copy information and bail out
szCDPath = &rawDriveLetters[ i ];
bRet = true;
break;
}
}
}
// proceed to next drive
while( 0 != rawDriveLetters[ i ] )
{
++i;
}
++i; // skip null termination of current drive
// check if we're out of drive letters
if( 0 == rawDriveLetters[ i ] )
{
// double null termination found, bail out
break;
}
}
}
#endif
return( bRet );
}
ITagPointManager* CXGame::GetTagPointManager()
{
return m_pTagPointManager;
}