dhewm3/neo/d3xp/Game_local.h
Daniel Gibson 1b2baf43ad Add information about dhewm3 build to savegames
like the dhewm3 version and the OS and architecture of the dhewm3
version that created the savegame.
Also added an internalSavegameVersion so be independent of BUILD_NUMBER

fixes #344
2021-02-21 06:05:47 +01:00

719 lines
27 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 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 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.
===========================================================================
*/
#ifndef __GAME_LOCAL_H__
#define __GAME_LOCAL_H__
#include "GameBase.h"
#include "idlib/containers/StrList.h"
#include "idlib/containers/LinkList.h"
#include "idlib/BitMsg.h"
#include "framework/Game.h"
#include "gamesys/SaveGame.h"
#include "physics/Clip.h"
#include "physics/Push.h"
#include "script/Script_Program.h"
#include "ai/AAS.h"
#include "anim/Anim.h"
#include "Pvs.h"
#include "MultiplayerGame.h"
#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
// This is real evil but allows the code to inspect arbitrary class variables.
#define private public
#define protected public
#endif
/*
===============================================================================
Local implementation of the public game interface.
===============================================================================
*/
class idDeclEntityDef;
class idRenderWorld;
class idSoundWorld;
class idUserInterface;
extern idRenderWorld * gameRenderWorld;
extern idSoundWorld * gameSoundWorld;
// classes used by idGameLocal
class idEntity;
class idActor;
class idPlayer;
class idCamera;
class idWorldspawn;
class idTestModel;
class idSmokeParticles;
class idEntityFx;
class idTypeInfo;
class idThread;
class idEditEntities;
class idLocationEntity;
//============================================================================
extern const int NUM_RENDER_PORTAL_BITS;
void gameError( const char *fmt, ... );
extern idRenderWorld * gameRenderWorld;
extern idSoundWorld * gameSoundWorld;
extern const int NUM_RENDER_PORTAL_BITS;
/*
===============================================================================
Local implementation of the public game interface.
===============================================================================
*/
typedef struct entityState_s {
int entityNumber;
idBitMsg state;
byte stateBuf[MAX_ENTITY_STATE_SIZE];
struct entityState_s * next;
} entityState_t;
typedef struct snapshot_s {
int sequence;
entityState_t * firstEntityState;
int pvs[ENTITY_PVS_SIZE];
struct snapshot_s * next;
} snapshot_t;
const int MAX_EVENT_PARAM_SIZE = 128;
typedef struct entityNetEvent_s {
int spawnId;
int event;
int time;
int paramsSize;
byte paramsBuf[MAX_EVENT_PARAM_SIZE];
struct entityNetEvent_s *next;
struct entityNetEvent_s *prev;
} entityNetEvent_t;
enum {
GAME_RELIABLE_MESSAGE_INIT_DECL_REMAP,
GAME_RELIABLE_MESSAGE_REMAP_DECL,
GAME_RELIABLE_MESSAGE_SPAWN_PLAYER,
GAME_RELIABLE_MESSAGE_DELETE_ENT,
GAME_RELIABLE_MESSAGE_CHAT,
GAME_RELIABLE_MESSAGE_TCHAT,
GAME_RELIABLE_MESSAGE_SOUND_EVENT,
GAME_RELIABLE_MESSAGE_SOUND_INDEX,
GAME_RELIABLE_MESSAGE_DB,
GAME_RELIABLE_MESSAGE_KILL,
GAME_RELIABLE_MESSAGE_DROPWEAPON,
GAME_RELIABLE_MESSAGE_RESTART,
GAME_RELIABLE_MESSAGE_SERVERINFO,
GAME_RELIABLE_MESSAGE_TOURNEYLINE,
GAME_RELIABLE_MESSAGE_CALLVOTE,
GAME_RELIABLE_MESSAGE_CASTVOTE,
GAME_RELIABLE_MESSAGE_STARTVOTE,
GAME_RELIABLE_MESSAGE_UPDATEVOTE,
GAME_RELIABLE_MESSAGE_PORTALSTATES,
GAME_RELIABLE_MESSAGE_PORTAL,
GAME_RELIABLE_MESSAGE_VCHAT,
GAME_RELIABLE_MESSAGE_STARTSTATE,
GAME_RELIABLE_MESSAGE_MENU,
GAME_RELIABLE_MESSAGE_WARMUPTIME,
GAME_RELIABLE_MESSAGE_EVENT
};
typedef enum {
GAMESTATE_UNINITIALIZED, // prior to Init being called
GAMESTATE_NOMAP, // no map loaded
GAMESTATE_STARTUP, // inside InitFromNewMap(). spawning map entities.
GAMESTATE_ACTIVE, // normal gameplay
GAMESTATE_SHUTDOWN // inside MapShutdown(). clearing memory.
} gameState_t;
typedef struct {
idEntity *ent;
int dist;
#ifdef CTF
int team;
#endif
} spawnSpot_t;
//============================================================================
class idEventQueue {
public:
typedef enum {
OUTOFORDER_IGNORE,
OUTOFORDER_DROP,
OUTOFORDER_SORT
} outOfOrderBehaviour_t;
idEventQueue() : start( NULL ), end( NULL ) {}
entityNetEvent_t * Alloc();
void Free( entityNetEvent_t *event );
void Shutdown();
void Init();
void Enqueue( entityNetEvent_t* event, outOfOrderBehaviour_t oooBehaviour );
entityNetEvent_t * Dequeue( void );
entityNetEvent_t * RemoveLast( void );
entityNetEvent_t * Start( void ) { return start; }
private:
entityNetEvent_t * start;
entityNetEvent_t * end;
idBlockAlloc<entityNetEvent_t,32> eventAllocator;
};
//============================================================================
template< class type >
class idEntityPtr {
public:
idEntityPtr();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
idEntityPtr<type> & operator=( type *ent );
// synchronize entity pointers over the network
int GetSpawnId( void ) const { return spawnId; }
bool SetSpawnId( int id );
bool UpdateSpawnId( void );
bool IsValid( void ) const;
type * GetEntity( void ) const;
int GetEntityNum( void ) const;
private:
int spawnId;
};
#ifdef _D3XP
struct timeState_t {
int time;
int previousTime;
int msec;
int framenum;
int realClientTime;
void Set( int t, int pt, int ms, int f, int rct ) { time = t; previousTime = pt; msec = ms; framenum = f; realClientTime = rct; };
void Get( int& t, int& pt, int& ms, int& f, int& rct ) { t = time; pt = previousTime; ms = msec; f = framenum; rct = realClientTime; };
void Save( idSaveGame *savefile ) const { savefile->WriteInt( time ); savefile->WriteInt( previousTime ); savefile->WriteInt( msec ); savefile->WriteInt( framenum ); savefile->WriteInt( realClientTime ); }
void Restore( idRestoreGame *savefile ) { savefile->ReadInt( time ); savefile->ReadInt( previousTime ); savefile->ReadInt( msec ); savefile->ReadInt( framenum ); savefile->ReadInt( realClientTime ); }
void Increment() { framenum++; previousTime = time; time += msec; realClientTime = time; };
};
enum slowmoState_t {
SLOWMO_STATE_OFF,
SLOWMO_STATE_RAMPUP,
SLOWMO_STATE_ON,
SLOWMO_STATE_RAMPDOWN
};
#endif
//============================================================================
class idGameLocal : public idGame {
public:
idDict serverInfo; // all the tunable parameters, like numclients, etc
int numClients; // pulled from serverInfo and verified
idDict userInfo[MAX_CLIENTS]; // client specific settings
usercmd_t usercmds[MAX_CLIENTS]; // client input commands
idDict persistentPlayerInfo[MAX_CLIENTS];
idEntity * entities[MAX_GENTITIES];// index to entities
int spawnIds[MAX_GENTITIES];// for use in idEntityPtr
int firstFreeIndex; // first free index in the entities array
int num_entities; // current number <= MAX_GENTITIES
idHashIndex entityHash; // hash table to quickly find entities by name
idWorldspawn * world; // world entity
idLinkList<idEntity> spawnedEntities; // all spawned entities
idLinkList<idEntity> activeEntities; // all thinking entities (idEntity::thinkFlags != 0)
int numEntitiesToDeactivate;// number of entities that became inactive in current frame
bool sortPushers; // true if active lists needs to be reordered to place pushers at the front
bool sortTeamMasters; // true if active lists needs to be reordered to place physics team masters before their slaves
idDict persistentLevelInfo; // contains args that are kept around between levels
// can be used to automatically effect every material in the world that references globalParms
float globalShaderParms[ MAX_GLOBAL_SHADER_PARMS ];
idRandom random; // random number generator used throughout the game
idProgram program; // currently loaded script and data space
idThread * frameCommandThread;
idClip clip; // collision detection
idPush push; // geometric pushing
idPVS pvs; // potential visible set
idTestModel * testmodel; // for development testing of models
idEntityFx * testFx; // for development testing of fx
idStr sessionCommand; // a target_sessionCommand can set this to return something to the session
idMultiplayerGame mpGame; // handles rules for standard dm
idSmokeParticles * smokeParticles; // global smoke trails
idEditEntities * editEntities; // in game editing
int cinematicSkipTime; // don't allow skipping cinemetics until this time has passed so player doesn't skip out accidently from a firefight
int cinematicStopTime; // cinematics have several camera changes, so keep track of when we stop them so that we don't reset cinematicSkipTime unnecessarily
int cinematicMaxSkipTime; // time to end cinematic when skipping. there's a possibility of an infinite loop if the map isn't set up right.
bool inCinematic; // game is playing cinematic (player controls frozen)
bool skipCinematic;
// are kept up to date with changes to serverInfo
int framenum;
int previousTime; // time in msec of last frame
int time; // in msec
int msec; // time since last update in milliseconds
int vacuumAreaNum; // -1 if level doesn't have any outside areas
gameType_t gameType;
bool isMultiplayer; // set if the game is run in multiplayer mode
bool isServer; // set if the game is run for a dedicated or listen server
bool isClient; // set if the game is run for a client
// discriminates between the RunFrame path and the ClientPrediction path
// NOTE: on a listen server, isClient is false
int localClientNum; // number of the local client. MP: -1 on a dedicated
idLinkList<idEntity> snapshotEntities; // entities from the last snapshot
int realClientTime; // real client time
bool isNewFrame; // true if this is a new game frame, not a rerun due to prediction
float clientSmoothing; // smoothing of other clients in the view
int entityDefBits; // bits required to store an entity def number
static const char * sufaceTypeNames[ MAX_SURFACE_TYPES ]; // text names for surface types
idEntityPtr<idEntity> lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f
int lastGUI; // last GUI on the lastGUIEnt
#ifdef _D3XP
idEntityPtr<idEntity> portalSkyEnt;
bool portalSkyActive;
void SetPortalSkyEnt( idEntity *ent );
bool IsPortalSkyAcive();
timeState_t fast;
timeState_t slow;
slowmoState_t slowmoState;
float slowmoMsec;
bool quickSlowmoReset;
virtual void SelectTimeGroup( int timeGroup );
virtual int GetTimeGroupTime( int timeGroup );
virtual void GetBestGameType( const char* map, const char* gametype, char buf[ MAX_STRING_CHARS ] );
void ComputeSlowMsec();
void RunTimeGroup2();
void ResetSlowTimeVars();
void QuickSlowmoReset();
bool NeedRestart();
#endif
void Tokenize( idStrList &out, const char *in );
// ---------------------- Public idGame Interface -------------------
idGameLocal();
virtual void Init( void );
virtual void Shutdown( void );
virtual void SetLocalClient( int clientNum );
virtual void ThrottleUserInfo( void );
virtual const idDict * SetUserInfo( int clientNum, const idDict &userInfo, bool isClient, bool canModify );
virtual const idDict * GetUserInfo( int clientNum );
virtual void SetServerInfo( const idDict &serverInfo );
virtual const idDict & GetPersistentPlayerInfo( int clientNum );
virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo );
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed );
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile );
virtual void SaveGame( idFile *saveGameFile );
virtual void MapShutdown( void );
virtual void CacheDictionaryMedia( const idDict *dict );
virtual void SpawnPlayer( int clientNum );
virtual gameReturn_t RunFrame( const usercmd_t *clientCmds );
virtual bool Draw( int clientNum );
virtual escReply_t HandleESC( idUserInterface **gui );
virtual idUserInterface *StartMenu( void );
virtual const char * HandleGuiCommands( const char *menuCommand );
virtual void HandleMainMenuCommands( const char *menuCommand, idUserInterface *gui );
virtual allowReply_t ServerAllowClient( int numClients, const char *IP, const char *guid, const char *password, char reason[MAX_STRING_CHARS] );
virtual void ServerClientConnect( int clientNum, const char *guid );
virtual void ServerClientBegin( int clientNum );
virtual void ServerClientDisconnect( int clientNum );
virtual void ServerWriteInitialReliableMessages( int clientNum );
virtual void ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, byte *clientInPVS, int numPVSClients );
virtual bool ServerApplySnapshot( int clientNum, int sequence );
virtual void ServerProcessReliableMessage( int clientNum, const idBitMsg &msg );
virtual void ClientReadSnapshot( int clientNum, int sequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg );
virtual bool ClientApplySnapshot( int clientNum, int sequence );
virtual void ClientProcessReliableMessage( int clientNum, const idBitMsg &msg );
virtual gameReturn_t ClientPrediction( int clientNum, const usercmd_t *clientCmds, bool lastPredictFrame );
virtual void GetClientStats( int clientNum, char *data, const int len );
virtual void SwitchTeam( int clientNum, int team );
virtual bool DownloadRequest( const char *IP, const char *guid, const char *paks, char urls[ MAX_STRING_CHARS ] );
virtual void GetMapLoadingGUI( char gui[ MAX_STRING_CHARS ] );
// ---------------------- Public idGameLocal Interface -------------------
void Printf( const char *fmt, ... ) const id_attribute((format(printf,2,3)));
void DPrintf( const char *fmt, ... ) const id_attribute((format(printf,2,3)));
void Warning( const char *fmt, ... ) const id_attribute((format(printf,2,3)));
void DWarning( const char *fmt, ... ) const id_attribute((format(printf,2,3)));
void Error( const char *fmt, ... ) const id_attribute((format(printf,2,3)));
// Initializes all map variables common to both save games and spawned games
void LoadMap( const char *mapName, int randseed );
void LocalMapRestart( void );
void MapRestart( void );
static void MapRestart_f( const idCmdArgs &args );
bool NextMap( void ); // returns wether serverinfo settings have been modified
static void NextMap_f( const idCmdArgs &args );
idMapFile * GetLevelMap( void );
const char * GetMapName( void ) const;
int NumAAS( void ) const;
idAAS * GetAAS( int num ) const;
idAAS * GetAAS( const char *name ) const;
void SetAASAreaState( const idBounds &bounds, const int areaContents, bool closed );
aasHandle_t AddAASObstacle( const idBounds &bounds );
void RemoveAASObstacle( const aasHandle_t handle );
void RemoveAllAASObstacles( void );
bool CheatsOk( bool requirePlayer = true );
void SetSkill( int value );
gameState_t GameState( void ) const;
idEntity * SpawnEntityType( const idTypeInfo &classdef, const idDict *args = NULL, bool bIsClientReadSnapshot = false );
bool SpawnEntityDef( const idDict &args, idEntity **ent = NULL, bool setDefaults = true );
int GetSpawnId( const idEntity *ent ) const;
const idDeclEntityDef * FindEntityDef( const char *name, bool makeDefault = true ) const;
const idDict * FindEntityDefDict( const char *name, bool makeDefault = true ) const;
void RegisterEntity( idEntity *ent );
void UnregisterEntity( idEntity *ent );
bool RequirementMet( idEntity *activator, const idStr &requires, int removeItem );
void AlertAI( idEntity *ent );
idActor * GetAlertEntity( void );
bool InPlayerPVS( idEntity *ent ) const;
bool InPlayerConnectedArea( idEntity *ent ) const;
#ifdef _D3XP
pvsHandle_t GetPlayerPVS() { return playerPVS; };
#endif
void SetCamera( idCamera *cam );
idCamera * GetCamera( void ) const;
bool SkipCinematic( void );
void CalcFov( float base_fov, float &fov_x, float &fov_y ) const;
void AddEntityToHash( const char *name, idEntity *ent );
bool RemoveEntityFromHash( const char *name, idEntity *ent );
int GetTargets( const idDict &args, idList< idEntityPtr<idEntity> > &list, const char *ref ) const;
// returns the master entity of a trace. for example, if the trace entity is the player's head, it will return the player.
idEntity * GetTraceEntity( const trace_t &trace ) const;
static void ArgCompletion_EntityName( const idCmdArgs &args, void(*callback)( const char *s ) );
idEntity * FindTraceEntity( idVec3 start, idVec3 end, const idTypeInfo &c, const idEntity *skip ) const;
idEntity * FindEntity( const char *name ) const;
idEntity * FindEntityUsingDef( idEntity *from, const char *match ) const;
int EntitiesWithinRadius( const idVec3 org, float radius, idEntity **entityList, int maxCount ) const;
void KillBox( idEntity *ent, bool catch_teleport = false );
void RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignoreDamage, idEntity *ignorePush, const char *damageDefName, float dmgPower = 1.0f );
void RadiusPush( const idVec3 &origin, const float radius, const float push, const idEntity *inflictor, const idEntity *ignore, float inflictorScale, const bool quake );
void RadiusPushClipModel( const idVec3 &origin, const float push, const idClipModel *clipModel );
void ProjectDecal( const idVec3 &origin, const idVec3 &dir, float depth, bool parallel, float size, const char *material, float angle = 0 );
void BloodSplat( const idVec3 &origin, const idVec3 &dir, float size, const char *material );
void CallFrameCommand( idEntity *ent, const function_t *frameCommand );
void CallObjectFrameCommand( idEntity *ent, const char *frameCommand );
const idVec3 & GetGravity( void ) const;
// added the following to assist licensees with merge issues
int GetFrameNum() const { return framenum; };
int GetTime() const { return time; };
int GetMSec() const { return msec; };
int GetNextClientNum( int current ) const;
idPlayer * GetClientByNum( int current ) const;
idPlayer * GetClientByName( const char *name ) const;
idPlayer * GetClientByCmdArgs( const idCmdArgs &args ) const;
idPlayer * GetLocalPlayer() const;
void SpreadLocations();
idLocationEntity * LocationForPoint( const idVec3 &point ); // May return NULL
idEntity * SelectInitialSpawnPoint( idPlayer *player );
void SetPortalState( qhandle_t portal, int blockingBits );
void SaveEntityNetworkEvent( const idEntity *ent, int event, const idBitMsg *msg );
void ServerSendChatMessage( int to, const char *name, const char *text );
int ServerRemapDecl( int clientNum, declType_t type, int index );
int ClientRemapDecl( declType_t type, int index );
void SetGlobalMaterial( const idMaterial *mat );
const idMaterial * GetGlobalMaterial();
void SetGibTime( int _time ) { nextGibTime = _time; };
int GetGibTime() { return nextGibTime; };
private:
const static int INITIAL_SPAWN_COUNT = 1;
const static int INTERNAL_SAVEGAME_VERSION = 1; // DG: added this for >= 1305 savegames
idStr mapFileName; // name of the map, empty string if no map loaded
idMapFile * mapFile; // will be NULL during the game unless in-game editing is used
bool mapCycleLoaded;
int spawnCount;
int mapSpawnCount; // it's handy to know which entities are part of the map
idLocationEntity ** locationEntities; // for location names, etc
idCamera * camera;
const idMaterial * globalMaterial; // for overriding everything
idList<idAAS *> aasList; // area system
idStrList aasNames;
idEntityPtr<idActor> lastAIAlertEntity;
int lastAIAlertTime;
idDict spawnArgs; // spawn args used during entity spawning FIXME: shouldn't be necessary anymore
pvsHandle_t playerPVS; // merged pvs of all players
pvsHandle_t playerConnectedAreas; // all areas connected to any player area
idVec3 gravity; // global gravity vector
gameState_t gamestate; // keeps track of whether we're spawning, shutting down, or normal gameplay
bool influenceActive; // true when a phantasm is happening
int nextGibTime;
idList<int> clientDeclRemap[MAX_CLIENTS][DECL_MAX_TYPES];
entityState_t * clientEntityStates[MAX_CLIENTS][MAX_GENTITIES];
int clientPVS[MAX_CLIENTS][ENTITY_PVS_SIZE];
snapshot_t * clientSnapshots[MAX_CLIENTS];
idBlockAlloc<entityState_t,256>entityStateAllocator;
idBlockAlloc<snapshot_t,64>snapshotAllocator;
idEventQueue eventQueue;
idEventQueue savedEventQueue;
idStaticList<spawnSpot_t, MAX_GENTITIES> spawnSpots;
idStaticList<idEntity *, MAX_GENTITIES> initialSpots;
int currentInitialSpot;
#ifdef CTF
idStaticList<spawnSpot_t, MAX_GENTITIES> teamSpawnSpots[2];
idStaticList<idEntity *, MAX_GENTITIES> teamInitialSpots[2];
int teamCurrentInitialSpot[2];
#endif
idDict newInfo;
idStrList shakeSounds;
byte lagometer[ LAGO_IMG_HEIGHT ][ LAGO_IMG_WIDTH ][ 4 ];
void Clear( void );
// returns true if the entity shouldn't be spawned at all in this game type or difficulty level
bool InhibitEntitySpawn( idDict &spawnArgs );
// spawn entities from the map file
void SpawnMapEntities( void );
// commons used by init, shutdown, and restart
void MapPopulate( void );
void MapClear( bool clearClients );
pvsHandle_t GetClientPVS( idPlayer *player, pvsType_t type );
void SetupPlayerPVS( void );
void FreePlayerPVS( void );
void UpdateGravity( void );
void SortActiveEntityList( void );
void ShowTargets( void );
void RunDebugInfo( void );
void InitScriptForMap( void );
void InitConsoleCommands( void );
void ShutdownConsoleCommands( void );
void InitAsyncNetwork( void );
void ShutdownAsyncNetwork( void );
void InitLocalClient( int clientNum );
void InitClientDeclRemap( int clientNum );
void ServerSendDeclRemapToClient( int clientNum, declType_t type, int index );
void FreeSnapshotsOlderThanSequence( int clientNum, int sequence );
bool ApplySnapshot( int clientNum, int sequence );
void WriteGameStateToSnapshot( idBitMsgDelta &msg ) const;
void ReadGameStateFromSnapshot( const idBitMsgDelta &msg );
void NetworkEventWarning( const entityNetEvent_t *event, const char *fmt, ... ) id_attribute((format(printf,3,4)));
void ServerProcessEntityNetworkEventQueue( void );
void ClientProcessEntityNetworkEventQueue( void );
void ClientShowSnapshot( int clientNum ) const;
// call after any change to serverInfo. Will update various quick-access flags
void UpdateServerInfoFlags( void );
void RandomizeInitialSpawns( void );
static int sortSpawnPoints( const void *ptr1, const void *ptr2 );
void DumpOggSounds( void );
void GetShakeSounds( const idDict *dict );
void UpdateLagometer( int aheadOfServer, int dupeUsercmds );
};
//============================================================================
extern idGameLocal gameLocal;
extern idAnimManager animationLib;
//============================================================================
class idGameError : public idException {
public:
idGameError( const char *text ) : idException( text ) {}
};
//============================================================================
template< class type >
ID_INLINE idEntityPtr<type>::idEntityPtr() {
spawnId = 0;
}
template< class type >
ID_INLINE void idEntityPtr<type>::Save( idSaveGame *savefile ) const {
savefile->WriteInt( spawnId );
}
template< class type >
ID_INLINE void idEntityPtr<type>::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( spawnId );
}
template< class type >
ID_INLINE idEntityPtr<type> &idEntityPtr<type>::operator=( type *ent ) {
if ( ent == NULL ) {
spawnId = 0;
} else {
spawnId = ( gameLocal.spawnIds[ent->entityNumber] << GENTITYNUM_BITS ) | ent->entityNumber;
}
return *this;
}
template< class type >
ID_INLINE bool idEntityPtr<type>::SetSpawnId( int id ) {
// the reason for this first check is unclear:
// the function returning false may mean the spawnId is already set right, or the entity is missing
if ( id == spawnId ) {
return false;
}
if ( ( id >> GENTITYNUM_BITS ) == gameLocal.spawnIds[ id & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
spawnId = id;
return true;
}
return false;
}
template< class type >
ID_INLINE bool idEntityPtr<type>::IsValid( void ) const {
return ( gameLocal.spawnIds[ spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] == ( spawnId >> GENTITYNUM_BITS ) );
}
template< class type >
ID_INLINE type *idEntityPtr<type>::GetEntity( void ) const {
int entityNum = spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
if ( gameLocal.spawnIds[ entityNum ] == ( spawnId >> GENTITYNUM_BITS ) ) {
return static_cast<type *>( gameLocal.entities[ entityNum ] );
}
return NULL;
}
template< class type >
ID_INLINE int idEntityPtr<type>::GetEntityNum( void ) const {
return ( spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) );
}
// ===========================================================================
//
// these defines work for all startsounds from all entity types
// make sure to change script/doom_defs.script if you add any channels, or change their order
//
typedef enum {
SND_CHANNEL_ANY = SCHANNEL_ANY,
SND_CHANNEL_VOICE = SCHANNEL_ONE,
SND_CHANNEL_VOICE2,
SND_CHANNEL_BODY,
SND_CHANNEL_BODY2,
SND_CHANNEL_BODY3,
SND_CHANNEL_WEAPON,
SND_CHANNEL_ITEM,
SND_CHANNEL_HEART,
SND_CHANNEL_PDA,
SND_CHANNEL_DEMONIC,
SND_CHANNEL_RADIO,
// internal use only. not exposed to script or framecommands.
SND_CHANNEL_AMBIENT,
SND_CHANNEL_DAMAGE
} gameSoundChannel_t;
extern const float DEFAULT_GRAVITY;
extern const idVec3 DEFAULT_GRAVITY_VEC3;
extern const int CINEMATIC_SKIP_DELAY;
#endif /* !__GAME_LOCAL_H__ */