2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 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.
24 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.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "../Game_local.h"
37 Save game related helper classes.
39 Save games are implemented in two classes, idSaveGame and idRestoreGame, that implement write/read functions for
40 common types. They're passed in to each entity and object for them to archive themselves. Each class
41 implements save/restore functions for it's own data. When restoring, all the objects are instantiated,
42 then the restore function is called on each, superclass first, then subclasses.
44 Pointers are restored by saving out an object index for each unique object pointer and adding them to a list of
45 objects that are to be saved. Restore instantiates all the objects in the list before calling the Restore function
46 on each object so that the pointers returned are valid. No object's restore function should rely on any other objects
47 being fully instantiated until after the restore process is complete. Post restore fixup should be done by posting
50 The savegame header will have the Game Name, Version, Map Name, and Player Persistent Info.
52 Changes in version make savegames incompatible, and the game will start from the beginning of the level with
53 the player's persistent info.
55 Changes to classes that don't need to break compatibilty can use the build number as the savegame version.
56 Later versions are responsible for restoring from previous versions by ignoring any unused data and initializing
57 variables that weren't in previous versions with safe information.
59 At the head of the save game is enough information to restore the player to the beginning of the level should the
60 file be unloadable in some way (for example, due to script changes).
65 idSaveGame::idSaveGame()
68 idSaveGame::idSaveGame( idFile *savefile ) {
72 // Put NULL at the start of the list so we can skip over it.
74 objects.Append( NULL );
79 idSaveGame::~idSaveGame()
82 idSaveGame::~idSaveGame() {
83 if ( objects.Num() ) {
93 void idSaveGame::Close( void ) {
99 idClipModel::SaveTraceModels( this );
101 for( i = 1; i < objects.Num(); i++ ) {
102 CallSave_r( objects[ i ]->GetType(), objects[ i ] );
107 #ifdef ID_DEBUG_MEMORY
108 idStr gameState = file->GetName();
109 gameState.StripFileExtension();
110 WriteGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ), false ) );
116 idSaveGame::WriteObjectList
119 void idSaveGame::WriteObjectList( void ) {
122 WriteInt( objects.Num() - 1 );
123 for( i = 1; i < objects.Num(); i++ ) {
124 WriteString( objects[ i ]->GetClassname() );
130 idSaveGame::CallSave_r
133 void idSaveGame::CallSave_r( const idTypeInfo *cls, const idClass *obj ) {
135 CallSave_r( cls->super, obj );
136 if ( cls->super->Save == cls->Save ) {
137 // don't call save on this inheritance level since the function was called in the super class
142 ( obj->*cls->Save )( this );
147 idSaveGame::AddObject
150 void idSaveGame::AddObject( const idClass *obj ) {
151 objects.AddUnique( obj );
159 void idSaveGame::Write( const void *buffer, int len ) {
160 file->Write( buffer, len );
168 void idSaveGame::WriteInt( const int value ) {
169 file->WriteInt( value );
174 idSaveGame::WriteJoint
177 void idSaveGame::WriteJoint( const jointHandle_t value ) {
178 file->WriteInt( (int&)value );
183 idSaveGame::WriteShort
186 void idSaveGame::WriteShort( const short value ) {
187 file->WriteShort( value );
192 idSaveGame::WriteByte
195 void idSaveGame::WriteByte( const byte value ) {
196 file->Write( &value, sizeof( value ) );
201 idSaveGame::WriteSignedChar
204 void idSaveGame::WriteSignedChar( const signed char value ) {
205 file->Write( &value, sizeof( value ) );
210 idSaveGame::WriteFloat
213 void idSaveGame::WriteFloat( const float value ) {
214 file->WriteFloat( value );
219 idSaveGame::WriteBool
222 void idSaveGame::WriteBool( const bool value ) {
223 file->WriteBool( value );
228 idSaveGame::WriteString
231 void idSaveGame::WriteString( const char *string ) {
234 len = strlen( string );
236 file->Write( string, len );
241 idSaveGame::WriteVec2
244 void idSaveGame::WriteVec2( const idVec2 &vec ) {
245 file->WriteVec2( vec );
250 idSaveGame::WriteVec3
253 void idSaveGame::WriteVec3( const idVec3 &vec ) {
254 file->WriteVec3( vec );
259 idSaveGame::WriteVec4
262 void idSaveGame::WriteVec4( const idVec4 &vec ) {
263 file->WriteVec4( vec );
268 idSaveGame::WriteVec6
271 void idSaveGame::WriteVec6( const idVec6 &vec ) {
272 file->WriteVec6( vec );
277 idSaveGame::WriteBounds
280 void idSaveGame::WriteBounds( const idBounds &bounds ) {
282 LittleRevBytes( &b, sizeof(float), sizeof(b)/sizeof(float) );
283 file->Write( &b, sizeof( b ) );
288 idSaveGame::WriteBounds
291 void idSaveGame::WriteWinding( const idWinding &w )
294 num = w.GetNumPoints();
295 file->WriteInt( num );
296 for ( i = 0; i < num; i++ ) {
298 LittleRevBytes(&v, sizeof(float), sizeof(v)/sizeof(float) );
299 file->Write( &v, sizeof(v) );
306 idSaveGame::WriteMat3
309 void idSaveGame::WriteMat3( const idMat3 &mat ) {
310 file->WriteMat3( mat );
315 idSaveGame::WriteAngles
318 void idSaveGame::WriteAngles( const idAngles &angles ) {
320 LittleRevBytes(&v, sizeof(float), sizeof(v)/sizeof(float) );
321 file->Write( &v, sizeof( v ) );
326 idSaveGame::WriteObject
329 void idSaveGame::WriteObject( const idClass *obj ) {
332 index = objects.FindIndex( obj );
334 gameLocal.DPrintf( "idSaveGame::WriteObject - WriteObject FindIndex failed\n" );
336 // Use the NULL index
345 idSaveGame::WriteStaticObject
348 void idSaveGame::WriteStaticObject( const idClass &obj ) {
349 CallSave_r( obj.GetType(), &obj );
354 idSaveGame::WriteDict
357 void idSaveGame::WriteDict( const idDict *dict ) {
360 const idKeyValue *kv;
365 num = dict->GetNumKeyVals();
367 for( i = 0; i < num; i++ ) {
368 kv = dict->GetKeyVal( i );
369 WriteString( kv->GetKey() );
370 WriteString( kv->GetValue() );
377 idSaveGame::WriteMaterial
380 void idSaveGame::WriteMaterial( const idMaterial *material ) {
384 WriteString( material->GetName() );
390 idSaveGame::WriteSkin
393 void idSaveGame::WriteSkin( const idDeclSkin *skin ) {
397 WriteString( skin->GetName() );
403 idSaveGame::WriteParticle
406 void idSaveGame::WriteParticle( const idDeclParticle *particle ) {
410 WriteString( particle->GetName() );
419 void idSaveGame::WriteFX( const idDeclFX *fx ) {
423 WriteString( fx->GetName() );
429 idSaveGame::WriteModelDef
432 void idSaveGame::WriteModelDef( const idDeclModelDef *modelDef ) {
436 WriteString( modelDef->GetName() );
442 idSaveGame::WriteSoundShader
445 void idSaveGame::WriteSoundShader( const idSoundShader *shader ) {
451 name = shader->GetName();
458 idSaveGame::WriteModel
461 void idSaveGame::WriteModel( const idRenderModel *model ) {
467 name = model->Name();
474 idSaveGame::WriteUserInterface
477 void idSaveGame::WriteUserInterface( const idUserInterface *ui, bool unique ) {
486 if ( ui->WriteToSaveGame( file ) == false ) {
487 gameLocal.Error( "idSaveGame::WriteUserInterface: ui failed to write properly\n" );
494 idSaveGame::WriteRenderEntity
497 void idSaveGame::WriteRenderEntity( const renderEntity_t &renderEntity ) {
500 WriteModel( renderEntity.hModel );
502 WriteInt( renderEntity.entityNum );
503 WriteInt( renderEntity.bodyId );
505 WriteBounds( renderEntity.bounds );
507 // callback is set by class's Restore function
509 WriteInt( renderEntity.suppressSurfaceInViewID );
510 WriteInt( renderEntity.suppressShadowInViewID );
511 WriteInt( renderEntity.suppressShadowInLightID );
512 WriteInt( renderEntity.allowSurfaceInViewID );
514 WriteVec3( renderEntity.origin );
515 WriteMat3( renderEntity.axis );
517 WriteMaterial( renderEntity.customShader );
518 WriteMaterial( renderEntity.referenceShader );
519 WriteSkin( renderEntity.customSkin );
521 if ( renderEntity.referenceSound != NULL ) {
522 WriteInt( renderEntity.referenceSound->Index() );
527 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
528 WriteFloat( renderEntity.shaderParms[ i ] );
531 for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
532 WriteUserInterface( renderEntity.gui[ i ], renderEntity.gui[ i ] ? renderEntity.gui[ i ]->IsUniqued() : false );
535 WriteFloat( renderEntity.modelDepthHack );
537 WriteBool( renderEntity.noSelfShadow );
538 WriteBool( renderEntity.noShadow );
539 WriteBool( renderEntity.noDynamicInteractions );
540 WriteBool( renderEntity.weaponDepthHack );
542 WriteInt( renderEntity.forceUpdate );
547 idSaveGame::WriteRenderLight
550 void idSaveGame::WriteRenderLight( const renderLight_t &renderLight ) {
553 WriteMat3( renderLight.axis );
554 WriteVec3( renderLight.origin );
556 WriteInt( renderLight.suppressLightInViewID );
557 WriteInt( renderLight.allowLightInViewID );
558 WriteBool( renderLight.noShadows );
559 WriteBool( renderLight.noSpecular );
560 WriteBool( renderLight.pointLight );
561 WriteBool( renderLight.parallel );
563 WriteVec3( renderLight.lightRadius );
564 WriteVec3( renderLight.lightCenter );
566 WriteVec3( renderLight.target );
567 WriteVec3( renderLight.right );
568 WriteVec3( renderLight.up );
569 WriteVec3( renderLight.start );
570 WriteVec3( renderLight.end );
572 // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
573 // WriteModel( renderLight.prelightModel );
575 WriteInt( renderLight.lightId );
577 WriteMaterial( renderLight.shader );
579 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
580 WriteFloat( renderLight.shaderParms[ i ] );
583 if ( renderLight.referenceSound != NULL ) {
584 WriteInt( renderLight.referenceSound->Index() );
592 idSaveGame::WriteRefSound
595 void idSaveGame::WriteRefSound( const refSound_t &refSound ) {
596 if ( refSound.referenceSound ) {
597 WriteInt( refSound.referenceSound->Index() );
601 WriteVec3( refSound.origin );
602 WriteInt( refSound.listenerId );
603 WriteSoundShader( refSound.shader );
604 WriteFloat( refSound.diversity );
605 WriteBool( refSound.waitfortrigger );
607 WriteFloat( refSound.parms.minDistance );
608 WriteFloat( refSound.parms.maxDistance );
609 WriteFloat( refSound.parms.volume );
610 WriteFloat( refSound.parms.shakes );
611 WriteInt( refSound.parms.soundShaderFlags );
612 WriteInt( refSound.parms.soundClass );
617 idSaveGame::WriteRenderView
620 void idSaveGame::WriteRenderView( const renderView_t &view ) {
623 WriteInt( view.viewID );
626 WriteInt( view.width );
627 WriteInt( view.height );
629 WriteFloat( view.fov_x );
630 WriteFloat( view.fov_y );
631 WriteVec3( view.vieworg );
632 WriteMat3( view.viewaxis );
634 WriteBool( view.cramZNear );
636 WriteInt( view.time );
638 for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
639 WriteFloat( view.shaderParms[ i ] );
645 idSaveGame::WriteUsercmd
648 void idSaveGame::WriteUsercmd( const usercmd_t &usercmd ) {
649 WriteInt( usercmd.gameFrame );
650 WriteInt( usercmd.gameTime );
651 WriteInt( usercmd.duplicateCount );
652 WriteByte( usercmd.buttons );
653 WriteSignedChar( usercmd.forwardmove );
654 WriteSignedChar( usercmd.rightmove );
655 WriteSignedChar( usercmd.upmove );
656 WriteShort( usercmd.angles[0] );
657 WriteShort( usercmd.angles[1] );
658 WriteShort( usercmd.angles[2] );
659 WriteShort( usercmd.mx );
660 WriteShort( usercmd.my );
661 WriteSignedChar( usercmd.impulse );
662 WriteByte( usercmd.flags );
663 WriteInt( usercmd.sequence );
668 idSaveGame::WriteContactInfo
671 void idSaveGame::WriteContactInfo( const contactInfo_t &contactInfo ) {
672 WriteInt( (int)contactInfo.type );
673 WriteVec3( contactInfo.point );
674 WriteVec3( contactInfo.normal );
675 WriteFloat( contactInfo.dist );
676 WriteInt( contactInfo.contents );
677 WriteMaterial( contactInfo.material );
678 WriteInt( contactInfo.modelFeature );
679 WriteInt( contactInfo.trmFeature );
680 WriteInt( contactInfo.entityNum );
681 WriteInt( contactInfo.id );
686 idSaveGame::WriteTrace
689 void idSaveGame::WriteTrace( const trace_t &trace ) {
690 WriteFloat( trace.fraction );
691 WriteVec3( trace.endpos );
692 WriteMat3( trace.endAxis );
693 WriteContactInfo( trace.c );
698 idRestoreGame::WriteTraceModel
701 void idSaveGame::WriteTraceModel( const idTraceModel &trace ) {
704 WriteInt( (int&)trace.type );
705 WriteInt( trace.numVerts );
706 for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
707 WriteVec3( trace.verts[j] );
709 WriteInt( trace.numEdges );
710 for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
711 WriteInt( trace.edges[j].v[0] );
712 WriteInt( trace.edges[j].v[1] );
713 WriteVec3( trace.edges[j].normal );
715 WriteInt( trace.numPolys );
716 for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
717 WriteVec3( trace.polys[j].normal );
718 WriteFloat( trace.polys[j].dist );
719 WriteBounds( trace.polys[j].bounds );
720 WriteInt( trace.polys[j].numEdges );
721 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
722 WriteInt( trace.polys[j].edges[k] );
725 WriteVec3( trace.offset );
726 WriteBounds( trace.bounds );
727 WriteBool( trace.isConvex );
728 // padding win32 native structs
730 memset( tmp, 0, sizeof( tmp ) );
731 file->Write( tmp, 3 );
736 idSaveGame::WriteClipModel
739 void idSaveGame::WriteClipModel( const idClipModel *clipModel ) {
740 if ( clipModel != NULL ) {
742 clipModel->Save( this );
750 idSaveGame::WriteSoundCommands
753 void idSaveGame::WriteSoundCommands( void ) {
754 gameSoundWorld->WriteToSaveGame( file );
758 ======================
759 idSaveGame::WriteBuildNumber
760 ======================
762 void idSaveGame::WriteBuildNumber( const int value ) {
763 file->WriteInt( BUILD_NUMBER );
766 /***********************************************************************
770 ***********************************************************************/
774 idRestoreGame::RestoreGame
777 idRestoreGame::idRestoreGame( idFile *savefile ) {
783 idRestoreGame::~idRestoreGame()
786 idRestoreGame::~idRestoreGame() {
791 void idRestoreGame::CreateObjects
794 void idRestoreGame::CreateObjects( void ) {
801 // create all the objects
802 objects.SetNum( num + 1 );
803 memset( objects.Ptr(), 0, sizeof( objects[ 0 ] ) * objects.Num() );
805 for( i = 1; i < objects.Num(); i++ ) {
806 ReadString( classname );
807 type = idClass::GetClass( classname );
809 Error( "idRestoreGame::CreateObjects: Unknown class '%s'", classname.c_str() );
811 objects[ i ] = type->CreateInstance();
813 #ifdef ID_DEBUG_MEMORY
814 InitTypeVariables( objects[i], type->classname, 0xce );
821 void idRestoreGame::RestoreObjects
824 void idRestoreGame::RestoreObjects( void ) {
830 idClipModel::RestoreTraceModels( this );
832 // restore all the objects
833 for( i = 1; i < objects.Num(); i++ ) {
834 CallRestore_r( objects[ i ]->GetType(), objects[ i ] );
837 // regenerate render entities and render lights because are not saved
838 for( i = 1; i < objects.Num(); i++ ) {
839 if ( objects[ i ]->IsType( idEntity::Type ) ) {
840 idEntity *ent = static_cast<idEntity *>( objects[ i ] );
841 ent->UpdateVisuals();
846 #ifdef ID_DEBUG_MEMORY
847 idStr gameState = file->GetName();
848 gameState.StripFileExtension();
849 WriteGameState_f( idCmdArgs( va( "test %s_restore", gameState.c_str() ), false ) );
850 //CompareGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ) ) );
851 gameLocal.Error( "dumped game states" );
857 void idRestoreGame::DeleteObjects
860 void idRestoreGame::DeleteObjects( void ) {
862 // Remove the NULL object before deleting
863 objects.RemoveIndex( 0 );
865 objects.DeleteContents( true );
873 void idRestoreGame::Error( const char *fmt, ... ) {
877 va_start( argptr, fmt );
878 vsprintf( text, fmt, argptr );
881 objects.DeleteContents( true );
883 gameLocal.Error( "%s", text );
888 idRestoreGame::CallRestore_r
891 void idRestoreGame::CallRestore_r( const idTypeInfo *cls, idClass *obj ) {
893 CallRestore_r( cls->super, obj );
894 if ( cls->super->Restore == cls->Restore ) {
895 // don't call save on this inheritance level since the function was called in the super class
900 ( obj->*cls->Restore )( this );
908 void idRestoreGame::Read( void *buffer, int len ) {
909 file->Read( buffer, len );
914 idRestoreGame::ReadInt
917 void idRestoreGame::ReadInt( int &value ) {
918 file->ReadInt( value );
923 idRestoreGame::ReadJoint
926 void idRestoreGame::ReadJoint( jointHandle_t &value ) {
927 file->ReadInt( (int&)value );
932 idRestoreGame::ReadShort
935 void idRestoreGame::ReadShort( short &value ) {
936 file->ReadShort( value );
941 idRestoreGame::ReadByte
944 void idRestoreGame::ReadByte( byte &value ) {
945 file->Read( &value, sizeof( value ) );
950 idRestoreGame::ReadSignedChar
953 void idRestoreGame::ReadSignedChar( signed char &value ) {
954 file->Read( &value, sizeof( value ) );
959 idRestoreGame::ReadFloat
962 void idRestoreGame::ReadFloat( float &value ) {
963 file->ReadFloat( value );
968 idRestoreGame::ReadBool
971 void idRestoreGame::ReadBool( bool &value ) {
972 file->ReadBool( value );
977 idRestoreGame::ReadString
980 void idRestoreGame::ReadString( idStr &string ) {
985 Error( "idRestoreGame::ReadString: invalid length" );
988 string.Fill( ' ', len );
989 file->Read( &string[ 0 ], len );
994 idRestoreGame::ReadVec2
997 void idRestoreGame::ReadVec2( idVec2 &vec ) {
998 file->ReadVec2( vec );
1003 idRestoreGame::ReadVec3
1006 void idRestoreGame::ReadVec3( idVec3 &vec ) {
1007 file->ReadVec3( vec );
1012 idRestoreGame::ReadVec4
1015 void idRestoreGame::ReadVec4( idVec4 &vec ) {
1016 file->ReadVec4( vec );
1021 idRestoreGame::ReadVec6
1024 void idRestoreGame::ReadVec6( idVec6 &vec ) {
1025 file->ReadVec6( vec );
1030 idRestoreGame::ReadBounds
1033 void idRestoreGame::ReadBounds( idBounds &bounds ) {
1034 file->Read( &bounds, sizeof( bounds ) );
1035 LittleRevBytes( &bounds, sizeof(float), sizeof(bounds)/sizeof(float) );
1040 idRestoreGame::ReadWinding
1043 void idRestoreGame::ReadWinding( idWinding &w )
1046 file->ReadInt( num );
1047 w.SetNumPoints( num );
1048 for ( i = 0; i < num; i++ ) {
1049 file->Read( &w[i], sizeof(idVec5) );
1050 LittleRevBytes(&w[i], sizeof(float), sizeof(idVec5)/sizeof(float) );
1056 idRestoreGame::ReadMat3
1059 void idRestoreGame::ReadMat3( idMat3 &mat ) {
1060 file->ReadMat3( mat );
1065 idRestoreGame::ReadAngles
1068 void idRestoreGame::ReadAngles( idAngles &angles ) {
1069 file->Read( &angles, sizeof( angles ) );
1070 LittleRevBytes(&angles, sizeof(float), sizeof(idAngles)/sizeof(float) );
1075 idRestoreGame::ReadObject
1078 void idRestoreGame::ReadObject( idClass *&obj ) {
1082 if ( ( index < 0 ) || ( index >= objects.Num() ) ) {
1083 Error( "idRestoreGame::ReadObject: invalid object index" );
1085 obj = objects[ index ];
1090 idRestoreGame::ReadStaticObject
1093 void idRestoreGame::ReadStaticObject( idClass &obj ) {
1094 CallRestore_r( obj.GetType(), &obj );
1099 idRestoreGame::ReadDict
1102 void idRestoreGame::ReadDict( idDict *dict ) {
1114 for( i = 0; i < num; i++ ) {
1116 ReadString( value );
1117 dict->Set( key, value );
1124 idRestoreGame::ReadMaterial
1127 void idRestoreGame::ReadMaterial( const idMaterial *&material ) {
1131 if ( !name.Length() ) {
1134 material = declManager->FindMaterial( name );
1140 idRestoreGame::ReadSkin
1143 void idRestoreGame::ReadSkin( const idDeclSkin *&skin ) {
1147 if ( !name.Length() ) {
1150 skin = declManager->FindSkin( name );
1156 idRestoreGame::ReadParticle
1159 void idRestoreGame::ReadParticle( const idDeclParticle *&particle ) {
1163 if ( !name.Length() ) {
1166 particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, name ) );
1172 idRestoreGame::ReadFX
1175 void idRestoreGame::ReadFX( const idDeclFX *&fx ) {
1179 if ( !name.Length() ) {
1182 fx = static_cast<const idDeclFX *>( declManager->FindType( DECL_FX, name ) );
1188 idRestoreGame::ReadSoundShader
1191 void idRestoreGame::ReadSoundShader( const idSoundShader *&shader ) {
1195 if ( !name.Length() ) {
1198 shader = declManager->FindSound( name );
1204 idRestoreGame::ReadModelDef
1207 void idRestoreGame::ReadModelDef( const idDeclModelDef *&modelDef ) {
1211 if ( !name.Length() ) {
1214 modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
1220 idRestoreGame::ReadModel
1223 void idRestoreGame::ReadModel( idRenderModel *&model ) {
1227 if ( !name.Length() ) {
1230 model = renderModelManager->FindModel( name );
1236 idRestoreGame::ReadUserInterface
1239 void idRestoreGame::ReadUserInterface( idUserInterface *&ui ) {
1243 if ( !name.Length() ) {
1248 ui = uiManager->FindGui( name, true, unique );
1250 if ( ui->ReadFromSaveGame( file ) == false ) {
1251 Error( "idSaveGame::ReadUserInterface: ui failed to read properly\n" );
1253 ui->StateChanged( gameLocal.time );
1261 idRestoreGame::ReadRenderEntity
1264 void idRestoreGame::ReadRenderEntity( renderEntity_t &renderEntity ) {
1268 ReadModel( renderEntity.hModel );
1270 ReadInt( renderEntity.entityNum );
1271 ReadInt( renderEntity.bodyId );
1273 ReadBounds( renderEntity.bounds );
1275 // callback is set by class's Restore function
1276 renderEntity.callback = NULL;
1277 renderEntity.callbackData = NULL;
1279 ReadInt( renderEntity.suppressSurfaceInViewID );
1280 ReadInt( renderEntity.suppressShadowInViewID );
1281 ReadInt( renderEntity.suppressShadowInLightID );
1282 ReadInt( renderEntity.allowSurfaceInViewID );
1284 ReadVec3( renderEntity.origin );
1285 ReadMat3( renderEntity.axis );
1287 ReadMaterial( renderEntity.customShader );
1288 ReadMaterial( renderEntity.referenceShader );
1289 ReadSkin( renderEntity.customSkin );
1292 renderEntity.referenceSound = gameSoundWorld->EmitterForIndex( index );
1294 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1295 ReadFloat( renderEntity.shaderParms[ i ] );
1298 for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
1299 ReadUserInterface( renderEntity.gui[ i ] );
1302 // idEntity will restore "cameraTarget", which will be used in idEntity::Present to restore the remoteRenderView
1303 renderEntity.remoteRenderView = NULL;
1305 renderEntity.joints = NULL;
1306 renderEntity.numJoints = 0;
1308 ReadFloat( renderEntity.modelDepthHack );
1310 ReadBool( renderEntity.noSelfShadow );
1311 ReadBool( renderEntity.noShadow );
1312 ReadBool( renderEntity.noDynamicInteractions );
1313 ReadBool( renderEntity.weaponDepthHack );
1315 ReadInt( renderEntity.forceUpdate );
1320 idRestoreGame::ReadRenderLight
1323 void idRestoreGame::ReadRenderLight( renderLight_t &renderLight ) {
1327 ReadMat3( renderLight.axis );
1328 ReadVec3( renderLight.origin );
1330 ReadInt( renderLight.suppressLightInViewID );
1331 ReadInt( renderLight.allowLightInViewID );
1332 ReadBool( renderLight.noShadows );
1333 ReadBool( renderLight.noSpecular );
1334 ReadBool( renderLight.pointLight );
1335 ReadBool( renderLight.parallel );
1337 ReadVec3( renderLight.lightRadius );
1338 ReadVec3( renderLight.lightCenter );
1340 ReadVec3( renderLight.target );
1341 ReadVec3( renderLight.right );
1342 ReadVec3( renderLight.up );
1343 ReadVec3( renderLight.start );
1344 ReadVec3( renderLight.end );
1346 // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
1347 // ReadModel( renderLight.prelightModel );
1348 renderLight.prelightModel = NULL;
1350 ReadInt( renderLight.lightId );
1352 ReadMaterial( renderLight.shader );
1354 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1355 ReadFloat( renderLight.shaderParms[ i ] );
1359 renderLight.referenceSound = gameSoundWorld->EmitterForIndex( index );
1364 idRestoreGame::ReadRefSound
1367 void idRestoreGame::ReadRefSound( refSound_t &refSound ) {
1371 refSound.referenceSound = gameSoundWorld->EmitterForIndex( index );
1372 ReadVec3( refSound.origin );
1373 ReadInt( refSound.listenerId );
1374 ReadSoundShader( refSound.shader );
1375 ReadFloat( refSound.diversity );
1376 ReadBool( refSound.waitfortrigger );
1378 ReadFloat( refSound.parms.minDistance );
1379 ReadFloat( refSound.parms.maxDistance );
1380 ReadFloat( refSound.parms.volume );
1381 ReadFloat( refSound.parms.shakes );
1382 ReadInt( refSound.parms.soundShaderFlags );
1383 ReadInt( refSound.parms.soundClass );
1388 idRestoreGame::ReadRenderView
1391 void idRestoreGame::ReadRenderView( renderView_t &view ) {
1394 ReadInt( view.viewID );
1397 ReadInt( view.width );
1398 ReadInt( view.height );
1400 ReadFloat( view.fov_x );
1401 ReadFloat( view.fov_y );
1402 ReadVec3( view.vieworg );
1403 ReadMat3( view.viewaxis );
1405 ReadBool( view.cramZNear );
1407 ReadInt( view.time );
1409 for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
1410 ReadFloat( view.shaderParms[ i ] );
1416 idRestoreGame::ReadUsercmd
1419 void idRestoreGame::ReadUsercmd( usercmd_t &usercmd ) {
1420 ReadInt( usercmd.gameFrame );
1421 ReadInt( usercmd.gameTime );
1422 ReadInt( usercmd.duplicateCount );
1423 ReadByte( usercmd.buttons );
1424 ReadSignedChar( usercmd.forwardmove );
1425 ReadSignedChar( usercmd.rightmove );
1426 ReadSignedChar( usercmd.upmove );
1427 ReadShort( usercmd.angles[0] );
1428 ReadShort( usercmd.angles[1] );
1429 ReadShort( usercmd.angles[2] );
1430 ReadShort( usercmd.mx );
1431 ReadShort( usercmd.my );
1432 ReadSignedChar( usercmd.impulse );
1433 ReadByte( usercmd.flags );
1434 ReadInt( usercmd.sequence );
1439 idRestoreGame::ReadContactInfo
1442 void idRestoreGame::ReadContactInfo( contactInfo_t &contactInfo ) {
1443 ReadInt( (int &)contactInfo.type );
1444 ReadVec3( contactInfo.point );
1445 ReadVec3( contactInfo.normal );
1446 ReadFloat( contactInfo.dist );
1447 ReadInt( contactInfo.contents );
1448 ReadMaterial( contactInfo.material );
1449 ReadInt( contactInfo.modelFeature );
1450 ReadInt( contactInfo.trmFeature );
1451 ReadInt( contactInfo.entityNum );
1452 ReadInt( contactInfo.id );
1457 idRestoreGame::ReadTrace
1460 void idRestoreGame::ReadTrace( trace_t &trace ) {
1461 ReadFloat( trace.fraction );
1462 ReadVec3( trace.endpos );
1463 ReadMat3( trace.endAxis );
1464 ReadContactInfo( trace.c );
1469 idRestoreGame::ReadTraceModel
1472 void idRestoreGame::ReadTraceModel( idTraceModel &trace ) {
1475 ReadInt( (int&)trace.type );
1476 ReadInt( trace.numVerts );
1477 for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
1478 ReadVec3( trace.verts[j] );
1480 ReadInt( trace.numEdges );
1481 for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
1482 ReadInt( trace.edges[j].v[0] );
1483 ReadInt( trace.edges[j].v[1] );
1484 ReadVec3( trace.edges[j].normal );
1486 ReadInt( trace.numPolys );
1487 for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
1488 ReadVec3( trace.polys[j].normal );
1489 ReadFloat( trace.polys[j].dist );
1490 ReadBounds( trace.polys[j].bounds );
1491 ReadInt( trace.polys[j].numEdges );
1492 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
1493 ReadInt( trace.polys[j].edges[k] );
1496 ReadVec3( trace.offset );
1497 ReadBounds( trace.bounds );
1498 ReadBool( trace.isConvex );
1499 // padding win32 native structs
1501 file->Read( tmp, 3 );
1505 =====================
1506 idRestoreGame::ReadClipModel
1507 =====================
1509 void idRestoreGame::ReadClipModel( idClipModel *&clipModel ) {
1510 bool restoreClipModel;
1512 ReadBool( restoreClipModel );
1513 if ( restoreClipModel ) {
1514 clipModel = new idClipModel();
1515 clipModel->Restore( this );
1522 =====================
1523 idRestoreGame::ReadSoundCommands
1524 =====================
1526 void idRestoreGame::ReadSoundCommands( void ) {
1527 gameSoundWorld->StopAllSounds();
1528 gameSoundWorld->ReadFromSaveGame( file );
1532 =====================
1533 idRestoreGame::ReadBuildNumber
1534 =====================
1536 void idRestoreGame::ReadBuildNumber( void ) {
1537 file->ReadInt( buildNumber );
1541 =====================
1542 idRestoreGame::GetBuildNumber
1543 =====================
1545 int idRestoreGame::GetBuildNumber( void ) {