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 );
545 WriteInt( renderEntity.timeGroup );
546 WriteInt( renderEntity.xrayIndex );
552 idSaveGame::WriteRenderLight
555 void idSaveGame::WriteRenderLight( const renderLight_t &renderLight ) {
558 WriteMat3( renderLight.axis );
559 WriteVec3( renderLight.origin );
561 WriteInt( renderLight.suppressLightInViewID );
562 WriteInt( renderLight.allowLightInViewID );
563 WriteBool( renderLight.noShadows );
564 WriteBool( renderLight.noSpecular );
565 WriteBool( renderLight.pointLight );
566 WriteBool( renderLight.parallel );
568 WriteVec3( renderLight.lightRadius );
569 WriteVec3( renderLight.lightCenter );
571 WriteVec3( renderLight.target );
572 WriteVec3( renderLight.right );
573 WriteVec3( renderLight.up );
574 WriteVec3( renderLight.start );
575 WriteVec3( renderLight.end );
577 // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
578 // WriteModel( renderLight.prelightModel );
580 WriteInt( renderLight.lightId );
582 WriteMaterial( renderLight.shader );
584 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
585 WriteFloat( renderLight.shaderParms[ i ] );
588 if ( renderLight.referenceSound != NULL ) {
589 WriteInt( renderLight.referenceSound->Index() );
597 idSaveGame::WriteRefSound
600 void idSaveGame::WriteRefSound( const refSound_t &refSound ) {
601 if ( refSound.referenceSound ) {
602 WriteInt( refSound.referenceSound->Index() );
606 WriteVec3( refSound.origin );
607 WriteInt( refSound.listenerId );
608 WriteSoundShader( refSound.shader );
609 WriteFloat( refSound.diversity );
610 WriteBool( refSound.waitfortrigger );
612 WriteFloat( refSound.parms.minDistance );
613 WriteFloat( refSound.parms.maxDistance );
614 WriteFloat( refSound.parms.volume );
615 WriteFloat( refSound.parms.shakes );
616 WriteInt( refSound.parms.soundShaderFlags );
617 WriteInt( refSound.parms.soundClass );
622 idSaveGame::WriteRenderView
625 void idSaveGame::WriteRenderView( const renderView_t &view ) {
628 WriteInt( view.viewID );
631 WriteInt( view.width );
632 WriteInt( view.height );
634 WriteFloat( view.fov_x );
635 WriteFloat( view.fov_y );
636 WriteVec3( view.vieworg );
637 WriteMat3( view.viewaxis );
639 WriteBool( view.cramZNear );
641 WriteInt( view.time );
643 for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
644 WriteFloat( view.shaderParms[ i ] );
650 idSaveGame::WriteUsercmd
653 void idSaveGame::WriteUsercmd( const usercmd_t &usercmd ) {
654 WriteInt( usercmd.gameFrame );
655 WriteInt( usercmd.gameTime );
656 WriteInt( usercmd.duplicateCount );
657 WriteByte( usercmd.buttons );
658 WriteSignedChar( usercmd.forwardmove );
659 WriteSignedChar( usercmd.rightmove );
660 WriteSignedChar( usercmd.upmove );
661 WriteShort( usercmd.angles[0] );
662 WriteShort( usercmd.angles[1] );
663 WriteShort( usercmd.angles[2] );
664 WriteShort( usercmd.mx );
665 WriteShort( usercmd.my );
666 WriteSignedChar( usercmd.impulse );
667 WriteByte( usercmd.flags );
668 WriteInt( usercmd.sequence );
673 idSaveGame::WriteContactInfo
676 void idSaveGame::WriteContactInfo( const contactInfo_t &contactInfo ) {
677 WriteInt( (int)contactInfo.type );
678 WriteVec3( contactInfo.point );
679 WriteVec3( contactInfo.normal );
680 WriteFloat( contactInfo.dist );
681 WriteInt( contactInfo.contents );
682 WriteMaterial( contactInfo.material );
683 WriteInt( contactInfo.modelFeature );
684 WriteInt( contactInfo.trmFeature );
685 WriteInt( contactInfo.entityNum );
686 WriteInt( contactInfo.id );
691 idSaveGame::WriteTrace
694 void idSaveGame::WriteTrace( const trace_t &trace ) {
695 WriteFloat( trace.fraction );
696 WriteVec3( trace.endpos );
697 WriteMat3( trace.endAxis );
698 WriteContactInfo( trace.c );
703 idRestoreGame::WriteTraceModel
706 void idSaveGame::WriteTraceModel( const idTraceModel &trace ) {
709 WriteInt( (int&)trace.type );
710 WriteInt( trace.numVerts );
711 for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
712 WriteVec3( trace.verts[j] );
714 WriteInt( trace.numEdges );
715 for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
716 WriteInt( trace.edges[j].v[0] );
717 WriteInt( trace.edges[j].v[1] );
718 WriteVec3( trace.edges[j].normal );
720 WriteInt( trace.numPolys );
721 for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
722 WriteVec3( trace.polys[j].normal );
723 WriteFloat( trace.polys[j].dist );
724 WriteBounds( trace.polys[j].bounds );
725 WriteInt( trace.polys[j].numEdges );
726 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
727 WriteInt( trace.polys[j].edges[k] );
730 WriteVec3( trace.offset );
731 WriteBounds( trace.bounds );
732 WriteBool( trace.isConvex );
733 // padding win32 native structs
735 memset( tmp, 0, sizeof( tmp ) );
736 file->Write( tmp, 3 );
741 idSaveGame::WriteClipModel
744 void idSaveGame::WriteClipModel( const idClipModel *clipModel ) {
745 if ( clipModel != NULL ) {
747 clipModel->Save( this );
755 idSaveGame::WriteSoundCommands
758 void idSaveGame::WriteSoundCommands( void ) {
759 gameSoundWorld->WriteToSaveGame( file );
763 ======================
764 idSaveGame::WriteBuildNumber
765 ======================
767 void idSaveGame::WriteBuildNumber( const int value ) {
768 file->WriteInt( BUILD_NUMBER );
771 /***********************************************************************
775 ***********************************************************************/
779 idRestoreGame::RestoreGame
782 idRestoreGame::idRestoreGame( idFile *savefile ) {
788 idRestoreGame::~idRestoreGame()
791 idRestoreGame::~idRestoreGame() {
796 void idRestoreGame::CreateObjects
799 void idRestoreGame::CreateObjects( void ) {
806 // create all the objects
807 objects.SetNum( num + 1 );
808 memset( objects.Ptr(), 0, sizeof( objects[ 0 ] ) * objects.Num() );
810 for( i = 1; i < objects.Num(); i++ ) {
811 ReadString( classname );
812 type = idClass::GetClass( classname );
814 Error( "idRestoreGame::CreateObjects: Unknown class '%s'", classname.c_str() );
816 objects[ i ] = type->CreateInstance();
818 #ifdef ID_DEBUG_MEMORY
819 InitTypeVariables( objects[i], type->classname, 0xce );
826 void idRestoreGame::RestoreObjects
829 void idRestoreGame::RestoreObjects( void ) {
835 idClipModel::RestoreTraceModels( this );
837 // restore all the objects
838 for( i = 1; i < objects.Num(); i++ ) {
839 CallRestore_r( objects[ i ]->GetType(), objects[ i ] );
842 // regenerate render entities and render lights because are not saved
843 for( i = 1; i < objects.Num(); i++ ) {
844 if ( objects[ i ]->IsType( idEntity::Type ) ) {
845 idEntity *ent = static_cast<idEntity *>( objects[ i ] );
846 ent->UpdateVisuals();
851 #ifdef ID_DEBUG_MEMORY
852 idStr gameState = file->GetName();
853 gameState.StripFileExtension();
854 WriteGameState_f( idCmdArgs( va( "test %s_restore", gameState.c_str() ), false ) );
855 //CompareGameState_f( idCmdArgs( va( "test %s_save", gameState.c_str() ) ) );
856 gameLocal.Error( "dumped game states" );
862 void idRestoreGame::DeleteObjects
865 void idRestoreGame::DeleteObjects( void ) {
867 // Remove the NULL object before deleting
868 objects.RemoveIndex( 0 );
870 objects.DeleteContents( true );
878 void idRestoreGame::Error( const char *fmt, ... ) {
882 va_start( argptr, fmt );
883 vsprintf( text, fmt, argptr );
886 objects.DeleteContents( true );
888 gameLocal.Error( "%s", text );
893 idRestoreGame::CallRestore_r
896 void idRestoreGame::CallRestore_r( const idTypeInfo *cls, idClass *obj ) {
898 CallRestore_r( cls->super, obj );
899 if ( cls->super->Restore == cls->Restore ) {
900 // don't call save on this inheritance level since the function was called in the super class
905 ( obj->*cls->Restore )( this );
913 void idRestoreGame::Read( void *buffer, int len ) {
914 file->Read( buffer, len );
919 idRestoreGame::ReadInt
922 void idRestoreGame::ReadInt( int &value ) {
923 file->ReadInt( value );
928 idRestoreGame::ReadJoint
931 void idRestoreGame::ReadJoint( jointHandle_t &value ) {
932 file->ReadInt( (int&)value );
937 idRestoreGame::ReadShort
940 void idRestoreGame::ReadShort( short &value ) {
941 file->ReadShort( value );
946 idRestoreGame::ReadByte
949 void idRestoreGame::ReadByte( byte &value ) {
950 file->Read( &value, sizeof( value ) );
955 idRestoreGame::ReadSignedChar
958 void idRestoreGame::ReadSignedChar( signed char &value ) {
959 file->Read( &value, sizeof( value ) );
964 idRestoreGame::ReadFloat
967 void idRestoreGame::ReadFloat( float &value ) {
968 file->ReadFloat( value );
973 idRestoreGame::ReadBool
976 void idRestoreGame::ReadBool( bool &value ) {
977 file->ReadBool( value );
982 idRestoreGame::ReadString
985 void idRestoreGame::ReadString( idStr &string ) {
990 Error( "idRestoreGame::ReadString: invalid length" );
993 string.Fill( ' ', len );
994 file->Read( &string[ 0 ], len );
999 idRestoreGame::ReadVec2
1002 void idRestoreGame::ReadVec2( idVec2 &vec ) {
1003 file->ReadVec2( vec );
1008 idRestoreGame::ReadVec3
1011 void idRestoreGame::ReadVec3( idVec3 &vec ) {
1012 file->ReadVec3( vec );
1017 idRestoreGame::ReadVec4
1020 void idRestoreGame::ReadVec4( idVec4 &vec ) {
1021 file->ReadVec4( vec );
1026 idRestoreGame::ReadVec6
1029 void idRestoreGame::ReadVec6( idVec6 &vec ) {
1030 file->ReadVec6( vec );
1035 idRestoreGame::ReadBounds
1038 void idRestoreGame::ReadBounds( idBounds &bounds ) {
1039 file->Read( &bounds, sizeof( bounds ) );
1040 LittleRevBytes( &bounds, sizeof(float), sizeof(bounds)/sizeof(float) );
1045 idRestoreGame::ReadWinding
1048 void idRestoreGame::ReadWinding( idWinding &w )
1051 file->ReadInt( num );
1052 w.SetNumPoints( num );
1053 for ( i = 0; i < num; i++ ) {
1054 file->Read( &w[i], sizeof(idVec5) );
1055 LittleRevBytes(&w[i], sizeof(float), sizeof(idVec5)/sizeof(float) );
1061 idRestoreGame::ReadMat3
1064 void idRestoreGame::ReadMat3( idMat3 &mat ) {
1065 file->ReadMat3( mat );
1070 idRestoreGame::ReadAngles
1073 void idRestoreGame::ReadAngles( idAngles &angles ) {
1074 file->Read( &angles, sizeof( angles ) );
1075 LittleRevBytes(&angles, sizeof(float), sizeof(idAngles)/sizeof(float) );
1080 idRestoreGame::ReadObject
1083 void idRestoreGame::ReadObject( idClass *&obj ) {
1087 if ( ( index < 0 ) || ( index >= objects.Num() ) ) {
1088 Error( "idRestoreGame::ReadObject: invalid object index" );
1090 obj = objects[ index ];
1095 idRestoreGame::ReadStaticObject
1098 void idRestoreGame::ReadStaticObject( idClass &obj ) {
1099 CallRestore_r( obj.GetType(), &obj );
1104 idRestoreGame::ReadDict
1107 void idRestoreGame::ReadDict( idDict *dict ) {
1119 for( i = 0; i < num; i++ ) {
1121 ReadString( value );
1122 dict->Set( key, value );
1129 idRestoreGame::ReadMaterial
1132 void idRestoreGame::ReadMaterial( const idMaterial *&material ) {
1136 if ( !name.Length() ) {
1139 material = declManager->FindMaterial( name );
1145 idRestoreGame::ReadSkin
1148 void idRestoreGame::ReadSkin( const idDeclSkin *&skin ) {
1152 if ( !name.Length() ) {
1155 skin = declManager->FindSkin( name );
1161 idRestoreGame::ReadParticle
1164 void idRestoreGame::ReadParticle( const idDeclParticle *&particle ) {
1168 if ( !name.Length() ) {
1171 particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, name ) );
1177 idRestoreGame::ReadFX
1180 void idRestoreGame::ReadFX( const idDeclFX *&fx ) {
1184 if ( !name.Length() ) {
1187 fx = static_cast<const idDeclFX *>( declManager->FindType( DECL_FX, name ) );
1193 idRestoreGame::ReadSoundShader
1196 void idRestoreGame::ReadSoundShader( const idSoundShader *&shader ) {
1200 if ( !name.Length() ) {
1203 shader = declManager->FindSound( name );
1209 idRestoreGame::ReadModelDef
1212 void idRestoreGame::ReadModelDef( const idDeclModelDef *&modelDef ) {
1216 if ( !name.Length() ) {
1219 modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name, false ) );
1225 idRestoreGame::ReadModel
1228 void idRestoreGame::ReadModel( idRenderModel *&model ) {
1232 if ( !name.Length() ) {
1235 model = renderModelManager->FindModel( name );
1241 idRestoreGame::ReadUserInterface
1244 void idRestoreGame::ReadUserInterface( idUserInterface *&ui ) {
1248 if ( !name.Length() ) {
1253 ui = uiManager->FindGui( name, true, unique );
1255 if ( ui->ReadFromSaveGame( file ) == false ) {
1256 Error( "idSaveGame::ReadUserInterface: ui failed to read properly\n" );
1258 ui->StateChanged( gameLocal.time );
1266 idRestoreGame::ReadRenderEntity
1269 void idRestoreGame::ReadRenderEntity( renderEntity_t &renderEntity ) {
1273 ReadModel( renderEntity.hModel );
1275 ReadInt( renderEntity.entityNum );
1276 ReadInt( renderEntity.bodyId );
1278 ReadBounds( renderEntity.bounds );
1280 // callback is set by class's Restore function
1281 renderEntity.callback = NULL;
1282 renderEntity.callbackData = NULL;
1284 ReadInt( renderEntity.suppressSurfaceInViewID );
1285 ReadInt( renderEntity.suppressShadowInViewID );
1286 ReadInt( renderEntity.suppressShadowInLightID );
1287 ReadInt( renderEntity.allowSurfaceInViewID );
1289 ReadVec3( renderEntity.origin );
1290 ReadMat3( renderEntity.axis );
1292 ReadMaterial( renderEntity.customShader );
1293 ReadMaterial( renderEntity.referenceShader );
1294 ReadSkin( renderEntity.customSkin );
1297 renderEntity.referenceSound = gameSoundWorld->EmitterForIndex( index );
1299 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1300 ReadFloat( renderEntity.shaderParms[ i ] );
1303 for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
1304 ReadUserInterface( renderEntity.gui[ i ] );
1307 // idEntity will restore "cameraTarget", which will be used in idEntity::Present to restore the remoteRenderView
1308 renderEntity.remoteRenderView = NULL;
1310 renderEntity.joints = NULL;
1311 renderEntity.numJoints = 0;
1313 ReadFloat( renderEntity.modelDepthHack );
1315 ReadBool( renderEntity.noSelfShadow );
1316 ReadBool( renderEntity.noShadow );
1317 ReadBool( renderEntity.noDynamicInteractions );
1318 ReadBool( renderEntity.weaponDepthHack );
1320 ReadInt( renderEntity.forceUpdate );
1323 ReadInt( renderEntity.timeGroup );
1324 ReadInt( renderEntity.xrayIndex );
1330 idRestoreGame::ReadRenderLight
1333 void idRestoreGame::ReadRenderLight( renderLight_t &renderLight ) {
1337 ReadMat3( renderLight.axis );
1338 ReadVec3( renderLight.origin );
1340 ReadInt( renderLight.suppressLightInViewID );
1341 ReadInt( renderLight.allowLightInViewID );
1342 ReadBool( renderLight.noShadows );
1343 ReadBool( renderLight.noSpecular );
1344 ReadBool( renderLight.pointLight );
1345 ReadBool( renderLight.parallel );
1347 ReadVec3( renderLight.lightRadius );
1348 ReadVec3( renderLight.lightCenter );
1350 ReadVec3( renderLight.target );
1351 ReadVec3( renderLight.right );
1352 ReadVec3( renderLight.up );
1353 ReadVec3( renderLight.start );
1354 ReadVec3( renderLight.end );
1356 // only idLight has a prelightModel and it's always based on the entityname, so we'll restore it there
1357 // ReadModel( renderLight.prelightModel );
1358 renderLight.prelightModel = NULL;
1360 ReadInt( renderLight.lightId );
1362 ReadMaterial( renderLight.shader );
1364 for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
1365 ReadFloat( renderLight.shaderParms[ i ] );
1369 renderLight.referenceSound = gameSoundWorld->EmitterForIndex( index );
1374 idRestoreGame::ReadRefSound
1377 void idRestoreGame::ReadRefSound( refSound_t &refSound ) {
1381 refSound.referenceSound = gameSoundWorld->EmitterForIndex( index );
1382 ReadVec3( refSound.origin );
1383 ReadInt( refSound.listenerId );
1384 ReadSoundShader( refSound.shader );
1385 ReadFloat( refSound.diversity );
1386 ReadBool( refSound.waitfortrigger );
1388 ReadFloat( refSound.parms.minDistance );
1389 ReadFloat( refSound.parms.maxDistance );
1390 ReadFloat( refSound.parms.volume );
1391 ReadFloat( refSound.parms.shakes );
1392 ReadInt( refSound.parms.soundShaderFlags );
1393 ReadInt( refSound.parms.soundClass );
1398 idRestoreGame::ReadRenderView
1401 void idRestoreGame::ReadRenderView( renderView_t &view ) {
1404 ReadInt( view.viewID );
1407 ReadInt( view.width );
1408 ReadInt( view.height );
1410 ReadFloat( view.fov_x );
1411 ReadFloat( view.fov_y );
1412 ReadVec3( view.vieworg );
1413 ReadMat3( view.viewaxis );
1415 ReadBool( view.cramZNear );
1417 ReadInt( view.time );
1419 for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
1420 ReadFloat( view.shaderParms[ i ] );
1426 idRestoreGame::ReadUsercmd
1429 void idRestoreGame::ReadUsercmd( usercmd_t &usercmd ) {
1430 ReadInt( usercmd.gameFrame );
1431 ReadInt( usercmd.gameTime );
1432 ReadInt( usercmd.duplicateCount );
1433 ReadByte( usercmd.buttons );
1434 ReadSignedChar( usercmd.forwardmove );
1435 ReadSignedChar( usercmd.rightmove );
1436 ReadSignedChar( usercmd.upmove );
1437 ReadShort( usercmd.angles[0] );
1438 ReadShort( usercmd.angles[1] );
1439 ReadShort( usercmd.angles[2] );
1440 ReadShort( usercmd.mx );
1441 ReadShort( usercmd.my );
1442 ReadSignedChar( usercmd.impulse );
1443 ReadByte( usercmd.flags );
1444 ReadInt( usercmd.sequence );
1449 idRestoreGame::ReadContactInfo
1452 void idRestoreGame::ReadContactInfo( contactInfo_t &contactInfo ) {
1453 ReadInt( (int &)contactInfo.type );
1454 ReadVec3( contactInfo.point );
1455 ReadVec3( contactInfo.normal );
1456 ReadFloat( contactInfo.dist );
1457 ReadInt( contactInfo.contents );
1458 ReadMaterial( contactInfo.material );
1459 ReadInt( contactInfo.modelFeature );
1460 ReadInt( contactInfo.trmFeature );
1461 ReadInt( contactInfo.entityNum );
1462 ReadInt( contactInfo.id );
1467 idRestoreGame::ReadTrace
1470 void idRestoreGame::ReadTrace( trace_t &trace ) {
1471 ReadFloat( trace.fraction );
1472 ReadVec3( trace.endpos );
1473 ReadMat3( trace.endAxis );
1474 ReadContactInfo( trace.c );
1479 idRestoreGame::ReadTraceModel
1482 void idRestoreGame::ReadTraceModel( idTraceModel &trace ) {
1485 ReadInt( (int&)trace.type );
1486 ReadInt( trace.numVerts );
1487 for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
1488 ReadVec3( trace.verts[j] );
1490 ReadInt( trace.numEdges );
1491 for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
1492 ReadInt( trace.edges[j].v[0] );
1493 ReadInt( trace.edges[j].v[1] );
1494 ReadVec3( trace.edges[j].normal );
1496 ReadInt( trace.numPolys );
1497 for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
1498 ReadVec3( trace.polys[j].normal );
1499 ReadFloat( trace.polys[j].dist );
1500 ReadBounds( trace.polys[j].bounds );
1501 ReadInt( trace.polys[j].numEdges );
1502 for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
1503 ReadInt( trace.polys[j].edges[k] );
1506 ReadVec3( trace.offset );
1507 ReadBounds( trace.bounds );
1508 ReadBool( trace.isConvex );
1509 // padding win32 native structs
1511 file->Read( tmp, 3 );
1515 =====================
1516 idRestoreGame::ReadClipModel
1517 =====================
1519 void idRestoreGame::ReadClipModel( idClipModel *&clipModel ) {
1520 bool restoreClipModel;
1522 ReadBool( restoreClipModel );
1523 if ( restoreClipModel ) {
1524 clipModel = new idClipModel();
1525 clipModel->Restore( this );
1532 =====================
1533 idRestoreGame::ReadSoundCommands
1534 =====================
1536 void idRestoreGame::ReadSoundCommands( void ) {
1537 gameSoundWorld->StopAllSounds();
1538 gameSoundWorld->ReadFromSaveGame( file );
1542 =====================
1543 idRestoreGame::ReadBuildNumber
1544 =====================
1546 void idRestoreGame::ReadBuildNumber( void ) {
1547 file->ReadInt( buildNumber );
1551 =====================
1552 idRestoreGame::GetBuildNumber
1553 =====================
1555 int idRestoreGame::GetBuildNumber( void ) {