DEADSOFTWARE

warnings for -O3
[d2df-sdl.git] / src / game / g_map.pas
1 unit g_map;
3 interface
5 uses
6 e_graphics, g_basic, MAPSTRUCT, g_textures, Classes,
7 g_phys, WADEDITOR, BinEditor, g_panel, md5;
9 type
10 TMapInfo = record
11 Map: String;
12 Name: String;
13 Description: String;
14 Author: String;
15 MusicName: String;
16 SkyName: String;
17 Height: Word;
18 Width: Word;
19 end;
21 PRespawnPoint = ^TRespawnPoint;
22 TRespawnPoint = record
23 X, Y: Integer;
24 Direction: TDirection;
25 PointType: Byte;
26 end;
28 PFlagPoint = ^TFlagPoint;
29 TFlagPoint = TRespawnPoint;
31 PFlag = ^TFlag;
32 TFlag = record
33 Obj: TObj;
34 RespawnType: Byte;
35 State: Byte;
36 Count: Integer;
37 CaptureTime: LongWord;
38 Animation: TAnimation;
39 Direction: TDirection;
40 end;
43 function g_Map_Load(Res: String): Boolean;
44 function g_Map_GetMapInfo(Res: String): TMapInfo;
45 function g_Map_GetMapsList(WADName: String): SArray;
46 function g_Map_Exist(Res: String): Boolean;
47 procedure g_Map_Free();
48 procedure g_Map_Update();
49 procedure g_Map_DrawPanels(PanelType: Word);
50 procedure g_Map_DrawBack(dx, dy: Integer);
51 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word;
52 PanelType: Word; b1x3: Boolean): Boolean;
53 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
54 procedure g_Map_EnableWall(ID: DWORD);
55 procedure g_Map_DisableWall(ID: DWORD);
56 procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0);
57 procedure g_Map_SetLift(ID: DWORD; t: Integer);
58 procedure g_Map_ReAdd_DieTriggers();
59 function g_Map_IsSpecialTexture(Texture: String): Boolean;
61 function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean;
62 function g_Map_GetPointCount(PointType: Byte): Word;
64 function g_Map_HaveFlagPoints(): Boolean;
66 procedure g_Map_ResetFlag(Flag: Byte);
67 procedure g_Map_DrawFlags();
69 procedure g_Map_SaveState(Var Mem: TBinMemoryWriter);
70 procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
72 const
73 RESPAWNPOINT_PLAYER1 = 1;
74 RESPAWNPOINT_PLAYER2 = 2;
75 RESPAWNPOINT_DM = 3;
76 RESPAWNPOINT_RED = 4;
77 RESPAWNPOINT_BLUE = 5;
79 FLAG_NONE = 0;
80 FLAG_RED = 1;
81 FLAG_BLUE = 2;
82 FLAG_DOM = 3;
84 FLAG_STATE_NONE = 0;
85 FLAG_STATE_NORMAL = 1;
86 FLAG_STATE_DROPPED = 2;
87 FLAG_STATE_CAPTURED = 3;
88 FLAG_STATE_SCORED = 4; // Äëÿ ýâåíòîâ ÷åðåç ñåòêó.
89 FLAG_STATE_RETURNED = 5; // Äëÿ ýâåíòîâ ÷åðåç ñåòêó.
91 FLAG_TIME = 720; // 20 seconds
93 SKY_STRETCH: Single = 1.5;
95 var
96 gWalls: TPanelArray;
97 gRenderBackgrounds: TPanelArray;
98 gRenderForegrounds: TPanelArray;
99 gWater, gAcid1, gAcid2: TPanelArray;
100 gSteps: TPanelArray;
101 gLifts: TPanelArray;
102 gBlockMon: TPanelArray;
103 gFlags: array [FLAG_RED..FLAG_BLUE] of TFlag;
104 //gDOMFlags: array of TFlag;
105 gMapInfo: TMapInfo;
106 gBackSize: TPoint;
107 gDoorMap: array of array of DWORD;
108 gLiftMap: array of array of DWORD;
109 gWADHash: TMD5Digest;
110 BackID: DWORD = DWORD(-1);
111 gExternalResources: TStringList;
113 implementation
115 uses
116 g_main, e_log, SysUtils, g_items, g_gfx, g_console,
117 GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG,
118 g_options, MAPREADER, g_triggers, g_player, MAPDEF,
119 Math, g_monsters, g_saveload, g_language, g_netmsg;
121 const
122 FLAGRECT: TRectWH = (X:15; Y:12; Width:33; Height:52);
123 MUSIC_SIGNATURE = $4953554D; // 'MUSI'
124 FLAG_SIGNATURE = $47414C46; // 'FLAG'
126 var
127 Textures: TLevelTextureArray;
128 RespawnPoints: Array of TRespawnPoint;
129 FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint;
130 //DOMFlagPoints: Array of TFlagPoint;
133 function g_Map_IsSpecialTexture(Texture: String): Boolean;
134 begin
135 Result := (Texture = TEXTURE_NAME_WATER) or
136 (Texture = TEXTURE_NAME_ACID1) or
137 (Texture = TEXTURE_NAME_ACID2);
138 end;
140 procedure CreateDoorMap();
141 var
142 PanelArray: Array of record
143 X, Y: Integer;
144 Width, Height: Word;
145 Active: Boolean;
146 PanelID: DWORD;
147 end;
148 a, b, c, m, i, len: Integer;
149 ok: Boolean;
150 begin
151 if gWalls = nil then
152 Exit;
154 i := 0;
155 len := 128;
156 SetLength(PanelArray, len);
158 for a := 0 to High(gWalls) do
159 if gWalls[a].Door then
160 begin
161 PanelArray[i].X := gWalls[a].X;
162 PanelArray[i].Y := gWalls[a].Y;
163 PanelArray[i].Width := gWalls[a].Width;
164 PanelArray[i].Height := gWalls[a].Height;
165 PanelArray[i].Active := True;
166 PanelArray[i].PanelID := a;
168 i := i + 1;
169 if i = len then
170 begin
171 len := len + 128;
172 SetLength(PanelArray, len);
173 end;
174 end;
176 // Íåò äâåðåé:
177 if i = 0 then
178 begin
179 PanelArray := nil;
180 Exit;
181 end;
183 SetLength(gDoorMap, 0);
185 g_Game_SetLoadingText(_lc[I_LOAD_DOOR_MAP], i-1, False);
187 for a := 0 to i-1 do
188 if PanelArray[a].Active then
189 begin
190 PanelArray[a].Active := False;
191 m := Length(gDoorMap);
192 SetLength(gDoorMap, m+1);
193 SetLength(gDoorMap[m], 1);
194 gDoorMap[m, 0] := PanelArray[a].PanelID;
195 ok := True;
197 while ok do
198 begin
199 ok := False;
201 for b := 0 to i-1 do
202 if PanelArray[b].Active then
203 for c := 0 to High(gDoorMap[m]) do
204 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
205 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
206 g_CollideAround(PanelArray[b].X, PanelArray[b].Y,
207 PanelArray[b].Width, PanelArray[b].Height,
208 gWalls[gDoorMap[m, c]].X,
209 gWalls[gDoorMap[m, c]].Y,
210 gWalls[gDoorMap[m, c]].Width,
211 gWalls[gDoorMap[m, c]].Height) then
212 begin
213 PanelArray[b].Active := False;
214 SetLength(gDoorMap[m],
215 Length(gDoorMap[m])+1);
216 gDoorMap[m, High(gDoorMap[m])] := PanelArray[b].PanelID;
217 ok := True;
218 Break;
219 end;
220 end;
222 g_Game_StepLoading();
223 end;
225 PanelArray := nil;
226 end;
228 procedure CreateLiftMap();
229 var
230 PanelArray: Array of record
231 X, Y: Integer;
232 Width, Height: Word;
233 Active: Boolean;
234 end;
235 a, b, c, len, i, j: Integer;
236 ok: Boolean;
237 begin
238 if gLifts = nil then
239 Exit;
241 len := Length(gLifts);
242 SetLength(PanelArray, len);
244 for a := 0 to len-1 do
245 begin
246 PanelArray[a].X := gLifts[a].X;
247 PanelArray[a].Y := gLifts[a].Y;
248 PanelArray[a].Width := gLifts[a].Width;
249 PanelArray[a].Height := gLifts[a].Height;
250 PanelArray[a].Active := True;
251 end;
253 SetLength(gLiftMap, len);
254 i := 0;
256 g_Game_SetLoadingText(_lc[I_LOAD_LIFT_MAP], len-1, False);
258 for a := 0 to len-1 do
259 if PanelArray[a].Active then
260 begin
261 PanelArray[a].Active := False;
262 SetLength(gLiftMap[i], 32);
263 j := 0;
264 gLiftMap[i, j] := a;
265 ok := True;
267 while ok do
268 begin
269 ok := False;
270 for b := 0 to len-1 do
271 if PanelArray[b].Active then
272 for c := 0 to j do
273 if g_CollideAround(PanelArray[b].X,
274 PanelArray[b].Y,
275 PanelArray[b].Width,
276 PanelArray[b].Height,
277 PanelArray[gLiftMap[i, c]].X,
278 PanelArray[gLiftMap[i, c]].Y,
279 PanelArray[gLiftMap[i, c]].Width,
280 PanelArray[gLiftMap[i, c]].Height) then
281 begin
282 PanelArray[b].Active := False;
283 j := j+1;
284 if j > High(gLiftMap[i]) then
285 SetLength(gLiftMap[i],
286 Length(gLiftMap[i])+32);
288 gLiftMap[i, j] := b;
289 ok := True;
291 Break;
292 end;
293 end;
295 SetLength(gLiftMap[i], j+1);
296 i := i+1;
298 g_Game_StepLoading();
299 end;
301 SetLength(gLiftMap, i);
303 PanelArray := nil;
304 end;
306 function CreatePanel(PanelRec: TPanelRec_1; AddTextures: TAddTextureArray;
307 CurTex: Integer; sav: Boolean): Integer;
308 var
309 len: Integer;
310 panels: ^TPanelArray;
311 begin
312 Result := -1;
314 case PanelRec.PanelType of
315 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR:
316 panels := @gWalls;
317 PANEL_BACK:
318 panels := @gRenderBackgrounds;
319 PANEL_FORE:
320 panels := @gRenderForegrounds;
321 PANEL_WATER:
322 panels := @gWater;
323 PANEL_ACID1:
324 panels := @gAcid1;
325 PANEL_ACID2:
326 panels := @gAcid2;
327 PANEL_STEP:
328 panels := @gSteps;
329 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT:
330 panels := @gLifts;
331 PANEL_BLOCKMON:
332 panels := @gBlockMon;
333 else
334 Exit;
335 end;
337 len := Length(panels^);
338 SetLength(panels^, len + 1);
340 panels^[len] := TPanel.Create(PanelRec, AddTextures,
341 CurTex, Textures);
342 if sav then
343 panels^[len].SaveIt := True;
345 Result := len;
346 end;
348 procedure CreateNullTexture(RecName: String);
349 begin
350 SetLength(Textures, Length(Textures)+1);
352 with Textures[High(Textures)] do
353 begin
354 TextureName := RecName;
355 Width := 1;
356 Height := 1;
357 Anim := False;
358 TextureID := TEXTURE_NONE;
359 end;
360 end;
362 function CreateTexture(RecName: String; Map: string; log: Boolean): Boolean;
363 var
364 WAD: TWADEditor_1;
365 TextureData: Pointer;
366 WADName: String;
367 SectionName: String;
368 TextureName: String;
369 a, ResLength: Integer;
370 begin
371 Result := False;
373 if Textures <> nil then
374 for a := 0 to High(Textures) do
375 if Textures[a].TextureName = RecName then
376 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
377 Result := True;
378 Exit;
379 end;
381 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
382 if (RecName = TEXTURE_NAME_WATER) or
383 (RecName = TEXTURE_NAME_ACID1) or
384 (RecName = TEXTURE_NAME_ACID2) then
385 begin
386 SetLength(Textures, Length(Textures)+1);
388 with Textures[High(Textures)] do
389 begin
390 TextureName := RecName;
392 if TextureName = TEXTURE_NAME_WATER then
393 TextureID := TEXTURE_SPECIAL_WATER
394 else
395 if TextureName = TEXTURE_NAME_ACID1 then
396 TextureID := TEXTURE_SPECIAL_ACID1
397 else
398 if TextureName = TEXTURE_NAME_ACID2 then
399 TextureID := TEXTURE_SPECIAL_ACID2;
401 Anim := False;
402 end;
404 Result := True;
405 Exit;
406 end;
408 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
409 g_ProcessResourceStr(RecName, WADName, SectionName, TextureName);
411 WAD := TWADEditor_1.Create();
413 if WADName <> '' then
414 WADName := GameDir+'/wads/'+WADName
415 else
416 WADName := Map;
418 WAD.ReadFile(WADName);
420 if WAD.GetResource(SectionName, TextureName, TextureData, ResLength) then
421 begin
422 SetLength(Textures, Length(Textures)+1);
423 if not e_CreateTextureMem(TextureData, Textures[High(Textures)].TextureID) then
424 Exit;
425 e_GetTextureSize(Textures[High(Textures)].TextureID,
426 @Textures[High(Textures)].Width,
427 @Textures[High(Textures)].Height);
428 FreeMem(TextureData);
429 Textures[High(Textures)].TextureName := RecName;
430 Textures[High(Textures)].Anim := False;
432 Result := True;
433 end
434 else // Íåò òàêîãî ðåóñðñà â WAD'å
435 if log then
436 begin
437 e_WriteLog(Format('Error loading texture %s', [RecName]), MSG_WARNING);
438 e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
439 end;
441 WAD.Free();
442 end;
444 function CreateAnimTexture(RecName: String; Map: string; log: Boolean): Boolean;
445 var
446 WAD: TWADEditor_1;
447 TextureWAD: Pointer;
448 TextData: Pointer;
449 TextureData: Pointer;
450 cfg: TConfig;
451 WADName: String;
452 SectionName: String;
453 TextureName: String;
454 ResLength: Integer;
455 TextureResource: String;
456 _width, _height, _framecount, _speed: Integer;
457 _backanimation: Boolean;
458 begin
459 Result := False;
461 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
462 g_ProcessResourceStr(RecName, WADName, SectionName, TextureName);
464 WAD := TWADEditor_1.Create();
466 if WADName <> '' then
467 WADName := GameDir+'/wads/'+WADName
468 else
469 WADName := Map;
471 WAD.ReadFile(WADName);
473 if not WAD.GetResource(SectionName, TextureName, TextureWAD, ResLength) then
474 begin
475 if log then
476 begin
477 e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
478 e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
479 end;
480 WAD.Free();
481 Exit;
482 end;
484 WAD.FreeWAD();
486 if not WAD.ReadMemory(TextureWAD, ResLength) then
487 begin
488 FreeMem(TextureWAD);
489 WAD.Free();
490 Exit;
491 end;
493 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
494 if not WAD.GetResource('TEXT', 'ANIM', TextData, ResLength) then
495 begin
496 FreeMem(TextureWAD);
497 WAD.Free();
498 Exit;
499 end;
501 cfg := TConfig.CreateMem(TextData, ResLength);
503 TextureResource := cfg.ReadStr('', 'resource', '');
505 if TextureResource = '' then
506 begin
507 FreeMem(TextureWAD);
508 FreeMem(TextData);
509 WAD.Free();
510 cfg.Free();
511 Exit;
512 end;
514 _width := cfg.ReadInt('', 'framewidth', 0);
515 _height := cfg.ReadInt('', 'frameheight', 0);
516 _framecount := cfg.ReadInt('', 'framecount', 0);
517 _speed := cfg.ReadInt('', 'waitcount', 0);
518 _backanimation := cfg.ReadBool('', 'backanimation', False);
520 cfg.Free();
522 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
523 if not WAD.GetResource('TEXTURES', TextureResource, TextureData, ResLength) then
524 begin
525 FreeMem(TextureWAD);
526 FreeMem(TextData);
527 WAD.Free();
528 Exit;
529 end;
531 WAD.Free();
533 SetLength(Textures, Length(Textures)+1);
534 with Textures[High(Textures)] do
535 begin
536 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
537 if g_Frames_CreateMemory(@FramesID, '', TextureData,
538 _width, _height, _framecount, _backanimation) then
539 begin
540 TextureName := RecName;
541 Width := _width;
542 Height := _height;
543 Anim := True;
544 FramesCount := _framecount;
545 Speed := _speed;
547 Result := True;
548 end
549 else
550 if log then
551 e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
552 end;
554 FreeMem(TextureWAD);
555 FreeMem(TextData);
556 end;
558 procedure CreateItem(Item: TItemRec_1);
559 begin
560 if g_Game_IsClient then Exit;
562 if (not (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF])) and
563 ByteBool(Item.Options and ITEM_OPTION_ONLYDM) then
564 Exit;
566 g_Items_Create(Item.X, Item.Y, Item.ItemType, ByteBool(Item.Options and ITEM_OPTION_FALL),
567 gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF, GM_COOP]);
568 end;
570 procedure CreateArea(Area: TAreaRec_1);
571 var
572 a: Integer;
573 id: DWORD;
574 begin
575 case Area.AreaType of
576 AREA_DMPOINT, AREA_PLAYERPOINT1, AREA_PLAYERPOINT2,
577 AREA_REDTEAMPOINT, AREA_BLUETEAMPOINT:
578 begin
579 SetLength(RespawnPoints, Length(RespawnPoints)+1);
580 with RespawnPoints[High(RespawnPoints)] do
581 begin
582 X := Area.X;
583 Y := Area.Y;
584 Direction := TDirection(Area.Direction);
586 case Area.AreaType of
587 AREA_DMPOINT: PointType := RESPAWNPOINT_DM;
588 AREA_PLAYERPOINT1: PointType := RESPAWNPOINT_PLAYER1;
589 AREA_PLAYERPOINT2: PointType := RESPAWNPOINT_PLAYER2;
590 AREA_REDTEAMPOINT: PointType := RESPAWNPOINT_RED;
591 AREA_BLUETEAMPOINT: PointType := RESPAWNPOINT_BLUE;
592 end;
593 end;
594 end;
596 AREA_REDFLAG, AREA_BLUEFLAG:
597 begin
598 if Area.AreaType = AREA_REDFLAG then a := FLAG_RED else a := FLAG_BLUE;
600 if FlagPoints[a] <> nil then Exit;
602 New(FlagPoints[a]);
604 with FlagPoints[a]^ do
605 begin
606 X := Area.X-FLAGRECT.X;
607 Y := Area.Y-FLAGRECT.Y;
608 Direction := TDirection(Area.Direction);
609 end;
611 with gFlags[a] do
612 begin
613 case a of
614 FLAG_RED: g_Frames_Get(id, 'FRAMES_FLAG_RED');
615 FLAG_BLUE: g_Frames_Get(id, 'FRAMES_FLAG_BLUE');
616 end;
618 Animation := TAnimation.Create(id, True, 8);
619 Obj.Rect := FLAGRECT;
621 g_Map_ResetFlag(a);
622 end;
623 end;
625 AREA_DOMFLAG:
626 begin
627 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
628 with DOMFlagPoints[High(DOMFlagPoints)] do
629 begin
630 X := Area.X;
631 Y := Area.Y;
632 Direction := TDirection(Area.Direction);
633 end;
635 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
636 end;
637 end;
638 end;
640 procedure CreateTrigger(Trigger: TTriggerRec_1; fTexturePanel1Type, fTexturePanel2Type: Word);
641 var
642 _trigger: TTrigger;
643 begin
644 if g_Game_IsClient and not (Trigger.TriggerType in [TRIGGER_SOUND, TRIGGER_MUSIC]) then Exit;
646 with _trigger do
647 begin
648 X := Trigger.X;
649 Y := Trigger.Y;
650 Width := Trigger.Width;
651 Height := Trigger.Height;
652 Enabled := ByteBool(Trigger.Enabled);
653 TexturePanel := Trigger.TexturePanel;
654 TexturePanelType := fTexturePanel1Type;
655 ShotPanelType := fTexturePanel2Type;
656 TriggerType := Trigger.TriggerType;
657 ActivateType := Trigger.ActivateType;
658 Keys := Trigger.Keys;
659 Data.Default := Trigger.DATA;
660 end;
662 g_Triggers_Create(_trigger);
663 end;
665 procedure CreateMonster(monster: TMonsterRec_1);
666 var
667 a, i: Integer;
668 begin
669 if g_Game_IsClient then Exit;
671 if (gGameSettings.GameType = GT_SINGLE)
672 or LongBool(gGameSettings.Options and GAME_OPTION_MONSTERS) then
673 begin
674 i := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y,
675 TDirection(monster.Direction));
677 if gTriggers <> nil then
678 for a := 0 to High(gTriggers) do
679 if gTriggers[a].TriggerType in [TRIGGER_PRESS,
680 TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
681 if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
682 gMonsters[i].AddTrigger(a);
684 if monster.MonsterType <> MONSTER_BARREL then
685 Inc(gTotalMonsters);
686 end;
687 end;
689 procedure g_Map_ReAdd_DieTriggers();
690 var
691 i, a: Integer;
692 begin
693 if g_Game_IsClient then Exit;
695 for i := 0 to High(gMonsters) do
696 if gMonsters[i] <> nil then
697 begin
698 gMonsters[i].ClearTriggers();
700 for a := 0 to High(gTriggers) do
701 if gTriggers[a].TriggerType in [TRIGGER_PRESS,
702 TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
703 if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
704 gMonsters[i].AddTrigger(a);
705 end;
706 end;
708 function extractWadName(resourceName: string): string;
709 var
710 posN: Integer;
711 begin
712 posN := Pos(':', resourceName);
713 if posN > 0 then
714 Result:= Copy(resourceName, 0, posN-1)
715 else
716 Result := '';
717 end;
719 procedure addResToExternalResList(res: string);
720 begin
721 res := extractWadName(res);
722 if (res <> '') and (gExternalResources.IndexOf(res) = -1) then
723 gExternalResources.Add(res);
724 end;
726 procedure generateExternalResourcesList(mapReader: TMapReader_1);
727 var
728 textures: TTexturesRec1Array;
729 mapHeader: TMapHeaderRec_1;
730 i: integer;
731 resFile: String = '';
732 begin
733 if gExternalResources = nil then
734 gExternalResources := TStringList.Create;
736 gExternalResources.Clear;
737 textures := mapReader.GetTextures();
738 for i := 0 to High(textures) do
739 begin
740 addResToExternalResList(resFile);
741 end;
743 textures := nil;
745 mapHeader := mapReader.GetMapHeader;
747 addResToExternalResList(mapHeader.MusicName);
748 addResToExternalResList(mapHeader.SkyName);
749 end;
751 function g_Map_Load(Res: String): Boolean;
752 const
753 DefaultMusRes = 'Standart.wad:STDMUS\MUS1';
754 DefaultSkyRes = 'Standart.wad:STDSKY\SKY0';
755 var
756 WAD: TWADEditor_1;
757 MapReader: TMapReader_1;
758 Header: TMapHeaderRec_1;
759 _textures: TTexturesRec1Array;
760 panels: TPanelsRec1Array;
761 items: TItemsRec1Array;
762 monsters: TMonsterRec1Array;
763 areas: TAreasRec1Array;
764 triggers: TTriggersRec1Array;
765 a, b, c, k: Integer;
766 PanelID: DWORD;
767 AddTextures: TAddTextureArray;
768 texture: TTextureRec_1;
769 TriggersTable: Array of record
770 TexturePanel: Integer;
771 LiftPanel: Integer;
772 DoorPanel: Integer;
773 ShotPanel: Integer;
774 end;
775 FileName, SectionName, ResName,
776 FileName2, s, TexName: String;
777 Data: Pointer;
778 Len: Integer;
779 ok, isAnim, trigRef: Boolean;
780 CurTex: Integer;
781 begin
782 Result := False;
783 gMapInfo.Map := Res;
784 TriggersTable := nil;
785 FillChar(texture, SizeOf(texture), 0);
787 // Çàãðóçêà WAD:
788 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
789 e_WriteLog('Loading map WAD: ' + FileName, MSG_NOTIFY);
790 g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False);
792 WAD := TWADEditor_1.Create();
793 if not WAD.ReadFile(FileName) then
794 begin
795 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_WAD], [FileName]));
796 WAD.Free();
797 Exit;
798 end;
799 if not WAD.GetResource('', ResName, Data, Len) then
800 begin
801 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_RES], [ResName]));
802 WAD.Free();
803 Exit;
804 end;
805 WAD.Free();
807 // Çàãðóçêà êàðòû:
808 e_WriteLog('Loading map: ' + ResName, MSG_NOTIFY);
809 g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False);
810 MapReader := TMapReader_1.Create();
812 if not MapReader.LoadMap(Data) then
813 begin
814 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]));
815 FreeMem(Data);
816 MapReader.Free();
817 Exit;
818 end;
820 FreeMem(Data);
821 generateExternalResourcesList(MapReader);
822 // Çàãðóçêà òåêñòóð:
823 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False);
824 _textures := MapReader.GetTextures();
826 // Äîáàâëåíèå òåêñòóð â Textures[]:
827 if _textures <> nil then
828 begin
829 e_WriteLog(' Loading textures:', MSG_NOTIFY);
830 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], High(_textures), False);
832 for a := 0 to High(_textures) do
833 begin
834 SetLength(s, 64);
835 CopyMemory(@s[1], @_textures[a].Resource[0], 64);
836 for b := 1 to Length(s) do
837 if s[b] = #0 then
838 begin
839 SetLength(s, b-1);
840 Break;
841 end;
842 e_WriteLog(' Loading texture: ' + s, MSG_NOTIFY);
843 // Àíèìèðîâàííàÿ òåêñòóðà:
844 if ByteBool(_textures[a].Anim) then
845 begin
846 if not CreateAnimTexture(_textures[a].Resource, FileName, True) then
847 begin
848 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s]));
849 CreateNullTexture(_textures[a].Resource);
850 end;
851 end
852 else // Îáû÷íàÿ òåêñòóðà:
853 if not CreateTexture(_textures[a].Resource, FileName, True) then
854 begin
855 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s]));
856 CreateNullTexture(_textures[a].Resource);
857 end;
859 g_Game_StepLoading();
860 end;
861 end;
863 // Çàãðóçêà òðèããåðîâ:
864 gTriggerClientID := 0;
865 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
866 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS], 0, False);
867 triggers := MapReader.GetTriggers();
869 // Çàãðóçêà ïàíåëåé:
870 e_WriteLog(' Loading panels...', MSG_NOTIFY);
871 g_Game_SetLoadingText(_lc[I_LOAD_PANELS], 0, False);
872 panels := MapReader.GetPanels();
874 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì):
875 if triggers <> nil then
876 begin
877 e_WriteLog(' Setting up trigger table...', MSG_NOTIFY);
878 SetLength(TriggersTable, Length(triggers));
879 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], High(TriggersTable), False);
881 for a := 0 to High(TriggersTable) do
882 begin
883 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè):
884 TriggersTable[a].TexturePanel := triggers[a].TexturePanel;
885 // Ëèôòû:
886 if triggers[a].TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then
887 TriggersTable[a].LiftPanel := TTriggerData(triggers[a].DATA).PanelID
888 else
889 TriggersTable[a].LiftPanel := -1;
890 // Äâåðè:
891 if triggers[a].TriggerType in [TRIGGER_OPENDOOR,
892 TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5,
893 TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
894 TriggersTable[a].DoorPanel := TTriggerData(triggers[a].DATA).PanelID
895 else
896 TriggersTable[a].DoorPanel := -1;
897 // Òóðåëü:
898 if triggers[a].TriggerType = TRIGGER_SHOT then
899 TriggersTable[a].ShotPanel := TTriggerData(triggers[a].DATA).ShotPanelID
900 else
901 TriggersTable[a].ShotPanel := -1;
903 g_Game_StepLoading();
904 end;
905 end;
907 // Ñîçäàåì ïàíåëè:
908 if panels <> nil then
909 begin
910 e_WriteLog(' Setting up trigger links...', MSG_NOTIFY);
911 g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], High(panels), False);
913 for a := 0 to High(panels) do
914 begin
915 SetLength(AddTextures, 0);
916 trigRef := False;
917 CurTex := -1;
918 if _textures <> nil then
919 begin
920 texture := _textures[panels[a].TextureNum];
921 ok := True;
922 end
923 else
924 ok := False;
926 if ok then
927 begin
928 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
929 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð:
930 ok := False;
931 if (TriggersTable <> nil) and (_textures <> nil) then
932 for b := 0 to High(TriggersTable) do
933 if (TriggersTable[b].TexturePanel = a)
934 or (TriggersTable[b].ShotPanel = a) then
935 begin
936 trigRef := True;
937 ok := True;
938 Break;
939 end;
940 end;
942 if ok then
943 begin // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
944 SetLength(s, 64);
945 CopyMemory(@s[1], @texture.Resource[0], 64);
946 // Èçìåðÿåì äëèíó:
947 Len := Length(s);
948 for c := Len downto 1 do
949 if s[c] <> #0 then
950 begin
951 Len := c;
952 Break;
953 end;
954 SetLength(s, Len);
956 // Ñïåö-òåêñòóðû çàïðåùåíû:
957 if g_Map_IsSpecialTexture(s) then
958 ok := False
959 else
960 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè:
961 ok := g_Texture_NumNameFindStart(s);
963 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
964 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #:
965 if ok then
966 begin
967 k := NNF_NAME_BEFORE;
968 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû:
969 while ok or (k = NNF_NAME_BEFORE) or
970 (k = NNF_NAME_EQUALS) do
971 begin
972 k := g_Texture_NumNameFindNext(TexName);
974 if (k = NNF_NAME_BEFORE) or
975 (k = NNF_NAME_AFTER) then
976 begin
977 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó:
978 if ByteBool(texture.Anim) then
979 begin // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
980 isAnim := True;
981 ok := CreateAnimTexture(TexName, FileName, False);
982 if not ok then
983 begin // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
984 isAnim := False;
985 ok := CreateTexture(TexName, FileName, False);
986 end;
987 end
988 else
989 begin // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
990 isAnim := False;
991 ok := CreateTexture(TexName, FileName, False);
992 if not ok then
993 begin // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
994 isAnim := True;
995 ok := CreateAnimTexture(TexName, FileName, False);
996 end;
997 end;
999 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè:
1000 if ok then
1001 begin
1002 for c := 0 to High(Textures) do
1003 if Textures[c].TextureName = TexName then
1004 begin
1005 SetLength(AddTextures, Length(AddTextures)+1);
1006 AddTextures[High(AddTextures)].Texture := c;
1007 AddTextures[High(AddTextures)].Anim := isAnim;
1008 Break;
1009 end;
1010 end;
1011 end
1012 else
1013 if k = NNF_NAME_EQUALS then
1014 begin
1015 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî:
1016 SetLength(AddTextures, Length(AddTextures)+1);
1017 AddTextures[High(AddTextures)].Texture := panels[a].TextureNum;
1018 AddTextures[High(AddTextures)].Anim := ByteBool(texture.Anim);
1019 CurTex := High(AddTextures);
1020 ok := True;
1021 end
1022 else // NNF_NO_NAME
1023 ok := False;
1024 end; // while ok...
1026 ok := True;
1027 end; // if ok - åñòü ñìåæíûå òåêñòóðû
1028 end; // if ok - ññûëàþòñÿ òðèããåðû
1030 if not ok then
1031 begin
1032 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó:
1033 SetLength(AddTextures, 1);
1034 AddTextures[0].Texture := panels[a].TextureNum;
1035 AddTextures[0].Anim := ByteBool(texture.Anim);
1036 CurTex := 0;
1037 end;
1039 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð:
1040 PanelID := CreatePanel(panels[a], AddTextures, CurTex, trigRef);
1042 // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID:
1043 if TriggersTable <> nil then
1044 for b := 0 to High(TriggersTable) do
1045 begin
1046 // Òðèããåð äâåðè/ëèôòà:
1047 if (TriggersTable[b].LiftPanel = a) or
1048 (TriggersTable[b].DoorPanel = a) then
1049 TTriggerData(triggers[b].DATA).PanelID := PanelID;
1050 // Òðèããåð ñìåíû òåêñòóðû:
1051 if TriggersTable[b].TexturePanel = a then
1052 triggers[b].TexturePanel := PanelID;
1053 // Òðèããåð "Òóðåëü":
1054 if TriggersTable[b].ShotPanel = a then
1055 TTriggerData(triggers[b].DATA).ShotPanelID := PanelID;
1056 end;
1058 g_Game_StepLoading();
1059 end;
1060 end;
1062 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû:
1063 if (triggers <> nil) and not gLoadGameMode then
1064 begin
1065 e_WriteLog(' Creating triggers...', MSG_NOTIFY);
1066 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_TRIGGERS], 0, False);
1067 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü:
1068 for a := 0 to High(triggers) do
1069 begin
1070 if triggers[a].TexturePanel <> -1 then
1071 b := panels[TriggersTable[a].TexturePanel].PanelType
1072 else
1073 b := 0;
1074 if (triggers[a].TriggerType = TRIGGER_SHOT) and
1075 (TTriggerData(triggers[a].DATA).ShotPanelID <> -1) then
1076 c := panels[TriggersTable[a].ShotPanel].PanelType
1077 else
1078 c := 0;
1079 CreateTrigger(triggers[a], b, c);
1080 end;
1081 end;
1083 // Çàãðóçêà ïðåäìåòîâ:
1084 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
1085 g_Game_SetLoadingText(_lc[I_LOAD_ITEMS], 0, False);
1086 items := MapReader.GetItems();
1088 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû:
1089 if (items <> nil) and not gLoadGameMode then
1090 begin
1091 e_WriteLog(' Spawning items...', MSG_NOTIFY);
1092 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_ITEMS], 0, False);
1093 for a := 0 to High(items) do
1094 CreateItem(Items[a]);
1095 end;
1097 // Çàãðóçêà îáëàñòåé:
1098 e_WriteLog(' Loading areas...', MSG_NOTIFY);
1099 g_Game_SetLoadingText(_lc[I_LOAD_AREAS], 0, False);
1100 areas := MapReader.GetAreas();
1102 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè:
1103 if areas <> nil then
1104 begin
1105 e_WriteLog(' Creating areas...', MSG_NOTIFY);
1106 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_AREAS], 0, False);
1107 for a := 0 to High(areas) do
1108 CreateArea(areas[a]);
1109 end;
1111 // Çàãðóçêà ìîíñòðîâ:
1112 e_WriteLog(' Loading monsters...', MSG_NOTIFY);
1113 g_Game_SetLoadingText(_lc[I_LOAD_MONSTERS], 0, False);
1114 monsters := MapReader.GetMonsters();
1116 gTotalMonsters := 0;
1118 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ:
1119 if (monsters <> nil) and not gLoadGameMode then
1120 begin
1121 e_WriteLog(' Spawning monsters...', MSG_NOTIFY);
1122 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_MONSTERS], 0, False);
1123 for a := 0 to High(monsters) do
1124 CreateMonster(monsters[a]);
1125 end;
1127 // Çàãðóçêà îïèñàíèÿ êàðòû:
1128 e_WriteLog(' Reading map info...', MSG_NOTIFY);
1129 g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
1130 Header := MapReader.GetMapHeader();
1132 MapReader.Free();
1134 with gMapInfo do
1135 begin
1136 Name := Header.MapName;
1137 Description := Header.MapDescription;
1138 Author := Header.MapAuthor;
1139 MusicName := Header.MusicName;
1140 SkyName := Header.SkyName;
1141 Height := Header.Height;
1142 Width := Header.Width;
1143 end;
1145 // Çàãðóçêà íåáà:
1146 if gMapInfo.SkyName <> '' then
1147 begin
1148 e_WriteLog(' Loading sky: ' + gMapInfo.SkyName, MSG_NOTIFY);
1149 g_Game_SetLoadingText(_lc[I_LOAD_SKY], 0, False);
1150 g_ProcessResourceStr(gMapInfo.SkyName, FileName, SectionName, ResName);
1152 if FileName <> '' then
1153 FileName := GameDir+'/wads/'+FileName
1154 else
1155 begin
1156 g_ProcessResourceStr(Res, @FileName2, nil, nil);
1157 FileName := FileName2;
1158 end;
1160 s := FileName+':'+SectionName+'/'+ResName;
1161 if g_Texture_CreateWAD(BackID, s) then
1162 begin
1163 g_Game_SetupScreenSize();
1164 end
1165 else
1166 g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s]));
1167 end;
1169 // Çàãðóçêà ìóçûêè:
1170 ok := False;
1171 if gMapInfo.MusicName <> '' then
1172 begin
1173 e_WriteLog(' Loading music: ' + gMapInfo.MusicName, MSG_NOTIFY);
1174 g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
1175 g_ProcessResourceStr(gMapInfo.MusicName, FileName, SectionName, ResName);
1177 if FileName <> '' then
1178 FileName := GameDir+'/wads/'+FileName
1179 else
1180 begin
1181 g_ProcessResourceStr(Res, @FileName2, nil, nil);
1182 FileName := FileName2;
1183 end;
1185 s := FileName+':'+SectionName+'/'+ResName;
1186 if g_Sound_CreateWADEx(gMapInfo.MusicName, s, True) then
1187 ok := True
1188 else
1189 g_FatalError(Format(_lc[I_GAME_ERROR_MUSIC], [s]));
1190 end;
1192 // Îñòàëüíûå óñòàíâêè:
1193 CreateDoorMap();
1194 CreateLiftMap();
1196 g_Items_Init();
1197 g_Weapon_Init();
1198 g_Monsters_Init();
1200 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
1201 if not gLoadGameMode then
1202 g_GFX_Init();
1204 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
1205 _textures := nil;
1206 panels := nil;
1207 items := nil;
1208 areas := nil;
1209 triggers := nil;
1210 TriggersTable := nil;
1211 AddTextures := nil;
1213 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
1214 if ok and (not gLoadGameMode) then
1215 begin
1216 gMusic.SetByName(gMapInfo.MusicName);
1217 gMusic.Play();
1218 end
1219 else
1220 gMusic.SetByName('');
1222 e_WriteLog('Done loading map.', MSG_NOTIFY);
1223 Result := True;
1224 end;
1226 function g_Map_GetMapInfo(Res: String): TMapInfo;
1227 var
1228 WAD: TWADEditor_1;
1229 MapReader: TMapReader_1;
1230 Header: TMapHeaderRec_1;
1231 FileName, SectionName, ResName: String;
1232 Data: Pointer;
1233 Len: Integer;
1234 begin
1235 FillChar(Result, SizeOf(Result), 0);
1236 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
1238 WAD := TWADEditor_1.Create();
1239 if not WAD.ReadFile(FileName) then
1240 begin
1241 WAD.Free();
1242 Exit;
1243 end;
1245 if not WAD.GetResource('', ResName, Data, Len) then
1246 begin
1247 WAD.Free();
1248 Exit;
1249 end;
1251 WAD.Free();
1253 MapReader := TMapReader_1.Create();
1255 if not MapReader.LoadMap(Data) then
1256 begin
1257 g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True);
1258 ZeroMemory(@Header, SizeOf(Header));
1259 Result.Name := _lc[I_GAME_ERROR_MAP_SELECT];
1260 Result.Description := _lc[I_GAME_ERROR_MAP_SELECT];
1261 end
1262 else
1263 begin
1264 Header := MapReader.GetMapHeader();
1265 Result.Name := Header.MapName;
1266 Result.Description := Header.MapDescription;
1267 end;
1269 FreeMem(Data);
1270 MapReader.Free();
1272 Result.Map := Res;
1273 Result.Author := Header.MapAuthor;
1274 Result.Height := Header.Height;
1275 Result.Width := Header.Width;
1276 end;
1278 function g_Map_GetMapsList(WADName: string): SArray;
1279 var
1280 WAD: TWADEditor_1;
1281 a: Integer;
1282 ResList: SArray;
1283 Data: Pointer;
1284 Len: Integer;
1285 Sign: Array [0..2] of Char;
1286 begin
1287 Result := nil;
1289 WAD := TWADEditor_1.Create();
1290 if not WAD.ReadFile(WADName) then
1291 begin
1292 WAD.Free();
1293 Exit;
1294 end;
1296 ResList := WAD.GetResourcesList('');
1298 if ResList <> nil then
1299 for a := 0 to High(ResList) do
1300 begin
1301 if not WAD.GetResource('', ResList[a], Data, Len) then Continue;
1302 CopyMemory(@Sign[0], Data, 3);
1303 FreeMem(Data);
1305 if Sign = MAP_SIGNATURE then
1306 begin
1307 SetLength(Result, Length(Result)+1);
1308 Result[High(Result)] := ResList[a];
1309 end;
1311 Sign := '';
1312 end;
1314 WAD.Free();
1315 end;
1317 function g_Map_Exist(Res: string): Boolean;
1318 var
1319 WAD: TWADEditor_1;
1320 FileName, SectionName, ResName: string;
1321 ResList: SArray;
1322 a: Integer;
1323 begin
1324 Result := False;
1326 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
1328 if Pos('.wad', LowerCase(FileName)) = 0 then FileName := FileName+'.wad';
1330 WAD := TWADEditor_1.Create;
1331 if not WAD.ReadFile(FileName) then
1332 begin
1333 WAD.Free();
1334 Exit;
1335 end;
1337 ResList := WAD.GetResourcesList('');
1338 WAD.Free();
1340 if ResList <> nil then
1341 for a := 0 to High(ResList) do if ResList[a] = ResName then
1342 begin
1343 Result := True;
1344 Exit;
1345 end;
1346 end;
1348 procedure g_Map_Free();
1349 var
1350 a: Integer;
1352 procedure FreePanelArray(var panels: TPanelArray);
1353 var
1354 i: Integer;
1356 begin
1357 if panels <> nil then
1358 begin
1359 for i := 0 to High(panels) do
1360 panels[i].Free();
1361 panels := nil;
1362 end;
1363 end;
1365 begin
1366 g_GFX_Free();
1367 g_Weapon_Free();
1368 g_Items_Free();
1369 g_Triggers_Free();
1370 g_Monsters_Free();
1372 RespawnPoints := nil;
1373 if FlagPoints[FLAG_RED] <> nil then
1374 begin
1375 Dispose(FlagPoints[FLAG_RED]);
1376 FlagPoints[FLAG_RED] := nil;
1377 end;
1378 if FlagPoints[FLAG_BLUE] <> nil then
1379 begin
1380 Dispose(FlagPoints[FLAG_BLUE]);
1381 FlagPoints[FLAG_BLUE] := nil;
1382 end;
1383 //DOMFlagPoints := nil;
1385 //gDOMFlags := nil;
1387 if Textures <> nil then
1388 begin
1389 for a := 0 to High(Textures) do
1390 if not g_Map_IsSpecialTexture(Textures[a].TextureName) then
1391 if Textures[a].Anim then
1392 g_Frames_DeleteByID(Textures[a].FramesID)
1393 else
1394 if Textures[a].TextureID <> TEXTURE_NONE then
1395 e_DeleteTexture(Textures[a].TextureID);
1397 Textures := nil;
1398 end;
1400 FreePanelArray(gWalls);
1401 FreePanelArray(gRenderBackgrounds);
1402 FreePanelArray(gRenderForegrounds);
1403 FreePanelArray(gWater);
1404 FreePanelArray(gAcid1);
1405 FreePanelArray(gAcid2);
1406 FreePanelArray(gSteps);
1407 FreePanelArray(gLifts);
1408 FreePanelArray(gBlockMon);
1410 if BackID <> DWORD(-1) then
1411 begin
1412 gBackSize.X := 0;
1413 gBackSize.Y := 0;
1414 e_DeleteTexture(BackID);
1415 BackID := DWORD(-1);
1416 end;
1418 g_Game_StopAllSounds(False);
1419 gMusic.FreeSound();
1420 g_Sound_Delete(gMapInfo.MusicName);
1422 gMapInfo.Name := '';
1423 gMapInfo.Description := '';
1424 gMapInfo.MusicName := '';
1425 gMapInfo.Height := 0;
1426 gMapInfo.Width := 0;
1428 gDoorMap := nil;
1429 gLiftMap := nil;
1430 end;
1432 procedure g_Map_Update();
1433 var
1434 a, d, j: Integer;
1435 m: Word;
1436 s: String;
1438 procedure UpdatePanelArray(var panels: TPanelArray);
1439 var
1440 i: Integer;
1442 begin
1443 if panels <> nil then
1444 for i := 0 to High(panels) do
1445 panels[i].Update();
1446 end;
1448 begin
1449 UpdatePanelArray(gWalls);
1450 UpdatePanelArray(gRenderBackgrounds);
1451 UpdatePanelArray(gRenderForegrounds);
1452 UpdatePanelArray(gWater);
1453 UpdatePanelArray(gAcid1);
1454 UpdatePanelArray(gAcid2);
1455 UpdatePanelArray(gSteps);
1457 if gGameSettings.GameMode = GM_CTF then
1458 begin
1459 for a := FLAG_RED to FLAG_BLUE do
1460 if not (gFlags[a].State in [FLAG_STATE_NONE, FLAG_STATE_CAPTURED]) then
1461 with gFlags[a] do
1462 begin
1463 if gFlags[a].Animation <> nil then
1464 gFlags[a].Animation.Update();
1466 m := g_Obj_Move(@Obj, True, True);
1468 if gTime mod (GAME_TICK*2) <> 0 then
1469 Continue;
1471 // Ñîïðîòèâëåíèå âîçäóõà:
1472 Obj.Vel.X := z_dec(Obj.Vel.X, 1);
1474 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó:
1475 if ((Count = 0) or ByteBool(m and MOVE_FALLOUT)) and g_Game_IsServer then
1476 begin
1477 g_Map_ResetFlag(a);
1478 gFlags[a].CaptureTime := 0;
1479 if a = FLAG_RED then
1480 s := _lc[I_PLAYER_FLAG_RED]
1481 else
1482 s := _lc[I_PLAYER_FLAG_BLUE];
1483 g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
1485 if g_Game_IsNet then
1486 MH_SEND_FlagEvent(FLAG_STATE_RETURNED, a, 0);
1487 Continue;
1488 end;
1490 if Count > 0 then
1491 Count := Count - 1;
1493 // Èãðîê áåðåò ôëàã:
1494 if gPlayers <> nil then
1495 begin
1496 j := Random(Length(gPlayers)) - 1;
1498 for d := 0 to High(gPlayers) do
1499 begin
1500 Inc(j);
1501 if j > High(gPlayers) then
1502 j := 0;
1504 if gPlayers[j] <> nil then
1505 if gPlayers[j].Live and
1506 g_Obj_Collide(@Obj, @gPlayers[j].Obj) then
1507 begin
1508 if gPlayers[j].GetFlag(a) then
1509 Break;
1510 end;
1511 end;
1512 end;
1513 end;
1514 end;
1515 end;
1517 procedure g_Map_DrawPanels(PanelType: Word);
1519 procedure DrawPanels(var panels: TPanelArray;
1520 drawDoors: Boolean = False);
1521 var
1522 a: Integer;
1524 begin
1525 if panels <> nil then
1526 for a := 0 to High(panels) do
1527 if not (drawDoors xor panels[a].Door) then
1528 panels[a].Draw();
1529 end;
1531 begin
1532 case PanelType of
1533 PANEL_WALL: DrawPanels(gWalls);
1534 PANEL_CLOSEDOOR: DrawPanels(gWalls, True);
1535 PANEL_BACK: DrawPanels(gRenderBackgrounds);
1536 PANEL_FORE: DrawPanels(gRenderForegrounds);
1537 PANEL_WATER: DrawPanels(gWater);
1538 PANEL_ACID1: DrawPanels(gAcid1);
1539 PANEL_ACID2: DrawPanels(gAcid2);
1540 PANEL_STEP: DrawPanels(gSteps);
1541 end;
1542 end;
1544 procedure g_Map_DrawBack(dx, dy: Integer);
1545 begin
1546 if gDrawBackGround and (BackID <> DWORD(-1)) then
1547 e_DrawSize(BackID, dx, dy, 0, False, False, gBackSize.X, gBackSize.Y)
1548 else
1549 e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
1550 end;
1552 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word;
1553 PanelType: Word; b1x3: Boolean): Boolean;
1554 var
1555 a, h: Integer;
1556 begin
1557 Result := False;
1559 if WordBool(PanelType and PANEL_WALL) then
1560 if gWalls <> nil then
1561 begin
1562 h := High(gWalls);
1564 for a := 0 to h do
1565 if gWalls[a].Enabled and
1566 g_Collide(X, Y, Width, Height,
1567 gWalls[a].X, gWalls[a].Y,
1568 gWalls[a].Width, gWalls[a].Height) then
1569 begin
1570 Result := True;
1571 Exit;
1572 end;
1573 end;
1575 if WordBool(PanelType and PANEL_WATER) then
1576 if gWater <> nil then
1577 begin
1578 h := High(gWater);
1580 for a := 0 to h do
1581 if g_Collide(X, Y, Width, Height,
1582 gWater[a].X, gWater[a].Y,
1583 gWater[a].Width, gWater[a].Height) then
1584 begin
1585 Result := True;
1586 Exit;
1587 end;
1588 end;
1590 if WordBool(PanelType and PANEL_ACID1) then
1591 if gAcid1 <> nil then
1592 begin
1593 h := High(gAcid1);
1595 for a := 0 to h do
1596 if g_Collide(X, Y, Width, Height,
1597 gAcid1[a].X, gAcid1[a].Y,
1598 gAcid1[a].Width, gAcid1[a].Height) then
1599 begin
1600 Result := True;
1601 Exit;
1602 end;
1603 end;
1605 if WordBool(PanelType and PANEL_ACID2) then
1606 if gAcid2 <> nil then
1607 begin
1608 h := High(gAcid2);
1610 for a := 0 to h do
1611 if g_Collide(X, Y, Width, Height,
1612 gAcid2[a].X, gAcid2[a].Y,
1613 gAcid2[a].Width, gAcid2[a].Height) then
1614 begin
1615 Result := True;
1616 Exit;
1617 end;
1618 end;
1620 if WordBool(PanelType and PANEL_STEP) then
1621 if gSteps <> nil then
1622 begin
1623 h := High(gSteps);
1625 for a := 0 to h do
1626 if g_Collide(X, Y, Width, Height,
1627 gSteps[a].X, gSteps[a].Y,
1628 gSteps[a].Width, gSteps[a].Height) then
1629 begin
1630 Result := True;
1631 Exit;
1632 end;
1633 end;
1635 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
1636 if gLifts <> nil then
1637 begin
1638 h := High(gLifts);
1640 for a := 0 to h do
1641 if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = 0)) or
1642 (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = 1)) or
1643 (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = 2)) or
1644 (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = 3))) and
1645 g_Collide(X, Y, Width, Height,
1646 gLifts[a].X, gLifts[a].Y,
1647 gLifts[a].Width, gLifts[a].Height) then
1648 begin
1649 Result := True;
1650 Exit;
1651 end;
1652 end;
1654 if WordBool(PanelType and PANEL_BLOCKMON) then
1655 if gBlockMon <> nil then
1656 begin
1657 h := High(gBlockMon);
1659 for a := 0 to h do
1660 if ( (not b1x3) or
1661 ((gBlockMon[a].Width + gBlockMon[a].Height) >= 64) ) and
1662 g_Collide(X, Y, Width, Height,
1663 gBlockMon[a].X, gBlockMon[a].Y,
1664 gBlockMon[a].Width, gBlockMon[a].Height) then
1665 begin
1666 Result := True;
1667 Exit;
1668 end;
1669 end;
1670 end;
1672 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
1673 var
1674 a, h: Integer;
1675 begin
1676 Result := TEXTURE_NONE;
1678 if gWater <> nil then
1679 begin
1680 h := High(gWater);
1682 for a := 0 to h do
1683 if g_Collide(X, Y, Width, Height,
1684 gWater[a].X, gWater[a].Y,
1685 gWater[a].Width, gWater[a].Height) then
1686 begin
1687 Result := gWater[a].GetTextureID();
1688 Exit;
1689 end;
1690 end;
1692 if gAcid1 <> nil then
1693 begin
1694 h := High(gAcid1);
1696 for a := 0 to h do
1697 if g_Collide(X, Y, Width, Height,
1698 gAcid1[a].X, gAcid1[a].Y,
1699 gAcid1[a].Width, gAcid1[a].Height) then
1700 begin
1701 Result := gAcid1[a].GetTextureID();
1702 Exit;
1703 end;
1704 end;
1706 if gAcid2 <> nil then
1707 begin
1708 h := High(gAcid2);
1710 for a := 0 to h do
1711 if g_Collide(X, Y, Width, Height,
1712 gAcid2[a].X, gAcid2[a].Y,
1713 gAcid2[a].Width, gAcid2[a].Height) then
1714 begin
1715 Result := gAcid2[a].GetTextureID();
1716 Exit;
1717 end;
1718 end;
1719 end;
1721 procedure g_Map_EnableWall(ID: DWORD);
1722 begin
1723 with gWalls[ID] do
1724 begin
1725 Enabled := True;
1726 g_Mark(X, Y, Width, Height, MARK_DOOR, True);
1728 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1729 end;
1730 end;
1732 procedure g_Map_DisableWall(ID: DWORD);
1733 begin
1734 with gWalls[ID] do
1735 begin
1736 Enabled := False;
1737 g_Mark(X, Y, Width, Height, MARK_DOOR, False);
1739 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1740 end;
1741 end;
1743 procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0);
1744 var
1745 tp: TPanel;
1746 begin
1747 case PanelType of
1748 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR:
1749 tp := gWalls[ID];
1750 PANEL_FORE:
1751 tp := gRenderForegrounds[ID];
1752 PANEL_BACK:
1753 tp := gRenderBackgrounds[ID];
1754 PANEL_WATER:
1755 tp := gWater[ID];
1756 PANEL_ACID1:
1757 tp := gAcid1[ID];
1758 PANEL_ACID2:
1759 tp := gAcid2[ID];
1760 PANEL_STEP:
1761 tp := gSteps[ID];
1762 else
1763 Exit;
1764 end;
1766 tp.NextTexture(AnimLoop);
1767 if g_Game_IsServer and g_Game_IsNet then
1768 MH_SEND_PanelTexture(PanelType, ID, AnimLoop);
1769 end;
1771 procedure g_Map_SetLift(ID: DWORD; t: Integer);
1772 begin
1773 if gLifts[ID].LiftType = t then
1774 Exit;
1776 with gLifts[ID] do
1777 begin
1778 LiftType := t;
1780 g_Mark(X, Y, Width, Height, MARK_LIFT, False);
1782 if LiftType = 0 then
1783 g_Mark(X, Y, Width, Height, MARK_LIFTUP, True)
1784 else if LiftType = 1 then
1785 g_Mark(X, Y, Width, Height, MARK_LIFTDOWN, True)
1786 else if LiftType = 2 then
1787 g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True)
1788 else if LiftType = 3 then
1789 g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True);
1791 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1792 end;
1793 end;
1795 function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean;
1796 var
1797 a: Integer;
1798 PointsArray: Array of TRespawnPoint;
1799 begin
1800 Result := False;
1801 SetLength(PointsArray, 0);
1803 if RespawnPoints = nil then
1804 Exit;
1806 for a := 0 to High(RespawnPoints) do
1807 if RespawnPoints[a].PointType = PointType then
1808 begin
1809 SetLength(PointsArray, Length(PointsArray)+1);
1810 PointsArray[High(PointsArray)] := RespawnPoints[a];
1811 end;
1813 if PointsArray = nil then
1814 Exit;
1816 RespawnPoint := PointsArray[Random(Length(PointsArray))];
1817 Result := True;
1818 end;
1820 function g_Map_GetPointCount(PointType: Byte): Word;
1821 var
1822 a: Integer;
1823 begin
1824 Result := 0;
1826 if RespawnPoints = nil then
1827 Exit;
1829 for a := 0 to High(RespawnPoints) do
1830 if RespawnPoints[a].PointType = PointType then
1831 Result := Result + 1;
1832 end;
1834 function g_Map_HaveFlagPoints(): Boolean;
1835 begin
1836 Result := (FlagPoints[FLAG_RED] <> nil) and (FlagPoints[FLAG_BLUE] <> nil);
1837 end;
1839 procedure g_Map_ResetFlag(Flag: Byte);
1840 begin
1841 with gFlags[Flag] do
1842 begin
1843 Obj.X := -1000;
1844 Obj.Y := -1000;
1845 Obj.Vel.X := 0;
1846 Obj.Vel.Y := 0;
1847 Direction := D_LEFT;
1848 State := FLAG_STATE_NONE;
1849 if FlagPoints[Flag] <> nil then
1850 begin
1851 Obj.X := FlagPoints[Flag]^.X;
1852 Obj.Y := FlagPoints[Flag]^.Y;
1853 Direction := FlagPoints[Flag]^.Direction;
1854 State := FLAG_STATE_NORMAL;
1855 end;
1856 Count := -1;
1857 end;
1858 end;
1860 procedure g_Map_DrawFlags();
1861 var
1862 i, dx: Integer;
1863 Mirror: TMirrorType;
1864 begin
1865 if gGameSettings.GameMode <> GM_CTF then
1866 Exit;
1868 for i := FLAG_RED to FLAG_BLUE do
1869 with gFlags[i] do
1870 if State <> FLAG_STATE_CAPTURED then
1871 begin
1872 if State = FLAG_STATE_NONE then
1873 continue;
1875 if Direction = D_LEFT then
1876 begin
1877 Mirror := M_HORIZONTAL;
1878 dx := -1;
1879 end
1880 else
1881 begin
1882 Mirror := M_NONE;
1883 dx := 1;
1884 end;
1886 Animation.Draw(Obj.X+dx, Obj.Y+1, Mirror);
1888 if g_debug_Frames then
1889 begin
1890 e_DrawQuad(Obj.X+Obj.Rect.X,
1891 Obj.Y+Obj.Rect.Y,
1892 Obj.X+Obj.Rect.X+Obj.Rect.Width-1,
1893 Obj.Y+Obj.Rect.Y+Obj.Rect.Height-1,
1894 0, 255, 0);
1895 end;
1896 end;
1897 end;
1899 procedure g_Map_SaveState(Var Mem: TBinMemoryWriter);
1900 var
1901 dw: DWORD;
1902 b: Byte;
1903 str: String;
1904 boo: Boolean;
1906 procedure SavePanelArray(var panels: TPanelArray);
1907 var
1908 PAMem: TBinMemoryWriter;
1909 i: Integer;
1910 begin
1911 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé:
1912 PAMem := TBinMemoryWriter.Create((Length(panels)+1) * 40);
1914 i := 0;
1915 while i < Length(panels) do
1916 begin
1917 if panels[i].SaveIt then
1918 begin
1919 // ID ïàíåëè:
1920 PAMem.WriteInt(i);
1921 // Ñîõðàíÿåì ïàíåëü:
1922 panels[i].SaveState(PAMem);
1923 end;
1924 Inc(i);
1925 end;
1927 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé:
1928 PAMem.SaveToMemory(Mem);
1929 PAMem.Free();
1930 end;
1932 procedure SaveFlag(flag: PFlag);
1933 begin
1934 // Ñèãíàòóðà ôëàãà:
1935 dw := FLAG_SIGNATURE; // 'FLAG'
1936 Mem.WriteDWORD(dw);
1937 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
1938 Mem.WriteByte(flag^.RespawnType);
1939 // Ñîñòîÿíèå ôëàãà:
1940 Mem.WriteByte(flag^.State);
1941 // Íàïðàâëåíèå ôëàãà:
1942 if flag^.Direction = D_LEFT then
1943 b := 1
1944 else // D_RIGHT
1945 b := 2;
1946 Mem.WriteByte(b);
1947 // Îáúåêò ôëàãà:
1948 Obj_SaveState(@flag^.Obj, Mem);
1949 end;
1951 begin
1952 Mem := TBinMemoryWriter.Create(1024 * 1024); // 1 MB
1954 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
1955 // Ñîõðàíÿåì ïàíåëè ñòåí è äâåðåé:
1956 SavePanelArray(gWalls);
1957 // Ñîõðàíÿåì ïàíåëè ôîíà:
1958 SavePanelArray(gRenderBackgrounds);
1959 // Ñîõðàíÿåì ïàíåëè ïåðåäíåãî ïëàíà:
1960 SavePanelArray(gRenderForegrounds);
1961 // Ñîõðàíÿåì ïàíåëè âîäû:
1962 SavePanelArray(gWater);
1963 // Ñîõðàíÿåì ïàíåëè êèñëîòû-1:
1964 SavePanelArray(gAcid1);
1965 // Ñîõðàíÿåì ïàíåëè êèñëîòû-2:
1966 SavePanelArray(gAcid2);
1967 // Ñîõðàíÿåì ïàíåëè ñòóïåíåé:
1968 SavePanelArray(gSteps);
1969 // Ñîõðàíÿåì ïàíåëè ëèôòîâ:
1970 SavePanelArray(gLifts);
1971 ///// /////
1973 ///// Ñîõðàíÿåì ìóçûêó: /////
1974 // Ñèãíàòóðà ìóçûêè:
1975 dw := MUSIC_SIGNATURE; // 'MUSI'
1976 Mem.WriteDWORD(dw);
1977 // Íàçâàíèå ìóçûêè:
1978 Assert(gMusic <> nil, 'g_Map_SaveState: gMusic = nil');
1979 if gMusic.NoMusic then
1980 str := ''
1981 else
1982 str := gMusic.Name;
1983 Mem.WriteString(str, 64);
1984 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
1985 dw := gMusic.GetPosition();
1986 Mem.WriteDWORD(dw);
1987 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
1988 boo := gMusic.SpecPause;
1989 Mem.WriteBoolean(boo);
1990 ///// /////
1992 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
1993 Mem.WriteInt(gTotalMonsters);
1994 ///// /////
1996 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
1997 if gGameSettings.GameMode = GM_CTF then
1998 begin
1999 // Ôëàã Êðàñíîé êîìàíäû:
2000 SaveFlag(@gFlags[FLAG_RED]);
2001 // Ôëàã Ñèíåé êîìàíäû:
2002 SaveFlag(@gFlags[FLAG_BLUE]);
2003 end;
2004 ///// /////
2006 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2007 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2008 begin
2009 // Î÷êè Êðàñíîé êîìàíäû:
2010 Mem.WriteSmallInt(gTeamStat[TEAM_RED].Goals);
2011 // Î÷êè Ñèíåé êîìàíäû:
2012 Mem.WriteSmallInt(gTeamStat[TEAM_BLUE].Goals);
2013 end;
2014 ///// /////
2015 end;
2017 procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
2018 var
2019 dw: DWORD;
2020 b: Byte;
2021 str: String;
2022 boo: Boolean;
2024 procedure LoadPanelArray(var panels: TPanelArray);
2025 var
2026 PAMem: TBinMemoryReader;
2027 i, id: Integer;
2028 begin
2029 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé:
2030 PAMem := TBinMemoryReader.Create();
2031 PAMem.LoadFromMemory(Mem);
2033 for i := 0 to Length(panels)-1 do
2034 if panels[i].SaveIt then
2035 begin
2036 // ID ïàíåëè:
2037 PAMem.ReadInt(id);
2038 if id <> i then
2039 begin
2040 raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel ID');
2041 end;
2042 // Çàãðóæàåì ïàíåëü:
2043 panels[i].LoadState(PAMem);
2044 end;
2046 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí:
2047 PAMem.Free();
2048 end;
2050 procedure LoadFlag(flag: PFlag);
2051 begin
2052 // Ñèãíàòóðà ôëàãà:
2053 Mem.ReadDWORD(dw);
2054 if dw <> FLAG_SIGNATURE then // 'FLAG'
2055 begin
2056 raise EBinSizeError.Create('g_Map_LoadState: LoadFlag: Wrong Flag Signature');
2057 end;
2058 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
2059 Mem.ReadByte(flag^.RespawnType);
2060 // Ñîñòîÿíèå ôëàãà:
2061 Mem.ReadByte(flag^.State);
2062 // Íàïðàâëåíèå ôëàãà:
2063 Mem.ReadByte(b);
2064 if b = 1 then
2065 flag^.Direction := D_LEFT
2066 else // b = 2
2067 flag^.Direction := D_RIGHT;
2068 // Îáúåêò ôëàãà:
2069 Obj_LoadState(@flag^.Obj, Mem);
2070 end;
2072 begin
2073 if Mem = nil then
2074 Exit;
2076 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
2077 // Çàãðóæàåì ïàíåëè ñòåí è äâåðåé:
2078 LoadPanelArray(gWalls);
2079 // Çàãðóæàåì ïàíåëè ôîíà:
2080 LoadPanelArray(gRenderBackgrounds);
2081 // Çàãðóæàåì ïàíåëè ïåðåäíåãî ïëàíà:
2082 LoadPanelArray(gRenderForegrounds);
2083 // Çàãðóæàåì ïàíåëè âîäû:
2084 LoadPanelArray(gWater);
2085 // Çàãðóæàåì ïàíåëè êèñëîòû-1:
2086 LoadPanelArray(gAcid1);
2087 // Çàãðóæàåì ïàíåëè êèñëîòû-2:
2088 LoadPanelArray(gAcid2);
2089 // Çàãðóæàåì ïàíåëè ñòóïåíåé:
2090 LoadPanelArray(gSteps);
2091 // Çàãðóæàåì ïàíåëè ëèôòîâ:
2092 LoadPanelArray(gLifts);
2093 ///// /////
2095 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé:
2096 g_GFX_Init();
2098 ///// Çàãðóæàåì ìóçûêó: /////
2099 // Ñèãíàòóðà ìóçûêè:
2100 Mem.ReadDWORD(dw);
2101 if dw <> MUSIC_SIGNATURE then // 'MUSI'
2102 begin
2103 raise EBinSizeError.Create('g_Map_LoadState: Wrong Music Signature');
2104 end;
2105 // Íàçâàíèå ìóçûêè:
2106 Assert(gMusic <> nil, 'g_Map_LoadState: gMusic = nil');
2107 Mem.ReadString(str);
2108 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
2109 Mem.ReadDWORD(dw);
2110 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
2111 Mem.ReadBoolean(boo);
2112 // Çàïóñêàåì ýòó ìóçûêó:
2113 gMusic.SetByName(str);
2114 gMusic.SpecPause := boo;
2115 gMusic.Play();
2116 gMusic.Pause(True);
2117 gMusic.SetPosition(dw);
2118 ///// /////
2120 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
2121 Mem.ReadInt(gTotalMonsters);
2122 ///// /////
2124 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
2125 if gGameSettings.GameMode = GM_CTF then
2126 begin
2127 // Ôëàã Êðàñíîé êîìàíäû:
2128 LoadFlag(@gFlags[FLAG_RED]);
2129 // Ôëàã Ñèíåé êîìàíäû:
2130 LoadFlag(@gFlags[FLAG_BLUE]);
2131 end;
2132 ///// /////
2134 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2135 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2136 begin
2137 // Î÷êè Êðàñíîé êîìàíäû:
2138 Mem.ReadSmallInt(gTeamStat[TEAM_RED].Goals);
2139 // Î÷êè Ñèíåé êîìàíäû:
2140 Mem.ReadSmallInt(gTeamStat[TEAM_BLUE].Goals);
2141 end;
2142 ///// /////
2143 end;
2145 end.