DEADSOFTWARE

2c611442025585a94d1c42d998ff5c900c6d2f6d
[d2df-sdl.git] / src / game / g_map.pas
1 {$MODE DELPHI}
2 unit g_map;
4 interface
6 uses
7 e_graphics, g_basic, MAPSTRUCT, g_textures, Classes,
8 g_phys, wadreader, BinEditor, g_panel, md5;
10 type
11 TMapInfo = record
12 Map: String;
13 Name: String;
14 Description: String;
15 Author: String;
16 MusicName: String;
17 SkyName: String;
18 Height: Word;
19 Width: Word;
20 end;
22 PRespawnPoint = ^TRespawnPoint;
23 TRespawnPoint = record
24 X, Y: Integer;
25 Direction: TDirection;
26 PointType: Byte;
27 end;
29 PFlagPoint = ^TFlagPoint;
30 TFlagPoint = TRespawnPoint;
32 PFlag = ^TFlag;
33 TFlag = record
34 Obj: TObj;
35 RespawnType: Byte;
36 State: Byte;
37 Count: Integer;
38 CaptureTime: LongWord;
39 Animation: TAnimation;
40 Direction: TDirection;
41 end;
44 function g_Map_Load(Res: String): Boolean;
45 function g_Map_GetMapInfo(Res: String): TMapInfo;
46 function g_Map_GetMapsList(WADName: String): SArray;
47 function g_Map_Exist(Res: String): Boolean;
48 procedure g_Map_Free();
49 procedure g_Map_Update();
50 procedure g_Map_DrawPanels(PanelType: Word);
51 procedure g_Map_DrawBack(dx, dy: Integer);
52 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word;
53 PanelType: Word; b1x3: Boolean): Boolean;
54 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
55 procedure g_Map_EnableWall(ID: DWORD);
56 procedure g_Map_DisableWall(ID: DWORD);
57 procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0);
58 procedure g_Map_SetLift(ID: DWORD; t: Integer);
59 procedure g_Map_ReAdd_DieTriggers();
60 function g_Map_IsSpecialTexture(Texture: String): Boolean;
62 function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean;
63 function g_Map_GetPointCount(PointType: Byte): Word;
65 function g_Map_HaveFlagPoints(): Boolean;
67 procedure g_Map_ResetFlag(Flag: Byte);
68 procedure g_Map_DrawFlags();
70 procedure g_Map_SaveState(Var Mem: TBinMemoryWriter);
71 procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
73 const
74 RESPAWNPOINT_PLAYER1 = 1;
75 RESPAWNPOINT_PLAYER2 = 2;
76 RESPAWNPOINT_DM = 3;
77 RESPAWNPOINT_RED = 4;
78 RESPAWNPOINT_BLUE = 5;
80 FLAG_NONE = 0;
81 FLAG_RED = 1;
82 FLAG_BLUE = 2;
83 FLAG_DOM = 3;
85 FLAG_STATE_NONE = 0;
86 FLAG_STATE_NORMAL = 1;
87 FLAG_STATE_DROPPED = 2;
88 FLAG_STATE_CAPTURED = 3;
89 FLAG_STATE_SCORED = 4; // Äëÿ ýâåíòîâ ÷åðåç ñåòêó.
90 FLAG_STATE_RETURNED = 5; // Äëÿ ýâåíòîâ ÷åðåç ñåòêó.
92 FLAG_TIME = 720; // 20 seconds
94 SKY_STRETCH: Single = 1.5;
96 var
97 gWalls: TPanelArray;
98 gRenderBackgrounds: TPanelArray;
99 gRenderForegrounds: TPanelArray;
100 gWater, gAcid1, gAcid2: TPanelArray;
101 gSteps: TPanelArray;
102 gLifts: TPanelArray;
103 gBlockMon: TPanelArray;
104 gFlags: array [FLAG_RED..FLAG_BLUE] of TFlag;
105 //gDOMFlags: array of TFlag;
106 gMapInfo: TMapInfo;
107 gBackSize: TPoint;
108 gDoorMap: array of array of DWORD;
109 gLiftMap: array of array of DWORD;
110 gWADHash: TMD5Digest;
111 BackID: DWORD = DWORD(-1);
112 gExternalResources: TStringList;
114 implementation
116 uses
117 g_main, e_log, SysUtils, g_items, g_gfx, g_console,
118 GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG,
119 g_options, MAPREADER, g_triggers, g_player, MAPDEF,
120 Math, g_monsters, g_saveload, g_language, g_netmsg,
121 utils, sfs;
123 const
124 FLAGRECT: TRectWH = (X:15; Y:12; Width:33; Height:52);
125 MUSIC_SIGNATURE = $4953554D; // 'MUSI'
126 FLAG_SIGNATURE = $47414C46; // 'FLAG'
128 var
129 Textures: TLevelTextureArray;
130 RespawnPoints: Array of TRespawnPoint;
131 FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint;
132 //DOMFlagPoints: Array of TFlagPoint;
135 function g_Map_IsSpecialTexture(Texture: String): Boolean;
136 begin
137 Result := (Texture = TEXTURE_NAME_WATER) or
138 (Texture = TEXTURE_NAME_ACID1) or
139 (Texture = TEXTURE_NAME_ACID2);
140 end;
142 procedure CreateDoorMap();
143 var
144 PanelArray: Array of record
145 X, Y: Integer;
146 Width, Height: Word;
147 Active: Boolean;
148 PanelID: DWORD;
149 end;
150 a, b, c, m, i, len: Integer;
151 ok: Boolean;
152 begin
153 if gWalls = nil then
154 Exit;
156 i := 0;
157 len := 128;
158 SetLength(PanelArray, len);
160 for a := 0 to High(gWalls) do
161 if gWalls[a].Door then
162 begin
163 PanelArray[i].X := gWalls[a].X;
164 PanelArray[i].Y := gWalls[a].Y;
165 PanelArray[i].Width := gWalls[a].Width;
166 PanelArray[i].Height := gWalls[a].Height;
167 PanelArray[i].Active := True;
168 PanelArray[i].PanelID := a;
170 i := i + 1;
171 if i = len then
172 begin
173 len := len + 128;
174 SetLength(PanelArray, len);
175 end;
176 end;
178 // Íåò äâåðåé:
179 if i = 0 then
180 begin
181 PanelArray := nil;
182 Exit;
183 end;
185 SetLength(gDoorMap, 0);
187 g_Game_SetLoadingText(_lc[I_LOAD_DOOR_MAP], i-1, False);
189 for a := 0 to i-1 do
190 if PanelArray[a].Active then
191 begin
192 PanelArray[a].Active := False;
193 m := Length(gDoorMap);
194 SetLength(gDoorMap, m+1);
195 SetLength(gDoorMap[m], 1);
196 gDoorMap[m, 0] := PanelArray[a].PanelID;
197 ok := True;
199 while ok do
200 begin
201 ok := False;
203 for b := 0 to i-1 do
204 if PanelArray[b].Active then
205 for c := 0 to High(gDoorMap[m]) do
206 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
207 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
208 g_CollideAround(PanelArray[b].X, PanelArray[b].Y,
209 PanelArray[b].Width, PanelArray[b].Height,
210 gWalls[gDoorMap[m, c]].X,
211 gWalls[gDoorMap[m, c]].Y,
212 gWalls[gDoorMap[m, c]].Width,
213 gWalls[gDoorMap[m, c]].Height) then
214 begin
215 PanelArray[b].Active := False;
216 SetLength(gDoorMap[m],
217 Length(gDoorMap[m])+1);
218 gDoorMap[m, High(gDoorMap[m])] := PanelArray[b].PanelID;
219 ok := True;
220 Break;
221 end;
222 end;
224 g_Game_StepLoading();
225 end;
227 PanelArray := nil;
228 end;
230 procedure CreateLiftMap();
231 var
232 PanelArray: Array of record
233 X, Y: Integer;
234 Width, Height: Word;
235 Active: Boolean;
236 end;
237 a, b, c, len, i, j: Integer;
238 ok: Boolean;
239 begin
240 if gLifts = nil then
241 Exit;
243 len := Length(gLifts);
244 SetLength(PanelArray, len);
246 for a := 0 to len-1 do
247 begin
248 PanelArray[a].X := gLifts[a].X;
249 PanelArray[a].Y := gLifts[a].Y;
250 PanelArray[a].Width := gLifts[a].Width;
251 PanelArray[a].Height := gLifts[a].Height;
252 PanelArray[a].Active := True;
253 end;
255 SetLength(gLiftMap, len);
256 i := 0;
258 g_Game_SetLoadingText(_lc[I_LOAD_LIFT_MAP], len-1, False);
260 for a := 0 to len-1 do
261 if PanelArray[a].Active then
262 begin
263 PanelArray[a].Active := False;
264 SetLength(gLiftMap[i], 32);
265 j := 0;
266 gLiftMap[i, j] := a;
267 ok := True;
269 while ok do
270 begin
271 ok := False;
272 for b := 0 to len-1 do
273 if PanelArray[b].Active then
274 for c := 0 to j do
275 if g_CollideAround(PanelArray[b].X,
276 PanelArray[b].Y,
277 PanelArray[b].Width,
278 PanelArray[b].Height,
279 PanelArray[gLiftMap[i, c]].X,
280 PanelArray[gLiftMap[i, c]].Y,
281 PanelArray[gLiftMap[i, c]].Width,
282 PanelArray[gLiftMap[i, c]].Height) then
283 begin
284 PanelArray[b].Active := False;
285 j := j+1;
286 if j > High(gLiftMap[i]) then
287 SetLength(gLiftMap[i],
288 Length(gLiftMap[i])+32);
290 gLiftMap[i, j] := b;
291 ok := True;
293 Break;
294 end;
295 end;
297 SetLength(gLiftMap[i], j+1);
298 i := i+1;
300 g_Game_StepLoading();
301 end;
303 SetLength(gLiftMap, i);
305 PanelArray := nil;
306 end;
308 function CreatePanel(PanelRec: TPanelRec_1; AddTextures: TAddTextureArray;
309 CurTex: Integer; sav: Boolean): Integer;
310 var
311 len: Integer;
312 panels: ^TPanelArray;
313 begin
314 Result := -1;
316 case PanelRec.PanelType of
317 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR:
318 panels := @gWalls;
319 PANEL_BACK:
320 panels := @gRenderBackgrounds;
321 PANEL_FORE:
322 panels := @gRenderForegrounds;
323 PANEL_WATER:
324 panels := @gWater;
325 PANEL_ACID1:
326 panels := @gAcid1;
327 PANEL_ACID2:
328 panels := @gAcid2;
329 PANEL_STEP:
330 panels := @gSteps;
331 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT:
332 panels := @gLifts;
333 PANEL_BLOCKMON:
334 panels := @gBlockMon;
335 else
336 Exit;
337 end;
339 len := Length(panels^);
340 SetLength(panels^, len + 1);
342 panels^[len] := TPanel.Create(PanelRec, AddTextures,
343 CurTex, Textures);
344 if sav then
345 panels^[len].SaveIt := True;
347 Result := len;
348 end;
350 function CreateNullTexture(RecName: String): Integer;
351 begin
352 SetLength(Textures, Length(Textures)+1);
353 result := High(Textures);
355 with Textures[High(Textures)] do
356 begin
357 TextureName := RecName;
358 Width := 1;
359 Height := 1;
360 Anim := False;
361 TextureID := TEXTURE_NONE;
362 end;
363 end;
365 function CreateTexture(RecName: String; Map: string; log: Boolean): Integer;
366 var
367 WAD: TWADFile;
368 TextureData: Pointer;
369 WADName: String;
370 a, ResLength: Integer;
371 begin
372 Result := -1;
374 if Textures <> nil then
375 for a := 0 to High(Textures) do
376 if Textures[a].TextureName = RecName then
377 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
378 Result := a;
379 Exit;
380 end;
382 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
383 if (RecName = TEXTURE_NAME_WATER) or
384 (RecName = TEXTURE_NAME_ACID1) or
385 (RecName = TEXTURE_NAME_ACID2) then
386 begin
387 SetLength(Textures, Length(Textures)+1);
389 with Textures[High(Textures)] do
390 begin
391 TextureName := RecName;
393 if TextureName = TEXTURE_NAME_WATER then
394 TextureID := TEXTURE_SPECIAL_WATER
395 else
396 if TextureName = TEXTURE_NAME_ACID1 then
397 TextureID := TEXTURE_SPECIAL_ACID1
398 else
399 if TextureName = TEXTURE_NAME_ACID2 then
400 TextureID := TEXTURE_SPECIAL_ACID2;
402 Anim := False;
403 end;
405 result := High(Textures);
406 Exit;
407 end;
409 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
410 WADName := g_ExtractWadName(RecName);
412 WAD := TWADFile.Create();
414 if WADName <> '' then
415 WADName := GameDir+'/wads/'+WADName
416 else
417 WADName := Map;
419 WAD.ReadFile(WADName);
421 if WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
422 begin
423 SetLength(Textures, Length(Textures)+1);
424 if not e_CreateTextureMem(TextureData, ResLength, Textures[High(Textures)].TextureID) then
425 Exit;
426 e_GetTextureSize(Textures[High(Textures)].TextureID,
427 @Textures[High(Textures)].Width,
428 @Textures[High(Textures)].Height);
429 FreeMem(TextureData);
430 Textures[High(Textures)].TextureName := RecName;
431 Textures[High(Textures)].Anim := False;
433 result := High(Textures);
434 end
435 else // Íåò òàêîãî ðåóñðñà â WAD'å
436 if log then
437 begin
438 e_WriteLog(Format('Error loading texture %s', [RecName]), MSG_WARNING);
439 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
440 end;
442 WAD.Free();
443 end;
445 function CreateAnimTexture(RecName: String; Map: string; log: Boolean): Integer;
446 var
447 WAD: TWADFile;
448 TextureWAD: Pointer;
449 TextData: Pointer;
450 TextureData: Pointer;
451 cfg: TConfig;
452 WADName: String;
453 ResLength: Integer;
454 TextureResource: String;
455 _width, _height, _framecount, _speed: Integer;
456 _backanimation: Boolean;
457 begin
458 Result := -1;
460 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
461 WADName := g_ExtractWadName(RecName);
463 WAD := TWADFile.Create();
465 if WADName <> '' then
466 WADName := GameDir+'/wads/'+WADName
467 else
468 WADName := Map;
470 WAD.ReadFile(WADName);
472 if not WAD.GetResource(g_ExtractFilePathName(RecName), TextureWAD, ResLength) then
473 begin
474 if log then
475 begin
476 e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
477 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
478 end;
479 WAD.Free();
480 Exit;
481 end;
483 WAD.FreeWAD();
485 if not WAD.ReadMemory(TextureWAD, ResLength) then
486 begin
487 FreeMem(TextureWAD);
488 WAD.Free();
489 Exit;
490 end;
492 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
493 if not WAD.GetResource('TEXT/ANIM', TextData, ResLength) then
494 begin
495 FreeMem(TextureWAD);
496 WAD.Free();
497 Exit;
498 end;
500 cfg := TConfig.CreateMem(TextData, ResLength);
502 TextureResource := cfg.ReadStr('', 'resource', '');
504 if TextureResource = '' then
505 begin
506 FreeMem(TextureWAD);
507 FreeMem(TextData);
508 WAD.Free();
509 cfg.Free();
510 Exit;
511 end;
513 _width := cfg.ReadInt('', 'framewidth', 0);
514 _height := cfg.ReadInt('', 'frameheight', 0);
515 _framecount := cfg.ReadInt('', 'framecount', 0);
516 _speed := cfg.ReadInt('', 'waitcount', 0);
517 _backanimation := cfg.ReadBool('', 'backanimation', False);
519 cfg.Free();
521 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
522 if not WAD.GetResource('TEXTURES/'+TextureResource, TextureData, ResLength) then
523 begin
524 FreeMem(TextureWAD);
525 FreeMem(TextData);
526 WAD.Free();
527 Exit;
528 end;
530 WAD.Free();
532 SetLength(Textures, Length(Textures)+1);
533 with Textures[High(Textures)] do
534 begin
535 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
536 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength,
537 _width, _height, _framecount, _backanimation) then
538 begin
539 TextureName := RecName;
540 Width := _width;
541 Height := _height;
542 Anim := True;
543 FramesCount := _framecount;
544 Speed := _speed;
546 result := High(Textures);
547 end
548 else
549 if log then
550 e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
551 end;
553 FreeMem(TextureWAD);
554 FreeMem(TextData);
555 end;
557 procedure CreateItem(Item: TItemRec_1);
558 begin
559 if g_Game_IsClient then Exit;
561 if (not (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF])) and
562 ByteBool(Item.Options and ITEM_OPTION_ONLYDM) then
563 Exit;
565 g_Items_Create(Item.X, Item.Y, Item.ItemType, ByteBool(Item.Options and ITEM_OPTION_FALL),
566 gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF, GM_COOP]);
567 end;
569 procedure CreateArea(Area: TAreaRec_1);
570 var
571 a: Integer;
572 id: DWORD;
573 begin
574 case Area.AreaType of
575 AREA_DMPOINT, AREA_PLAYERPOINT1, AREA_PLAYERPOINT2,
576 AREA_REDTEAMPOINT, AREA_BLUETEAMPOINT:
577 begin
578 SetLength(RespawnPoints, Length(RespawnPoints)+1);
579 with RespawnPoints[High(RespawnPoints)] do
580 begin
581 X := Area.X;
582 Y := Area.Y;
583 Direction := TDirection(Area.Direction);
585 case Area.AreaType of
586 AREA_DMPOINT: PointType := RESPAWNPOINT_DM;
587 AREA_PLAYERPOINT1: PointType := RESPAWNPOINT_PLAYER1;
588 AREA_PLAYERPOINT2: PointType := RESPAWNPOINT_PLAYER2;
589 AREA_REDTEAMPOINT: PointType := RESPAWNPOINT_RED;
590 AREA_BLUETEAMPOINT: PointType := RESPAWNPOINT_BLUE;
591 end;
592 end;
593 end;
595 AREA_REDFLAG, AREA_BLUEFLAG:
596 begin
597 if Area.AreaType = AREA_REDFLAG then a := FLAG_RED else a := FLAG_BLUE;
599 if FlagPoints[a] <> nil then Exit;
601 New(FlagPoints[a]);
603 with FlagPoints[a]^ do
604 begin
605 X := Area.X-FLAGRECT.X;
606 Y := Area.Y-FLAGRECT.Y;
607 Direction := TDirection(Area.Direction);
608 end;
610 with gFlags[a] do
611 begin
612 case a of
613 FLAG_RED: g_Frames_Get(id, 'FRAMES_FLAG_RED');
614 FLAG_BLUE: g_Frames_Get(id, 'FRAMES_FLAG_BLUE');
615 end;
617 Animation := TAnimation.Create(id, True, 8);
618 Obj.Rect := FLAGRECT;
620 g_Map_ResetFlag(a);
621 end;
622 end;
624 AREA_DOMFLAG:
625 begin
626 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
627 with DOMFlagPoints[High(DOMFlagPoints)] do
628 begin
629 X := Area.X;
630 Y := Area.Y;
631 Direction := TDirection(Area.Direction);
632 end;
634 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
635 end;
636 end;
637 end;
639 procedure CreateTrigger(Trigger: TTriggerRec_1; fTexturePanel1Type, fTexturePanel2Type: Word);
640 var
641 _trigger: TTrigger;
642 begin
643 if g_Game_IsClient and not (Trigger.TriggerType in [TRIGGER_SOUND, TRIGGER_MUSIC]) then Exit;
645 with _trigger do
646 begin
647 X := Trigger.X;
648 Y := Trigger.Y;
649 Width := Trigger.Width;
650 Height := Trigger.Height;
651 Enabled := ByteBool(Trigger.Enabled);
652 TexturePanel := Trigger.TexturePanel;
653 TexturePanelType := fTexturePanel1Type;
654 ShotPanelType := fTexturePanel2Type;
655 TriggerType := Trigger.TriggerType;
656 ActivateType := Trigger.ActivateType;
657 Keys := Trigger.Keys;
658 Data.Default := Trigger.DATA;
659 end;
661 g_Triggers_Create(_trigger);
662 end;
664 procedure CreateMonster(monster: TMonsterRec_1);
665 var
666 a, i: Integer;
667 begin
668 if g_Game_IsClient then Exit;
670 if (gGameSettings.GameType = GT_SINGLE)
671 or LongBool(gGameSettings.Options and GAME_OPTION_MONSTERS) then
672 begin
673 i := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y,
674 TDirection(monster.Direction));
676 if gTriggers <> nil then
677 for a := 0 to High(gTriggers) do
678 if gTriggers[a].TriggerType in [TRIGGER_PRESS,
679 TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
680 if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
681 gMonsters[i].AddTrigger(a);
683 if monster.MonsterType <> MONSTER_BARREL then
684 Inc(gTotalMonsters);
685 end;
686 end;
688 procedure g_Map_ReAdd_DieTriggers();
689 var
690 i, a: Integer;
691 begin
692 if g_Game_IsClient then Exit;
694 for i := 0 to High(gMonsters) do
695 if gMonsters[i] <> nil then
696 begin
697 gMonsters[i].ClearTriggers();
699 for a := 0 to High(gTriggers) do
700 if gTriggers[a].TriggerType in [TRIGGER_PRESS,
701 TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
702 if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
703 gMonsters[i].AddTrigger(a);
704 end;
705 end;
707 function extractWadName(resourceName: string): string;
708 var
709 posN: Integer;
710 begin
711 posN := Pos(':', resourceName);
712 if posN > 0 then
713 Result:= Copy(resourceName, 0, posN-1)
714 else
715 Result := '';
716 end;
718 procedure addResToExternalResList(res: string);
719 begin
720 res := extractWadName(res);
721 if (res <> '') and (gExternalResources.IndexOf(res) = -1) then
722 gExternalResources.Add(res);
723 end;
725 procedure generateExternalResourcesList(mapReader: TMapReader_1);
726 var
727 textures: TTexturesRec1Array;
728 mapHeader: TMapHeaderRec_1;
729 i: integer;
730 resFile: String = '';
731 begin
732 if gExternalResources = nil then
733 gExternalResources := TStringList.Create;
735 gExternalResources.Clear;
736 textures := mapReader.GetTextures();
737 for i := 0 to High(textures) do
738 begin
739 addResToExternalResList(resFile);
740 end;
742 textures := nil;
744 mapHeader := mapReader.GetMapHeader;
746 addResToExternalResList(mapHeader.MusicName);
747 addResToExternalResList(mapHeader.SkyName);
748 end;
750 function g_Map_Load(Res: String): Boolean;
751 const
752 DefaultMusRes = 'Standart.wad:STDMUS\MUS1';
753 DefaultSkyRes = 'Standart.wad:STDSKY\SKY0';
754 var
755 WAD: TWADFile;
756 MapReader: TMapReader_1;
757 Header: TMapHeaderRec_1;
758 _textures: TTexturesRec1Array;
759 _texnummap: array of Integer; // `_textures` -> `Textures`
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, mapResName, s, TexName: String;
776 Data: Pointer;
777 Len: Integer;
778 ok, isAnim, trigRef: Boolean;
779 CurTex, ntn: Integer;
780 begin
781 Result := False;
782 gMapInfo.Map := Res;
783 TriggersTable := nil;
784 FillChar(texture, SizeOf(texture), 0);
786 sfsGCDisable(); // temporary disable removing of temporary volumes
787 try
788 // Çàãðóçêà WAD:
789 FileName := g_ExtractWadName(Res);
790 e_WriteLog('Loading map WAD: '+FileName, MSG_NOTIFY);
791 g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False);
793 WAD := TWADFile.Create();
794 if not WAD.ReadFile(FileName) then
795 begin
796 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_WAD], [FileName]));
797 WAD.Free();
798 Exit;
799 end;
800 //k8: why loader ignores path here?
801 mapResName := g_ExtractFileName(Res);
802 if not WAD.GetMapResource(mapResName, Data, Len) then
803 begin
804 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_RES], [mapResName]));
805 WAD.Free();
806 Exit;
807 end;
808 WAD.Free();
810 // Çàãðóçêà êàðòû:
811 e_WriteLog('Loading map: '+mapResName, MSG_NOTIFY);
812 g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False);
813 MapReader := TMapReader_1.Create();
815 if not MapReader.LoadMap(Data) then
816 begin
817 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]));
818 FreeMem(Data);
819 MapReader.Free();
820 Exit;
821 end;
823 FreeMem(Data);
824 generateExternalResourcesList(MapReader);
825 // Çàãðóçêà òåêñòóð:
826 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False);
827 _textures := MapReader.GetTextures();
828 _texnummap := nil;
830 // Äîáàâëåíèå òåêñòóð â Textures[]:
831 if _textures <> nil then
832 begin
833 e_WriteLog(' Loading textures:', MSG_NOTIFY);
834 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], High(_textures), False);
835 SetLength(_texnummap, length(_textures));
837 for a := 0 to High(_textures) do
838 begin
839 SetLength(s, 64);
840 CopyMemory(@s[1], @_textures[a].Resource[0], 64);
841 for b := 1 to Length(s) do
842 if s[b] = #0 then
843 begin
844 SetLength(s, b-1);
845 Break;
846 end;
847 e_WriteLog(Format(' Loading texture #%d: %s', [a, s]), MSG_NOTIFY);
848 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
849 // Àíèìèðîâàííàÿ òåêñòóðà:
850 if ByteBool(_textures[a].Anim) then
851 begin
852 ntn := CreateAnimTexture(_textures[a].Resource, FileName, True);
853 if ntn < 0 then
854 begin
855 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s]));
856 ntn := CreateNullTexture(_textures[a].Resource);
857 end;
858 end
859 else // Îáû÷íàÿ òåêñòóðà:
860 ntn := CreateTexture(_textures[a].Resource, FileName, True);
861 if ntn < 0 then
862 begin
863 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s]));
864 ntn := CreateNullTexture(_textures[a].Resource);
865 end;
867 _texnummap[a] := ntn; // fix texture number
868 g_Game_StepLoading();
869 end;
870 end;
872 // Çàãðóçêà òðèããåðîâ:
873 gTriggerClientID := 0;
874 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
875 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS], 0, False);
876 triggers := MapReader.GetTriggers();
878 // Çàãðóçêà ïàíåëåé:
879 e_WriteLog(' Loading panels...', MSG_NOTIFY);
880 g_Game_SetLoadingText(_lc[I_LOAD_PANELS], 0, False);
881 panels := MapReader.GetPanels();
883 // check texture numbers for panels
884 for a := 0 to High(panels) do
885 begin
886 if panels[a].TextureNum > High(_textures) then
887 begin
888 e_WriteLog('error loading map: invalid texture index for panel', MSG_FATALERROR);
889 result := false;
890 exit;
891 end;
892 panels[a].TextureNum := _texnummap[panels[a].TextureNum];
893 end;
895 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì):
896 if triggers <> nil then
897 begin
898 e_WriteLog(' Setting up trigger table...', MSG_NOTIFY);
899 SetLength(TriggersTable, Length(triggers));
900 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], High(TriggersTable), False);
902 for a := 0 to High(TriggersTable) do
903 begin
904 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè):
905 TriggersTable[a].TexturePanel := triggers[a].TexturePanel;
906 // Ëèôòû:
907 if triggers[a].TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then
908 TriggersTable[a].LiftPanel := TTriggerData(triggers[a].DATA).PanelID
909 else
910 TriggersTable[a].LiftPanel := -1;
911 // Äâåðè:
912 if triggers[a].TriggerType in [TRIGGER_OPENDOOR,
913 TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5,
914 TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
915 TriggersTable[a].DoorPanel := TTriggerData(triggers[a].DATA).PanelID
916 else
917 TriggersTable[a].DoorPanel := -1;
918 // Òóðåëü:
919 if triggers[a].TriggerType = TRIGGER_SHOT then
920 TriggersTable[a].ShotPanel := TTriggerData(triggers[a].DATA).ShotPanelID
921 else
922 TriggersTable[a].ShotPanel := -1;
924 g_Game_StepLoading();
925 end;
926 end;
928 // Ñîçäàåì ïàíåëè:
929 if panels <> nil then
930 begin
931 e_WriteLog(' Setting up trigger links...', MSG_NOTIFY);
932 g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], High(panels), False);
934 for a := 0 to High(panels) do
935 begin
936 SetLength(AddTextures, 0);
937 trigRef := False;
938 CurTex := -1;
939 if _textures <> nil then
940 begin
941 texture := _textures[panels[a].TextureNum];
942 ok := True;
943 end
944 else
945 ok := False;
947 if ok then
948 begin
949 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
950 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð:
951 ok := False;
952 if (TriggersTable <> nil) and (_textures <> nil) then
953 for b := 0 to High(TriggersTable) do
954 if (TriggersTable[b].TexturePanel = a)
955 or (TriggersTable[b].ShotPanel = a) then
956 begin
957 trigRef := True;
958 ok := True;
959 Break;
960 end;
961 end;
963 if ok then
964 begin // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
965 SetLength(s, 64);
966 CopyMemory(@s[1], @texture.Resource[0], 64);
967 // Èçìåðÿåì äëèíó:
968 Len := Length(s);
969 for c := Len downto 1 do
970 if s[c] <> #0 then
971 begin
972 Len := c;
973 Break;
974 end;
975 SetLength(s, Len);
977 // Ñïåö-òåêñòóðû çàïðåùåíû:
978 if g_Map_IsSpecialTexture(s) then
979 ok := False
980 else
981 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè:
982 ok := g_Texture_NumNameFindStart(s);
984 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
985 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #:
986 if ok then
987 begin
988 k := NNF_NAME_BEFORE;
989 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû:
990 while ok or (k = NNF_NAME_BEFORE) or
991 (k = NNF_NAME_EQUALS) do
992 begin
993 k := g_Texture_NumNameFindNext(TexName);
995 if (k = NNF_NAME_BEFORE) or
996 (k = NNF_NAME_AFTER) then
997 begin
998 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó:
999 if ByteBool(texture.Anim) then
1000 begin // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
1001 isAnim := True;
1002 ok := CreateAnimTexture(TexName, FileName, False) >= 0;
1003 if not ok then
1004 begin // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
1005 isAnim := False;
1006 ok := CreateTexture(TexName, FileName, False) >= 0;
1007 end;
1008 end
1009 else
1010 begin // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
1011 isAnim := False;
1012 ok := CreateTexture(TexName, FileName, False) >= 0;
1013 if not ok then
1014 begin // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
1015 isAnim := True;
1016 ok := CreateAnimTexture(TexName, FileName, False) >= 0;
1017 end;
1018 end;
1020 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè:
1021 if ok then
1022 begin
1023 for c := 0 to High(Textures) do
1024 if Textures[c].TextureName = TexName then
1025 begin
1026 SetLength(AddTextures, Length(AddTextures)+1);
1027 AddTextures[High(AddTextures)].Texture := c;
1028 AddTextures[High(AddTextures)].Anim := isAnim;
1029 Break;
1030 end;
1031 end;
1032 end
1033 else
1034 if k = NNF_NAME_EQUALS then
1035 begin
1036 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî:
1037 SetLength(AddTextures, Length(AddTextures)+1);
1038 AddTextures[High(AddTextures)].Texture := panels[a].TextureNum;
1039 AddTextures[High(AddTextures)].Anim := ByteBool(texture.Anim);
1040 CurTex := High(AddTextures);
1041 ok := True;
1042 end
1043 else // NNF_NO_NAME
1044 ok := False;
1045 end; // while ok...
1047 ok := True;
1048 end; // if ok - åñòü ñìåæíûå òåêñòóðû
1049 end; // if ok - ññûëàþòñÿ òðèããåðû
1051 if not ok then
1052 begin
1053 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó:
1054 SetLength(AddTextures, 1);
1055 AddTextures[0].Texture := panels[a].TextureNum;
1056 AddTextures[0].Anim := ByteBool(texture.Anim);
1057 CurTex := 0;
1058 end;
1060 //e_WriteLog(Format('panel #%d: TextureNum=%d; ht=%d; ht1=%d; atl=%d', [a, panels[a].TextureNum, High(_textures), High(Textures), High(AddTextures)]), MSG_NOTIFY);
1062 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð:
1063 PanelID := CreatePanel(panels[a], AddTextures, CurTex, trigRef);
1065 // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID:
1066 if TriggersTable <> nil then
1067 for b := 0 to High(TriggersTable) do
1068 begin
1069 // Òðèããåð äâåðè/ëèôòà:
1070 if (TriggersTable[b].LiftPanel = a) or
1071 (TriggersTable[b].DoorPanel = a) then
1072 TTriggerData(triggers[b].DATA).PanelID := PanelID;
1073 // Òðèããåð ñìåíû òåêñòóðû:
1074 if TriggersTable[b].TexturePanel = a then
1075 triggers[b].TexturePanel := PanelID;
1076 // Òðèããåð "Òóðåëü":
1077 if TriggersTable[b].ShotPanel = a then
1078 TTriggerData(triggers[b].DATA).ShotPanelID := PanelID;
1079 end;
1081 g_Game_StepLoading();
1082 end;
1083 end;
1085 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû:
1086 if (triggers <> nil) and not gLoadGameMode then
1087 begin
1088 e_WriteLog(' Creating triggers...', MSG_NOTIFY);
1089 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_TRIGGERS], 0, False);
1090 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü:
1091 for a := 0 to High(triggers) do
1092 begin
1093 if triggers[a].TexturePanel <> -1 then
1094 b := panels[TriggersTable[a].TexturePanel].PanelType
1095 else
1096 b := 0;
1097 if (triggers[a].TriggerType = TRIGGER_SHOT) and
1098 (TTriggerData(triggers[a].DATA).ShotPanelID <> -1) then
1099 c := panels[TriggersTable[a].ShotPanel].PanelType
1100 else
1101 c := 0;
1102 CreateTrigger(triggers[a], b, c);
1103 end;
1104 end;
1106 // Çàãðóçêà ïðåäìåòîâ:
1107 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
1108 g_Game_SetLoadingText(_lc[I_LOAD_ITEMS], 0, False);
1109 items := MapReader.GetItems();
1111 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû:
1112 if (items <> nil) and not gLoadGameMode then
1113 begin
1114 e_WriteLog(' Spawning items...', MSG_NOTIFY);
1115 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_ITEMS], 0, False);
1116 for a := 0 to High(items) do
1117 CreateItem(Items[a]);
1118 end;
1120 // Çàãðóçêà îáëàñòåé:
1121 e_WriteLog(' Loading areas...', MSG_NOTIFY);
1122 g_Game_SetLoadingText(_lc[I_LOAD_AREAS], 0, False);
1123 areas := MapReader.GetAreas();
1125 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè:
1126 if areas <> nil then
1127 begin
1128 e_WriteLog(' Creating areas...', MSG_NOTIFY);
1129 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_AREAS], 0, False);
1130 for a := 0 to High(areas) do
1131 CreateArea(areas[a]);
1132 end;
1134 // Çàãðóçêà ìîíñòðîâ:
1135 e_WriteLog(' Loading monsters...', MSG_NOTIFY);
1136 g_Game_SetLoadingText(_lc[I_LOAD_MONSTERS], 0, False);
1137 monsters := MapReader.GetMonsters();
1139 gTotalMonsters := 0;
1141 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ:
1142 if (monsters <> nil) and not gLoadGameMode then
1143 begin
1144 e_WriteLog(' Spawning monsters...', MSG_NOTIFY);
1145 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_MONSTERS], 0, False);
1146 for a := 0 to High(monsters) do
1147 CreateMonster(monsters[a]);
1148 end;
1150 // Çàãðóçêà îïèñàíèÿ êàðòû:
1151 e_WriteLog(' Reading map info...', MSG_NOTIFY);
1152 g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
1153 Header := MapReader.GetMapHeader();
1155 MapReader.Free();
1157 with gMapInfo do
1158 begin
1159 Name := Header.MapName;
1160 Description := Header.MapDescription;
1161 Author := Header.MapAuthor;
1162 MusicName := Header.MusicName;
1163 SkyName := Header.SkyName;
1164 Height := Header.Height;
1165 Width := Header.Width;
1166 end;
1168 // Çàãðóçêà íåáà:
1169 if gMapInfo.SkyName <> '' then
1170 begin
1171 e_WriteLog(' Loading sky: ' + gMapInfo.SkyName, MSG_NOTIFY);
1172 g_Game_SetLoadingText(_lc[I_LOAD_SKY], 0, False);
1173 FileName := g_ExtractWadName(gMapInfo.SkyName);
1175 if FileName <> '' then
1176 FileName := GameDir+'/wads/'+FileName
1177 else
1178 begin
1179 FileName := g_ExtractWadName(Res);
1180 end;
1182 s := FileName+':'+g_ExtractFilePathName(gMapInfo.SkyName);
1183 if g_Texture_CreateWAD(BackID, s) then
1184 begin
1185 g_Game_SetupScreenSize();
1186 end
1187 else
1188 g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s]));
1189 end;
1191 // Çàãðóçêà ìóçûêè:
1192 ok := False;
1193 if gMapInfo.MusicName <> '' then
1194 begin
1195 e_WriteLog(' Loading music: ' + gMapInfo.MusicName, MSG_NOTIFY);
1196 g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
1197 FileName := g_ExtractWadName(gMapInfo.MusicName);
1199 if FileName <> '' then
1200 FileName := GameDir+'/wads/'+FileName
1201 else
1202 begin
1203 FileName := g_ExtractWadName(Res);
1204 end;
1206 s := FileName+':'+g_ExtractFilePathName(gMapInfo.MusicName);
1207 if g_Sound_CreateWADEx(gMapInfo.MusicName, s, True) then
1208 ok := True
1209 else
1210 g_FatalError(Format(_lc[I_GAME_ERROR_MUSIC], [s]));
1211 end;
1213 // Îñòàëüíûå óñòàíâêè:
1214 CreateDoorMap();
1215 CreateLiftMap();
1217 g_Items_Init();
1218 g_Weapon_Init();
1219 g_Monsters_Init();
1221 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
1222 if not gLoadGameMode then
1223 g_GFX_Init();
1225 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
1226 _textures := nil;
1227 panels := nil;
1228 items := nil;
1229 areas := nil;
1230 triggers := nil;
1231 TriggersTable := nil;
1232 AddTextures := nil;
1234 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
1235 if ok and (not gLoadGameMode) then
1236 begin
1237 gMusic.SetByName(gMapInfo.MusicName);
1238 gMusic.Play();
1239 end
1240 else
1241 gMusic.SetByName('');
1242 finally
1243 sfsGCEnable(); // enable releasing unused volumes
1244 end;
1246 e_WriteLog('Done loading map.', MSG_NOTIFY);
1247 Result := True;
1248 end;
1250 function g_Map_GetMapInfo(Res: String): TMapInfo;
1251 var
1252 WAD: TWADFile;
1253 MapReader: TMapReader_1;
1254 Header: TMapHeaderRec_1;
1255 FileName: String;
1256 Data: Pointer;
1257 Len: Integer;
1258 begin
1259 FillChar(Result, SizeOf(Result), 0);
1260 FileName := g_ExtractWadName(Res);
1262 WAD := TWADFile.Create();
1263 if not WAD.ReadFile(FileName) then
1264 begin
1265 WAD.Free();
1266 Exit;
1267 end;
1269 //k8: it ignores path again
1270 if not WAD.GetMapResource(g_ExtractFileName(Res), Data, Len) then
1271 begin
1272 WAD.Free();
1273 Exit;
1274 end;
1276 WAD.Free();
1278 MapReader := TMapReader_1.Create();
1280 if not MapReader.LoadMap(Data) then
1281 begin
1282 g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True);
1283 ZeroMemory(@Header, SizeOf(Header));
1284 Result.Name := _lc[I_GAME_ERROR_MAP_SELECT];
1285 Result.Description := _lc[I_GAME_ERROR_MAP_SELECT];
1286 end
1287 else
1288 begin
1289 Header := MapReader.GetMapHeader();
1290 Result.Name := Header.MapName;
1291 Result.Description := Header.MapDescription;
1292 end;
1294 FreeMem(Data);
1295 MapReader.Free();
1297 Result.Map := Res;
1298 Result.Author := Header.MapAuthor;
1299 Result.Height := Header.Height;
1300 Result.Width := Header.Width;
1301 end;
1303 function g_Map_GetMapsList(WADName: string): SArray;
1304 var
1305 WAD: TWADFile;
1306 a: Integer;
1307 ResList: SArray;
1308 begin
1309 Result := nil;
1310 WAD := TWADFile.Create();
1311 if not WAD.ReadFile(WADName) then
1312 begin
1313 WAD.Free();
1314 Exit;
1315 end;
1316 ResList := WAD.GetMapResources();
1317 if ResList <> nil then
1318 begin
1319 for a := 0 to High(ResList) do
1320 begin
1321 SetLength(Result, Length(Result)+1);
1322 Result[High(Result)] := ResList[a];
1323 end;
1324 end;
1325 WAD.Free();
1326 end;
1328 function g_Map_Exist(Res: string): Boolean;
1329 var
1330 WAD: TWADFile;
1331 FileName, mnn: string;
1332 ResList: SArray;
1333 a: Integer;
1334 begin
1335 Result := False;
1337 FileName := addWadExtension(g_ExtractWadName(Res));
1339 WAD := TWADFile.Create;
1340 if not WAD.ReadFile(FileName) then
1341 begin
1342 WAD.Free();
1343 Exit;
1344 end;
1346 ResList := WAD.GetMapResources();
1347 WAD.Free();
1349 mnn := g_ExtractFileName(Res);
1350 if ResList <> nil then
1351 for a := 0 to High(ResList) do if StrEquCI1251(ResList[a], mnn) then
1352 begin
1353 Result := True;
1354 Exit;
1355 end;
1356 end;
1358 procedure g_Map_Free();
1359 var
1360 a: Integer;
1362 procedure FreePanelArray(var panels: TPanelArray);
1363 var
1364 i: Integer;
1366 begin
1367 if panels <> nil then
1368 begin
1369 for i := 0 to High(panels) do
1370 panels[i].Free();
1371 panels := nil;
1372 end;
1373 end;
1375 begin
1376 g_GFX_Free();
1377 g_Weapon_Free();
1378 g_Items_Free();
1379 g_Triggers_Free();
1380 g_Monsters_Free();
1382 RespawnPoints := nil;
1383 if FlagPoints[FLAG_RED] <> nil then
1384 begin
1385 Dispose(FlagPoints[FLAG_RED]);
1386 FlagPoints[FLAG_RED] := nil;
1387 end;
1388 if FlagPoints[FLAG_BLUE] <> nil then
1389 begin
1390 Dispose(FlagPoints[FLAG_BLUE]);
1391 FlagPoints[FLAG_BLUE] := nil;
1392 end;
1393 //DOMFlagPoints := nil;
1395 //gDOMFlags := nil;
1397 if Textures <> nil then
1398 begin
1399 for a := 0 to High(Textures) do
1400 if not g_Map_IsSpecialTexture(Textures[a].TextureName) then
1401 if Textures[a].Anim then
1402 g_Frames_DeleteByID(Textures[a].FramesID)
1403 else
1404 if Textures[a].TextureID <> TEXTURE_NONE then
1405 e_DeleteTexture(Textures[a].TextureID);
1407 Textures := nil;
1408 end;
1410 FreePanelArray(gWalls);
1411 FreePanelArray(gRenderBackgrounds);
1412 FreePanelArray(gRenderForegrounds);
1413 FreePanelArray(gWater);
1414 FreePanelArray(gAcid1);
1415 FreePanelArray(gAcid2);
1416 FreePanelArray(gSteps);
1417 FreePanelArray(gLifts);
1418 FreePanelArray(gBlockMon);
1420 if BackID <> DWORD(-1) then
1421 begin
1422 gBackSize.X := 0;
1423 gBackSize.Y := 0;
1424 e_DeleteTexture(BackID);
1425 BackID := DWORD(-1);
1426 end;
1428 g_Game_StopAllSounds(False);
1429 gMusic.FreeSound();
1430 g_Sound_Delete(gMapInfo.MusicName);
1432 gMapInfo.Name := '';
1433 gMapInfo.Description := '';
1434 gMapInfo.MusicName := '';
1435 gMapInfo.Height := 0;
1436 gMapInfo.Width := 0;
1438 gDoorMap := nil;
1439 gLiftMap := nil;
1440 end;
1442 procedure g_Map_Update();
1443 var
1444 a, d, j: Integer;
1445 m: Word;
1446 s: String;
1448 procedure UpdatePanelArray(var panels: TPanelArray);
1449 var
1450 i: Integer;
1452 begin
1453 if panels <> nil then
1454 for i := 0 to High(panels) do
1455 panels[i].Update();
1456 end;
1458 begin
1459 UpdatePanelArray(gWalls);
1460 UpdatePanelArray(gRenderBackgrounds);
1461 UpdatePanelArray(gRenderForegrounds);
1462 UpdatePanelArray(gWater);
1463 UpdatePanelArray(gAcid1);
1464 UpdatePanelArray(gAcid2);
1465 UpdatePanelArray(gSteps);
1467 if gGameSettings.GameMode = GM_CTF then
1468 begin
1469 for a := FLAG_RED to FLAG_BLUE do
1470 if not (gFlags[a].State in [FLAG_STATE_NONE, FLAG_STATE_CAPTURED]) then
1471 with gFlags[a] do
1472 begin
1473 if gFlags[a].Animation <> nil then
1474 gFlags[a].Animation.Update();
1476 m := g_Obj_Move(@Obj, True, True);
1478 if gTime mod (GAME_TICK*2) <> 0 then
1479 Continue;
1481 // Ñîïðîòèâëåíèå âîçäóõà:
1482 Obj.Vel.X := z_dec(Obj.Vel.X, 1);
1484 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó:
1485 if ((Count = 0) or ByteBool(m and MOVE_FALLOUT)) and g_Game_IsServer then
1486 begin
1487 g_Map_ResetFlag(a);
1488 gFlags[a].CaptureTime := 0;
1489 if a = FLAG_RED then
1490 s := _lc[I_PLAYER_FLAG_RED]
1491 else
1492 s := _lc[I_PLAYER_FLAG_BLUE];
1493 g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
1495 if g_Game_IsNet then
1496 MH_SEND_FlagEvent(FLAG_STATE_RETURNED, a, 0);
1497 Continue;
1498 end;
1500 if Count > 0 then
1501 Count := Count - 1;
1503 // Èãðîê áåðåò ôëàã:
1504 if gPlayers <> nil then
1505 begin
1506 j := Random(Length(gPlayers)) - 1;
1508 for d := 0 to High(gPlayers) do
1509 begin
1510 Inc(j);
1511 if j > High(gPlayers) then
1512 j := 0;
1514 if gPlayers[j] <> nil then
1515 if gPlayers[j].Live and
1516 g_Obj_Collide(@Obj, @gPlayers[j].Obj) then
1517 begin
1518 if gPlayers[j].GetFlag(a) then
1519 Break;
1520 end;
1521 end;
1522 end;
1523 end;
1524 end;
1525 end;
1527 procedure g_Map_DrawPanels(PanelType: Word);
1529 procedure DrawPanels(var panels: TPanelArray;
1530 drawDoors: Boolean = False);
1531 var
1532 a: Integer;
1534 begin
1535 if panels <> nil then
1536 for a := 0 to High(panels) do
1537 if not (drawDoors xor panels[a].Door) then
1538 panels[a].Draw();
1539 end;
1541 begin
1542 case PanelType of
1543 PANEL_WALL: DrawPanels(gWalls);
1544 PANEL_CLOSEDOOR: DrawPanels(gWalls, True);
1545 PANEL_BACK: DrawPanels(gRenderBackgrounds);
1546 PANEL_FORE: DrawPanels(gRenderForegrounds);
1547 PANEL_WATER: DrawPanels(gWater);
1548 PANEL_ACID1: DrawPanels(gAcid1);
1549 PANEL_ACID2: DrawPanels(gAcid2);
1550 PANEL_STEP: DrawPanels(gSteps);
1551 end;
1552 end;
1554 procedure g_Map_DrawBack(dx, dy: Integer);
1555 begin
1556 if gDrawBackGround and (BackID <> DWORD(-1)) then
1557 e_DrawSize(BackID, dx, dy, 0, False, False, gBackSize.X, gBackSize.Y)
1558 else
1559 e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
1560 end;
1562 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word;
1563 PanelType: Word; b1x3: Boolean): Boolean;
1564 var
1565 a, h: Integer;
1566 begin
1567 Result := False;
1569 if WordBool(PanelType and PANEL_WALL) then
1570 if gWalls <> nil then
1571 begin
1572 h := High(gWalls);
1574 for a := 0 to h do
1575 if gWalls[a].Enabled and
1576 g_Collide(X, Y, Width, Height,
1577 gWalls[a].X, gWalls[a].Y,
1578 gWalls[a].Width, gWalls[a].Height) then
1579 begin
1580 Result := True;
1581 Exit;
1582 end;
1583 end;
1585 if WordBool(PanelType and PANEL_WATER) then
1586 if gWater <> nil then
1587 begin
1588 h := High(gWater);
1590 for a := 0 to h do
1591 if g_Collide(X, Y, Width, Height,
1592 gWater[a].X, gWater[a].Y,
1593 gWater[a].Width, gWater[a].Height) then
1594 begin
1595 Result := True;
1596 Exit;
1597 end;
1598 end;
1600 if WordBool(PanelType and PANEL_ACID1) then
1601 if gAcid1 <> nil then
1602 begin
1603 h := High(gAcid1);
1605 for a := 0 to h do
1606 if g_Collide(X, Y, Width, Height,
1607 gAcid1[a].X, gAcid1[a].Y,
1608 gAcid1[a].Width, gAcid1[a].Height) then
1609 begin
1610 Result := True;
1611 Exit;
1612 end;
1613 end;
1615 if WordBool(PanelType and PANEL_ACID2) then
1616 if gAcid2 <> nil then
1617 begin
1618 h := High(gAcid2);
1620 for a := 0 to h do
1621 if g_Collide(X, Y, Width, Height,
1622 gAcid2[a].X, gAcid2[a].Y,
1623 gAcid2[a].Width, gAcid2[a].Height) then
1624 begin
1625 Result := True;
1626 Exit;
1627 end;
1628 end;
1630 if WordBool(PanelType and PANEL_STEP) then
1631 if gSteps <> nil then
1632 begin
1633 h := High(gSteps);
1635 for a := 0 to h do
1636 if g_Collide(X, Y, Width, Height,
1637 gSteps[a].X, gSteps[a].Y,
1638 gSteps[a].Width, gSteps[a].Height) then
1639 begin
1640 Result := True;
1641 Exit;
1642 end;
1643 end;
1645 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
1646 if gLifts <> nil then
1647 begin
1648 h := High(gLifts);
1650 for a := 0 to h do
1651 if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = 0)) or
1652 (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = 1)) or
1653 (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = 2)) or
1654 (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = 3))) and
1655 g_Collide(X, Y, Width, Height,
1656 gLifts[a].X, gLifts[a].Y,
1657 gLifts[a].Width, gLifts[a].Height) then
1658 begin
1659 Result := True;
1660 Exit;
1661 end;
1662 end;
1664 if WordBool(PanelType and PANEL_BLOCKMON) then
1665 if gBlockMon <> nil then
1666 begin
1667 h := High(gBlockMon);
1669 for a := 0 to h do
1670 if ( (not b1x3) or
1671 ((gBlockMon[a].Width + gBlockMon[a].Height) >= 64) ) and
1672 g_Collide(X, Y, Width, Height,
1673 gBlockMon[a].X, gBlockMon[a].Y,
1674 gBlockMon[a].Width, gBlockMon[a].Height) then
1675 begin
1676 Result := True;
1677 Exit;
1678 end;
1679 end;
1680 end;
1682 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
1683 var
1684 a, h: Integer;
1685 begin
1686 Result := TEXTURE_NONE;
1688 if gWater <> nil then
1689 begin
1690 h := High(gWater);
1692 for a := 0 to h do
1693 if g_Collide(X, Y, Width, Height,
1694 gWater[a].X, gWater[a].Y,
1695 gWater[a].Width, gWater[a].Height) then
1696 begin
1697 Result := gWater[a].GetTextureID();
1698 Exit;
1699 end;
1700 end;
1702 if gAcid1 <> nil then
1703 begin
1704 h := High(gAcid1);
1706 for a := 0 to h do
1707 if g_Collide(X, Y, Width, Height,
1708 gAcid1[a].X, gAcid1[a].Y,
1709 gAcid1[a].Width, gAcid1[a].Height) then
1710 begin
1711 Result := gAcid1[a].GetTextureID();
1712 Exit;
1713 end;
1714 end;
1716 if gAcid2 <> nil then
1717 begin
1718 h := High(gAcid2);
1720 for a := 0 to h do
1721 if g_Collide(X, Y, Width, Height,
1722 gAcid2[a].X, gAcid2[a].Y,
1723 gAcid2[a].Width, gAcid2[a].Height) then
1724 begin
1725 Result := gAcid2[a].GetTextureID();
1726 Exit;
1727 end;
1728 end;
1729 end;
1731 procedure g_Map_EnableWall(ID: DWORD);
1732 begin
1733 with gWalls[ID] do
1734 begin
1735 Enabled := True;
1736 g_Mark(X, Y, Width, Height, MARK_DOOR, True);
1738 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1739 end;
1740 end;
1742 procedure g_Map_DisableWall(ID: DWORD);
1743 begin
1744 with gWalls[ID] do
1745 begin
1746 Enabled := False;
1747 g_Mark(X, Y, Width, Height, MARK_DOOR, False);
1749 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1750 end;
1751 end;
1753 procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0);
1754 var
1755 tp: TPanel;
1756 begin
1757 case PanelType of
1758 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR:
1759 tp := gWalls[ID];
1760 PANEL_FORE:
1761 tp := gRenderForegrounds[ID];
1762 PANEL_BACK:
1763 tp := gRenderBackgrounds[ID];
1764 PANEL_WATER:
1765 tp := gWater[ID];
1766 PANEL_ACID1:
1767 tp := gAcid1[ID];
1768 PANEL_ACID2:
1769 tp := gAcid2[ID];
1770 PANEL_STEP:
1771 tp := gSteps[ID];
1772 else
1773 Exit;
1774 end;
1776 tp.NextTexture(AnimLoop);
1777 if g_Game_IsServer and g_Game_IsNet then
1778 MH_SEND_PanelTexture(PanelType, ID, AnimLoop);
1779 end;
1781 procedure g_Map_SetLift(ID: DWORD; t: Integer);
1782 begin
1783 if gLifts[ID].LiftType = t then
1784 Exit;
1786 with gLifts[ID] do
1787 begin
1788 LiftType := t;
1790 g_Mark(X, Y, Width, Height, MARK_LIFT, False);
1792 if LiftType = 0 then
1793 g_Mark(X, Y, Width, Height, MARK_LIFTUP, True)
1794 else if LiftType = 1 then
1795 g_Mark(X, Y, Width, Height, MARK_LIFTDOWN, True)
1796 else if LiftType = 2 then
1797 g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True)
1798 else if LiftType = 3 then
1799 g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True);
1801 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1802 end;
1803 end;
1805 function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean;
1806 var
1807 a: Integer;
1808 PointsArray: Array of TRespawnPoint;
1809 begin
1810 Result := False;
1811 SetLength(PointsArray, 0);
1813 if RespawnPoints = nil then
1814 Exit;
1816 for a := 0 to High(RespawnPoints) do
1817 if RespawnPoints[a].PointType = PointType then
1818 begin
1819 SetLength(PointsArray, Length(PointsArray)+1);
1820 PointsArray[High(PointsArray)] := RespawnPoints[a];
1821 end;
1823 if PointsArray = nil then
1824 Exit;
1826 RespawnPoint := PointsArray[Random(Length(PointsArray))];
1827 Result := True;
1828 end;
1830 function g_Map_GetPointCount(PointType: Byte): Word;
1831 var
1832 a: Integer;
1833 begin
1834 Result := 0;
1836 if RespawnPoints = nil then
1837 Exit;
1839 for a := 0 to High(RespawnPoints) do
1840 if RespawnPoints[a].PointType = PointType then
1841 Result := Result + 1;
1842 end;
1844 function g_Map_HaveFlagPoints(): Boolean;
1845 begin
1846 Result := (FlagPoints[FLAG_RED] <> nil) and (FlagPoints[FLAG_BLUE] <> nil);
1847 end;
1849 procedure g_Map_ResetFlag(Flag: Byte);
1850 begin
1851 with gFlags[Flag] do
1852 begin
1853 Obj.X := -1000;
1854 Obj.Y := -1000;
1855 Obj.Vel.X := 0;
1856 Obj.Vel.Y := 0;
1857 Direction := D_LEFT;
1858 State := FLAG_STATE_NONE;
1859 if FlagPoints[Flag] <> nil then
1860 begin
1861 Obj.X := FlagPoints[Flag]^.X;
1862 Obj.Y := FlagPoints[Flag]^.Y;
1863 Direction := FlagPoints[Flag]^.Direction;
1864 State := FLAG_STATE_NORMAL;
1865 end;
1866 Count := -1;
1867 end;
1868 end;
1870 procedure g_Map_DrawFlags();
1871 var
1872 i, dx: Integer;
1873 Mirror: TMirrorType;
1874 begin
1875 if gGameSettings.GameMode <> GM_CTF then
1876 Exit;
1878 for i := FLAG_RED to FLAG_BLUE do
1879 with gFlags[i] do
1880 if State <> FLAG_STATE_CAPTURED then
1881 begin
1882 if State = FLAG_STATE_NONE then
1883 continue;
1885 if Direction = D_LEFT then
1886 begin
1887 Mirror := M_HORIZONTAL;
1888 dx := -1;
1889 end
1890 else
1891 begin
1892 Mirror := M_NONE;
1893 dx := 1;
1894 end;
1896 Animation.Draw(Obj.X+dx, Obj.Y+1, Mirror);
1898 if g_debug_Frames then
1899 begin
1900 e_DrawQuad(Obj.X+Obj.Rect.X,
1901 Obj.Y+Obj.Rect.Y,
1902 Obj.X+Obj.Rect.X+Obj.Rect.Width-1,
1903 Obj.Y+Obj.Rect.Y+Obj.Rect.Height-1,
1904 0, 255, 0);
1905 end;
1906 end;
1907 end;
1909 procedure g_Map_SaveState(Var Mem: TBinMemoryWriter);
1910 var
1911 dw: DWORD;
1912 b: Byte;
1913 str: String;
1914 boo: Boolean;
1916 procedure SavePanelArray(var panels: TPanelArray);
1917 var
1918 PAMem: TBinMemoryWriter;
1919 i: Integer;
1920 begin
1921 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé:
1922 PAMem := TBinMemoryWriter.Create((Length(panels)+1) * 40);
1924 i := 0;
1925 while i < Length(panels) do
1926 begin
1927 if panels[i].SaveIt then
1928 begin
1929 // ID ïàíåëè:
1930 PAMem.WriteInt(i);
1931 // Ñîõðàíÿåì ïàíåëü:
1932 panels[i].SaveState(PAMem);
1933 end;
1934 Inc(i);
1935 end;
1937 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé:
1938 PAMem.SaveToMemory(Mem);
1939 PAMem.Free();
1940 end;
1942 procedure SaveFlag(flag: PFlag);
1943 begin
1944 // Ñèãíàòóðà ôëàãà:
1945 dw := FLAG_SIGNATURE; // 'FLAG'
1946 Mem.WriteDWORD(dw);
1947 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
1948 Mem.WriteByte(flag^.RespawnType);
1949 // Ñîñòîÿíèå ôëàãà:
1950 Mem.WriteByte(flag^.State);
1951 // Íàïðàâëåíèå ôëàãà:
1952 if flag^.Direction = D_LEFT then
1953 b := 1
1954 else // D_RIGHT
1955 b := 2;
1956 Mem.WriteByte(b);
1957 // Îáúåêò ôëàãà:
1958 Obj_SaveState(@flag^.Obj, Mem);
1959 end;
1961 begin
1962 Mem := TBinMemoryWriter.Create(1024 * 1024); // 1 MB
1964 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
1965 // Ñîõðàíÿåì ïàíåëè ñòåí è äâåðåé:
1966 SavePanelArray(gWalls);
1967 // Ñîõðàíÿåì ïàíåëè ôîíà:
1968 SavePanelArray(gRenderBackgrounds);
1969 // Ñîõðàíÿåì ïàíåëè ïåðåäíåãî ïëàíà:
1970 SavePanelArray(gRenderForegrounds);
1971 // Ñîõðàíÿåì ïàíåëè âîäû:
1972 SavePanelArray(gWater);
1973 // Ñîõðàíÿåì ïàíåëè êèñëîòû-1:
1974 SavePanelArray(gAcid1);
1975 // Ñîõðàíÿåì ïàíåëè êèñëîòû-2:
1976 SavePanelArray(gAcid2);
1977 // Ñîõðàíÿåì ïàíåëè ñòóïåíåé:
1978 SavePanelArray(gSteps);
1979 // Ñîõðàíÿåì ïàíåëè ëèôòîâ:
1980 SavePanelArray(gLifts);
1981 ///// /////
1983 ///// Ñîõðàíÿåì ìóçûêó: /////
1984 // Ñèãíàòóðà ìóçûêè:
1985 dw := MUSIC_SIGNATURE; // 'MUSI'
1986 Mem.WriteDWORD(dw);
1987 // Íàçâàíèå ìóçûêè:
1988 Assert(gMusic <> nil, 'g_Map_SaveState: gMusic = nil');
1989 if gMusic.NoMusic then
1990 str := ''
1991 else
1992 str := gMusic.Name;
1993 Mem.WriteString(str, 64);
1994 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
1995 dw := gMusic.GetPosition();
1996 Mem.WriteDWORD(dw);
1997 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
1998 boo := gMusic.SpecPause;
1999 Mem.WriteBoolean(boo);
2000 ///// /////
2002 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
2003 Mem.WriteInt(gTotalMonsters);
2004 ///// /////
2006 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
2007 if gGameSettings.GameMode = GM_CTF then
2008 begin
2009 // Ôëàã Êðàñíîé êîìàíäû:
2010 SaveFlag(@gFlags[FLAG_RED]);
2011 // Ôëàã Ñèíåé êîìàíäû:
2012 SaveFlag(@gFlags[FLAG_BLUE]);
2013 end;
2014 ///// /////
2016 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2017 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2018 begin
2019 // Î÷êè Êðàñíîé êîìàíäû:
2020 Mem.WriteSmallInt(gTeamStat[TEAM_RED].Goals);
2021 // Î÷êè Ñèíåé êîìàíäû:
2022 Mem.WriteSmallInt(gTeamStat[TEAM_BLUE].Goals);
2023 end;
2024 ///// /////
2025 end;
2027 procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
2028 var
2029 dw: DWORD;
2030 b: Byte;
2031 str: String;
2032 boo: Boolean;
2034 procedure LoadPanelArray(var panels: TPanelArray);
2035 var
2036 PAMem: TBinMemoryReader;
2037 i, id: Integer;
2038 begin
2039 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé:
2040 PAMem := TBinMemoryReader.Create();
2041 PAMem.LoadFromMemory(Mem);
2043 for i := 0 to Length(panels)-1 do
2044 if panels[i].SaveIt then
2045 begin
2046 // ID ïàíåëè:
2047 PAMem.ReadInt(id);
2048 if id <> i then
2049 begin
2050 raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel ID');
2051 end;
2052 // Çàãðóæàåì ïàíåëü:
2053 panels[i].LoadState(PAMem);
2054 end;
2056 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí:
2057 PAMem.Free();
2058 end;
2060 procedure LoadFlag(flag: PFlag);
2061 begin
2062 // Ñèãíàòóðà ôëàãà:
2063 Mem.ReadDWORD(dw);
2064 if dw <> FLAG_SIGNATURE then // 'FLAG'
2065 begin
2066 raise EBinSizeError.Create('g_Map_LoadState: LoadFlag: Wrong Flag Signature');
2067 end;
2068 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
2069 Mem.ReadByte(flag^.RespawnType);
2070 // Ñîñòîÿíèå ôëàãà:
2071 Mem.ReadByte(flag^.State);
2072 // Íàïðàâëåíèå ôëàãà:
2073 Mem.ReadByte(b);
2074 if b = 1 then
2075 flag^.Direction := D_LEFT
2076 else // b = 2
2077 flag^.Direction := D_RIGHT;
2078 // Îáúåêò ôëàãà:
2079 Obj_LoadState(@flag^.Obj, Mem);
2080 end;
2082 begin
2083 if Mem = nil then
2084 Exit;
2086 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
2087 // Çàãðóæàåì ïàíåëè ñòåí è äâåðåé:
2088 LoadPanelArray(gWalls);
2089 // Çàãðóæàåì ïàíåëè ôîíà:
2090 LoadPanelArray(gRenderBackgrounds);
2091 // Çàãðóæàåì ïàíåëè ïåðåäíåãî ïëàíà:
2092 LoadPanelArray(gRenderForegrounds);
2093 // Çàãðóæàåì ïàíåëè âîäû:
2094 LoadPanelArray(gWater);
2095 // Çàãðóæàåì ïàíåëè êèñëîòû-1:
2096 LoadPanelArray(gAcid1);
2097 // Çàãðóæàåì ïàíåëè êèñëîòû-2:
2098 LoadPanelArray(gAcid2);
2099 // Çàãðóæàåì ïàíåëè ñòóïåíåé:
2100 LoadPanelArray(gSteps);
2101 // Çàãðóæàåì ïàíåëè ëèôòîâ:
2102 LoadPanelArray(gLifts);
2103 ///// /////
2105 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé:
2106 g_GFX_Init();
2108 ///// Çàãðóæàåì ìóçûêó: /////
2109 // Ñèãíàòóðà ìóçûêè:
2110 Mem.ReadDWORD(dw);
2111 if dw <> MUSIC_SIGNATURE then // 'MUSI'
2112 begin
2113 raise EBinSizeError.Create('g_Map_LoadState: Wrong Music Signature');
2114 end;
2115 // Íàçâàíèå ìóçûêè:
2116 Assert(gMusic <> nil, 'g_Map_LoadState: gMusic = nil');
2117 Mem.ReadString(str);
2118 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
2119 Mem.ReadDWORD(dw);
2120 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
2121 Mem.ReadBoolean(boo);
2122 // Çàïóñêàåì ýòó ìóçûêó:
2123 gMusic.SetByName(str);
2124 gMusic.SpecPause := boo;
2125 gMusic.Play();
2126 gMusic.Pause(True);
2127 gMusic.SetPosition(dw);
2128 ///// /////
2130 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
2131 Mem.ReadInt(gTotalMonsters);
2132 ///// /////
2134 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
2135 if gGameSettings.GameMode = GM_CTF then
2136 begin
2137 // Ôëàã Êðàñíîé êîìàíäû:
2138 LoadFlag(@gFlags[FLAG_RED]);
2139 // Ôëàã Ñèíåé êîìàíäû:
2140 LoadFlag(@gFlags[FLAG_BLUE]);
2141 end;
2142 ///// /////
2144 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2145 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2146 begin
2147 // Î÷êè Êðàñíîé êîìàíäû:
2148 Mem.ReadSmallInt(gTeamStat[TEAM_RED].Goals);
2149 // Î÷êè Ñèíåé êîìàíäû:
2150 Mem.ReadSmallInt(gTeamStat[TEAM_BLUE].Goals);
2151 end;
2152 ///// /////
2153 end;
2155 end.