2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code 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 .
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
# include "Game_local.h"
# ifdef GAME_DLL
2012-11-28 15:47:07 +00:00
idSys * sys = NULL ;
idCommon * common = NULL ;
idCmdSystem * cmdSystem = NULL ;
idCVarSystem * cvarSystem = NULL ;
idFileSystem * fileSystem = NULL ;
idRenderSystem * renderSystem = NULL ;
idSoundSystem * soundSystem = NULL ;
idRenderModelManager * renderModelManager = NULL ;
idUserInterfaceManager * uiManager = NULL ;
idDeclManager * declManager = NULL ;
idAASFileManager * AASFileManager = NULL ;
idCollisionModelManager * collisionModelManager = NULL ;
idCVar * idCVar : : staticVars = NULL ;
idCVar com_forceGenericSIMD ( " com_forceGenericSIMD " , " 0 " , CVAR_BOOL | CVAR_SYSTEM , " force generic platform independent SIMD " ) ;
2012-11-26 18:58:24 +00:00
# endif
2012-11-28 15:47:07 +00:00
idRenderWorld * gameRenderWorld = NULL ; // all drawing is done to this world
idSoundWorld * gameSoundWorld = NULL ; // all audio goes to this world
2012-11-26 18:58:24 +00:00
static gameExport_t gameExport ;
// global animation lib
idAnimManager animationLib ;
// the rest of the engine will only reference the "game" variable, while all local aspects stay hidden
idGameLocal gameLocal ;
2012-11-28 15:47:07 +00:00
idGame * game = & gameLocal ; // statically pointed at an idGameLocal
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
const char * idGameLocal : : sufaceTypeNames [ MAX_SURFACE_TYPES ] =
{
2012-11-26 18:58:24 +00:00
" none " , " metal " , " stone " , " flesh " , " wood " , " cardboard " , " liquid " , " glass " , " plastic " ,
" ricochet " , " surftype10 " , " surftype11 " , " surftype12 " , " surftype13 " , " surftype14 " , " surftype15 "
} ;
idCVar net_usercmd_timing_debug ( " net_usercmd_timing_debug " , " 0 " , CVAR_BOOL , " Print messages about usercmd timing. " ) ;
// List of all defs used by the player that will stay on the fast timeline
2012-12-11 22:48:55 +00:00
static const char * fastEntityList [ ] =
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
" player_doommarine " ,
2012-11-28 15:47:07 +00:00
" weapon_chainsaw " ,
" weapon_fists " ,
" weapon_flashlight " ,
" weapon_rocketlauncher " ,
" projectile_rocket " ,
" weapon_machinegun " ,
" projectile_bullet_machinegun " ,
" weapon_pistol " ,
" projectile_bullet_pistol " ,
" weapon_handgrenade " ,
" projectile_grenade " ,
" weapon_bfg " ,
" projectile_bfg " ,
" weapon_chaingun " ,
" projectile_chaingunbullet " ,
" weapon_pda " ,
" weapon_plasmagun " ,
" projectile_plasmablast " ,
" weapon_shotgun " ,
" projectile_bullet_shotgun " ,
" weapon_soulcube " ,
" projectile_soulblast " ,
" weapon_shotgun_double " ,
" projectile_shotgunbullet_double " ,
" weapon_grabber " ,
" weapon_bloodstone_active1 " ,
" weapon_bloodstone_active2 " ,
" weapon_bloodstone_active3 " ,
" weapon_bloodstone_passive " ,
NULL
} ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = =
GetGameAPI
= = = = = = = = = = = =
*/
# if __MWERKS__
# pragma export on
# endif
# if __GNUC__ >= 4
# pragma GCC visibility push(default)
# endif
2012-11-28 15:47:07 +00:00
extern " C " gameExport_t * GetGameAPI ( gameImport_t * import )
{
2012-11-26 18:58:24 +00:00
# if __MWERKS__
# pragma export off
# endif
2012-11-28 15:47:07 +00:00
if ( import - > version = = GAME_API_VERSION )
{
2012-11-26 18:58:24 +00:00
// set interface pointers used by the game
sys = import - > sys ;
common = import - > common ;
cmdSystem = import - > cmdSystem ;
cvarSystem = import - > cvarSystem ;
fileSystem = import - > fileSystem ;
renderSystem = import - > renderSystem ;
soundSystem = import - > soundSystem ;
renderModelManager = import - > renderModelManager ;
uiManager = import - > uiManager ;
declManager = import - > declManager ;
AASFileManager = import - > AASFileManager ;
collisionModelManager = import - > collisionModelManager ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set interface pointers used by idLib
idLib : : sys = sys ;
idLib : : common = common ;
idLib : : cvarSystem = cvarSystem ;
idLib : : fileSystem = fileSystem ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup export interface
gameExport . version = GAME_API_VERSION ;
gameExport . game = game ;
gameExport . gameEdit = gameEdit ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return & gameExport ;
}
# if __GNUC__ >= 4
# pragma GCC visibility pop
# endif
/*
= = = = = = = = = = =
TestGameAPI
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void TestGameAPI ( )
{
2012-11-26 18:58:24 +00:00
gameImport_t testImport ;
gameExport_t testExport ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
testImport . sys = : : sys ;
testImport . common = : : common ;
testImport . cmdSystem = : : cmdSystem ;
testImport . cvarSystem = : : cvarSystem ;
testImport . fileSystem = : : fileSystem ;
testImport . renderSystem = : : renderSystem ;
testImport . soundSystem = : : soundSystem ;
testImport . renderModelManager = : : renderModelManager ;
testImport . uiManager = : : uiManager ;
testImport . declManager = : : declManager ;
testImport . AASFileManager = : : AASFileManager ;
testImport . collisionModelManager = : : collisionModelManager ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
testExport = * GetGameAPI ( & testImport ) ;
}
/*
= = = = = = = = = = =
idGameLocal : : idGameLocal
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idGameLocal : : idGameLocal ( )
{
2012-11-26 18:58:24 +00:00
Clear ( ) ;
}
/*
= = = = = = = = = = =
idGameLocal : : Clear
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Clear ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
serverInfo . Clear ( ) ;
numClients = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
2012-11-26 18:58:24 +00:00
persistentPlayerInfo [ i ] . Clear ( ) ;
}
memset ( entities , 0 , sizeof ( entities ) ) ;
memset ( spawnIds , - 1 , sizeof ( spawnIds ) ) ;
firstFreeEntityIndex [ 0 ] = 0 ;
firstFreeEntityIndex [ 1 ] = ENTITYNUM_FIRST_NON_REPLICATED ;
num_entities = 0 ;
spawnedEntities . Clear ( ) ;
activeEntities . Clear ( ) ;
numEntitiesToDeactivate = 0 ;
sortPushers = false ;
sortTeamMasters = false ;
persistentLevelInfo . Clear ( ) ;
memset ( globalShaderParms , 0 , sizeof ( globalShaderParms ) ) ;
random . SetSeed ( 0 ) ;
world = NULL ;
frameCommandThread = NULL ;
testmodel = NULL ;
testFx = NULL ;
clip . Shutdown ( ) ;
pvs . Shutdown ( ) ;
sessionCommand . Clear ( ) ;
locationEntities = NULL ;
smokeParticles = NULL ;
editEntities = NULL ;
entityHash . Clear ( 1024 , MAX_GENTITIES ) ;
inCinematic = false ;
framenum = 0 ;
previousTime = 0 ;
time = 0 ;
vacuumAreaNum = 0 ;
mapFileName . Clear ( ) ;
mapFile = NULL ;
spawnCount = INITIAL_SPAWN_COUNT ;
mapSpawnCount = 0 ;
camera = NULL ;
aasList . Clear ( ) ;
aasNames . Clear ( ) ;
lastAIAlertEntity = NULL ;
lastAIAlertTime = 0 ;
spawnArgs . Clear ( ) ;
gravity . Set ( 0 , 0 , - 1 ) ;
2012-11-28 15:47:07 +00:00
playerPVS . h = ( unsigned int ) - 1 ;
playerConnectedAreas . h = ( unsigned int ) - 1 ;
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_UNINITIALIZED ;
influenceActive = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
realClientTime = 0 ;
isNewFrame = true ;
clientSmoothing = 0.1f ;
entityDefBits = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
nextGibTime = 0 ;
globalMaterial = NULL ;
newInfo . Clear ( ) ;
lastGUIEnt = NULL ;
lastGUI = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
eventQueue . Init ( ) ;
savedEventQueue . Init ( ) ;
shellHandler = NULL ;
selectedGroup = 0 ;
portalSkyEnt = NULL ;
portalSkyActive = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ResetSlowTimeVars ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastCmdRunTimeOnClient . Zero ( ) ;
lastCmdRunTimeOnServer . Zero ( ) ;
}
/*
= = = = = = = = = = =
idGameLocal : : Init
initialize the game object , only happens once at startup , not each level load
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Init ( )
{
const idDict * dict ;
idAAS * aas ;
2012-11-26 18:58:24 +00:00
# ifndef GAME_DLL
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
TestGameAPI ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# else
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// initialize idLib
idLib : : Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// register static cvars declared in the game
idCVar : : RegisterStaticVars ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// initialize processor specific SIMD
idSIMD : : InitProcessor ( " game " , com_forceGenericSIMD . GetBool ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " --------- Initializing Game ---------- \n " ) ;
Printf ( " gamename: %s \n " , GAME_VERSION ) ;
Printf ( " gamedate: %s \n " , __DATE__ ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// register game specific decl types
declManager - > RegisterDeclType ( " model " , DECL_MODELDEF , idDeclAllocator < idDeclModelDef > ) ;
declManager - > RegisterDeclType ( " export " , DECL_MODELEXPORT , idDeclAllocator < idDecl > ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// register game specific decl folders
declManager - > RegisterDeclFolder ( " def " , " .def " , DECL_ENTITYDEF ) ;
declManager - > RegisterDeclFolder ( " fx " , " .fx " , DECL_FX ) ;
declManager - > RegisterDeclFolder ( " particles " , " .prt " , DECL_PARTICLE ) ;
declManager - > RegisterDeclFolder ( " af " , " .af " , DECL_AF ) ;
declManager - > RegisterDeclFolder ( " newpdas " , " .pda " , DECL_PDA ) ;
2012-11-28 15:47:07 +00:00
cmdSystem - > AddCommand ( " listModelDefs " , idListDecls_f < DECL_MODELDEF > , CMD_FL_SYSTEM | CMD_FL_GAME , " lists model defs " ) ;
cmdSystem - > AddCommand ( " printModelDefs " , idPrintDecls_f < DECL_MODELDEF > , CMD_FL_SYSTEM | CMD_FL_GAME , " prints a model def " , idCmdSystem : : ArgCompletion_Decl < DECL_MODELDEF > ) ;
2012-11-26 18:58:24 +00:00
Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idEvent : : Init ( ) ;
idClass : : Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitConsoleCommands ( ) ;
2012-11-28 15:47:07 +00:00
shellHandler = new ( TAG_SWF ) idMenuHandler_Shell ( ) ;
if ( ! g_xp_bind_run_once . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
//The default config file contains remapped controls that support the XP weapons
//We want to run this once after the base doom config file has run so we can
//have the correct xp binds
cmdSystem - > BufferCommandText ( CMD_EXEC_APPEND , " exec default.cfg \n " ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_APPEND , " seta g_xp_bind_run_once 1 \n " ) ;
cmdSystem - > ExecuteCommandBuffer ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load default scripts
program . Startup ( SCRIPT_DEFAULT ) ;
2012-11-28 15:47:07 +00:00
smokeParticles = new ( TAG_PARTICLE ) idSmokeParticles ;
2012-11-26 18:58:24 +00:00
// set up the aas
dict = FindEntityDefDict ( " aas_types " ) ;
2012-11-28 15:47:07 +00:00
if ( dict = = NULL )
{
2012-11-26 18:58:24 +00:00
Error ( " Unable to find entityDef for 'aas_types' " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// allocate space for the aas
2012-11-28 15:47:07 +00:00
const idKeyValue * kv = dict - > MatchPrefix ( " type " ) ;
while ( kv ! = NULL )
{
2012-11-26 18:58:24 +00:00
aas = idAAS : : Alloc ( ) ;
aasList . Append ( aas ) ;
aasNames . Append ( kv - > GetValue ( ) ) ;
kv = dict - > MatchPrefix ( " type " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_NOMAP ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ...%d aas types \n " , aasList . Num ( ) ) ;
Printf ( " game initialized. \n " ) ;
Printf ( " -------------------------------------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = =
idGameLocal : : Shutdown
shut down the entire game
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shutdown ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! common )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ------------ Game Shutdown ----------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Shell_Cleanup ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGame . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MapShutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aasList . DeleteContents ( true ) ;
aasNames . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idAI : : FreeObstacleAvoidanceNodes ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idEvent : : Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete [ ] locationEntities ;
locationEntities = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete smokeParticles ;
smokeParticles = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idClass : : Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear list with forces
idForce : : ClearForceList ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free the program data
program . FreeData ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// delete the .map file
delete mapFile ;
mapFile = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free the collision map
collisionModelManager - > FreeMap ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ShutdownConsoleCommands ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free memory allocated by class objects
Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// shut down the animation manager
animationLib . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " -------------------------------------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef GAME_DLL
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove auto-completion function pointers pointing into this DLL
cvarSystem - > RemoveFlaggedAutoCompletion ( CVAR_GAME ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enable leak test
Mem_EnableLeakTest ( " game " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// shutdown idLib
idLib : : ShutDown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# endif
}
idCVar g_recordSaveGameTrace ( " g_recordSaveGameTrace " , " 0 " , CVAR_BOOL , " " ) ;
/*
= = = = = = = = = = =
idGameLocal : : SaveGame
save the current player state , level name , and level state
the session may have written some data to the file already
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SaveGame ( idFile * f , idFile * strings )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
idEntity * link ;
2012-11-26 18:58:24 +00:00
int startTimeMs = Sys_Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
if ( g_recordSaveGameTrace . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
bool result = BeginTraceRecording ( " e: \\ savegame_trace.pix2 " ) ;
2012-11-28 15:47:07 +00:00
if ( ! result )
{
2012-11-26 18:58:24 +00:00
//idLib::Printf( "BeginTraceRecording: error %d\n", GetLastError() );
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idSaveGame savegame ( f , strings , BUILD_NUMBER ) ;
2012-11-28 15:47:07 +00:00
if ( g_flushSave . GetBool ( ) = = true )
{
2012-11-26 18:58:24 +00:00
// force flushing with each write... for tracking down
// save game bugs.
f - > ForceFlush ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// go through all entities and threads and add them to the object list
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GENTITIES ; i + + )
{
2012-11-26 18:58:24 +00:00
ent = entities [ i ] ;
2012-11-28 15:47:07 +00:00
if ( ent )
{
if ( ent - > GetTeamMaster ( ) & & ent - > GetTeamMaster ( ) ! = ent )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
for ( link = ent ; link ! = NULL ; link = link - > GetNextTeamEntity ( ) )
{
2012-11-26 18:58:24 +00:00
savegame . AddObject ( link ) ;
}
}
}
2012-11-28 15:47:07 +00:00
idList < idThread * > threads ;
2012-11-26 18:58:24 +00:00
threads = idThread : : GetThreads ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < threads . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savegame . AddObject ( threads [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// write out complete object list
savegame . WriteObjectList ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
program . Save ( & savegame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( g_skill . GetInteger ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteDecls ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteDict ( & serverInfo ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( numClients ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
2012-11-26 18:58:24 +00:00
//savegame.WriteUsercmd( usercmds[ i ] );
// Now that usercmds are handled by the idUserCmdMgr,
// do we need another solution here?
usercmd_t dummy ;
savegame . WriteUsercmd ( dummy ) ;
savegame . WriteDict ( & persistentPlayerInfo [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GENTITIES ; i + + )
{
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( entities [ i ] ) ;
savegame . WriteInt ( spawnIds [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// There shouldn't be any non-replicated entities in SP,
// so we shouldn't have to save the first free replicated entity index.
savegame . WriteInt ( firstFreeEntityIndex [ 0 ] ) ;
savegame . WriteInt ( num_entities ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enityHash is restored by idEntity::Restore setting the entity name.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( world ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( spawnedEntities . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( ent ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( activeEntities . Num ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( ent ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( numEntitiesToDeactivate ) ;
savegame . WriteBool ( sortPushers ) ;
savegame . WriteBool ( sortTeamMasters ) ;
savegame . WriteDict ( & persistentLevelInfo ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GLOBAL_SHADER_PARMS ; i + + )
{
2012-11-26 18:58:24 +00:00
savegame . WriteFloat ( globalShaderParms [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( random . GetSeed ( ) ) ;
savegame . WriteObject ( frameCommandThread ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clip
// push
// pvs
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
testmodel = NULL ;
testFx = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteString ( sessionCommand ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: save smoke particles
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteBool ( inCinematic ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( gameType ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( framenum ) ;
savegame . WriteInt ( previousTime ) ;
savegame . WriteInt ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( vacuumAreaNum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( entityDefBits ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( GetLocalClientNum ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// snapshotEntities is used for multiplayer only
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( realClientTime ) ;
savegame . WriteBool ( isNewFrame ) ;
savegame . WriteFloat ( clientSmoothing ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
portalSkyEnt . Save ( & savegame ) ;
savegame . WriteBool ( portalSkyActive ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fast . Save ( & savegame ) ;
slow . Save ( & savegame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( slowmoState ) ;
savegame . WriteFloat ( slowmoScale ) ;
savegame . WriteBool ( quickSlowmoReset ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteBool ( mapCycleLoaded ) ;
savegame . WriteInt ( spawnCount ) ;
2012-11-28 15:47:07 +00:00
if ( ! locationEntities )
{
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( gameRenderWorld - > NumAreas ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < gameRenderWorld - > NumAreas ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( locationEntities [ i ] ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteObject ( camera ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteMaterial ( globalMaterial ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastAIAlertEntity . Save ( & savegame ) ;
savegame . WriteInt ( lastAIAlertTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteDict ( & spawnArgs ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteInt ( playerPVS . i ) ;
savegame . WriteInt ( playerPVS . h ) ;
savegame . WriteInt ( playerConnectedAreas . i ) ;
savegame . WriteInt ( playerConnectedAreas . h ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteVec3 ( gravity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// gamestate
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . WriteBool ( influenceActive ) ;
savegame . WriteInt ( nextGibTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spawnSpots
// initialSpots
// currentInitialSpot
// newInfo
// makingBuild
// shakeSounds
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// write out pending events
idEvent : : Save ( & savegame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . Close ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int endTimeMs = Sys_Milliseconds ( ) ;
idLib : : Printf ( " Save time: %dms \n " , ( endTimeMs - startTimeMs ) ) ;
2012-11-28 15:47:07 +00:00
if ( g_recordSaveGameTrace . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
EndTraceRecording ( ) ;
g_recordSaveGameTrace . SetBool ( false ) ;
}
}
/*
= = = = = = = = = = =
idGameLocal : : GetSaveGameDetails
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : GetSaveGameDetails ( idSaveGameDetails & gameDetails )
{
idLocationEntity * locationEnt = LocationForPoint ( gameLocal . GetLocalPlayer ( ) - > GetEyePosition ( ) ) ;
const char * locationStr = locationEnt ? locationEnt - > GetLocation ( ) : idLocalization : : GetString ( " #str_02911 " ) ;
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > shortMapName = mapFileName ;
shortMapName . StripFileExtension ( ) ;
shortMapName . StripLeading ( " maps/ " ) ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * mapDef = static_cast < const idDeclEntityDef * > ( declManager - > FindType ( DECL_MAPDEF , shortMapName , false ) ) ;
const char * mapPrettyName = mapDef ? idLocalization : : GetString ( mapDef - > dict . GetString ( " name " , shortMapName ) ) : shortMapName . c_str ( ) ;
idPlayer * player = GetClientByNum ( 0 ) ;
2012-11-26 18:58:24 +00:00
int playTime = player ? player - > GetPlayedTime ( ) : 0 ;
gameExpansionType_t expansionType = player ? player - > GetExpansionType ( ) : GAME_BASE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameDetails . descriptors . Clear ( ) ;
gameDetails . descriptors . SetInt ( SAVEGAME_DETAIL_FIELD_EXPANSION , expansionType ) ;
gameDetails . descriptors . Set ( SAVEGAME_DETAIL_FIELD_MAP , mapPrettyName ) ;
gameDetails . descriptors . Set ( SAVEGAME_DETAIL_FIELD_MAP_LOCATE , locationStr ) ;
gameDetails . descriptors . SetInt ( SAVEGAME_DETAIL_FIELD_SAVE_VERSION , BUILD_NUMBER ) ;
gameDetails . descriptors . SetInt ( SAVEGAME_DETAIL_FIELD_DIFFICULTY , g_skill . GetInteger ( ) ) ;
gameDetails . descriptors . SetInt ( SAVEGAME_DETAIL_FIELD_PLAYTIME , playTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// PS3 only strings that use the dict just set
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// even though we don't use this when we enumerate, when we save, we use this descriptors file later so we need the date populated now
gameDetails . date = : : time ( NULL ) ;
}
/*
= = = = = = = = = = =
idGameLocal : : GetPersistentPlayerInfo
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDict & idGameLocal : : GetPersistentPlayerInfo ( int clientNum )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
persistentPlayerInfo [ clientNum ] . Clear ( ) ;
ent = entities [ clientNum ] ;
2012-11-28 15:47:07 +00:00
if ( ent & & ent - > IsType ( idPlayer : : Type ) )
{
static_cast < idPlayer * > ( ent ) - > SavePersistantInfo ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return persistentPlayerInfo [ clientNum ] ;
}
/*
= = = = = = = = = = =
idGameLocal : : SetPersistentPlayerInfo
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetPersistentPlayerInfo ( int clientNum , const idDict & playerInfo )
{
2012-11-26 18:58:24 +00:00
persistentPlayerInfo [ clientNum ] = playerInfo ;
}
/*
= = = = = = = = = = = =
idGameLocal : : Printf
= = = = = = = = = = = =
*/
2012-12-11 22:48:55 +00:00
void idGameLocal : : Printf ( const char * fmt , . . . ) const // DG: FIXME: printf-annotation
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s " , text ) ;
}
/*
= = = = = = = = = = = =
idGameLocal : : DPrintf
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : DPrintf ( const char * fmt , . . . ) const
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
if ( ! developer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s " , text ) ;
}
/*
= = = = = = = = = = = =
idGameLocal : : Warning
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Warning ( const char * fmt , . . . ) const
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
idThread * thread ;
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
thread = idThread : : CurrentThread ( ) ;
2012-11-28 15:47:07 +00:00
if ( thread )
{
2012-11-26 18:58:24 +00:00
thread - > Warning ( " %s " , text ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " %s " , text ) ;
}
}
/*
= = = = = = = = = = = =
idGameLocal : : DWarning
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : DWarning ( const char * fmt , . . . ) const
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
idThread * thread ;
if ( ! developer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
thread = idThread : : CurrentThread ( ) ;
2012-11-28 15:47:07 +00:00
if ( thread )
{
2012-11-26 18:58:24 +00:00
thread - > Warning ( " %s " , text ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > DWarning ( " %s " , text ) ;
}
}
/*
= = = = = = = = = = = =
idGameLocal : : Error
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Error ( const char * fmt , . . . ) const
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
idThread * thread ;
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
thread = idThread : : CurrentThread ( ) ;
2012-11-28 15:47:07 +00:00
if ( thread )
{
2012-11-26 18:58:24 +00:00
thread - > Error ( " %s " , text ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Error ( " %s " , text ) ;
}
}
/*
= = = = = = = = = = = = = = =
gameError
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void gameError ( const char * fmt , . . . )
{
2012-11-26 18:58:24 +00:00
va_list argptr ;
char text [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( text , sizeof ( text ) , fmt , argptr ) ;
va_end ( argptr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " %s " , text ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : SetServerGameTimeMs
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetServerGameTimeMs ( const int time )
{
2012-11-26 18:58:24 +00:00
previousServerTime = this - > serverTime ;
this - > serverTime = time ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : GetServerGameTimeMs
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetServerGameTimeMs ( ) const
{
2012-11-26 18:58:24 +00:00
return serverTime ;
}
/*
= = = = = = = = = = =
idGameLocal : : SetServerInfo
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetServerInfo ( const idDict & _serverInfo )
{
2012-11-26 18:58:24 +00:00
serverInfo = _serverInfo ;
2012-11-28 15:47:07 +00:00
if ( gameType = = GAME_LASTMAN )
{
if ( serverInfo . GetInt ( " si_fraglimit " ) < = 0 )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " Last Man Standing - setting fraglimit 1 " ) ;
serverInfo . SetInt ( " si_fraglimit " , 1 ) ;
}
}
}
/*
= = = = = = = = = = =
idGameLocal : : GetServerInfo
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDict & idGameLocal : : GetServerInfo ( )
{
2012-11-26 18:58:24 +00:00
return serverInfo ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : LoadMap
Initializes all map variables common to both save games and spawned games .
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : LoadMap ( const char * mapName , int randseed )
{
bool sameMap = ( mapFile & & idStr : : Icmp ( mapFileName , mapName ) = = 0 ) ;
2012-11-26 18:58:24 +00:00
// clear the sound system
gameSoundWorld - > ClearAllSoundEmitters ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear envirosuit sound fx
gameSoundWorld - > SetEnviroSuit ( false ) ;
gameSoundWorld - > SetSlowmoSpeed ( 1.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitAsyncNetwork ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! sameMap | | ( mapFile & & mapFile - > NeedsReload ( ) ) )
{
2012-11-26 18:58:24 +00:00
// load the .map file
2012-11-28 15:47:07 +00:00
if ( mapFile )
{
2012-11-26 18:58:24 +00:00
delete mapFile ;
}
2012-11-28 15:47:07 +00:00
mapFile = new ( TAG_GAME ) idMapFile ;
if ( ! mapFile - > Parse ( idStr ( mapName ) + " .map " ) )
{
2012-11-26 18:58:24 +00:00
delete mapFile ;
mapFile = NULL ;
Error ( " Couldn't load %s " , mapName ) ;
}
}
mapFileName = mapFile - > GetName ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load the collision map
collisionModelManager - > LoadMap ( mapFile ) ;
collisionModelManager - > Preload ( mapName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numClients = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// initialize all entities for this game
memset ( entities , 0 , sizeof ( entities ) ) ;
memset ( spawnIds , - 1 , sizeof ( spawnIds ) ) ;
spawnCount = INITIAL_SPAWN_COUNT ;
spawnedEntities . Clear ( ) ;
activeEntities . Clear ( ) ;
aimAssistEntities . Clear ( ) ;
numEntitiesToDeactivate = 0 ;
sortTeamMasters = false ;
sortPushers = false ;
lastGUIEnt = NULL ;
lastGUI = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
globalMaterial = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( globalShaderParms , 0 , sizeof ( globalShaderParms ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// These used to be a non-pot adjustment for portal skies
// they're no longer needed, but we can't update the materials
globalShaderParms [ 4 ] = 1.0f ;
globalShaderParms [ 5 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// always leave room for the max number of clients,
// even if they aren't all used, so numbers inside that
// range are NEVER anything but clients
num_entities = MAX_CLIENTS ;
firstFreeEntityIndex [ 0 ] = MAX_CLIENTS ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset the random number generator.
random . SetSeed ( common - > IsMultiplayer ( ) ? randseed : 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
camera = NULL ;
world = NULL ;
testmodel = NULL ;
testFx = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastAIAlertEntity = NULL ;
lastAIAlertTime = 0 ;
previousTime = 0 ;
time = 0 ;
framenum = 0 ;
sessionCommand = " " ;
nextGibTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
portalSkyEnt = NULL ;
portalSkyActive = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ResetSlowTimeVars ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
vacuumAreaNum = - 1 ; // if an info_vacuum is spawned, it will set this
2012-11-28 15:47:07 +00:00
if ( ! editEntities )
{
editEntities = new ( TAG_GAME ) idEditEntities ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gravity . Set ( 0 , 0 , - g_gravity . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inCinematic = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clip . Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pvs . Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
playerPVS . i = - 1 ;
playerConnectedAreas . i = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load navigation system for all the different monster sizes
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < aasNames . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aasList [ i ] - > Init ( idStr ( mapFileName ) . SetFileExtension ( aasNames [ i ] ) . c_str ( ) , mapFile - > GetGeometryCRC ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the smoke particle free list
smokeParticles - > Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// cache miscellaneous media references
FindEntityDef ( " preCacheExtras " , false ) ;
FindEntityDef ( " ammo_types " , false ) ;
FindEntityDef ( " ammo_names " , false ) ;
FindEntityDef ( " ammo_types_d3xp " , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FindEntityDef ( " damage_noair " , false ) ;
FindEntityDef ( " damage_moverCrush " , false ) ;
FindEntityDef ( " damage_crush " , false ) ;
FindEntityDef ( " damage_triggerhurt_1000 " , false ) ;
FindEntityDef ( " damage_telefrag " , false ) ;
FindEntityDef ( " damage_suicide " , false ) ;
FindEntityDef ( " damage_explosion " , false ) ;
FindEntityDef ( " damage_generic " , false ) ;
FindEntityDef ( " damage_painTrigger " , false ) ;
FindEntityDef ( " damage_thrown_ragdoll " , false ) ;
FindEntityDef ( " damage_gib " , false ) ;
FindEntityDef ( " damage_softfall " , false ) ;
FindEntityDef ( " damage_hardfall " , false ) ;
FindEntityDef ( " damage_fatalfall " , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FindEntityDef ( " envirosuit_light " , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_EMAIL , " highScore " , false ) ;
declManager - > FindType ( DECL_EMAIL , " MartianBuddyGameComplete " , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
declManager - > FindMaterial ( " itemHighlightShell " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! sameMap )
{
2012-11-26 18:58:24 +00:00
mapFile - > RemovePrimitiveData ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : LocalMapRestart
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : LocalMapRestart ( )
{
2012-11-26 18:58:24 +00:00
int i , latchSpawnCount ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ----------- Game Map Restart ------------ \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_SHUTDOWN ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( entities [ i ] & & entities [ i ] - > IsType ( idPlayer : : Type ) )
{
static_cast < idPlayer * > ( entities [ i ] ) - > PrepareForRestart ( ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
eventQueue . Shutdown ( ) ;
savedEventQueue . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MapClear ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the smoke particle free list
smokeParticles - > Init ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the sound system
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > ClearAllSoundEmitters ( ) ;
// clear envirosuit sound fx
gameSoundWorld - > SetEnviroSuit ( false ) ;
gameSoundWorld - > SetSlowmoSpeed ( 1.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the spawnCount is reset to zero temporarily to spawn the map entities with the same spawnId
// if we don't do that, network clients are confused and don't show any map entities
latchSpawnCount = spawnCount ;
spawnCount = INITIAL_SPAWN_COUNT ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_STARTUP ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
program . Restart ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitScriptForMap ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MapPopulate ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// once the map is populated, set the spawnCount back to where it was so we don't risk any collision
// (note that if there are no players in the game, we could just leave it at it's current value)
spawnCount = latchSpawnCount ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup the client entities again
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( entities [ i ] & & entities [ i ] - > IsType ( idPlayer : : Type ) )
{
static_cast < idPlayer * > ( entities [ i ] ) - > Restart ( ) ;
2012-11-26 18:58:24 +00:00
}
}
gamestate = GAMESTATE_ACTIVE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " -------------------------------------- \n " ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : MapRestart
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : MapRestart ( )
{
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
LocalMapRestart ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
session - > GetActingGameStateLobbyBase ( ) . SendReliable ( GAME_RELIABLE_MESSAGE_RESTART , msg , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
LocalMapRestart ( ) ;
mpGame . MapRestart ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . mpGame . ReloadScoreboard ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : MapRestart_f
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : MapRestart_f ( const idCmdArgs & args )
{
if ( ! common - > IsMultiplayer ( ) | | common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " server is not running - use spawnServer \n " ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_APPEND , " spawnServer \n " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . MapRestart ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : MapPopulate
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : MapPopulate ( )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
cvarSystem - > SetCVarBool ( " r_skipSpecular " , false ) ;
}
// parse the key/value pairs and spawn entities
SpawnMapEntities ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// mark location entities in all connected areas
SpreadLocations ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// prepare the list of randomized initial spawn spots
RandomizeInitialSpawns ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spawnCount - 1 is the number of entities spawned into the map, their indexes started at MAX_CLIENTS (included)
// mapSpawnCount is used as the max index of map entities, it's the first index of non-map entities
mapSpawnCount = MAX_CLIENTS + spawnCount - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// execute pending events before the very first game frame
// this makes sure the map script main() function is called
// before the physics are run so entities can bind correctly
Printf ( " ==== Processing events ==== \n " ) ;
idEvent : : ServiceEvents ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Must set GAME_FPS for script after populating, because some maps run their own scripts
// when spawning the world, and GAME_FPS will not be found before then.
SetScriptFPS ( com_engineHz_latched ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : InitFromNewMap
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : InitFromNewMap ( const char * mapName , idRenderWorld * renderWorld , idSoundWorld * soundWorld , int gameMode , int randseed )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
this - > gameType = ( gameType_t ) idMath : : ClampInt ( GAME_SP , GAME_COUNT - 1 , gameMode ) ;
if ( mapFileName . Length ( ) )
{
2012-11-26 18:58:24 +00:00
MapShutdown ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ----------- Game Map Init ------------ \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_STARTUP ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameRenderWorld = renderWorld ;
gameSoundWorld = soundWorld ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
g_skill . SetInteger ( 1 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
g_skill . SetInteger ( idMath : : ClampInt ( 0 , 3 , g_skill . GetInteger ( ) ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
LoadMap ( mapName , randseed ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitScriptForMap ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MapPopulate ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGame . Reset ( ) ;
mpGame . Precache ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SyncPlayersWithLobbyUsers ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free up any unused animations
animationLib . FlushUnusedAnims ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_ACTIVE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " -------------------------------------- \n " ) ;
}
/*
= = = = = = = = = = = = = = = = =
idGameLocal : : InitFromSaveGame
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : InitFromSaveGame ( const char * mapName , idRenderWorld * renderWorld , idSoundWorld * soundWorld , idFile * saveGameFile , idFile * stringTableFile , int saveGameVersion )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
2012-11-26 18:58:24 +00:00
idDict si ;
2012-11-28 15:47:07 +00:00
if ( mapFileName . Length ( ) )
{
2012-11-26 18:58:24 +00:00
MapShutdown ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ------- Game Map Init SaveGame ------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_STARTUP ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameRenderWorld = renderWorld ;
gameSoundWorld = soundWorld ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetScriptFPS ( com_engineHz_latched ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load the map needed for this savegame
LoadMap ( mapName , 0 ) ;
2012-11-28 15:47:07 +00:00
idFile_SaveGamePipelined * pipelineFile = new ( TAG_SAVEGAMES ) idFile_SaveGamePipelined ( ) ;
2012-11-26 18:58:24 +00:00
pipelineFile - > OpenForReading ( saveGameFile ) ;
idRestoreGame savegame ( pipelineFile , stringTableFile , saveGameVersion ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Create the list of all objects in the game
savegame . CreateObjects ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Load the idProgram, also checking to make sure scripting hasn't changed since the savegame
2012-11-28 15:47:07 +00:00
if ( program . Restore ( & savegame ) = = false )
{
2012-11-26 18:58:24 +00:00
// Abort the load process, and let the session know so that it can restart the level
// with the player persistent data.
savegame . DeleteObjects ( ) ;
program . Restart ( ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( i ) ;
g_skill . SetInteger ( i ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// precache any media specified in the map
savegame . ReadDecls ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadDict ( & si ) ;
SetServerInfo ( si ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( numClients ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
2012-11-26 18:58:24 +00:00
//savegame.ReadUsercmd( usercmds[ i ] );
// Now that usercmds are handled by the idUserCmdMgr,
// do we need another solution here?
usercmd_t dummy ;
savegame . ReadUsercmd ( dummy ) ;
savegame . ReadDict ( & persistentPlayerInfo [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GENTITIES ; i + + )
{
savegame . ReadObject ( reinterpret_cast < idClass * & > ( entities [ i ] ) ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( spawnIds [ i ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore the entityNumber
2012-11-28 15:47:07 +00:00
if ( entities [ i ] ! = NULL )
{
2012-11-26 18:58:24 +00:00
entities [ i ] - > entityNumber = i ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Connect players with lobby users
// There should only be 1 player and 1 lobby user, but I'm using a loop just to be safe
2012-11-28 15:47:07 +00:00
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
2012-11-26 18:58:24 +00:00
int numLobbyUsers = lobby . GetNumLobbyUsers ( ) ;
int lobbyUserNum = 0 ;
assert ( numLobbyUsers = = 1 ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < MAX_PLAYERS & & lobbyUserNum < numLobbyUsers ; i + + )
{
if ( entities [ i ] = = NULL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
lobbyUserIDs [ i ] = lobby . GetLobbyUserIdByOrdinal ( lobbyUserNum + + ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( firstFreeEntityIndex [ 0 ] ) ;
savegame . ReadInt ( num_entities ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enityHash is restored by idEntity::Restore setting the entity name.
2012-11-28 15:47:07 +00:00
savegame . ReadObject ( reinterpret_cast < idClass * & > ( world ) ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
savegame . ReadObject ( reinterpret_cast < idClass * & > ( ent ) ) ;
2012-11-26 18:58:24 +00:00
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > spawnNode . AddToEnd ( spawnedEntities ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
savegame . ReadObject ( reinterpret_cast < idClass * & > ( ent ) ) ;
2012-11-26 18:58:24 +00:00
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
if ( ent )
{
2012-11-26 18:58:24 +00:00
ent - > activeNode . AddToEnd ( activeEntities ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( numEntitiesToDeactivate ) ;
savegame . ReadBool ( sortPushers ) ;
savegame . ReadBool ( sortTeamMasters ) ;
savegame . ReadDict ( & persistentLevelInfo ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_GLOBAL_SHADER_PARMS ; i + + )
{
2012-11-26 18:58:24 +00:00
savegame . ReadFloat ( globalShaderParms [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( i ) ;
random . SetSeed ( i ) ;
2012-11-28 15:47:07 +00:00
savegame . ReadObject ( reinterpret_cast < idClass * & > ( frameCommandThread ) ) ;
2012-11-26 18:58:24 +00:00
// clip
// push
// pvs
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// testmodel = "<NULL>"
// testFx = "<NULL>"
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadString ( sessionCommand ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: save smoke particles
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadBool ( inCinematic ) ;
2012-11-28 15:47:07 +00:00
savegame . ReadInt ( ( int & ) gameType ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( framenum ) ;
savegame . ReadInt ( previousTime ) ;
savegame . ReadInt ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( vacuumAreaNum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( entityDefBits ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the localClientNum member of idGameLocal was removed,
// but to preserve savegame compatibility, we still need
// to read an int here even though it's not used.
int dummyLocalClientNum = 0 ;
savegame . ReadInt ( dummyLocalClientNum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// snapshotEntities is used for multiplayer only
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( realClientTime ) ;
savegame . ReadBool ( isNewFrame ) ;
savegame . ReadFloat ( clientSmoothing ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
portalSkyEnt . Restore ( & savegame ) ;
savegame . ReadBool ( portalSkyActive ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fast . Restore ( & savegame ) ;
slow . Restore ( & savegame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
framenum = MSEC_TO_FRAME_FLOOR ( fast . time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int blah ;
savegame . ReadInt ( blah ) ;
2012-11-28 15:47:07 +00:00
slowmoState = ( slowmoState_t ) blah ;
2012-11-26 18:58:24 +00:00
savegame . ReadFloat ( slowmoScale ) ;
savegame . ReadBool ( quickSlowmoReset ) ;
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetSlowmoSpeed ( slowmoScale ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadBool ( mapCycleLoaded ) ;
savegame . ReadInt ( spawnCount ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( num ) ;
2012-11-28 15:47:07 +00:00
if ( num )
{
if ( num ! = gameRenderWorld - > NumAreas ( ) )
{
2012-11-26 18:58:24 +00:00
savegame . Error ( " idGameLocal::InitFromSaveGame: number of areas in map differs from save game. " ) ;
}
2012-11-28 15:47:07 +00:00
locationEntities = new ( TAG_GAME ) idLocationEntity * [ num ] ;
for ( i = 0 ; i < num ; i + + )
{
savegame . ReadObject ( reinterpret_cast < idClass * & > ( locationEntities [ i ] ) ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
savegame . ReadObject ( reinterpret_cast < idClass * & > ( camera ) ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadMaterial ( globalMaterial ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastAIAlertEntity . Restore ( & savegame ) ;
savegame . ReadInt ( lastAIAlertTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadDict ( & spawnArgs ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( playerPVS . i ) ;
2012-11-28 15:47:07 +00:00
savegame . ReadInt ( ( int & ) playerPVS . h ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadInt ( playerConnectedAreas . i ) ;
2012-11-28 15:47:07 +00:00
savegame . ReadInt ( ( int & ) playerConnectedAreas . h ) ;
2012-11-26 18:58:24 +00:00
savegame . ReadVec3 ( gravity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// gamestate is restored after restoring everything else
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . ReadBool ( influenceActive ) ;
savegame . ReadInt ( nextGibTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spawnSpots
// initialSpots
// currentInitialSpot
// newInfo
// makingBuild
// shakeSounds
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Read out pending events
idEvent : : Restore ( & savegame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savegame . RestoreObjects ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGame . Reset ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGame . Precache ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free up any unused animations
animationLib . FlushUnusedAnims ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_ACTIVE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " -------------------------------------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete pipelineFile ;
pipelineFile = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = =
idGameLocal : : MapClear
= = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : MapClear ( bool clearClients )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = ( clearClients ? 0 : MAX_CLIENTS ) ; i < MAX_GENTITIES ; i + + )
{
2012-11-26 18:58:24 +00:00
delete entities [ i ] ;
// ~idEntity is in charge of setting the pointer to NULL
// it will also clear pending events for this entity
assert ( ! entities [ i ] ) ;
spawnIds [ i ] = - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
entityHash . Clear ( 1024 , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
if ( ! clearClients )
{
2012-11-26 18:58:24 +00:00
// add back the hashes of the clients
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( ! entities [ i ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
entityHash . Add ( entityHash . GenerateKey ( entities [ i ] - > name . c_str ( ) , true ) , i ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete frameCommandThread ;
frameCommandThread = NULL ;
2012-11-28 15:47:07 +00:00
if ( editEntities )
{
2012-11-26 18:58:24 +00:00
delete editEntities ;
editEntities = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete [ ] locationEntities ;
locationEntities = NULL ;
}
/*
= = = = = = = = = = =
idGameLocal : : MapShutdown
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : MapShutdown ( )
{
2012-11-26 18:58:24 +00:00
Printf ( " --------- Game Map Shutdown ---------- \n " ) ;
gamestate = GAMESTATE_SHUTDOWN ;
2012-11-28 15:47:07 +00:00
if ( gameRenderWorld )
{
2012-11-26 18:58:24 +00:00
// clear any debug lines, text, and polygons
gameRenderWorld - > DebugClearLines ( 0 ) ;
gameRenderWorld - > DebugClearPolygons ( 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear out camera if we're in a cinematic
2012-11-28 15:47:07 +00:00
if ( inCinematic )
{
2012-11-26 18:58:24 +00:00
camera = NULL ;
inCinematic = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
MapClear ( true ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset the script to the state it was before the map was started
program . Restart ( ) ;
2012-11-28 15:47:07 +00:00
if ( smokeParticles )
{
2012-11-26 18:58:24 +00:00
smokeParticles - > Shutdown ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pvs . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clip . Shutdown ( ) ;
idClipModel : : ClearTraceModelCache ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
collisionModelManager - > FreeMap ( ) ; // Fixes an issue where when maps were reloaded the materials wouldn't get their surfaceFlags re-set. Now we free the map collision model forcing materials to be reparsed.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ShutdownAsyncNetwork ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > mapName = mapFileName ;
mapName . StripPath ( ) ;
mapName . StripFileExtension ( ) ;
fileSystem - > UnloadMapResources ( mapName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapFileName . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameRenderWorld = NULL ;
gameSoundWorld = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gamestate = GAMESTATE_NOMAP ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " -------------------------------------- \n " ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : GetAimAssistAngles
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : GetAimAssistAngles ( idAngles & angles )
{
2012-11-26 18:58:24 +00:00
angles . Zero ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Take a look at serializing this to the clients
2012-11-28 15:47:07 +00:00
idPlayer * player = GetLocalPlayer ( ) ;
if ( player = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idAimAssist * aimAssist = player - > GetAimAssist ( ) ;
if ( aimAssist = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
aimAssist - > GetAngleCorrection ( angles ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : GetAimAssistSensitivity
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idGameLocal : : GetAimAssistSensitivity ( )
{
2012-11-26 18:58:24 +00:00
// Take a look at serializing this to the clients
2012-11-28 15:47:07 +00:00
idPlayer * player = GetLocalPlayer ( ) ;
if ( player = = NULL )
{
2012-11-26 18:58:24 +00:00
return 1.0f ;
}
2012-11-28 15:47:07 +00:00
idAimAssist * aimAssist = player - > GetAimAssist ( ) ;
if ( aimAssist = = NULL )
{
2012-11-26 18:58:24 +00:00
return 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return aimAssist - > GetFrictionScalar ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : MapPeerToClient
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : MapPeerToClient ( int peer ) const
{
idLobbyBase & lobby = session - > GetActingGameStateLobbyBase ( ) ;
for ( int userNum = 0 ; userNum < lobbyUserIDs . Num ( ) ; + + userNum )
{
2012-11-26 18:58:24 +00:00
const int peerForUser = lobby . PeerIndexFromLobbyUser ( lobbyUserIDs [ userNum ] ) ;
2012-11-28 15:47:07 +00:00
if ( peerForUser = = peer )
{
2012-11-26 18:58:24 +00:00
return userNum ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : GetLocalClientNum
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetLocalClientNum ( ) const
{
2012-11-26 18:58:24 +00:00
localUserHandle_t localUserHandle = session - > GetSignInManager ( ) . GetMasterLocalUserHandle ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! localUserHandle . IsValid ( ) )
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < lobbyUserIDs . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
lobbyUserID_t lobbyUserID = lobbyUserIDs [ i ] ;
2012-11-28 15:47:07 +00:00
if ( localUserHandle = = lobbyUserID . GetLocalUserHandle ( ) )
{
2012-11-26 18:58:24 +00:00
return i ;
}
}
return 0 ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : Preload
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Preload ( const idPreloadManifest & manifest )
{
2012-11-26 18:58:24 +00:00
animationLib . Preload ( manifest ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : CacheDictionaryMedia
This is called after parsing an EntityDef and for each entity spawnArgs before
merging the entitydef . It could be done post - merge , but that would
avoid the fast pre - cache check associated with each entityDef
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : CacheDictionaryMedia ( const idDict * dict )
{
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " model " ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > MediaPrint ( " Precaching model %s \n " , kv - > GetValue ( ) . c_str ( ) ) ;
// precache model/animations
2012-11-28 15:47:07 +00:00
if ( declManager - > FindType ( DECL_MODELDEF , kv - > GetValue ( ) , false ) = = NULL )
{
2012-11-26 18:58:24 +00:00
// precache the render model
renderModelManager - > FindModel ( kv - > GetValue ( ) ) ;
// precache .cm files only
collisionModelManager - > LoadModel ( kv - > GetValue ( ) ) ;
}
}
kv = dict - > MatchPrefix ( " model " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > FindKey ( " s_shader " ) ;
2012-11-28 15:47:07 +00:00
if ( kv ! = NULL & & kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_SOUND , kv - > GetValue ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " snd " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_SOUND , kv - > GetValue ( ) ) ;
}
kv = dict - > MatchPrefix ( " snd " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " gui " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
if ( ! idStr : : Icmp ( kv - > GetKey ( ) , " gui_noninteractive " )
| | ! idStr : : Icmpn ( kv - > GetKey ( ) , " gui_parm " , 8 )
| | ! idStr : : Icmp ( kv - > GetKey ( ) , " gui_inventory " ) )
{
2012-11-26 18:58:24 +00:00
// unfortunate flag names, they aren't actually a gui
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
declManager - > MediaPrint ( " Precaching gui %s \n " , kv - > GetValue ( ) . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
idUserInterface * gui = uiManager - > Alloc ( ) ;
if ( gui )
{
2012-11-26 18:58:24 +00:00
gui - > InitFromFile ( kv - > GetValue ( ) ) ;
uiManager - > DeAlloc ( gui ) ;
}
}
}
kv = dict - > MatchPrefix ( " gui " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > FindKey ( " texture " ) ;
2012-11-28 15:47:07 +00:00
if ( kv ! = NULL & & kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_MATERIAL , kv - > GetValue ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " mtr " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_MATERIAL , kv - > GetValue ( ) ) ;
}
kv = dict - > MatchPrefix ( " mtr " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// handles hud icons
kv = dict - > MatchPrefix ( " inv_icon " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_MATERIAL , kv - > GetValue ( ) ) ;
}
kv = dict - > MatchPrefix ( " inv_icon " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// handles teleport fx.. this is not ideal but the actual decision on which fx to use
// is handled by script code based on the teleport number
kv = dict - > MatchPrefix ( " teleport " , NULL ) ;
2012-11-28 15:47:07 +00:00
if ( kv ! = NULL & & kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
int teleportType = atoi ( kv - > GetValue ( ) ) ;
2012-11-28 15:47:07 +00:00
const char * p = ( teleportType ) ? va ( " fx/teleporter%i.fx " , teleportType ) : " fx/teleporter.fx " ;
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_FX , p ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " fx " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > MediaPrint ( " Precaching fx %s \n " , kv - > GetValue ( ) . c_str ( ) ) ;
declManager - > FindType ( DECL_FX , kv - > GetValue ( ) ) ;
}
kv = dict - > MatchPrefix ( " fx " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " smoke " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
idStr prtName = kv - > GetValue ( ) ;
2012-11-28 15:47:07 +00:00
int dash = prtName . Find ( ' - ' ) ;
if ( dash > 0 )
{
2012-11-26 18:58:24 +00:00
prtName = prtName . Left ( dash ) ;
}
declManager - > FindType ( DECL_PARTICLE , prtName ) ;
}
kv = dict - > MatchPrefix ( " smoke " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " skin " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > MediaPrint ( " Precaching skin %s \n " , kv - > GetValue ( ) . c_str ( ) ) ;
declManager - > FindType ( DECL_SKIN , kv - > GetValue ( ) ) ;
}
kv = dict - > MatchPrefix ( " skin " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " def " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
FindEntityDef ( kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " def " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Precache all available grabber "catch" damage decls
kv = dict - > MatchPrefix ( " def_damage " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
FindEntityDef ( kv - > GetValue ( ) + " _catch " , false ) ;
}
kv = dict - > MatchPrefix ( " def_damage " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Should have been def_monster_damage!!
kv = dict - > FindKey ( " monster_damage " ) ;
2012-11-28 15:47:07 +00:00
if ( kv ! = NULL & & kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
FindEntityDef ( kv - > GetValue ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " item " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
FindEntityDefDict ( kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " item " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " pda_name " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_PDA , kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " pda_name " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " video " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_VIDEO , kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " video " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " audio " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_AUDIO , kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " audio " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = dict - > MatchPrefix ( " email " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
if ( kv - > GetValue ( ) . Length ( ) )
{
2012-11-26 18:58:24 +00:00
declManager - > FindType ( DECL_EMAIL , kv - > GetValue ( ) . c_str ( ) , false ) ;
}
kv = dict - > MatchPrefix ( " email " , kv ) ;
}
}
/*
= = = = = = = = = = =
idGameLocal : : InitScriptForMap
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : InitScriptForMap ( )
{
2012-11-26 18:58:24 +00:00
// create a thread to run frame commands on
frameCommandThread = new idThread ( ) ;
frameCommandThread - > ManualDelete ( ) ;
frameCommandThread - > SetThreadName ( " frameCommands " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// run the main game script function (not the level specific main)
2012-11-28 15:47:07 +00:00
const function_t * func = program . FindFunction ( SCRIPT_DEFAULTFUNC ) ;
if ( func ! = NULL )
{
idThread * thread = new idThread ( func ) ;
if ( thread - > Start ( ) )
{
2012-11-26 18:58:24 +00:00
// thread has finished executing, so delete it
delete thread ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : SetScriptFPS
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetScriptFPS ( const float engineHz )
{
idVarDef * fpsDef = program . GetDef ( & type_float , " GAME_FPS " , & def_namespace ) ;
if ( fpsDef ! = NULL )
{
2012-11-26 18:58:24 +00:00
eval_t fpsValue ;
fpsValue . _float = engineHz ;
fpsDef - > SetValue ( fpsValue , false ) ;
}
}
/*
= = = = = = = = = = =
idGameLocal : : GetMPPlayerDefName
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idGameLocal : : GetMPPlayerDefName ( ) const
{
if ( gameType = = GAME_CTF )
{
2012-11-26 18:58:24 +00:00
return " player_doommarine_ctf " ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return " player_doommarine_mp " ;
}
/*
= = = = = = = = = = =
idGameLocal : : SpawnPlayer
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SpawnPlayer ( int clientNum )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
idDict args ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// they can connect
Printf ( " SpawnPlayer: %i \n " , clientNum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
args . SetInt ( " spawn_entnum " , clientNum ) ;
args . Set ( " name " , va ( " player%d " , clientNum + 1 ) ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
args . Set ( " classname " , GetMPPlayerDefName ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// precache the player
args . Set ( " classname " , gameLocal . world - > spawnArgs . GetString ( " def_player " , " player_doommarine " ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// It's important that we increment numClients before calling SpawnEntityDef, because some
// entities want to check gameLocal.numClients to see who to operate on (such as target_removeweapons)
2012-11-28 15:47:07 +00:00
if ( clientNum > = numClients )
{
2012-11-26 18:58:24 +00:00
numClients = clientNum + 1 ;
}
2012-11-28 15:47:07 +00:00
if ( ! SpawnEntityDef ( args , & ent ) | | clientNum > = MAX_GENTITIES | | entities [ clientNum ] = = NULL )
{
2012-11-26 18:58:24 +00:00
Error ( " Failed to spawn player as '%s' " , args . GetString ( " classname " ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure it's a compatible class
2012-11-28 15:47:07 +00:00
if ( ! ent - > IsType ( idPlayer : : Type ) )
{
2012-11-26 18:58:24 +00:00
Error ( " '%s' spawned the player as a '%s'. Player spawnclass must be a subclass of idPlayer. " , args . GetString ( " classname " ) , ent - > GetClassname ( ) ) ;
}
mpGame . SpawnPlayer ( clientNum ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetClientByNum
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPlayer * idGameLocal : : GetClientByNum ( int current ) const
{
if ( current < 0 | | current > = numClients )
{
2012-11-26 18:58:24 +00:00
current = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( entities [ current ] )
{
return static_cast < idPlayer * > ( entities [ current ] ) ;
2012-11-26 18:58:24 +00:00
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetNextClientNum
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetNextClientNum ( int _current ) const
{
2012-11-26 18:58:24 +00:00
int i , current ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
2012-11-26 18:58:24 +00:00
current = ( _current + i + 1 ) % numClients ;
2012-11-28 15:47:07 +00:00
if ( entities [ current ] & & entities [ current ] - > IsType ( idPlayer : : Type ) )
{
2012-11-26 18:58:24 +00:00
return current ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return current ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetLocalPlayer
Nothing in the game tic should EVER make a decision based on what the
local client number is , it shouldn ' t even be aware that there is a
draw phase even happening . This just returns client 0 , which will
be correct for single player .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPlayer * idGameLocal : : GetLocalPlayer ( ) const
{
if ( GetLocalClientNum ( ) < 0 )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
if ( ! entities [ GetLocalClientNum ( ) ] | | ! entities [ GetLocalClientNum ( ) ] - > IsType ( idPlayer : : Type ) )
{
2012-11-26 18:58:24 +00:00
// not fully in game yet
return NULL ;
}
2012-11-28 15:47:07 +00:00
return static_cast < idPlayer * > ( entities [ GetLocalClientNum ( ) ] ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : SetupClientPVS
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
pvsHandle_t idGameLocal : : GetClientPVS ( idPlayer * player , pvsType_t type )
{
if ( player - > GetPrivateCameraView ( ) )
{
2012-11-26 18:58:24 +00:00
return pvs . SetupCurrentPVS ( player - > GetPrivateCameraView ( ) - > GetPVSAreas ( ) , player - > GetPrivateCameraView ( ) - > GetNumPVSAreas ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else if ( camera )
{
2012-11-26 18:58:24 +00:00
return pvs . SetupCurrentPVS ( camera - > GetPVSAreas ( ) , camera - > GetNumPVSAreas ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return pvs . SetupCurrentPVS ( player - > GetPVSAreas ( ) , player - > GetNumPVSAreas ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : SetupPlayerPVS
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetupPlayerPVS ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
idPlayer * player ;
2012-11-26 18:58:24 +00:00
pvsHandle_t otherPVS , newPVS ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
playerPVS . i = - 1 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
2012-11-26 18:58:24 +00:00
ent = entities [ i ] ;
2012-11-28 15:47:07 +00:00
if ( ! ent | | ! ent - > IsType ( idPlayer : : Type ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
player = static_cast < idPlayer * > ( ent ) ;
if ( playerPVS . i = = - 1 )
{
2012-11-26 18:58:24 +00:00
playerPVS = GetClientPVS ( player , PVS_NORMAL ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
otherPVS = GetClientPVS ( player , PVS_NORMAL ) ;
newPVS = pvs . MergeCurrentPVS ( playerPVS , otherPVS ) ;
pvs . FreeCurrentPVS ( playerPVS ) ;
pvs . FreeCurrentPVS ( otherPVS ) ;
playerPVS = newPVS ;
}
2012-11-28 15:47:07 +00:00
if ( playerConnectedAreas . i = = - 1 )
{
2012-11-26 18:58:24 +00:00
playerConnectedAreas = GetClientPVS ( player , PVS_CONNECTED_AREAS ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
otherPVS = GetClientPVS ( player , PVS_CONNECTED_AREAS ) ;
newPVS = pvs . MergeCurrentPVS ( playerConnectedAreas , otherPVS ) ;
pvs . FreeCurrentPVS ( playerConnectedAreas ) ;
pvs . FreeCurrentPVS ( otherPVS ) ;
playerConnectedAreas = newPVS ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if portalSky is preset, then merge into pvs so we get rotating brushes, etc
2012-11-28 15:47:07 +00:00
if ( portalSkyEnt . GetEntity ( ) )
{
idEntity * skyEnt = portalSkyEnt . GetEntity ( ) ;
2012-11-26 18:58:24 +00:00
otherPVS = pvs . SetupCurrentPVS ( skyEnt - > GetPVSAreas ( ) , skyEnt - > GetNumPVSAreas ( ) ) ;
newPVS = pvs . MergeCurrentPVS ( playerPVS , otherPVS ) ;
pvs . FreeCurrentPVS ( playerPVS ) ;
pvs . FreeCurrentPVS ( otherPVS ) ;
playerPVS = newPVS ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
otherPVS = pvs . SetupCurrentPVS ( skyEnt - > GetPVSAreas ( ) , skyEnt - > GetNumPVSAreas ( ) ) ;
newPVS = pvs . MergeCurrentPVS ( playerConnectedAreas , otherPVS ) ;
pvs . FreeCurrentPVS ( playerConnectedAreas ) ;
pvs . FreeCurrentPVS ( otherPVS ) ;
playerConnectedAreas = newPVS ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : FreePlayerPVS
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : FreePlayerPVS ( )
{
if ( playerPVS . i ! = - 1 )
{
2012-11-26 18:58:24 +00:00
pvs . FreeCurrentPVS ( playerPVS ) ;
playerPVS . i = - 1 ;
}
2012-11-28 15:47:07 +00:00
if ( playerConnectedAreas . i ! = - 1 )
{
2012-11-26 18:58:24 +00:00
pvs . FreeCurrentPVS ( playerConnectedAreas ) ;
playerConnectedAreas . i = - 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : InPlayerPVS
should only be called during entity thinking and event handling
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : InPlayerPVS ( idEntity * ent ) const
{
if ( playerPVS . i = = - 1 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
return pvs . InCurrentPVS ( playerPVS , ent - > GetPVSAreas ( ) , ent - > GetNumPVSAreas ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : InPlayerConnectedArea
should only be called during entity thinking and event handling
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : InPlayerConnectedArea ( idEntity * ent ) const
{
if ( playerConnectedAreas . i = = - 1 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
return pvs . InCurrentPVS ( playerConnectedAreas , ent - > GetPVSAreas ( ) , ent - > GetNumPVSAreas ( ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : UpdateGravity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : UpdateGravity ( )
{
idEntity * ent ;
if ( g_gravity . IsModified ( ) )
{
if ( g_gravity . GetFloat ( ) = = 0.0f )
{
2012-11-26 18:58:24 +00:00
g_gravity . SetFloat ( 1.0f ) ;
}
2012-11-28 15:47:07 +00:00
gravity . Set ( 0 , 0 , - g_gravity . GetFloat ( ) ) ;
2012-11-26 18:58:24 +00:00
// update all physics objects
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ent - > IsType ( idAFEntity_Generic : : Type ) )
{
idPhysics * phys = ent - > GetPhysics ( ) ;
if ( phys )
{
2012-11-26 18:58:24 +00:00
phys - > SetGravity ( gravity ) ;
}
}
}
g_gravity . ClearModified ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetGravity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idVec3 & idGameLocal : : GetGravity ( ) const
{
2012-11-26 18:58:24 +00:00
return gravity ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : SortActiveEntityList
Sorts the active entity list such that pushing entities come first ,
actors come next and physics team slaves appear after their master .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SortActiveEntityList ( )
{
idEntity * ent , * next_ent , * master , * part ;
2012-11-26 18:58:24 +00:00
// if the active entity list needs to be reordered to place physics team masters at the front
2012-11-28 15:47:07 +00:00
if ( sortTeamMasters )
{
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = next_ent )
{
2012-11-26 18:58:24 +00:00
next_ent = ent - > activeNode . Next ( ) ;
master = ent - > GetTeamMaster ( ) ;
2012-11-28 15:47:07 +00:00
if ( master & & master = = ent )
{
2012-11-26 18:58:24 +00:00
ent - > activeNode . Remove ( ) ;
ent - > activeNode . AddToFront ( activeEntities ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the active entity list needs to be reordered to place pushers at the front
2012-11-28 15:47:07 +00:00
if ( sortPushers )
{
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = next_ent )
{
2012-11-26 18:58:24 +00:00
next_ent = ent - > activeNode . Next ( ) ;
master = ent - > GetTeamMaster ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! master | | master = = ent )
{
2012-11-26 18:58:24 +00:00
// check if there is an actor on the team
2012-11-28 15:47:07 +00:00
for ( part = ent ; part ! = NULL ; part = part - > GetNextTeamEntity ( ) )
{
if ( part - > GetPhysics ( ) - > IsType ( idPhysics_Actor : : Type ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
// if there is an actor on the team
2012-11-28 15:47:07 +00:00
if ( part )
{
2012-11-26 18:58:24 +00:00
ent - > activeNode . Remove ( ) ;
ent - > activeNode . AddToFront ( activeEntities ) ;
}
}
}
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = next_ent )
{
2012-11-26 18:58:24 +00:00
next_ent = ent - > activeNode . Next ( ) ;
master = ent - > GetTeamMaster ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! master | | master = = ent )
{
2012-11-26 18:58:24 +00:00
// check if there is an entity on the team using parametric physics
2012-11-28 15:47:07 +00:00
for ( part = ent ; part ! = NULL ; part = part - > GetNextTeamEntity ( ) )
{
if ( part - > GetPhysics ( ) - > IsType ( idPhysics_Parametric : : Type ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
// if there is an entity on the team using parametric physics
2012-11-28 15:47:07 +00:00
if ( part )
{
2012-11-26 18:58:24 +00:00
ent - > activeNode . Remove ( ) ;
ent - > activeNode . AddToFront ( activeEntities ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sortTeamMasters = false ;
sortPushers = false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : SetInterpolation
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetInterpolation ( const float fraction , const int serverGameMS , const int ssStartTime , const int ssEndTime )
{
2012-11-26 18:58:24 +00:00
netInterpolationInfo . previousServerGameMs = netInterpolationInfo . serverGameMs ;
netInterpolationInfo . pct = fraction ;
netInterpolationInfo . serverGameMs = serverGameMS ;
netInterpolationInfo . ssStartTime = ssStartTime ;
netInterpolationInfo . ssEndTime = ssEndTime ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RunTimeGroup2
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunTimeGroup2 ( idUserCmdMgr & userCmdMgr )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
int num = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SelectTimeGroup ( true ) ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
if ( ent - > timeGroup ! = TIME_GROUP2 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
RunEntityThink ( * ent , userCmdMgr ) ;
num + + ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SelectTimeGroup ( false ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RunEntityThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunEntityThink ( idEntity & ent , idUserCmdMgr & userCmdMgr )
{
if ( ent . entityNumber < MAX_PLAYERS )
{
2012-11-26 18:58:24 +00:00
// Players may run more than one think per frame in MP,
// if there is a large buffer of usercmds from the network.
// Players will always run exactly one think in singleplayer.
RunAllUserCmdsForPlayer ( userCmdMgr , ent . entityNumber ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Non-player entities always run one think.
ent . Think ( ) ;
}
}
idCVar g_recordTrace ( " g_recordTrace " , " 0 " , CVAR_BOOL , " " ) ;
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RunFrame
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunFrame ( idUserCmdMgr & cmdMgr , gameReturn_t & ret )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
int num ;
float ms ;
idTimer timer_think , timer_events , timer_singlethink ;
2012-11-28 15:47:07 +00:00
idPlayer * player ;
const renderView_t * view ;
if ( g_recordTrace . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
bool result = BeginTraceRecording ( " e: \\ gametrace.pix2 " ) ;
2012-11-28 15:47:07 +00:00
if ( ! result )
{
2012-11-26 18:58:24 +00:00
//idLib::Printf( "BeginTraceRecording: error %d\n", GetLastError() );
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef _DEBUG
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( ! common - > IsClient ( ) ) ;
}
# endif
2012-11-28 15:47:07 +00:00
if ( gameRenderWorld = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SyncPlayersWithLobbyUsers ( false ) ;
ServerSendNetworkSyncCvars ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
player = GetLocalPlayer ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) & & g_stopTime . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// clear any debug lines from a previous frame
gameRenderWorld - > DebugClearLines ( time + 1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the user commands for this frame
2012-11-28 15:47:07 +00:00
if ( player )
{
2012-11-26 18:58:24 +00:00
player - > HandleUserCmds ( cmdMgr . GetUserCmdForPlayer ( GetLocalClientNum ( ) ) ) ;
cmdMgr . MakeReadPtrCurrentForPlayer ( GetLocalClientNum ( ) ) ;
player - > Think ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// update the game time
framenum + + ;
fast . previousTime = FRAME_TO_MSEC ( framenum - 1 ) ;
fast . time = FRAME_TO_MSEC ( framenum ) ;
fast . realClientTime = fast . time ;
SetServerGameTimeMs ( fast . time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ComputeSlowScale ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
slow . previousTime = slow . time ;
slow . time + = idMath : : Ftoi ( ( fast . time - fast . previousTime ) * slowmoScale ) ;
slow . realClientTime = slow . time ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SelectTimeGroup ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef GAME_DLL
// allow changing SIMD usage on the fly
2012-11-28 15:47:07 +00:00
if ( com_forceGenericSIMD . IsModified ( ) )
{
2012-11-26 18:58:24 +00:00
idSIMD : : InitProcessor ( " game " , com_forceGenericSIMD . GetBool ( ) ) ;
}
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the random number counter is used each frame so random events
// are influenced by the player's actions
random . RandomInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( player )
{
2012-11-26 18:58:24 +00:00
// update the renderview so that any gui videos play from the right frame
view = player - > GetRenderView ( ) ;
2012-11-28 15:47:07 +00:00
if ( view )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > SetRenderView ( view ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear any debug lines from a previous frame
gameRenderWorld - > DebugClearLines ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear any debug polygons from a previous frame
gameRenderWorld - > DebugClearPolygons ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free old smoke particles
smokeParticles - > FreeSmokes ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// process events on the server
ServerProcessEntityNetworkEventQueue ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update our gravity vector if needed.
UpdateGravity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// create a merged pvs for all players
SetupPlayerPVS ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// sort the active entity list
SortActiveEntityList ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
timer_think . Clear ( ) ;
timer_think . Start ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let entities think
2012-11-28 15:47:07 +00:00
if ( g_timeentities . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
num = 0 ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
if ( g_cinematic . GetBool ( ) & & inCinematic & & ! ent - > cinematic )
{
2012-11-26 18:58:24 +00:00
ent - > GetPhysics ( ) - > UpdateTime ( time ) ;
continue ;
}
timer_singlethink . Clear ( ) ;
timer_singlethink . Start ( ) ;
RunEntityThink ( * ent , cmdMgr ) ;
timer_singlethink . Stop ( ) ;
ms = timer_singlethink . Milliseconds ( ) ;
2012-11-28 15:47:07 +00:00
if ( ms > = g_timeentities . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
Printf ( " %d: entity '%s': %.1f ms \n " , time , ent - > name . c_str ( ) , ms ) ;
}
num + + ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( inCinematic )
{
2012-11-26 18:58:24 +00:00
num = 0 ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
if ( g_cinematic . GetBool ( ) & & ! ent - > cinematic )
{
2012-11-26 18:58:24 +00:00
ent - > GetPhysics ( ) - > UpdateTime ( time ) ;
continue ;
}
RunEntityThink ( * ent , cmdMgr ) ;
num + + ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
num = 0 ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
if ( ent - > timeGroup ! = TIME_GROUP1 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
RunEntityThink ( * ent , cmdMgr ) ;
num + + ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RunTimeGroup2 ( cmdMgr ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Run catch-up for any client projectiles.
// This is done after the main think so that all projectiles will be up-to-date
// when snapshots are created.
//if ( common->IsMultiplayer() ) {
2012-11-28 15:47:07 +00:00
//while ( SimulateProjectiles() ) {
//clientGame.gameLibEffects.Update( clientGame.GetGameMs(), clientGame.GetGameMsPerFrame(), clientGame.GetServerGameTime() );
2012-11-26 18:58:24 +00:00
//}
2012-11-28 15:47:07 +00:00
//}
2012-11-26 18:58:24 +00:00
// remove any entities that have stopped thinking
2012-11-28 15:47:07 +00:00
if ( numEntitiesToDeactivate )
{
idEntity * next_ent ;
2012-11-26 18:58:24 +00:00
int c = 0 ;
2012-11-28 15:47:07 +00:00
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = next_ent )
{
2012-11-26 18:58:24 +00:00
next_ent = ent - > activeNode . Next ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! ent - > thinkFlags )
{
2012-11-26 18:58:24 +00:00
ent - > activeNode . Remove ( ) ;
c + + ;
}
}
//assert( numEntitiesToDeactivate == c );
numEntitiesToDeactivate = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
timer_think . Stop ( ) ;
timer_events . Clear ( ) ;
timer_events . Start ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// service any pending events
idEvent : : ServiceEvents ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// service pending fast events
SelectTimeGroup ( true ) ;
idEvent : : ServiceFastEvents ( ) ;
SelectTimeGroup ( false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
timer_events . Stop ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free the player pvs
FreePlayerPVS ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do multiplayer related stuff
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
mpGame . Run ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// display how long it took to calculate the current game frame
2012-11-28 15:47:07 +00:00
if ( g_frametime . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
Printf ( " game %d: all:%.1f th:%.1f ev:%.1f %d ents \n " ,
2012-11-28 15:47:07 +00:00
time , timer_think . Milliseconds ( ) + timer_events . Milliseconds ( ) ,
timer_think . Milliseconds ( ) , timer_events . Milliseconds ( ) , num ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
BuildReturnValue ( ret ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// show any debug info for this frame
RunDebugInfo ( ) ;
D_DrawDebugLines ( ) ;
2012-11-28 15:47:07 +00:00
if ( g_recordTrace . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
EndTraceRecording ( ) ;
g_recordTrace . SetBool ( false ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idGameLocal : : BuildReturnValue
Fills out gameReturn_t , called on server and clients .
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : BuildReturnValue ( gameReturn_t & ret )
{
2012-11-26 18:58:24 +00:00
ret . sessionCommand [ 0 ] = 0 ;
2012-11-28 15:47:07 +00:00
if ( GetLocalPlayer ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
GetLocalPlayer ( ) - > GetControllerShake ( ret . vibrationLow , ret . vibrationHigh ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Dedicated server?
ret . vibrationLow = 0 ;
ret . vibrationHigh = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if a target_sessionCommand has forced a changelevel
2012-11-28 15:47:07 +00:00
if ( sessionCommand . Length ( ) )
{
2012-11-26 18:58:24 +00:00
strncpy ( ret . sessionCommand , sessionCommand , sizeof ( ret . sessionCommand ) ) ;
sessionCommand . Clear ( ) ; // Fixes a double loading bug for the e3 demo. Since we run the game thread in SMP mode, we could run this twice and re-set the ret.sessionCommand to a stale sessionCommand (since that doesn't get cleared until LoadMap is called!)
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idGameLocal : : RunSinglelUserCmd
Runs a Think or a ClientThink for a player . Will write the client ' s
position and firecount to the usercmd .
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunSingleUserCmd ( usercmd_t & cmd , idPlayer & player )
{
2012-11-26 18:58:24 +00:00
player . HandleUserCmds ( cmd ) ;
// To fix the stupid chaingun script that depends on frame counts instead of
// milliseconds in the case of the server running at 60Hz and the client running
// at 120Hz, we need to set the script's GAME_FPS value to the client's effective rate.
// (I'd like to just fix the script to use milliseconds, but we don't want to change assets
// at this point.)
2012-11-28 15:47:07 +00:00
if ( ! player . IsLocallyControlled ( ) )
{
2012-11-26 18:58:24 +00:00
const float usercmdMillisecondDelta = player . usercmd . clientGameMilliseconds - player . oldCmd . clientGameMilliseconds ;
const float clientEngineHz = 1000.0f / usercmdMillisecondDelta ;
// Force to 60 or 120, those are the only values allowed in multiplayer.
const float forcedClientEngineHz = ( clientEngineHz < 90.0f ) ? 60.0f : 120.0f ;
SetScriptFPS ( forcedClientEngineHz ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) | | common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
player . Think ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Keep track of the client time of the usercmd we just ran. We will send this back to clients
// in a snapshot so they know when they can stop predicting certain things.
usercmdLastClientMilliseconds [ player . GetEntityNumber ( ) ] = cmd . clientGameMilliseconds ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
player . ClientThink ( netInterpolationInfo . serverGameMs , netInterpolationInfo . pct , true ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Since the client is authoritative on its position, we have to update the usercmd
// that will be sent over the network after the player thinks.
cmd . pos = player . usercmd . pos ;
cmd . fireCount = player . GetClientFireCount ( ) ;
2012-11-28 15:47:07 +00:00
if ( player . GetPhysics ( ) )
{
2012-11-26 18:58:24 +00:00
cmd . speedSquared = player . GetPhysics ( ) - > GetLinearVelocity ( ) . LengthSqr ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idGameLocal : : RunAllUserCmdsForPlayer
Runs a Think or ClientThink for each usercmd , but leaves a few cmds in the buffer
so that we have something to process while we wait for more from the network .
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunAllUserCmdsForPlayer ( idUserCmdMgr & cmdMgr , const int playerNumber )
{
2012-11-26 18:58:24 +00:00
//idLib::Printf( "Frame: %i = [%i-%i] ", gameLocal.framenum,
//cmdMgr.readFrame[0], cmdMgr.writeFrame[0] ); // !@#
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Run thinks on any players that have queued up usercmds for networking.
assert ( playerNumber < MAX_PLAYERS ) ;
2012-11-28 15:47:07 +00:00
if ( entities [ playerNumber ] = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
idPlayer & player = static_cast < idPlayer & > ( * entities [ playerNumber ] ) ;
2012-11-26 18:58:24 +00:00
// Only run a single userCmd each game frame for local players, otherwise when
// we are running < 60fps things like footstep sounds may get started right on top
// of each other instead of spread out in time.
2012-11-28 15:47:07 +00:00
if ( player . IsLocallyControlled ( ) )
{
if ( cmdMgr . HasUserCmdForPlayer ( playerNumber ) )
{
if ( net_usercmd_timing_debug . GetBool ( ) )
{
idLib : : Printf ( " [%d]Running local cmd for player %d, %d buffered. \n " ,
common - > GetGameFrame ( ) , playerNumber , cmdMgr . GetNumUnreadFrames ( playerNumber ) ) ;
2012-11-26 18:58:24 +00:00
}
RunSingleUserCmd ( cmdMgr . GetWritableUserCmdForPlayer ( playerNumber ) , player ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
RunSingleUserCmd ( player . usercmd , player ) ;
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Only the server runs remote commands.
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
// Make sure to run a command for remote players. May duplicate the previous command
// if the server is running faster, or run an "empty" command if the buffer
// underflows.
2012-11-28 15:47:07 +00:00
if ( cmdMgr . HasUserCmdForPlayer ( player . GetEntityNumber ( ) ) )
{
2012-11-26 18:58:24 +00:00
const int clientTimeOfNextCommand = cmdMgr . GetNextUserCmdClientTime ( playerNumber ) ;
const int timeDeltaBetweenClientCommands = clientTimeOfNextCommand - lastCmdRunTimeOnClient [ playerNumber ] ;
const int timeSinceServerRanLastCommand = gameLocal . time - lastCmdRunTimeOnServer [ playerNumber ] ;
int clientTimeRunSoFar = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Handle clients who may be running faster than the server. Potentiallly runs multiple
// usercmds so that the server can catch up.
2012-11-28 15:47:07 +00:00
if ( timeDeltaBetweenClientCommands - timeSinceServerRanLastCommand < = 1 )
{
while ( clientTimeRunSoFar < ( timeSinceServerRanLastCommand - 1 ) & & cmdMgr . HasUserCmdForPlayer ( player . GetEntityNumber ( ) ) )
{
usercmd_t & currentCommand = cmdMgr . GetWritableUserCmdForPlayer ( playerNumber ) ;
2012-11-26 18:58:24 +00:00
RunSingleUserCmd ( currentCommand , player ) ;
lastCmdRunTimeOnClient [ playerNumber ] = currentCommand . clientGameMilliseconds ;
lastCmdRunTimeOnServer [ playerNumber ] = gameLocal . serverTime ;
clientTimeRunSoFar + = timeDeltaBetweenClientCommands ;
2012-11-28 15:47:07 +00:00
if ( clientTimeRunSoFar = = 0 )
{
2012-11-26 18:58:24 +00:00
// Hack to avoid infinite loop
break ;
}
2012-11-28 15:47:07 +00:00
if ( net_usercmd_timing_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " [%d]Running initial cmd for player %d, %d buffered, %d so far, %d serverDelta. \n " ,
common - > GetGameFrame ( ) , playerNumber , cmdMgr . GetNumUnreadFrames ( playerNumber ) ,
clientTimeRunSoFar , timeSinceServerRanLastCommand ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// If we get here, it is likely that the client is running at 60Hz but the server
// is running at 120Hz. Duplicate the previous
// usercmd and run it so that the server doesn't starve.
usercmd_t lastPlayerCmd = player . usercmd ;
RunSingleUserCmd ( lastPlayerCmd , player ) ;
2012-11-28 15:47:07 +00:00
if ( net_usercmd_timing_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " [%d]Running duplicated command for player %d to prevent server from starving. clientCmdTimeDelta = %d, runCmdTimeDeltaOnServer = %d. \n " ,
common - > GetGameFrame ( ) , playerNumber , timeDeltaBetweenClientCommands , timeSinceServerRanLastCommand ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Run an "empty" cmd, ran out of buffer.
usercmd_t emptyCmd = player . usercmd ;
emptyCmd . forwardmove = 0 ;
emptyCmd . rightmove = 0 ;
RunSingleUserCmd ( emptyCmd , player ) ;
lastCmdRunTimeOnServer [ playerNumber ] = gameLocal . serverTime ;
2012-11-28 15:47:07 +00:00
if ( net_usercmd_timing_debug . GetBool ( ) )
{
idLib : : Printf ( " [%d]Ran out of commands for player %d. \n " , common - > GetGameFrame ( ) , playerNumber ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// For remote players on the server, run enough commands
// to leave only a buffer that will hold us over for a
// number of milliseconds equal to the net_ucmdRate + one frame.
const int MaxExtraCommandsPerFrame = 15 ;
int numPasses = 0 ;
2012-11-28 15:47:07 +00:00
for ( ; numPasses < MaxExtraCommandsPerFrame ; numPasses + + )
{
2012-11-26 18:58:24 +00:00
// Run remote player extra commands
extern idCVar net_ucmdRate ;
// Add some extra time to smooth out network inconsistencies.
const int extraFrameMilliseconds = FRAME_TO_MSEC ( common - > GetGameFrame ( ) + 2 ) - FRAME_TO_MSEC ( common - > GetGameFrame ( ) ) ;
const int millisecondBuffer = MSEC_ALIGN_TO_FRAME ( net_ucmdRate . GetInteger ( ) + extraFrameMilliseconds ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool hasNextCmd = cmdMgr . HasUserCmdForClientTimeBuffer ( playerNumber , millisecondBuffer ) ;
2012-11-28 15:47:07 +00:00
if ( hasNextCmd )
{
usercmd_t & currentCommand = cmdMgr . GetWritableUserCmdForPlayer ( playerNumber ) ;
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( net_usercmd_timing_debug . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " [%d]Pass %d, running extra cmd for player %d, %d buffered \n " , common - > GetGameFrame ( ) , numPasses , playerNumber , cmdMgr . GetNumUnreadFrames ( playerNumber ) ) ;
}
RunSingleUserCmd ( currentCommand , player ) ;
lastCmdRunTimeOnClient [ playerNumber ] = currentCommand . clientGameMilliseconds ;
lastCmdRunTimeOnServer [ playerNumber ] = gameLocal . serverTime ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Reset the script FPS in case it was changed to accomodate an MP client
// running at a different framerate.
SetScriptFPS ( com_engineHz_latched ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//idLib::Printf( "\n" );//!@#
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Game view drawing
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = =
idGameLocal : : CalcFov
Calculates the horizontal and vertical field of view based on a horizontal field of view and custom aspect ratio
= = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : CalcFov ( float base_fov , float & fov_x , float & fov_y ) const
{
2012-11-26 18:58:24 +00:00
const int width = renderSystem - > GetWidth ( ) ;
const int height = renderSystem - > GetHeight ( ) ;
2012-11-28 15:47:07 +00:00
if ( width = = height )
{
2012-11-26 18:58:24 +00:00
// this is the Rift, so don't mess with our aspect ratio corrections
fov_x = base_fov ;
fov_y = base_fov ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Calculate the fov_y based on an ideal aspect ratio
const float ideal_ratio_x = 16.0f ;
const float ideal_ratio_y = 9.0f ;
const float tanHalfX = idMath : : Tan ( DEG2RAD ( base_fov * 0.5f ) ) ;
fov_y = 2.0f * RAD2DEG ( idMath : : ATan ( ideal_ratio_y * tanHalfX , ideal_ratio_x ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Then calculate fov_x based on the true aspect ratio
const float ratio_x = width * renderSystem - > GetPixelAspect ( ) ;
const float ratio_y = height ;
const float tanHalfY = idMath : : Tan ( DEG2RAD ( fov_y * 0.5f ) ) ;
fov_x = 2.0f * RAD2DEG ( idMath : : ATan ( ratio_x * tanHalfY , ratio_y ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : Draw
makes rendering and sound system calls
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : Draw ( int clientNum )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( clientNum = = - 1 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & session - > GetState ( ) = = idSession : : INGAME )
{
2012-11-26 18:58:24 +00:00
return mpGame . Draw ( clientNum ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// chose the optimized or legacy device context code
uiManager - > SetDrawingDC ( ) ;
2012-11-28 15:47:07 +00:00
idPlayer * player = static_cast < idPlayer * > ( entities [ clientNum ] ) ;
if ( ( player = = NULL ) | | ( player - > GetRenderView ( ) = = NULL ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// render the scene
player - > playerView . RenderPlayerView ( player - > hudManager ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : HandleGuiCommands
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : HandlePlayerGuiEvent ( const sysEvent_t * ev )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
idPlayer * player = GetLocalPlayer ( ) ;
2012-11-26 18:58:24 +00:00
bool handled = false ;
2012-11-28 15:47:07 +00:00
if ( player ! = NULL )
{
2012-11-26 18:58:24 +00:00
handled = player - > HandleGuiEvents ( ev ) ;
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ! handled )
{
2012-11-26 18:58:24 +00:00
handled = mpGame . HandleGuiEvent ( ev ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return handled ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetLevelMap
should only be used for in - game level editing
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idMapFile * idGameLocal : : GetLevelMap ( )
{
if ( mapFile & & mapFile - > HasPrimitiveData ( ) )
{
2012-11-26 18:58:24 +00:00
return mapFile ;
}
2012-11-28 15:47:07 +00:00
if ( ! mapFileName . Length ( ) )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
if ( mapFile )
{
2012-11-26 18:58:24 +00:00
delete mapFile ;
}
2012-11-28 15:47:07 +00:00
mapFile = new ( TAG_GAME ) idMapFile ;
if ( ! mapFile - > Parse ( mapFileName ) )
{
2012-11-26 18:58:24 +00:00
delete mapFile ;
mapFile = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return mapFile ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetMapName
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idGameLocal : : GetMapName ( ) const
{
2012-11-26 18:58:24 +00:00
return mapFileName . c_str ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : CallFrameCommand
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : CallFrameCommand ( idEntity * ent , const function_t * frameCommand )
{
2012-11-26 18:58:24 +00:00
frameCommandThread - > CallFunction ( ent , frameCommand , true ) ;
frameCommandThread - > Execute ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : CallObjectFrameCommand
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : CallObjectFrameCommand ( idEntity * ent , const char * frameCommand )
{
const function_t * func ;
2012-11-26 18:58:24 +00:00
func = ent - > scriptObject . GetFunction ( frameCommand ) ;
2012-11-28 15:47:07 +00:00
if ( ! func )
{
if ( ! ent - > IsType ( idTestModel : : Type ) )
{
2012-11-26 18:58:24 +00:00
Error ( " Unknown function '%s' called for frame command on entity '%s' " , frameCommand , ent - > name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
frameCommandThread - > CallFunction ( ent , func , true ) ;
frameCommandThread - > Execute ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : ShowTargets
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : ShowTargets ( )
{
2012-11-26 18:58:24 +00:00
idMat3 axis = GetLocalPlayer ( ) - > viewAngles . ToMat3 ( ) ;
idVec3 up = axis [ 2 ] * 5.0f ;
2012-11-28 15:47:07 +00:00
const idVec3 & viewPos = GetLocalPlayer ( ) - > GetPhysics ( ) - > GetOrigin ( ) ;
2012-11-26 18:58:24 +00:00
idBounds viewTextBounds ( viewPos ) ;
idBounds viewBounds ( viewPos ) ;
idBounds box ( idVec3 ( - 4.0f , - 4.0f , - 4.0f ) , idVec3 ( 4.0f , 4.0f , 4.0f ) ) ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
idEntity * target ;
2012-11-26 18:58:24 +00:00
int i ;
idBounds totalBounds ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
viewTextBounds . ExpandSelf ( 128.0f ) ;
viewBounds . ExpandSelf ( 512.0f ) ;
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
totalBounds = ent - > GetPhysics ( ) - > GetAbsBounds ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < ent - > targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
target = ent - > targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( target )
{
2012-11-26 18:58:24 +00:00
totalBounds . AddBounds ( target - > GetPhysics ( ) - > GetAbsBounds ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! viewBounds . IntersectsBounds ( totalBounds ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float dist ;
idVec3 dir = totalBounds . GetCenter ( ) - viewPos ;
dir . NormalizeFast ( ) ;
totalBounds . RayIntersection ( viewPos , dir , dist ) ;
float frac = ( 512.0f - dist ) / 512.0f ;
2012-11-28 15:47:07 +00:00
if ( frac < 0.0f )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( ( ent - > IsHidden ( ) ? colorLtGrey : colorOrange ) * frac , ent - > GetPhysics ( ) - > GetAbsBounds ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( viewTextBounds . IntersectsBounds ( ent - > GetPhysics ( ) - > GetAbsBounds ( ) ) )
{
2012-11-26 18:58:24 +00:00
idVec3 center = ent - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) ;
gameRenderWorld - > DrawText ( ent - > name . c_str ( ) , center - up , 0.1f , colorWhite * frac , axis , 1 ) ;
gameRenderWorld - > DrawText ( ent - > GetEntityDefName ( ) , center , 0.1f , colorWhite * frac , axis , 1 ) ;
gameRenderWorld - > DrawText ( va ( " #%d " , ent - > entityNumber ) , center + up , 0.1f , colorWhite * frac , axis , 1 ) ;
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < ent - > targets . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
target = ent - > targets [ i ] . GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( target )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugArrow ( colorYellow * frac , ent - > GetPhysics ( ) - > GetAbsBounds ( ) . GetCenter ( ) , target - > GetPhysics ( ) - > GetOrigin ( ) , 10 , 0 ) ;
gameRenderWorld - > DebugBounds ( colorGreen * frac , box , target - > GetPhysics ( ) - > GetOrigin ( ) ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RunDebugInfo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RunDebugInfo ( )
{
idEntity * ent ;
idPlayer * player ;
2012-11-26 18:58:24 +00:00
player = GetLocalPlayer ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! player )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const idVec3 & origin = player - > GetPhysics ( ) - > GetOrigin ( ) ;
if ( g_showEntityInfo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idMat3 axis = player - > viewAngles . ToMat3 ( ) ;
idVec3 up = axis [ 2 ] * 5.0f ;
idBounds viewTextBounds ( origin ) ;
idBounds viewBounds ( origin ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
viewTextBounds . ExpandSelf ( 128.0f ) ;
viewBounds . ExpandSelf ( 512.0f ) ;
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
// don't draw the worldspawn
2012-11-28 15:47:07 +00:00
if ( ent = = world )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip if the entity is very far away
2012-11-28 15:47:07 +00:00
if ( ! viewBounds . IntersectsBounds ( ent - > GetPhysics ( ) - > GetAbsBounds ( ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
const idBounds & entBounds = ent - > GetPhysics ( ) - > GetAbsBounds ( ) ;
2012-11-26 18:58:24 +00:00
int contents = ent - > GetPhysics ( ) - > GetContents ( ) ;
2012-11-28 15:47:07 +00:00
if ( contents & CONTENTS_BODY )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorCyan , entBounds ) ;
2012-11-28 15:47:07 +00:00
}
else if ( contents & CONTENTS_TRIGGER )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorOrange , entBounds ) ;
2012-11-28 15:47:07 +00:00
}
else if ( contents & CONTENTS_SOLID )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorGreen , entBounds ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! entBounds . GetVolume ( ) )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorMdGrey , entBounds . Expand ( 8.0f ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorMdGrey , entBounds ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( viewTextBounds . IntersectsBounds ( entBounds ) )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DrawText ( ent - > name . c_str ( ) , entBounds . GetCenter ( ) , 0.1f , colorWhite , axis , 1 ) ;
gameRenderWorld - > DrawText ( va ( " #%d " , ent - > entityNumber ) , entBounds . GetCenter ( ) + up , 0.1f , colorWhite , axis , 1 ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// debug tool to draw bounding boxes around active entities
2012-11-28 15:47:07 +00:00
if ( g_showActiveEntities . GetBool ( ) )
{
for ( ent = activeEntities . Next ( ) ; ent ! = NULL ; ent = ent - > activeNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
idBounds b = ent - > GetPhysics ( ) - > GetBounds ( ) ;
2012-11-28 15:47:07 +00:00
if ( b . GetVolume ( ) < = 0 )
{
2012-11-26 18:58:24 +00:00
b [ 0 ] [ 0 ] = b [ 0 ] [ 1 ] = b [ 0 ] [ 2 ] = - 8 ;
b [ 1 ] [ 0 ] = b [ 1 ] [ 1 ] = b [ 1 ] [ 2 ] = 8 ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > fl . isDormant )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorYellow , b , ent - > GetPhysics ( ) - > GetOrigin ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > DebugBounds ( colorGreen , b , ent - > GetPhysics ( ) - > GetOrigin ( ) ) ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( g_showTargets . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
ShowTargets ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showTriggers . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idTrigger : : DrawDebugInfo ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ai_showCombatNodes . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idCombatNode : : DrawDebugInfo ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ai_showPaths . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idPathCorner : : DrawDebugInfo ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_editEntityMode . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
editEntities - > DisplayEntities ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showCollisionWorld . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
collisionModelManager - > DrawModel ( 0 , vec3_origin , mat3_identity , origin , 128.0f ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showCollisionModels . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
clip . DrawClipModels ( player - > GetEyePosition ( ) , g_maxShowDistance . GetFloat ( ) , pm_thirdPerson . GetBool ( ) ? NULL : player ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showCollisionTraces . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
clip . PrintStatistics ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( g_showPVS . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
pvs . DrawPVS ( origin , ( g_showPVS . GetInteger ( ) = = 2 ) ? PVS_ALL_PORTALS_OPEN : PVS_NORMAL ) ;
}
2012-11-28 15:47:07 +00:00
if ( aas_test . GetInteger ( ) > = 0 )
{
idAAS * aas = GetAAS ( aas_test . GetInteger ( ) ) ;
if ( aas )
{
2012-11-26 18:58:24 +00:00
aas - > Test ( origin ) ;
2012-11-28 15:47:07 +00:00
if ( ai_testPredictPath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idVec3 velocity ;
predictedPath_t path ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
velocity . x = cos ( DEG2RAD ( player - > viewAngles . yaw ) ) * 100.0f ;
velocity . y = sin ( DEG2RAD ( player - > viewAngles . yaw ) ) * 100.0f ;
velocity . z = 0.0f ;
idAI : : PredictPath ( player , aas , origin , velocity , 1000 , 100 , SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA , path ) ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( ai_showObstacleAvoidance . GetInteger ( ) = = 2 )
{
idAAS * aas = GetAAS ( 0 ) ;
if ( aas )
{
2012-11-26 18:58:24 +00:00
idVec3 seekPos ;
obstaclePath_t path ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
seekPos = player - > GetPhysics ( ) - > GetOrigin ( ) + player - > viewAxis [ 0 ] * 200.0f ;
idAI : : FindPathAroundObstacles ( player - > GetPhysics ( ) , aas , NULL , player - > GetPhysics ( ) - > GetOrigin ( ) , seekPos , path ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// collision map debug output
collisionModelManager - > DebugOutput ( player - > GetEyePosition ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : NumAAS
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : NumAAS ( ) const
{
2012-11-26 18:58:24 +00:00
return aasList . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : GetAAS
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAAS * idGameLocal : : GetAAS ( int num ) const
{
if ( ( num > = 0 ) & & ( num < aasList . Num ( ) ) )
{
if ( aasList [ num ] & & aasList [ num ] - > GetSettings ( ) )
{
2012-11-26 18:58:24 +00:00
return aasList [ num ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : GetAAS
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAAS * idGameLocal : : GetAAS ( const char * name ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasNames . Num ( ) ; i + + )
{
if ( aasNames [ i ] = = name )
{
if ( ! aasList [ i ] - > GetSettings ( ) )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return aasList [ i ] ;
}
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : SetAASAreaState
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetAASAreaState ( const idBounds & bounds , const int areaContents , bool closed )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasList . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aasList [ i ] - > SetAreaState ( bounds , areaContents , closed ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : AddAASObstacle
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
aasHandle_t idGameLocal : : AddAASObstacle ( const idBounds & bounds )
{
2012-11-26 18:58:24 +00:00
int i ;
aasHandle_t obstacle ;
aasHandle_t check ;
2012-11-28 15:47:07 +00:00
if ( ! aasList . Num ( ) )
{
2012-11-26 18:58:24 +00:00
return - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
obstacle = aasList [ 0 ] - > AddObstacle ( bounds ) ;
2012-11-28 15:47:07 +00:00
for ( i = 1 ; i < aasList . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
check = aasList [ i ] - > AddObstacle ( bounds ) ;
assert ( check = = obstacle ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return obstacle ;
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : RemoveAASObstacle
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RemoveAASObstacle ( const aasHandle_t handle )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasList . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aasList [ i ] - > RemoveObstacle ( handle ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : RemoveAllAASObstacles
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RemoveAllAASObstacles ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < aasList . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
aasList [ i ] - > RemoveAllObstacles ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
idGameLocal : : CheatsOk
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : CheatsOk ( bool requirePlayer )
{
2012-11-26 18:58:24 +00:00
extern idCVar net_allowCheats ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ! net_allowCheats . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
Printf ( " Not allowed in multiplayer. \n " ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
if ( developer . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
idPlayer * player = GetLocalPlayer ( ) ;
if ( ! requirePlayer | | ( player ! = NULL & & ( player - > health > 0 ) ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " You must be alive to use this command. \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : RegisterEntity
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RegisterEntity ( idEntity * ent , int forceSpawnId , const idDict & spawnArgsToCopy )
{
2012-11-26 18:58:24 +00:00
int spawn_entnum ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent - > fl . skipReplication = spawnArgsToCopy . GetBool ( " net_skip_replication " , false ) ;
2012-11-28 15:47:07 +00:00
if ( spawnCount > = ( 1 < < ( 32 - GENTITYNUM_BITS ) ) )
{
2012-11-26 18:58:24 +00:00
Error ( " idGameLocal::RegisterEntity: spawn count overflow " ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! spawnArgsToCopy . GetInt ( " spawn_entnum " , " 0 " , spawn_entnum ) )
{
2012-11-26 18:58:24 +00:00
const int freeListType = ( common - > IsMultiplayer ( ) & & ent - > GetSkipReplication ( ) ) ? 1 : 0 ;
const int maxEntityNum = ( common - > IsMultiplayer ( ) & & ! ent - > GetSkipReplication ( ) ) ? ENTITYNUM_FIRST_NON_REPLICATED : ENTITYNUM_MAX_NORMAL ;
int freeIndex = firstFreeEntityIndex [ freeListType ] ;
2012-11-28 15:47:07 +00:00
while ( entities [ freeIndex ] ! = NULL & & freeIndex < maxEntityNum )
{
2012-11-26 18:58:24 +00:00
freeIndex + + ;
}
2012-11-28 15:47:07 +00:00
if ( freeIndex > = maxEntityNum )
{
2012-11-26 18:58:24 +00:00
Error ( " no free entities[%d] " , freeListType ) ;
}
spawn_entnum = freeIndex + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
firstFreeEntityIndex [ freeListType ] = freeIndex ;
}
entities [ spawn_entnum ] = ent ;
spawnIds [ spawn_entnum ] = ( forceSpawnId > = 0 ) ? forceSpawnId : spawnCount + + ;
ent - > entityNumber = spawn_entnum ;
ent - > spawnNode . AddToEnd ( spawnedEntities ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Make a copy because TransferKeyValues clears the input parameter.
idDict copiedArgs = spawnArgsToCopy ;
ent - > spawnArgs . TransferKeyValues ( copiedArgs ) ;
2012-11-28 15:47:07 +00:00
if ( spawn_entnum > = num_entities )
{
2012-11-26 18:58:24 +00:00
num_entities + + ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : UnregisterEntity
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : UnregisterEntity ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
if ( editEntities )
{
2012-11-26 18:58:24 +00:00
editEntities - > RemoveSelectedEntity ( ent ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! verify ( ent - > entityNumber < MAX_GENTITIES ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " invalid entity number " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( ( ent - > entityNumber ! = ENTITYNUM_NONE ) & & ( entities [ ent - > entityNumber ] = = ent ) )
{
2012-11-26 18:58:24 +00:00
ent - > spawnNode . Remove ( ) ;
entities [ ent - > entityNumber ] = NULL ;
spawnIds [ ent - > entityNumber ] = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int freeListType = ( common - > IsMultiplayer ( ) & & ent - > entityNumber > = ENTITYNUM_FIRST_NON_REPLICATED ) ? 1 : 0 ;
2012-11-28 15:47:07 +00:00
if ( ent - > entityNumber > = MAX_CLIENTS & & ent - > entityNumber < firstFreeEntityIndex [ freeListType ] )
{
2012-11-26 18:58:24 +00:00
firstFreeEntityIndex [ freeListType ] = ent - > entityNumber ;
}
ent - > entityNumber = ENTITYNUM_NONE ;
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : SpawnEntityType
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : SpawnEntityType ( const idTypeInfo & classdef , const idDict * args , bool bIsClientReadSnapshot )
{
idClass * obj ;
2012-11-26 18:58:24 +00:00
# if _DEBUG
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( bIsClientReadSnapshot ) ;
}
# endif
2012-11-28 15:47:07 +00:00
if ( ! classdef . IsType ( idEntity : : Type ) )
{
2012-11-26 18:58:24 +00:00
Error ( " Attempted to spawn non-entity class '%s' " , classdef . classname ) ;
}
2012-11-28 15:47:07 +00:00
try
{
if ( args )
{
2012-11-26 18:58:24 +00:00
spawnArgs = * args ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
spawnArgs . Clear ( ) ;
}
obj = classdef . CreateInstance ( ) ;
obj - > CallSpawn ( ) ;
}
2012-11-28 15:47:07 +00:00
catch ( idAllocError & )
{
2012-11-26 18:58:24 +00:00
obj = NULL ;
}
spawnArgs . Clear ( ) ;
2012-11-28 15:47:07 +00:00
return static_cast < idEntity * > ( obj ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : SpawnEntityDef
Finds the spawn function for the entity and calls it ,
returning false if not found
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : SpawnEntityDef ( const idDict & args , idEntity * * ent , bool setDefaults )
{
const char * classname ;
const char * spawn ;
idTypeInfo * cls ;
idClass * obj ;
2012-11-26 18:58:24 +00:00
idStr error ;
2012-11-28 15:47:07 +00:00
const char * name ;
if ( ent )
{
2012-11-26 18:58:24 +00:00
* ent = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs = args ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " name " , " " , & name ) )
{
sprintf ( error , " on '%s' " , name ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetString ( " classname " , NULL , & classname ) ;
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * def = FindEntityDef ( classname , false ) ;
if ( ! def )
{
2012-11-26 18:58:24 +00:00
Warning ( " Unknown classname '%s'%s. " , classname , error . c_str ( ) ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . SetDefaults ( & def - > dict ) ;
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . FindKey ( " slowmo " ) )
{
2012-11-26 18:58:24 +00:00
bool slowmo = true ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; fastEntityList [ i ] ; i + + )
{
if ( ! idStr : : Cmp ( classname , fastEntityList [ i ] ) )
{
2012-11-26 18:58:24 +00:00
slowmo = false ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! slowmo )
{
2012-11-26 18:58:24 +00:00
spawnArgs . SetBool ( " slowmo " , slowmo ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we should spawn a class object
spawnArgs . GetString ( " spawnclass " , NULL , & spawn ) ;
2012-11-28 15:47:07 +00:00
if ( spawn )
{
2012-11-26 18:58:24 +00:00
cls = idClass : : GetClass ( spawn ) ;
2012-11-28 15:47:07 +00:00
if ( ! cls )
{
2012-11-26 18:58:24 +00:00
Warning ( " Could not spawn '%s'. Class '%s' not found%s. " , classname , spawn , error . c_str ( ) ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
obj = cls - > CreateInstance ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! obj )
{
2012-11-26 18:58:24 +00:00
Warning ( " Could not spawn '%s'. Instance could not be created%s. " , classname , error . c_str ( ) ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
obj - > CallSpawn ( ) ;
2012-11-28 15:47:07 +00:00
if ( ent & & obj - > IsType ( idEntity : : Type ) )
{
* ent = static_cast < idEntity * > ( obj ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if we should call a script function to spawn
spawnArgs . GetString ( " spawnfunc " , NULL , & spawn ) ;
2012-11-28 15:47:07 +00:00
if ( spawn )
{
const function_t * func = program . FindFunction ( spawn ) ;
if ( ! func )
{
2012-11-26 18:58:24 +00:00
Warning ( " Could not spawn '%s'. Script function '%s' not found%s. " , classname , spawn , error . c_str ( ) ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
idThread * thread = new idThread ( func ) ;
2012-11-26 18:58:24 +00:00
thread - > DelayedStart ( 0 ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Warning ( " %s doesn't include a spawnfunc or spawnclass%s. " , classname , error . c_str ( ) ) ;
return false ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : FindEntityDef
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDeclEntityDef * idGameLocal : : FindEntityDef ( const char * name , bool makeDefault ) const
{
const idDecl * decl = NULL ;
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
decl = declManager - > FindType ( DECL_ENTITYDEF , va ( " %s_mp " , name ) , false ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
decl = declManager - > FindType ( DECL_ENTITYDEF , name , makeDefault ) ;
}
2012-11-28 15:47:07 +00:00
return static_cast < const idDeclEntityDef * > ( decl ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : FindEntityDefDict
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDict * idGameLocal : : FindEntityDefDict ( const char * name , bool makeDefault ) const
{
const idDeclEntityDef * decl = FindEntityDef ( name , makeDefault ) ;
2012-11-26 18:58:24 +00:00
return decl ? & decl - > dict : NULL ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : InhibitEntitySpawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : InhibitEntitySpawn ( idDict & spawnArgs )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
bool result = false ;
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " not_multiplayer " , " 0 " , result ) ;
2012-11-28 15:47:07 +00:00
}
else if ( g_skill . GetInteger ( ) = = 0 )
{
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " not_easy " , " 0 " , result ) ;
2012-11-28 15:47:07 +00:00
}
else if ( g_skill . GetInteger ( ) = = 1 )
{
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " not_medium " , " 0 " , result ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " not_hard " , " 0 " , result ) ;
2012-11-28 15:47:07 +00:00
if ( ! result & & g_skill . GetInteger ( ) = = 3 )
{
2012-11-26 18:58:24 +00:00
spawnArgs . GetBool ( " not_nightmare " , " 0 " , result ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( g_skill . GetInteger ( ) = = 3 )
{
const char * name = spawnArgs . GetString ( " classname " ) ;
2012-11-26 18:58:24 +00:00
// _D3XP :: remove moveable medkit packs also
2012-11-28 15:47:07 +00:00
if ( idStr : : Icmp ( name , " item_medkit " ) = = 0 | | idStr : : Icmp ( name , " item_medkit_small " ) = = 0 | |
idStr : : Icmp ( name , " moveable_item_medkit " ) = = 0 | | idStr : : Icmp ( name , " moveable_item_medkit_small " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
result = true ;
}
}
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
const char * name = spawnArgs . GetString ( " classname " ) ;
if ( idStr : : Icmp ( name , " weapon_bfg " ) = = 0 | | idStr : : Icmp ( name , " weapon_soulcube " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
result = true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return result ;
}
/*
= = = = = = = = = = = = = =
idGameLocal : : GameState
Used to allow entities to know if they ' re being spawned during the initial spawn .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
gameState_t idGameLocal : : GameState ( ) const
{
2012-11-26 18:58:24 +00:00
return gamestate ;
}
/*
= = = = = = = = = = = = = =
idGameLocal : : SpawnMapEntities
Parses textual entity definitions out of an entstring and spawns gentities .
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SpawnMapEntities ( )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
int inhibit ;
2012-11-28 15:47:07 +00:00
idMapEntity * mapEnt ;
2012-11-26 18:58:24 +00:00
int numEntities ;
idDict args ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " Spawning entities \n " ) ;
2012-11-28 15:47:07 +00:00
if ( mapFile = = NULL )
{
Printf ( " No mapfile present \n " ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntities = mapFile - > GetNumEntities ( ) ;
2012-11-28 15:47:07 +00:00
if ( numEntities = = 0 )
{
2012-11-26 18:58:24 +00:00
Error ( " ...no entities " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the worldspawn is a special that performs any global setup
// needed by a level
mapEnt = mapFile - > GetEntity ( 0 ) ;
args = mapEnt - > epairs ;
args . SetInt ( " spawn_entnum " , ENTITYNUM_WORLD ) ;
2012-11-28 15:47:07 +00:00
if ( ! SpawnEntityDef ( args ) | | ! entities [ ENTITYNUM_WORLD ] | | ! entities [ ENTITYNUM_WORLD ] - > IsType ( idWorldspawn : : Type ) )
{
2012-11-26 18:58:24 +00:00
Error ( " Problem spawning world entity " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = 1 ;
inhibit = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 1 ; i < numEntities ; i + + )
{
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapEnt = mapFile - > GetEntity ( i ) ;
args = mapEnt - > epairs ;
2012-11-28 15:47:07 +00:00
if ( ! InhibitEntitySpawn ( args ) )
{
2012-11-26 18:58:24 +00:00
// precache any media specified in the map entity
CacheDictionaryMedia ( & args ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SpawnEntityDef ( args ) ;
num + + ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
inhibit + + ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Printf ( " ...%i entities spawned, %i inhibited \n \n " , num , inhibit ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : AddEntityToHash
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : AddEntityToHash ( const char * name , idEntity * ent )
{
if ( FindEntity ( name ) )
{
2012-11-26 18:58:24 +00:00
Error ( " Multiple entities named '%s' " , name ) ;
}
entityHash . Add ( entityHash . GenerateKey ( name , true ) , ent - > entityNumber ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RemoveEntityFromHash
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : RemoveEntityFromHash ( const char * name , idEntity * ent )
{
2012-11-26 18:58:24 +00:00
int hash , i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hash = entityHash . GenerateKey ( name , true ) ;
2012-11-28 15:47:07 +00:00
for ( i = entityHash . First ( hash ) ; i ! = - 1 ; i = entityHash . Next ( i ) )
{
if ( entities [ i ] & & entities [ i ] = = ent & & entities [ i ] - > name . Icmp ( name ) = = 0 )
{
2012-11-26 18:58:24 +00:00
entityHash . Remove ( hash , i ) ;
return true ;
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetTargets
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetTargets ( const idDict & args , idList < idEntityPtr < idEntity > > & list , const char * ref ) const
{
2012-11-26 18:58:24 +00:00
int i , num , refLength ;
2012-11-28 15:47:07 +00:00
const idKeyValue * arg ;
idEntity * ent ;
2012-11-26 18:58:24 +00:00
list . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
refLength = strlen ( ref ) ;
num = args . GetNumKeyVals ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
arg = args . GetKeyVal ( i ) ;
2012-11-28 15:47:07 +00:00
if ( arg - > GetKey ( ) . Icmpn ( ref , refLength ) = = 0 )
{
2012-11-26 18:58:24 +00:00
ent = FindEntity ( arg - > GetValue ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( ent )
{
idEntityPtr < idEntity > & entityPtr = list . Alloc ( ) ;
entityPtr = ent ;
2012-11-26 18:58:24 +00:00
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return list . Num ( ) ;
}
/*
= = = = = = = = = = = = =
idGameLocal : : GetTraceEntity
returns the master entity of a trace . for example , if the trace entity is the player ' s head , it will return the player .
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : GetTraceEntity ( const trace_t & trace ) const
{
idEntity * master ;
if ( ! entities [ trace . c . entityNum ] )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
master = entities [ trace . c . entityNum ] - > GetBindMaster ( ) ;
2012-11-28 15:47:07 +00:00
if ( master )
{
2012-11-26 18:58:24 +00:00
return master ;
}
return entities [ trace . c . entityNum ] ;
}
/*
= = = = = = = = = = = = =
idGameLocal : : ArgCompletion_EntityName
Argument completion for entity names
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : ArgCompletion_EntityName ( const idCmdArgs & args , void ( * callback ) ( const char * s ) )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < gameLocal . num_entities ; i + + )
{
if ( gameLocal . entities [ i ] )
{
2012-11-26 18:58:24 +00:00
callback ( va ( " %s %s " , args . Argv ( 0 ) , gameLocal . entities [ i ] - > name . c_str ( ) ) ) ;
}
}
}
/*
= = = = = = = = = = = = =
idGameLocal : : FindEntity
Returns the entity whose name matches the specified string .
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : FindEntity ( const char * name ) const
{
2012-11-26 18:58:24 +00:00
int hash , i ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hash = entityHash . GenerateKey ( name , true ) ;
2012-11-28 15:47:07 +00:00
for ( i = entityHash . First ( hash ) ; i ! = - 1 ; i = entityHash . Next ( i ) )
{
if ( entities [ i ] & & entities [ i ] - > name . Icmp ( name ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return entities [ i ] ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = =
idGameLocal : : FindEntityUsingDef
Searches all active entities for the next one using the specified entityDef .
Searches beginning at the entity after from , or the beginning if NULL
NULL will be returned if the end of the list is reached .
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : FindEntityUsingDef ( idEntity * from , const char * match ) const
{
idEntity * ent ;
if ( ! from )
{
2012-11-26 18:58:24 +00:00
ent = spawnedEntities . Next ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ent = from - > spawnNode . Next ( ) ;
}
2012-11-28 15:47:07 +00:00
for ( ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
2012-11-26 18:58:24 +00:00
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
if ( idStr : : Icmp ( ent - > GetEntityDefName ( ) , match ) = = 0 )
{
2012-11-26 18:58:24 +00:00
return ent ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = = =
idGameLocal : : FindTraceEntity
Searches all active entities for the closest ( to start ) match that intersects
the line start , end
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : FindTraceEntity ( idVec3 start , idVec3 end , const idTypeInfo & c , const idEntity * skip ) const
{
idEntity * ent ;
idEntity * bestEnt ;
2012-11-26 18:58:24 +00:00
float scale ;
float bestScale ;
idBounds b ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bestEnt = NULL ;
bestScale = 1.0f ;
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ent - > IsType ( c ) & & ent ! = skip )
{
2012-11-26 18:58:24 +00:00
b = ent - > GetPhysics ( ) - > GetAbsBounds ( ) . Expand ( 16 ) ;
2012-11-28 15:47:07 +00:00
if ( b . RayIntersection ( start , end - start , scale ) )
{
if ( scale > = 0.0f & & scale < bestScale )
{
2012-11-26 18:58:24 +00:00
bestEnt = ent ;
bestScale = scale ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return bestEnt ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : EntitiesWithinRadius
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : EntitiesWithinRadius ( const idVec3 org , float radius , idEntity * * entityList , int maxCount ) const
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
idBounds bo ( org ) ;
int entCount = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bo . ExpandSelf ( radius ) ;
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ent - > GetPhysics ( ) - > GetAbsBounds ( ) . IntersectsBounds ( bo ) )
{
2012-11-26 18:58:24 +00:00
entityList [ entCount + + ] = ent ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return entCount ;
}
/*
= = = = = = = = = = = = = = = = =
idGameLocal : : KillBox
Kills all entities that would touch the proposed new positioning of ent . The ent itself will not being killed .
Checks if player entities are in the teleporter , and marks them to die at teleport exit instead of immediately .
If catch_teleport , this only marks teleport players for death on exit
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : KillBox ( idEntity * ent , bool catch_teleport )
{
2012-11-26 18:58:24 +00:00
int i ;
int num ;
2012-11-28 15:47:07 +00:00
idEntity * hit ;
idClipModel * cm ;
idClipModel * clipModels [ MAX_GENTITIES ] ;
idPhysics * phys ;
2012-11-26 18:58:24 +00:00
phys = ent - > GetPhysics ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! phys - > GetNumClipModels ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
num = clip . ClipModelsTouchingBounds ( phys - > GetAbsBounds ( ) , phys - > GetClipMask ( ) , clipModels , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < num ; i + + )
{
2012-11-26 18:58:24 +00:00
cm = clipModels [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't check render entities
2012-11-28 15:47:07 +00:00
if ( cm - > IsRenderModel ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hit = cm - > GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ( hit = = ent ) | | ! hit - > fl . takedamage )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! phys - > ClipContents ( cm ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// nail it
2012-11-28 15:47:07 +00:00
idPlayer * otherPlayer = NULL ;
if ( hit - > IsType ( idPlayer : : Type ) )
{
otherPlayer = static_cast < idPlayer * > ( hit ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( otherPlayer ! = NULL )
{
if ( otherPlayer - > IsInTeleport ( ) )
{
2012-11-26 18:58:24 +00:00
otherPlayer - > TeleportDeath ( ent - > entityNumber ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ! catch_teleport )
{
2012-11-26 18:58:24 +00:00
hit - > Damage ( ent , ent , vec3_origin , " damage_telefrag " , 1.0f , INVALID_JOINT ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ! catch_teleport )
{
2012-11-26 18:58:24 +00:00
hit - > Damage ( ent , ent , vec3_origin , " damage_telefrag " , 1.0f , INVALID_JOINT ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : RequirementMet
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : RequirementMet ( idEntity * activator , const idStr & requires , int removeItem )
{
if ( requires . Length ( ) )
{
if ( activator - > IsType ( idPlayer : : Type ) )
{
idPlayer * player = static_cast < idPlayer * > ( activator ) ;
idDict * item = player - > FindInventoryItem ( requires ) ;
if ( item )
{
if ( removeItem )
{
2012-11-26 18:58:24 +00:00
player - > RemoveInventoryItem ( item ) ;
}
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return false ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = =
idGameLocal : : AlertAI
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : AlertAI ( idEntity * ent )
{
if ( ent & & ent - > IsType ( idActor : : Type ) )
{
2012-11-26 18:58:24 +00:00
// alert them for the next frame
lastAIAlertTime = time + 1 ;
2012-11-28 15:47:07 +00:00
lastAIAlertEntity = static_cast < idActor * > ( ent ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = =
idGameLocal : : GetAlertEntity
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idActor * idGameLocal : : GetAlertEntity ( )
{
2012-11-26 18:58:24 +00:00
int timeGroup = 0 ;
2012-11-28 15:47:07 +00:00
if ( lastAIAlertTime & & lastAIAlertEntity . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
timeGroup = lastAIAlertEntity . GetEntity ( ) - > timeGroup ;
}
SetTimeState ts ( timeGroup ) ;
2012-11-28 15:47:07 +00:00
if ( lastAIAlertTime > = time )
{
2012-11-26 18:58:24 +00:00
return lastAIAlertEntity . GetEntity ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return NULL ;
}
/*
= = = = = = = = = = = =
idGameLocal : : RadiusDamage
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RadiusDamage ( const idVec3 & origin , idEntity * inflictor , idEntity * attacker , idEntity * ignoreDamage , idEntity * ignorePush , const char * damageDefName , float dmgPower )
{
2012-11-26 18:58:24 +00:00
float dist , damageScale , attackerDamageScale , attackerPushScale ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
idEntity * entityList [ MAX_GENTITIES ] ;
2012-11-26 18:58:24 +00:00
int numListedEntities ;
idBounds bounds ;
idVec3 v , damagePoint , dir ;
int i , e , damage , radius , push ;
2012-11-28 15:47:07 +00:00
const idDict * damageDef = FindEntityDefDict ( damageDefName , false ) ;
if ( ! damageDef )
{
2012-11-26 18:58:24 +00:00
Warning ( " Unknown damageDef '%s' " , damageDefName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
damageDef - > GetInt ( " damage " , " 20 " , damage ) ;
damageDef - > GetInt ( " radius " , " 50 " , radius ) ;
damageDef - > GetInt ( " push " , va ( " %d " , damage * 100 ) , push ) ;
damageDef - > GetFloat ( " attackerDamageScale " , " 0.5 " , attackerDamageScale ) ;
damageDef - > GetFloat ( " attackerPushScale " , " 0 " , attackerPushScale ) ;
2012-11-28 15:47:07 +00:00
if ( radius < 1 )
{
2012-11-26 18:58:24 +00:00
radius = 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds = idBounds ( origin ) . Expand ( radius ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get all entities touching the bounds
numListedEntities = clip . EntitiesTouchingBounds ( bounds , - 1 , entityList , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
if ( inflictor & & inflictor - > IsType ( idAFAttachment : : Type ) )
{
inflictor = static_cast < idAFAttachment * > ( inflictor ) - > GetBody ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( attacker & & attacker - > IsType ( idAFAttachment : : Type ) )
{
attacker = static_cast < idAFAttachment * > ( attacker ) - > GetBody ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ignoreDamage & & ignoreDamage - > IsType ( idAFAttachment : : Type ) )
{
ignoreDamage = static_cast < idAFAttachment * > ( ignoreDamage ) - > GetBody ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// apply damage to the entities
2012-11-28 15:47:07 +00:00
for ( e = 0 ; e < numListedEntities ; e + + )
{
2012-11-26 18:58:24 +00:00
ent = entityList [ e ] ;
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
if ( ! ent - > fl . takedamage )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent = = inflictor | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) = = inflictor ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent = = ignoreDamage | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) = = ignoreDamage ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't damage a dead player
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) & & ent - > entityNumber < MAX_CLIENTS & & ent - > IsType ( idPlayer : : Type ) & & static_cast < idPlayer * > ( ent ) - > health < 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the distance from the edge of the bounding box
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
if ( origin [ i ] < ent - > GetPhysics ( ) - > GetAbsBounds ( ) [ 0 ] [ i ] )
{
2012-11-26 18:58:24 +00:00
v [ i ] = ent - > GetPhysics ( ) - > GetAbsBounds ( ) [ 0 ] [ i ] - origin [ i ] ;
2012-11-28 15:47:07 +00:00
}
else if ( origin [ i ] > ent - > GetPhysics ( ) - > GetAbsBounds ( ) [ 1 ] [ i ] )
{
2012-11-26 18:58:24 +00:00
v [ i ] = origin [ i ] - ent - > GetPhysics ( ) - > GetAbsBounds ( ) [ 1 ] [ i ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
v [ i ] = 0 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dist = v . Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( dist > = radius )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > CanDamage ( origin , damagePoint ) )
{
2012-11-26 18:58:24 +00:00
// push the center of mass higher than the origin so players
// get knocked into the air more
dir = ent - > GetPhysics ( ) - > GetOrigin ( ) - origin ;
dir [ 2 ] + = 24 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the damage scale
damageScale = dmgPower * ( 1.0f - dist / radius ) ;
2012-11-28 15:47:07 +00:00
if ( ent = = attacker | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) = = attacker ) )
{
2012-11-26 18:58:24 +00:00
damageScale * = attackerDamageScale ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool killedBySplash = true ;
2012-11-28 15:47:07 +00:00
if ( ent - > health < = 0 )
{
2012-11-26 18:58:24 +00:00
killedBySplash = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent - > Damage ( inflictor , attacker , dir , damageDefName , damageScale , INVALID_JOINT ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If the player is local. SHAkkkkkkeeee!
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) & & ent - > entityNumber = = GetLocalClientNum ( ) )
{
if ( ent - > IsType ( idPlayer : : Type ) )
{
idPlayer * player = static_cast < idPlayer * > ( ent ) ;
if ( player )
{
2012-11-26 18:58:24 +00:00
player - > ControllerShakeFromDamage ( damage ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if our inflictor is a projectile, we want to count up how many kills the splash damage has chalked up.
2012-11-28 15:47:07 +00:00
if ( ent - > health < = 0 & & killedBySplash )
{
if ( inflictor & & inflictor - > IsType ( idProjectile : : Type ) )
{
if ( attacker & & attacker - > IsType ( idPlayer : : Type ) )
{
if ( ent - > IsType ( idActor : : Type ) & & ent ! = attacker )
{
idPlayer * player = static_cast < idPlayer * > ( attacker ) ;
2012-11-26 18:58:24 +00:00
player - > AddProjectileKills ( ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// push physics objects
2012-11-28 15:47:07 +00:00
if ( push )
{
2012-11-26 18:58:24 +00:00
RadiusPush ( origin , radius , push * dmgPower , attacker , ignorePush , attackerPushScale , false ) ;
}
}
/*
= = = = = = = = = = = = = =
idGameLocal : : RadiusPush
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RadiusPush ( const idVec3 & origin , const float radius , const float push , const idEntity * inflictor , const idEntity * ignore , float inflictorScale , const bool quake )
{
2012-11-26 18:58:24 +00:00
int i , numListedClipModels ;
2012-11-28 15:47:07 +00:00
idClipModel * clipModel ;
idClipModel * clipModelList [ MAX_GENTITIES ] ;
2012-11-26 18:58:24 +00:00
idVec3 dir ;
idBounds bounds ;
modelTrace_t result ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
2012-11-26 18:58:24 +00:00
float scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dir . Set ( 0.0f , 0.0f , 1.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds = idBounds ( origin ) . Expand ( radius ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get all clip models touching the bounds
numListedClipModels = clip . ClipModelsTouchingBounds ( bounds , - 1 , clipModelList , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
if ( inflictor & & inflictor - > IsType ( idAFAttachment : : Type ) )
{
inflictor = static_cast < const idAFAttachment * > ( inflictor ) - > GetBody ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ignore & & ignore - > IsType ( idAFAttachment : : Type ) )
{
ignore = static_cast < const idAFAttachment * > ( ignore ) - > GetBody ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// apply impact to all the clip models through their associated physics objects
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numListedClipModels ; i + + )
{
2012-11-26 18:58:24 +00:00
clipModel = clipModelList [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never push render models
2012-11-28 15:47:07 +00:00
if ( clipModel - > IsRenderModel ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ent = clipModel - > GetEntity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never push projectiles
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idProjectile : : Type ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// players use "knockback" in idPlayer::Damage
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idPlayer : : Type ) & & ! quake )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't push the ignore entity
2012-11-28 15:47:07 +00:00
if ( ent = = ignore | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) = = ignore ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( gameRenderWorld - > FastWorldTrace ( result , origin , clipModel - > GetOrigin ( ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// scale the push for the inflictor
2012-11-28 15:47:07 +00:00
if ( ent = = inflictor | | ( ent - > IsType ( idAFAttachment : : Type ) & & static_cast < idAFAttachment * > ( ent ) - > GetBody ( ) = = inflictor ) )
{
2012-11-26 18:58:24 +00:00
scale = inflictorScale ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
scale = 1.0f ;
}
2012-11-28 15:47:07 +00:00
if ( quake )
{
2012-11-26 18:58:24 +00:00
clipModel - > GetEntity ( ) - > ApplyImpulse ( world , clipModel - > GetId ( ) , clipModel - > GetOrigin ( ) , scale * push * dir ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
RadiusPushClipModel ( origin , scale * push , clipModel ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idGameLocal : : RadiusPushClipModel
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RadiusPushClipModel ( const idVec3 & origin , const float push , const idClipModel * clipModel )
{
2012-11-26 18:58:24 +00:00
int i , j ;
float dot , dist , area ;
2012-11-28 15:47:07 +00:00
const idTraceModel * trm ;
const traceModelPoly_t * poly ;
2012-11-26 18:58:24 +00:00
idFixedWinding w ;
idVec3 v , localOrigin , center , impulse ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
trm = clipModel - > GetTraceModel ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! trm | | 1 )
{
2012-11-26 18:58:24 +00:00
impulse = clipModel - > GetAbsBounds ( ) . GetCenter ( ) - origin ;
impulse . Normalize ( ) ;
impulse . z + = 1.0f ;
clipModel - > GetEntity ( ) - > ApplyImpulse ( world , clipModel - > GetId ( ) , clipModel - > GetOrigin ( ) , push * impulse ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
localOrigin = ( origin - clipModel - > GetOrigin ( ) ) * clipModel - > GetAxis ( ) . Transpose ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < trm - > numPolys ; i + + )
{
2012-11-26 18:58:24 +00:00
poly = & trm - > polys [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
center . Zero ( ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < poly - > numEdges ; j + + )
{
v = trm - > verts [ trm - > edges [ abs ( poly - > edges [ j ] ) ] . v [ INT32_SIGNBITSET ( poly - > edges [ j ] ) ] ] ;
2012-11-26 18:58:24 +00:00
center + = v ;
v - = localOrigin ;
v . NormalizeFast ( ) ; // project point on a unit sphere
w . AddPoint ( v ) ;
}
center / = poly - > numEdges ;
v = center - localOrigin ;
dist = v . NormalizeFast ( ) ;
dot = v * poly - > normal ;
2012-11-28 15:47:07 +00:00
if ( dot > 0.0f )
{
2012-11-26 18:58:24 +00:00
continue ;
}
area = w . GetArea ( ) ;
// impulse in polygon normal direction
impulse = poly - > normal * clipModel - > GetAxis ( ) ;
// always push up for nicer effect
impulse . z - = 1.0f ;
// scale impulse based on visible surface area and polygon angle
impulse * = push * ( dot * area * ( 1.0f / ( 4.0f * idMath : : PI ) ) ) ;
// scale away distance for nicer effect
impulse * = ( dist * 2.0f ) ;
// impulse is applied to the center of the polygon
center = clipModel - > GetOrigin ( ) + center * clipModel - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > GetEntity ( ) - > ApplyImpulse ( world , clipModel - > GetId ( ) , center , impulse ) ;
}
}
/*
= = = = = = = = = = = = = = =
idGameLocal : : ProjectDecal
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : ProjectDecal ( const idVec3 & origin , const idVec3 & dir , float depth , bool parallel , float size , const char * material , float angle )
{
2012-11-26 18:58:24 +00:00
float s , c ;
idMat3 axis , axistemp ;
idFixedWinding winding ;
idVec3 windingOrigin , projectionOrigin ;
2012-11-28 15:47:07 +00:00
static idVec3 decalWinding [ 4 ] =
{
idVec3 ( 1.0f , 1.0f , 0.0f ) ,
2012-11-26 18:58:24 +00:00
idVec3 ( - 1.0f , 1.0f , 0.0f ) ,
idVec3 ( - 1.0f , - 1.0f , 0.0f ) ,
2012-11-28 15:47:07 +00:00
idVec3 ( 1.0f , - 1.0f , 0.0f )
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
if ( ! g_decals . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// randomly rotate the decal winding
idMath : : SinCos16 ( ( angle ) ? angle : random . RandomFloat ( ) * idMath : : TWO_PI , s , c ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// winding orientation
axis [ 2 ] = dir ;
axis [ 2 ] . Normalize ( ) ;
axis [ 2 ] . NormalVectors ( axistemp [ 0 ] , axistemp [ 1 ] ) ;
axis [ 0 ] = axistemp [ 0 ] * c + axistemp [ 1 ] * - s ;
axis [ 1 ] = axistemp [ 0 ] * - s + axistemp [ 1 ] * - c ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
windingOrigin = origin + depth * axis [ 2 ] ;
2012-11-28 15:47:07 +00:00
if ( parallel )
{
2012-11-26 18:58:24 +00:00
projectionOrigin = origin - depth * axis [ 2 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
projectionOrigin = origin ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
size * = 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
winding . Clear ( ) ;
winding + = idVec5 ( windingOrigin + ( axis * decalWinding [ 0 ] ) * size , idVec2 ( 1 , 1 ) ) ;
winding + = idVec5 ( windingOrigin + ( axis * decalWinding [ 1 ] ) * size , idVec2 ( 0 , 1 ) ) ;
winding + = idVec5 ( windingOrigin + ( axis * decalWinding [ 2 ] ) * size , idVec2 ( 0 , 0 ) ) ;
winding + = idVec5 ( windingOrigin + ( axis * decalWinding [ 3 ] ) * size , idVec2 ( 1 , 0 ) ) ;
gameRenderWorld - > ProjectDecalOntoWorld ( winding , projectionOrigin , parallel , depth * 0.5f , declManager - > FindMaterial ( material ) , gameLocal . slow . time /* _D3XP */ ) ;
}
/*
= = = = = = = = = = = = = =
idGameLocal : : BloodSplat
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : BloodSplat ( const idVec3 & origin , const idVec3 & dir , float size , const char * material )
{
2012-11-26 18:58:24 +00:00
float halfSize = size * 0.5f ;
idVec3 verts [ ] = { idVec3 ( 0.0f , + halfSize , + halfSize ) ,
idVec3 ( 0.0f , + halfSize , - halfSize ) ,
idVec3 ( 0.0f , - halfSize , - halfSize ) ,
2012-11-28 15:47:07 +00:00
idVec3 ( 0.0f , - halfSize , + halfSize )
} ;
2012-11-26 18:58:24 +00:00
idTraceModel trm ;
idClipModel mdl ;
trace_t results ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: get from damage def
2012-11-28 15:47:07 +00:00
if ( ! g_bloodEffects . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
size = halfSize + random . RandomFloat ( ) * halfSize ;
trm . SetupPolygon ( verts , 4 ) ;
mdl . LoadModel ( trm ) ;
clip . Translation ( results , origin , origin + dir * 64.0f , & mdl , mat3_identity , CONTENTS_SOLID , NULL ) ;
ProjectDecal ( results . endpos , dir , 2.0f * size , true , size , material ) ;
}
/*
= = = = = = = = = = = = =
idGameLocal : : SetCamera
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetCamera ( idCamera * cam )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
idAI * ai ;
2012-11-26 18:58:24 +00:00
// this should fix going into a cinematic when dead.. rare but happens
2012-11-28 15:47:07 +00:00
idPlayer * client = GetLocalPlayer ( ) ;
if ( client - > health < = 0 | | client - > AI_DEAD )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
camera = cam ;
2012-11-28 15:47:07 +00:00
if ( camera )
{
2012-11-26 18:58:24 +00:00
inCinematic = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set r_znear so that transitioning into/out of the player's head doesn't clip through the view
cvarSystem - > SetCVarFloat ( " r_znear " , 1.0f ) ;
// hide all the player models
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
if ( entities [ i ] )
{
2012-11-26 18:58:24 +00:00
client = static_cast < idPlayer * > ( entities [ i ] ) ;
client - > EnterCinematic ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! cam - > spawnArgs . GetBool ( " ignore_enemies " ) )
{
2012-11-26 18:58:24 +00:00
// kill any active monsters that are enemies of the player
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ent - > cinematic | | ent - > fl . isDormant )
{
2012-11-26 18:58:24 +00:00
// only kill entities that aren't needed for cinematics and aren't dormant
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idAI : : Type ) )
{
ai = static_cast < idAI * > ( ent ) ;
if ( ! ai - > GetEnemy ( ) | | ! ai - > IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
// no enemy, or inactive, so probably safe to ignore
continue ;
}
2012-11-28 15:47:07 +00:00
}
else if ( ent - > IsType ( idProjectile : : Type ) )
{
2012-11-26 18:58:24 +00:00
// remove all projectiles
2012-11-28 15:47:07 +00:00
}
else if ( ent - > spawnArgs . GetBool ( " cinematic_remove " ) )
{
2012-11-26 18:58:24 +00:00
// remove anything marked to be removed during cinematics
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// ignore everything else
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove it
DPrintf ( " removing '%s' for cinematic \n " , ent - > GetName ( ) ) ;
ent - > PostEventMS ( & EV_Remove , 0 ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
inCinematic = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore r_znear
cvarSystem - > SetCVarFloat ( " r_znear " , 3.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// show all the player models
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numClients ; i + + )
{
if ( entities [ i ] )
{
idPlayer * client = static_cast < idPlayer * > ( entities [ i ] ) ;
2012-11-26 18:58:24 +00:00
client - > ExitCinematic ( ) ;
}
}
}
}
/*
= = = = = = = = = = = = =
idGameLocal : : GetCamera
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idCamera * idGameLocal : : GetCamera ( ) const
{
2012-11-26 18:58:24 +00:00
return camera ;
}
/*
= = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : SpreadLocations
Now that everything has been spawned , associate areas with location entities
= = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SpreadLocations ( )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
// allocate the area table
int numAreas = gameRenderWorld - > NumAreas ( ) ;
2012-11-28 15:47:07 +00:00
locationEntities = new ( TAG_GAME ) idLocationEntity * [ numAreas ] ;
2012-11-26 18:58:24 +00:00
memset ( locationEntities , 0 , numAreas * sizeof ( * locationEntities ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// for each location entity, make pointers from every area it touches
2012-11-28 15:47:07 +00:00
for ( ent = spawnedEntities . Next ( ) ; ent ! = NULL ; ent = ent - > spawnNode . Next ( ) )
{
if ( ! ent - > IsType ( idLocationEntity : : Type ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
idVec3 point = ent - > spawnArgs . GetVector ( " origin " ) ;
int areaNum = gameRenderWorld - > PointInArea ( point ) ;
2012-11-28 15:47:07 +00:00
if ( areaNum < 0 )
{
2012-11-26 18:58:24 +00:00
Printf ( " SpreadLocations: location '%s' is not in a valid area \n " , ent - > spawnArgs . GetString ( " name " ) ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( areaNum > = numAreas )
{
2012-11-26 18:58:24 +00:00
Error ( " idGameLocal::SpreadLocations: areaNum >= gameRenderWorld->NumAreas() " ) ;
}
2012-11-28 15:47:07 +00:00
if ( locationEntities [ areaNum ] )
{
2012-11-26 18:58:24 +00:00
Warning ( " location entity '%s' overlaps '%s' " , ent - > spawnArgs . GetString ( " name " ) ,
2012-11-28 15:47:07 +00:00
locationEntities [ areaNum ] - > spawnArgs . GetString ( " name " ) ) ;
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
locationEntities [ areaNum ] = static_cast < idLocationEntity * > ( ent ) ;
2012-11-26 18:58:24 +00:00
// spread to all other connected areas
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numAreas ; i + + )
{
if ( i = = areaNum )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( gameRenderWorld - > AreasAreConnected ( areaNum , i , PS_BLOCK_LOCATION ) )
{
locationEntities [ i ] = static_cast < idLocationEntity * > ( ent ) ;
2012-11-26 18:58:24 +00:00
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = =
idGameLocal : : LocationForPoint
The player checks the location each frame to update the HUD text display
May return NULL
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idLocationEntity * idGameLocal : : LocationForPoint ( const idVec3 & point )
{
if ( ! locationEntities )
{
2012-11-26 18:58:24 +00:00
// before SpreadLocations() has been called
return NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int areaNum = gameRenderWorld - > PointInArea ( point ) ;
2012-11-28 15:47:07 +00:00
if ( areaNum < 0 )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
if ( areaNum > = gameRenderWorld - > NumAreas ( ) )
{
2012-11-26 18:58:24 +00:00
Error ( " idGameLocal::LocationForPoint: areaNum >= gameRenderWorld->NumAreas() " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return locationEntities [ areaNum ] ;
}
/*
= = = = = = = = = = = =
idGameLocal : : SetPortalState
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetPortalState ( qhandle_t portal , int blockingBits )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > SetPortalState ( portal , blockingBits ) ;
}
/*
= = = = = = = = = = = =
idGameLocal : : sortSpawnPoints
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : sortSpawnPoints ( const void * ptr1 , const void * ptr2 )
{
const spawnSpot_t * spot1 = static_cast < const spawnSpot_t * > ( ptr1 ) ;
const spawnSpot_t * spot2 = static_cast < const spawnSpot_t * > ( ptr2 ) ;
2012-11-26 18:58:24 +00:00
float diff ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
diff = spot1 - > dist - spot2 - > dist ;
2012-11-28 15:47:07 +00:00
if ( diff < 0.0f )
{
2012-11-26 18:58:24 +00:00
return 1 ;
2012-11-28 15:47:07 +00:00
}
else if ( diff > 0.0f )
{
2012-11-26 18:58:24 +00:00
return - 1 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
}
/*
= = = = = = = = = = =
idGameLocal : : RandomizeInitialSpawns
randomize the order of the initial spawns
prepare for a sequence of initial player spawns
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : RandomizeInitialSpawns ( )
{
2012-11-26 18:58:24 +00:00
spawnSpot_t spot ;
int i , j ;
int k ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
if ( ! common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
spawnSpots . Clear ( ) ;
initialSpots . Clear ( ) ;
teamSpawnSpots [ 0 ] . Clear ( ) ;
teamSpawnSpots [ 1 ] . Clear ( ) ;
teamInitialSpots [ 0 ] . Clear ( ) ;
teamInitialSpots [ 1 ] . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spot . dist = 0 ;
spot . ent = FindEntityUsingDef ( NULL , " info_player_deathmatch " ) ;
2012-11-28 15:47:07 +00:00
while ( spot . ent )
{
2012-11-26 18:58:24 +00:00
spot . ent - > spawnArgs . GetInt ( " team " , " -1 " , spot . team ) ;
2012-11-28 15:47:07 +00:00
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
2012-11-26 18:58:24 +00:00
{
2012-11-28 15:47:07 +00:00
if ( spot . team = = 0 | | spot . team = = 1 )
2012-11-26 18:58:24 +00:00
teamSpawnSpots [ spot . team ] . Append ( spot ) ;
else
2012-11-28 15:47:07 +00:00
common - > Warning ( " info_player_deathmatch : invalid or no team attached to spawn point \n " ) ;
2012-11-26 18:58:24 +00:00
}
spawnSpots . Append ( spot ) ;
2012-11-28 15:47:07 +00:00
if ( spot . ent - > spawnArgs . GetBool ( " initial " ) )
{
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
2012-11-26 18:58:24 +00:00
{
assert ( spot . team = = 0 | | spot . team = = 1 ) ;
teamInitialSpots [ spot . team ] . Append ( spot . ent ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
initialSpots . Append ( spot . ent ) ;
}
spot . ent = FindEntityUsingDef ( spot . ent , " info_player_deathmatch " ) ;
}
2012-11-28 15:47:07 +00:00
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
if ( ! teamSpawnSpots [ 0 ] . Num ( ) )
2012-11-26 18:58:24 +00:00
common - > Warning ( " red team : no info_player_deathmatch in map " ) ;
2012-11-28 15:47:07 +00:00
if ( ! teamSpawnSpots [ 1 ] . Num ( ) )
2012-11-26 18:58:24 +00:00
common - > Warning ( " blue team : no info_player_deathmatch in map " ) ;
2012-11-28 15:47:07 +00:00
if ( ! teamSpawnSpots [ 0 ] . Num ( ) | | ! teamSpawnSpots [ 1 ] . Num ( ) )
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! spawnSpots . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " no info_player_deathmatch in map " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " red team : %d spawns (%d initials) \n " , teamSpawnSpots [ 0 ] . Num ( ) , teamInitialSpots [ 0 ] . Num ( ) ) ;
// if there are no initial spots in the map, consider they can all be used as initial
2012-11-28 15:47:07 +00:00
if ( ! teamInitialSpots [ 0 ] . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " red team : no info_player_deathmatch entities marked initial in map " ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < teamSpawnSpots [ 0 ] . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
teamInitialSpots [ 0 ] . Append ( teamSpawnSpots [ 0 ] [ i ] . ent ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " blue team : %d spawns (%d initials) \n " , teamSpawnSpots [ 1 ] . Num ( ) , teamInitialSpots [ 1 ] . Num ( ) ) ;
// if there are no initial spots in the map, consider they can all be used as initial
2012-11-28 15:47:07 +00:00
if ( ! teamInitialSpots [ 1 ] . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " blue team : no info_player_deathmatch entities marked initial in map " ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < teamSpawnSpots [ 1 ] . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
teamInitialSpots [ 1 ] . Append ( teamSpawnSpots [ 1 ] [ i ] . ent ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %d spawns (%d initials) \n " , spawnSpots . Num ( ) , initialSpots . Num ( ) ) ;
// if there are no initial spots in the map, consider they can all be used as initial
2012-11-28 15:47:07 +00:00
if ( ! initialSpots . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " no info_player_deathmatch entities marked initial in map " ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < spawnSpots . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
initialSpots . Append ( spawnSpots [ i ] . ent ) ;
}
}
2012-11-28 15:47:07 +00:00
for ( k = 0 ; k < 2 ; k + + )
{
for ( i = 0 ; i < teamInitialSpots [ k ] . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
j = random . RandomInt ( teamInitialSpots [ k ] . Num ( ) ) ;
ent = teamInitialSpots [ k ] [ i ] ;
teamInitialSpots [ k ] [ i ] = teamInitialSpots [ k ] [ j ] ;
teamInitialSpots [ k ] [ j ] = ent ;
}
}
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < initialSpots . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
j = random . RandomInt ( initialSpots . Num ( ) ) ;
ent = initialSpots [ i ] ;
initialSpots [ i ] = initialSpots [ j ] ;
initialSpots [ j ] = ent ;
}
// reset the counter
currentInitialSpot = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teamCurrentInitialSpot [ 0 ] = 0 ;
teamCurrentInitialSpot [ 1 ] = 0 ;
}
/*
= = = = = = = = = = =
idGameLocal : : SelectInitialSpawnPoint
spectators are spawned randomly anywhere
in - game clients are spawned based on distance to active players ( randomized on the first half )
upon map restart , initial spawns are used ( randomized ordered list of spawns flagged " initial " )
if there are more players than initial spots , overflow to regular spawning
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idEntity * idGameLocal : : SelectInitialSpawnPoint ( idPlayer * player )
{
2012-11-26 18:58:24 +00:00
int i , j , which ;
spawnSpot_t spot ;
idVec3 pos ;
float dist ;
bool alone ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsMultiplayer ( ) | | ! spawnSpots . Num ( ) | | ( mpGame . IsGametypeFlagBased ( ) & & ( ! teamSpawnSpots [ 0 ] . Num ( ) | | ! teamSpawnSpots [ 1 ] . Num ( ) ) ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
spot . ent = FindEntityUsingDef ( NULL , " info_player_start " ) ;
2012-11-28 15:47:07 +00:00
if ( ! spot . ent )
{
2012-11-26 18:58:24 +00:00
Error ( " No info_player_start on map. \n " ) ;
}
return spot . ent ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool useInitialSpots = false ;
2012-11-28 15:47:07 +00:00
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
assert ( player - > team = = 0 | | player - > team = = 1 ) ;
useInitialSpots = player - > useInitialSpawns & & teamCurrentInitialSpot [ player - > team ] < teamInitialSpots [ player - > team ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
useInitialSpots = player - > useInitialSpawns & & currentInitialSpot < initialSpots . Num ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( player - > spectating )
{
2012-11-26 18:58:24 +00:00
// plain random spot, don't bother
return spawnSpots [ random . RandomInt ( spawnSpots . Num ( ) ) ] . ent ;
2012-11-28 15:47:07 +00:00
}
else if ( useInitialSpots )
{
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
assert ( player - > team = = 0 | | player - > team = = 1 ) ;
player - > useInitialSpawns = false ; // only use the initial spawn once
return teamInitialSpots [ player - > team ] [ teamCurrentInitialSpot [ player - > team ] + + ] ;
}
return initialSpots [ currentInitialSpot + + ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// check if we are alone in map
alone = true ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < MAX_CLIENTS ; j + + )
{
if ( entities [ j ] & & entities [ j ] ! = player )
{
2012-11-26 18:58:24 +00:00
alone = false ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( alone )
{
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
assert ( player - > team = = 0 | | player - > team = = 1 ) ;
return teamSpawnSpots [ player - > team ] [ random . RandomInt ( teamSpawnSpots [ player - > team ] . Num ( ) ) ] . ent ;
}
// don't do distance-based
return spawnSpots [ random . RandomInt ( spawnSpots . Num ( ) ) ] . ent ;
}
2012-11-28 15:47:07 +00:00
if ( mpGame . IsGametypeFlagBased ( ) ) /* CTF */
{
2012-11-26 18:58:24 +00:00
// TODO : make as reusable method, same code as below
int team = player - > team ;
assert ( team = = 0 | | team = = 1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the distance to the closest active player for each spawn spot
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < teamSpawnSpots [ team ] . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
pos = teamSpawnSpots [ team ] [ i ] . ent - > GetPhysics ( ) - > GetOrigin ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip initial spawn points for CTF
2012-11-28 15:47:07 +00:00
if ( teamSpawnSpots [ team ] [ i ] . ent - > spawnArgs . GetBool ( " initial " ) )
{
2012-11-26 18:58:24 +00:00
teamSpawnSpots [ team ] [ i ] . dist = 0x0 ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
teamSpawnSpots [ team ] [ i ] . dist = 0x7fffffff ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < MAX_CLIENTS ; j + + )
{
if ( ! entities [ j ] | | ! entities [ j ] - > IsType ( idPlayer : : Type )
| | entities [ j ] = = player
| | static_cast < idPlayer * > ( entities [ j ] ) - > spectating )
{
2012-11-26 18:58:24 +00:00
continue ;
}
dist = ( pos - entities [ j ] - > GetPhysics ( ) - > GetOrigin ( ) ) . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
if ( dist < teamSpawnSpots [ team ] [ i ] . dist )
{
2012-11-26 18:58:24 +00:00
teamSpawnSpots [ team ] [ i ] . dist = dist ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// sort the list
2012-11-28 15:47:07 +00:00
qsort ( ( void * ) teamSpawnSpots [ team ] . Ptr ( ) , teamSpawnSpots [ team ] . Num ( ) , sizeof ( spawnSpot_t ) , ( int ( * ) ( const void * , const void * ) ) sortSpawnPoints ) ;
2012-11-26 18:58:24 +00:00
// choose a random one in the top half
which = random . RandomInt ( teamSpawnSpots [ team ] . Num ( ) / 2 ) ;
spot = teamSpawnSpots [ team ] [ which ] ;
// assert( teamSpawnSpots[ team ][ which ].dist != 0 );
return spot . ent ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the distance to the closest active player for each spawn spot
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < spawnSpots . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
pos = spawnSpots [ i ] . ent - > GetPhysics ( ) - > GetOrigin ( ) ;
spawnSpots [ i ] . dist = 0x7fffffff ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < MAX_CLIENTS ; j + + )
{
if ( ! entities [ j ] | | ! entities [ j ] - > IsType ( idPlayer : : Type )
| | entities [ j ] = = player
| | static_cast < idPlayer * > ( entities [ j ] ) - > spectating )
{
2012-11-26 18:58:24 +00:00
continue ;
}
dist = ( pos - entities [ j ] - > GetPhysics ( ) - > GetOrigin ( ) ) . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
if ( dist < spawnSpots [ i ] . dist )
{
2012-11-26 18:58:24 +00:00
spawnSpots [ i ] . dist = dist ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// sort the list
2012-11-28 15:47:07 +00:00
qsort ( ( void * ) spawnSpots . Ptr ( ) , spawnSpots . Num ( ) , sizeof ( spawnSpot_t ) , ( int ( * ) ( const void * , const void * ) ) sortSpawnPoints ) ;
2012-11-26 18:58:24 +00:00
// choose a random one in the top half
which = random . RandomInt ( spawnSpots . Num ( ) / 2 ) ;
spot = spawnSpots [ which ] ;
}
return spot . ent ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : SetGlobalMaterial
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetGlobalMaterial ( const idMaterial * mat )
{
2012-11-26 18:58:24 +00:00
globalMaterial = mat ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetGlobalMaterial
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idMaterial * idGameLocal : : GetGlobalMaterial ( )
{
2012-11-26 18:58:24 +00:00
return globalMaterial ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetSpawnId
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetSpawnId ( const idEntity * ent ) const
{
2012-11-26 18:58:24 +00:00
return ( gameLocal . spawnIds [ ent - > entityNumber ] < < GENTITYNUM_BITS ) | ent - > entityNumber ;
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : SetPortalSkyEnt
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SetPortalSkyEnt ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
portalSkyEnt = ent ;
}
/*
= = = = = = = = = = = = = = = = =
idPlayer : : IsPortalSkyAcive
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : IsPortalSkyAcive ( )
{
2012-11-26 18:58:24 +00:00
return portalSkyActive ;
}
/*
= = = = = = = = = = =
idGameLocal : : SelectTimeGroup
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : SelectTimeGroup ( int timeGroup )
{
if ( timeGroup )
{
2012-11-26 18:58:24 +00:00
fast . Get ( time , previousTime , realClientTime ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
slow . Get ( time , previousTime , realClientTime ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
selectedGroup = timeGroup ;
}
/*
= = = = = = = = = = =
idGameLocal : : GetTimeGroupTime
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetTimeGroupTime ( int timeGroup )
{
if ( timeGroup )
{
2012-11-26 18:58:24 +00:00
return fast . time ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return slow . time ;
}
}
/*
= = = = = = = = = = =
idGameLocal : : ComputeSlowScale
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : ComputeSlowScale ( )
{
2012-11-26 18:58:24 +00:00
// check if we need to do a quick reset
2012-11-28 15:47:07 +00:00
if ( quickSlowmoReset )
{
2012-11-26 18:58:24 +00:00
quickSlowmoReset = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop the sounds
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetSlowmoSpeed ( 1.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop the state
slowmoState = SLOWMO_STATE_OFF ;
slowmoScale = 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check the player state
2012-11-28 15:47:07 +00:00
idPlayer * player = GetLocalPlayer ( ) ;
2012-11-26 18:58:24 +00:00
bool powerupOn = false ;
2012-11-28 15:47:07 +00:00
if ( player ! = NULL & & player - > PowerUpActive ( HELLTIME ) )
{
2012-11-26 18:58:24 +00:00
powerupOn = true ;
}
2012-11-28 15:47:07 +00:00
else if ( g_enableSlowmo . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
powerupOn = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine proper slowmo state
2012-11-28 15:47:07 +00:00
if ( powerupOn & & slowmoState = = SLOWMO_STATE_OFF )
{
2012-11-26 18:58:24 +00:00
slowmoState = SLOWMO_STATE_RAMPUP ;
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetSlowmoSpeed ( slowmoScale ) ;
}
}
2012-11-28 15:47:07 +00:00
else if ( ! powerupOn & & slowmoState = = SLOWMO_STATE_ON )
{
2012-11-26 18:58:24 +00:00
slowmoState = SLOWMO_STATE_RAMPDOWN ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// play the stop sound
2012-11-28 15:47:07 +00:00
if ( player ! = NULL )
{
2012-11-26 18:58:24 +00:00
player - > PlayHelltimeStopSound ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do any necessary ramping
2012-11-28 15:47:07 +00:00
if ( slowmoState = = SLOWMO_STATE_RAMPUP )
{
2012-11-26 18:58:24 +00:00
float delta = ( 0.25f - slowmoScale ) ;
2012-11-28 15:47:07 +00:00
if ( fabs ( delta ) < g_slowmoStepRate . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
slowmoScale = 0.25f ;
slowmoState = SLOWMO_STATE_ON ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
slowmoScale + = delta * g_slowmoStepRate . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld ! = NULL )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetSlowmoSpeed ( slowmoScale ) ;
}
}
2012-11-28 15:47:07 +00:00
else if ( slowmoState = = SLOWMO_STATE_RAMPDOWN )
{
2012-11-26 18:58:24 +00:00
float delta = ( 1.0f - slowmoScale ) ;
2012-11-28 15:47:07 +00:00
if ( fabs ( delta ) < g_slowmoStepRate . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
slowmoScale = 1.0f ;
slowmoState = SLOWMO_STATE_OFF ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
slowmoScale + = delta * g_slowmoStepRate . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( gameSoundWorld ! = NULL )
{
2012-11-26 18:58:24 +00:00
gameSoundWorld - > SetSlowmoSpeed ( slowmoScale ) ;
}
}
}
/*
= = = = = = = = = = =
idGameLocal : : ResetSlowTimeVars
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : ResetSlowTimeVars ( )
{
2012-11-26 18:58:24 +00:00
slowmoScale = 1.0f ;
slowmoState = SLOWMO_STATE_OFF ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fast . previousTime = 0 ;
fast . time = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
slow . previousTime = 0 ;
slow . time = 0 ;
}
/*
= = = = = = = = = = =
idGameLocal : : QuickSlowmoReset
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : QuickSlowmoReset ( )
{
2012-11-26 18:58:24 +00:00
quickSlowmoReset = true ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetClientStats
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : GetClientStats ( int clientNum , char * data , const int len )
{
2012-11-26 18:58:24 +00:00
mpGame . PlayerStats ( clientNum , data , len ) ;
}
/*
= = = = = = = = = = = = = = = =
idGameLocal : : GetMPGameModes
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idGameLocal : : GetMPGameModes ( const char * * * gameModes , const char * * * gameModesDisplay )
{
2012-11-26 18:58:24 +00:00
return mpGame . GetGameModes ( gameModes , gameModesDisplay ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : IsPDAOpen
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : IsPDAOpen ( ) const
{
2012-11-26 18:58:24 +00:00
return GetLocalPlayer ( ) & & GetLocalPlayer ( ) - > objectiveSystemOpen ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : IsPlayerChatting
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : IsPlayerChatting ( ) const
{
2012-11-26 18:58:24 +00:00
return GetLocalPlayer ( ) & & ( GetLocalPlayer ( ) - > isChatting > 0 ) & & ! GetLocalPlayer ( ) - > spectating ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : InhibitControls
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : InhibitControls ( )
{
2012-11-26 18:58:24 +00:00
return ( Shell_IsActive ( ) | | IsPDAOpen ( ) | | IsPlayerChatting ( ) | | ( common - > IsMultiplayer ( ) & & mpGame . IsScoreboardActive ( ) ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Leaderboards_Init
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Leaderboards_Init ( )
{
2012-11-26 18:58:24 +00:00
LeaderboardLocal_Init ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Leaderboards_Shutdown
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Leaderboards_Shutdown ( )
{
2012-11-26 18:58:24 +00:00
LeaderboardLocal_Shutdown ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_ClearRepeater
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_ClearRepeater ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > ClearWidgetActionRepeater ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_Init
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_Init ( const char * filename , idSoundWorld * sw )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > Initialize ( filename , sw ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_Init
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_Cleanup ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
delete shellHandler ;
shellHandler = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mpGame . CleanupScoreboard ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_CreateMenu
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_CreateMenu ( bool inGame )
{
2012-11-26 18:58:24 +00:00
Shell_ResetMenu ( ) ;
2012-11-28 15:47:07 +00:00
if ( shellHandler ! = NULL )
{
if ( ! inGame )
{
2012-11-26 18:58:24 +00:00
shellHandler - > SetInGame ( false ) ;
Shell_Init ( " shell " , common - > MenuSW ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
shellHandler - > SetInGame ( true ) ;
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
Shell_Init ( " pause " , common - > SW ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Shell_Init ( " pause " , common - > MenuSW ( ) ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_ClosePause
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_ClosePause ( )
{
if ( shellHandler ! = NULL )
{
if ( ! common - > IsMultiplayer ( ) & & GetLocalPlayer ( ) & & GetLocalPlayer ( ) - > health < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( shellHandler - > GetGameComplete ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
shellHandler - > SetNextScreen ( SHELL_AREA_INVALID , MENU_TRANSITION_SIMPLE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_Show
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_Show ( bool show )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > ActivateMenu ( show ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_IsActive
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : Shell_IsActive ( ) const
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
return shellHandler - > IsActive ( ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_HandleGuiEvent
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : Shell_HandleGuiEvent ( const sysEvent_t * sev )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
return shellHandler - > HandleGuiEvent ( sev ) ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_Render
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_Render ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > Update ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_ResetMenu
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_ResetMenu ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
delete shellHandler ;
2012-11-28 15:47:07 +00:00
shellHandler = new ( TAG_SWF ) idMenuHandler_Shell ( ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = =
idGameLocal : : Shell_SyncWithSession
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_SyncWithSession ( )
{
if ( shellHandler = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
switch ( session - > GetState ( ) )
{
2012-11-26 18:58:24 +00:00
case idSession : : PRESS_START :
shellHandler - > SetShellState ( SHELL_STATE_PRESS_START ) ;
break ;
case idSession : : INGAME :
shellHandler - > SetShellState ( SHELL_STATE_PAUSED ) ;
break ;
case idSession : : IDLE :
shellHandler - > SetShellState ( SHELL_STATE_IDLE ) ;
break ;
case idSession : : PARTY_LOBBY :
shellHandler - > SetShellState ( SHELL_STATE_PARTY_LOBBY ) ;
break ;
case idSession : : GAME_LOBBY :
shellHandler - > SetShellState ( SHELL_STATE_GAME_LOBBY ) ;
break ;
case idSession : : SEARCHING :
shellHandler - > SetShellState ( SHELL_STATE_SEARCHING ) ;
break ;
case idSession : : LOADING :
shellHandler - > SetShellState ( SHELL_STATE_LOADING ) ;
break ;
case idSession : : CONNECTING :
shellHandler - > SetShellState ( SHELL_STATE_CONNECTING ) ;
break ;
case idSession : : BUSY :
shellHandler - > SetShellState ( SHELL_STATE_BUSY ) ;
break ;
}
}
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_SetGameComplete ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > SetGameComplete ( ) ;
Shell_Show ( true ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_SetState_GameLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_UpdateSavedGames ( )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > UpdateSavedGames ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_SetCanContinue
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_SetCanContinue ( bool valid )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > SetCanContinue ( valid ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_SetState_GameLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_UpdateClientCountdown ( int countdown )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > SetTimeRemaining ( countdown ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : Shell_SetState_GameLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idGameLocal : : Shell_UpdateLeaderboard ( const idLeaderboardCallback * callback )
{
if ( shellHandler ! = NULL )
{
2012-11-26 18:58:24 +00:00
shellHandler - > UpdateLeaderboard ( callback ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idGameLocal : : SimulateProjectiles
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idGameLocal : : SimulateProjectiles ( )
{
2012-11-26 18:58:24 +00:00
bool moreProjectiles = false ;
// Simulate projectiles
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < idProjectile : : MAX_SIMULATED_PROJECTILES ; i + + )
{
if ( idProjectile : : projectilesToSimulate [ i ] . projectile ! = NULL & & idProjectile : : projectilesToSimulate [ i ] . startTime ! = 0 )
{
2012-11-26 18:58:24 +00:00
const int startTime = idProjectile : : projectilesToSimulate [ i ] . startTime ;
const int startFrame = MSEC_TO_FRAME_FLOOR ( startTime ) ;
const int endFrame = startFrame + 1 ;
const int endTime = FRAME_TO_MSEC ( endFrame ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idProjectile : : projectilesToSimulate [ i ] . projectile - > SimulateProjectileFrame ( endTime - startTime , endTime ) ;
2012-11-28 15:47:07 +00:00
if ( idProjectile : : projectilesToSimulate [ i ] . projectile ! = NULL )
{
if ( endTime > = previousServerTime )
{
2012-11-26 18:58:24 +00:00
idProjectile : : projectilesToSimulate [ i ] . projectile - > PostSimulate ( endTime ) ;
idProjectile : : projectilesToSimulate [ i ] . startTime = 0 ;
idProjectile : : projectilesToSimulate [ i ] . projectile = NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idProjectile : : projectilesToSimulate [ i ] . startTime = endTime ;
moreProjectiles = true ;
}
}
}
}
return moreProjectiles ;
}