6 e_graphics
, g_phys
, g_textures
, BinEditor
;
8 function g_GetSaveName(n
: Integer): String;
9 function g_SaveGame(n
: Integer; Name
: String): Boolean;
10 function g_LoadGame(n
: Integer): Boolean;
11 procedure Obj_SaveState(o
: PObj
; var Mem
: TBinMemoryWriter
);
12 procedure Obj_LoadState(o
: PObj
; var Mem
: TBinMemoryReader
);
17 g_game
, g_items
, g_map
, g_monsters
, g_triggers
,
18 g_basic
, g_main
, SysUtils
, Math
, WADEDITOR
,
19 MAPSTRUCT
, MAPDEF
, g_weapons
, g_player
, g_console
,
23 SAVE_SIGNATURE
= $56534644; // 'DFSV'
25 END_MARKER_STRING
= 'END';
26 PLAYER_VIEW_SIGNATURE
= $57564C50; // 'PLVW'
27 OBJ_SIGNATURE
= $4A424F5F; // '_OBJ'
29 procedure Obj_SaveState(o
: PObj
; var Mem
: TBinMemoryWriter
);
37 sig
:= OBJ_SIGNATURE
; // '_OBJ'
39 // Ïîëîæåíèå ïî-ãîðèçîíòàëè:
41 // Ïîëîæåíèå ïî-âåðòèêàëè:
43 // Îãðàíè÷èâàþùèé ïðÿìîóãîëüíèê:
44 Mem
.WriteInt(o
^.Rect
.X
);
45 Mem
.WriteInt(o
^.Rect
.Y
);
46 Mem
.WriteWord(o
^.Rect
.Width
);
47 Mem
.WriteWord(o
^.Rect
.Height
);
49 Mem
.WriteInt(o
^.Vel
.X
);
50 Mem
.WriteInt(o
^.Vel
.Y
);
51 // Ïðèáàâêà ê ñêîðîñòè:
52 Mem
.WriteInt(o
^.Accel
.X
);
53 Mem
.WriteInt(o
^.Accel
.Y
);
56 procedure Obj_LoadState(o
: PObj
; var Mem
: TBinMemoryReader
);
65 if sig
<> OBJ_SIGNATURE
then // '_OBJ'
67 raise EBinSizeError
.Create('Obj_LoadState: Wrong Object Signature');
69 // Ïîëîæåíèå ïî-ãîðèçîíòàëè:
71 // Ïîëîæåíèå ïî-âåðòèêàëè:
73 // Îãðàíè÷èâàþùèé ïðÿìîóãîëüíèê:
74 Mem
.ReadInt(o
^.Rect
.X
);
75 Mem
.ReadInt(o
^.Rect
.Y
);
76 Mem
.ReadWord(o
^.Rect
.Width
);
77 Mem
.ReadWord(o
^.Rect
.Height
);
79 Mem
.ReadInt(o
^.Vel
.X
);
80 Mem
.ReadInt(o
^.Vel
.Y
);
81 // Ïðèáàâêà ê ñêîðîñòè:
82 Mem
.ReadInt(o
^.Accel
.X
);
83 Mem
.ReadInt(o
^.Accel
.Y
);
86 function g_GetSaveName(n
: Integer): String;
88 bFile
: TBinFileReader
;
89 bMem
: TBinMemoryReader
;
98 // Îòêðûâàåì ôàéë ñîõðàíåíèé:
99 bFile
:= TBinFileReader
.Create();
100 if bFile
.OpenFile(DataDir
+ 'SAVGAME' + IntToStr(n
) + '.DAT',
101 SAVE_SIGNATURE
, SAVE_VERSION
) then
103 // ×èòàåì ïåðâûé áëîê - ñîñòîÿíèå èãðû:
104 bMem
:= TBinMemoryReader
.Create();
105 bFile
.ReadMemory(bMem
);
107 bMem
.ReadString(str
);
114 on E1
: EInOutError
do
115 e_WriteLog('GetSaveName I/O Error: '+E1
.Message, MSG_WARNING
);
116 on E2
: EBinSizeError
do
117 e_WriteLog('GetSaveName Size Error: '+E2
.Message, MSG_WARNING
);
126 function g_SaveGame(n
: Integer; Name
: String): Boolean;
128 bFile
: TBinFileWriter
;
129 bMem
: TBinMemoryWriter
;
141 // Ñîçäàåì ôàéë ñîõðàíåíèÿ:
142 bFile
:= TBinFileWriter
.Create();
143 bFile
.OpenFile(DataDir
+ 'SAVGAME' + IntToStr(n
) + '.DAT',
144 SAVE_SIGNATURE
, SAVE_VERSION
);
146 ///// Ïîëó÷àåì ñîñòîÿíèå èãðû: /////
147 bMem
:= TBinMemoryWriter
.Create(256);
149 bMem
.WriteString(Name
, 32);
151 str
:= gGameSettings
.WAD
;
152 bMem
.WriteString(str
, 128);
154 g_ProcessResourceStr(gMapInfo
.Map
, nil, nil, @str
);
155 bMem
.WriteString(str
, 32);
156 // Êîëè÷åñòâî èãðîêîâ:
157 nPlayers
:= g_Player_GetCount();
158 bMem
.WriteByte(nPlayers
);
160 bMem
.WriteDWORD(gTime
);
162 bMem
.WriteByte(gGameSettings
.GameType
);
164 bMem
.WriteByte(gGameSettings
.GameMode
);
166 bMem
.WriteWord(gGameSettings
.TimeLimit
);
168 bMem
.WriteWord(gGameSettings
.GoalLimit
);
170 bMem
.WriteByte(gGameSettings
.MaxLives
);
172 bMem
.WriteDWORD(gGameSettings
.Options
);
174 bMem
.WriteWord(gCoopMonstersKilled
);
175 bMem
.WriteWord(gCoopSecretsFound
);
176 bMem
.WriteWord(gCoopTotalMonstersKilled
);
177 bMem
.WriteWord(gCoopTotalSecretsFound
);
178 bMem
.WriteWord(gCoopTotalMonsters
);
179 bMem
.WriteWord(gCoopTotalSecrets
);
180 // Ñîõðàíÿåì ñîñòîÿíèå èãðû:
181 bFile
.WriteMemory(bMem
);
186 ///// Ñîõðàíÿåì ñîñòîÿíèå îáëàñòåé ïðîñìîòðà: /////
187 bMem
:= TBinMemoryWriter
.Create(8);
188 sig
:= PLAYER_VIEW_SIGNATURE
;
189 bMem
.WriteDWORD(sig
); // 'PLVW'
192 if gPlayer1
<> nil then
193 PID1
:= gPlayer1
.UID
;
194 if gPlayer2
<> nil then
195 PID2
:= gPlayer2
.UID
;
196 bMem
.WriteWord(PID1
);
197 bMem
.WriteWord(PID2
);
198 bFile
.WriteMemory(bMem
);
203 ///// Ïîëó÷àåì ñîñòîÿíèå êàðòû: /////
204 g_Map_SaveState(bMem
);
205 // Ñîõðàíÿåì ñîñòîÿíèå êàðòû:
206 bFile
.WriteMemory(bMem
);
211 ///// Ïîëó÷àåì ñîñòîÿíèå ïðåäìåòîâ: /////
212 g_Items_SaveState(bMem
);
213 // Ñîõðàíÿåì ñîñòîÿíèå ïðåäìåòîâ:
214 bFile
.WriteMemory(bMem
);
219 ///// Ïîëó÷àåì ñîñòîÿíèå òðèããåðîâ: /////
220 g_Triggers_SaveState(bMem
);
221 // Ñîõðàíÿåì ñîñòîÿíèå òðèããåðîâ:
222 bFile
.WriteMemory(bMem
);
227 ///// Ïîëó÷àåì ñîñòîÿíèå îðóæèÿ: /////
228 g_Weapon_SaveState(bMem
);
229 // Ñîõðàíÿåì ñîñòîÿíèå îðóæèÿ:
230 bFile
.WriteMemory(bMem
);
235 ///// Ïîëó÷àåì ñîñòîÿíèå ìîíñòðîâ: /////
236 g_Monsters_SaveState(bMem
);
237 // Ñîõðàíÿåì ñîñòîÿíèå ìîíñòðîâ:
238 bFile
.WriteMemory(bMem
);
243 ///// Ïîëó÷àåì ñîñòîÿíèå òðóïîâ: /////
244 g_Player_Corpses_SaveState(bMem
);
245 // Ñîõðàíÿåì ñîñòîÿíèå òðóïîâ:
246 bFile
.WriteMemory(bMem
);
251 ///// Ñîõðàíÿåì èãðîêîâ (â òîì ÷èñëå áîòîâ): /////
255 for i
:= 0 to High(gPlayers
) do
256 if gPlayers
[i
] <> nil then
258 // Ïîëó÷àåì ñîñòîÿíèå èãðîêà:
259 gPlayers
[i
].SaveState(bMem
);
260 // Ñîõðàíÿåì ñîñòîÿíèå èãðîêà:
261 bFile
.WriteMemory(bMem
);
267 // Âñå ëè èãðîêè íà ìåñòå:
268 if k
<> nPlayers
then
270 raise EInOutError
.Create('g_SaveGame: Wrong Players Count');
275 ///// Ìàðêåð îêîí÷àíèÿ: /////
276 bMem
:= TBinMemoryWriter
.Create(4);
277 // Ñòðîêà - îáîçíà÷åíèå êîíöà:
278 str
:= END_MARKER_STRING
; // 'END'
279 bMem
.WriteString(str
, 3);
280 // Ñîõðàíÿåì ìàðêåð îêîí÷àíèÿ:
281 bFile
.WriteMemory(bMem
);
286 // Çàêðûâàåì ôàéë ñîõðàíåíèÿ:
291 on E1
: EInOutError
do
293 g_Console_Add(_lc
[I_GAME_ERROR_SAVE
]);
294 e_WriteLog('SaveState I/O Error: '+E1
.Message, MSG_WARNING
);
296 on E2
: EBinSizeError
do
298 g_Console_Add(_lc
[I_GAME_ERROR_SAVE
]);
299 e_WriteLog('SaveState Size Error: '+E2
.Message, MSG_WARNING
);
307 function g_LoadGame(n
: Integer): Boolean;
309 bFile
: TBinFileReader
;
310 bMem
: TBinMemoryReader
;
312 str
, WAD_Path
, Map_Name
: String;
313 nPlayers
, Game_Type
, Game_Mode
, Game_MaxLives
: Byte;
314 Game_TimeLimit
, Game_GoalLimit
: Word;
315 Game_Time
, Game_Options
: Cardinal;
316 Game_CoopMonstersKilled
,
317 Game_CoopSecretsFound
,
318 Game_CoopTotalMonstersKilled
,
319 Game_CoopTotalSecretsFound
,
320 Game_CoopTotalMonsters
,
321 Game_CoopTotalSecrets
,
330 // Îòêðûâàåì ôàéë ñ ñîõðàíåíèåì:
331 bFile
:= TBinFileReader
.Create();
332 if not bFile
.OpenFile(DataDir
+ 'SAVGAME' + IntToStr(n
) + '.DAT',
333 SAVE_SIGNATURE
, SAVE_VERSION
) then
339 e_WriteLog('Loading saved game...', MSG_NOTIFY
);
342 g_Game_ClearLoading();
343 g_Game_SetLoadingText(_lc
[I_LOAD_SAVE_FILE
], 0, False);
344 gLoadGameMode
:= True;
346 ///// Çàãðóæàåì ñîñòîÿíèå èãðû: /////
347 bMem
:= TBinMemoryReader
.Create();
348 bFile
.ReadMemory(bMem
);
350 bMem
.ReadString(str
);
352 bMem
.ReadString(WAD_Path
);
354 bMem
.ReadString(Map_Name
);
355 // Êîëè÷åñòâî èãðîêîâ:
356 bMem
.ReadByte(nPlayers
);
358 bMem
.ReadDWORD(Game_Time
);
360 bMem
.ReadByte(Game_Type
);
362 bMem
.ReadByte(Game_Mode
);
364 bMem
.ReadWord(Game_TimeLimit
);
366 bMem
.ReadWord(Game_GoalLimit
);
368 bMem
.ReadByte(Game_MaxLives
);
370 bMem
.ReadDWORD(Game_Options
);
372 bMem
.ReadWord(Game_CoopMonstersKilled
);
373 bMem
.ReadWord(Game_CoopSecretsFound
);
374 bMem
.ReadWord(Game_CoopTotalMonstersKilled
);
375 bMem
.ReadWord(Game_CoopTotalSecretsFound
);
376 bMem
.ReadWord(Game_CoopTotalMonsters
);
377 bMem
.ReadWord(Game_CoopTotalSecrets
);
378 // Cîñòîÿíèå èãðû çàãðóæåíî:
383 ///// Çàãðóæàåì ñîñòîÿíèå îáëàñòåé ïðîñìîòðà: /////
384 bMem
:= TBinMemoryReader
.Create();
385 bFile
.ReadMemory(bMem
);
387 if sig
<> PLAYER_VIEW_SIGNATURE
then // 'PLVW'
389 raise EInOutError
.Create('g_LoadGame: Wrong Player View Signature');
398 ZeroMemory(@gGameSettings
, SizeOf(TGameSettings
));
401 if (Game_Type
= GT_NONE
) or (Game_Type
= GT_SINGLE
) then
404 gGameSettings
.GameType
:= GT_SINGLE
;
405 gGameSettings
.MaxLives
:= 0;
406 gGameSettings
.Options
:= gGameSettings
.Options
+ GAME_OPTION_ALLOWEXIT
;
407 gGameSettings
.Options
:= gGameSettings
.Options
+ GAME_OPTION_MONSTERS
;
408 gGameSettings
.Options
:= gGameSettings
.Options
+ GAME_OPTION_BOTVSMONSTER
;
409 gSwitchGameMode
:= GM_SINGLE
;
414 gGameSettings
.GameType
:= GT_CUSTOM
;
415 gGameSettings
.GameMode
:= Game_Mode
;
416 gSwitchGameMode
:= Game_Mode
;
417 gGameSettings
.TimeLimit
:= Game_TimeLimit
;
418 gGameSettings
.GoalLimit
:= Game_GoalLimit
;
419 gGameSettings
.MaxLives
:= IfThen(Game_Mode
= GM_CTF
, 0, Game_MaxLives
);
420 gGameSettings
.Options
:= Game_Options
;
422 g_Game_ExecuteEvent('ongamestart');
424 // Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ:
425 g_Game_SetupScreenSize();
427 // Çàãðóçêà è çàïóñê êàðòû:
428 if not g_Game_StartMap(WAD_Path
+ ':\' + Map_Name
, True) then
430 g_FatalError(Format(_lc
[I_GAME_ERROR_MAP_LOAD
], [WAD_Path
+ ':\' + Map_Name
]));
434 // Íàñòðîéêè èãðîêîâ è áîòîâ:
437 // Óñòàíàâëèâàåì âðåìÿ:
440 gCoopMonstersKilled
:= Game_CoopMonstersKilled
;
441 gCoopSecretsFound
:= Game_CoopSecretsFound
;
442 gCoopTotalMonstersKilled
:= Game_CoopTotalMonstersKilled
;
443 gCoopTotalSecretsFound
:= Game_CoopTotalSecretsFound
;
444 gCoopTotalMonsters
:= Game_CoopTotalMonsters
;
445 gCoopTotalSecrets
:= Game_CoopTotalSecrets
;
447 ///// Çàãðóæàåì ñîñòîÿíèå êàðòû: /////
448 bMem
:= TBinMemoryReader
.Create();
449 bFile
.ReadMemory(bMem
);
451 g_Map_LoadState(bMem
);
456 ///// Çàãðóæàåì ñîñòîÿíèå ïðåäìåòîâ: /////
457 bMem
:= TBinMemoryReader
.Create();
458 bFile
.ReadMemory(bMem
);
459 // Ñîñòîÿíèå ïðåäìåòîâ:
460 g_Items_LoadState(bMem
);
465 ///// Çàãðóæàåì ñîñòîÿíèå òðèããåðîâ: /////
466 bMem
:= TBinMemoryReader
.Create();
467 bFile
.ReadMemory(bMem
);
468 // Ñîñòîÿíèå òðèããåðîâ:
469 g_Triggers_LoadState(bMem
);
474 ///// Çàãðóæàåì ñîñòîÿíèå îðóæèÿ: /////
475 bMem
:= TBinMemoryReader
.Create();
476 bFile
.ReadMemory(bMem
);
478 g_Weapon_LoadState(bMem
);
483 ///// Çàãðóæàåì ñîñòîÿíèå ìîíñòðîâ: /////
484 bMem
:= TBinMemoryReader
.Create();
485 bFile
.ReadMemory(bMem
);
486 // Ñîñòîÿíèå ìîíñòðîâ:
487 g_Monsters_LoadState(bMem
);
492 ///// Çàãðóæàåì ñîñòîÿíèå òðóïîâ: /////
493 bMem
:= TBinMemoryReader
.Create();
494 bFile
.ReadMemory(bMem
);
496 g_Player_Corpses_LoadState(bMem
);
501 ///// Çàãðóæàåì èãðîêîâ (â òîì ÷èñëå áîòîâ): /////
505 for i
:= 0 to nPlayers
-1 do
507 // Çàãðóæàåì ñîñòîÿíèå èãðîêà:
508 bMem
:= TBinMemoryReader
.Create();
509 bFile
.ReadMemory(bMem
);
510 // Ñîñòîÿíèå èãðîêà/áîòà:
511 g_Player_CreateFromState(bMem
);
516 // Ïðèâÿçûâàåì îñíîâíûõ èãðîêîâ ê îáëàñòÿì ïðîñìîòðà:
517 gPlayer1
:= g_Player_Get(PID1
);
518 gPlayer2
:= g_Player_Get(PID2
);
519 if gPlayer1
<> nil then
521 gPlayer1
.Name
:= gPlayer1Settings
.Name
;
522 gPlayer1
.FPreferredTeam
:= gPlayer1Settings
.Team
;
523 gPlayer1
.FActualModelName
:= gPlayer1Settings
.Model
;
524 gPlayer1
.SetModel(gPlayer1
.FActualModelName
);
525 gPlayer1
.SetColor(gPlayer1Settings
.Color
);
527 if gPlayer2
<> nil then
529 gPlayer2
.Name
:= gPlayer2Settings
.Name
;
530 gPlayer2
.FPreferredTeam
:= gPlayer2Settings
.Team
;
531 gPlayer2
.FActualModelName
:= gPlayer2Settings
.Model
;
532 gPlayer2
.SetModel(gPlayer2
.FActualModelName
);
533 gPlayer2
.SetColor(gPlayer2Settings
.Color
);
537 ///// Ìàðêåð îêîí÷àíèÿ: /////
538 bMem
:= TBinMemoryReader
.Create();
539 bFile
.ReadMemory(bMem
);
540 // Ñòðîêà - îáîçíà÷åíèå êîíöà:
541 bMem
.ReadString(str
);
542 if str
<> END_MARKER_STRING
then // 'END'
544 raise EInOutError
.Create('g_LoadGame: No END Marker');
546 // Ìàðêåð îêîí÷àíèÿ çàãðóæåí:
551 // Èùåì òðèããåðû ñ óñëîâèåì ñìåðòè ìîíñòðîâ:
552 if (gMonsters
<> nil) and (gTriggers
<> nil) then
553 g_Map_ReAdd_DieTriggers();
555 // Çàêðûâàåì ôàéë çàãðóçêè:
557 gLoadGameMode
:= False;
561 on E1
: EInOutError
do
563 g_Console_Add(_lc
[I_GAME_ERROR_LOAD
]);
564 e_WriteLog('LoadState I/O Error: '+E1
.Message, MSG_WARNING
);
566 on E2
: EBinSizeError
do
568 g_Console_Add(_lc
[I_GAME_ERROR_LOAD
]);
569 e_WriteLog('LoadState Size Error: '+E2
.Message, MSG_WARNING
);