DEADSOFTWARE

initial commit:
[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;
785 // Çàãðóçêà WAD:
786 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
787 e_WriteLog('Loading map WAD: ' + FileName, MSG_NOTIFY);
788 g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False);
790 WAD := TWADEditor_1.Create();
791 if not WAD.ReadFile(FileName) then
792 begin
793 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_WAD], [FileName]));
794 WAD.Free();
795 Exit;
796 end;
797 if not WAD.GetResource('', ResName, Data, Len) then
798 begin
799 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_RES], [ResName]));
800 WAD.Free();
801 Exit;
802 end;
803 WAD.Free();
805 // Çàãðóçêà êàðòû:
806 e_WriteLog('Loading map: ' + ResName, MSG_NOTIFY);
807 g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False);
808 MapReader := TMapReader_1.Create();
810 if not MapReader.LoadMap(Data) then
811 begin
812 g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]));
813 FreeMem(Data);
814 MapReader.Free();
815 Exit;
816 end;
818 FreeMem(Data);
819 generateExternalResourcesList(MapReader);
820 // Çàãðóçêà òåêñòóð:
821 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False);
822 _textures := MapReader.GetTextures();
824 // Äîáàâëåíèå òåêñòóð â Textures[]:
825 if _textures <> nil then
826 begin
827 e_WriteLog(' Loading textures:', MSG_NOTIFY);
828 g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], High(_textures), False);
830 for a := 0 to High(_textures) do
831 begin
832 SetLength(s, 64);
833 CopyMemory(@s[1], @_textures[a].Resource[0], 64);
834 for b := 1 to Length(s) do
835 if s[b] = #0 then
836 begin
837 SetLength(s, b-1);
838 Break;
839 end;
840 e_WriteLog(' Loading texture: ' + s, MSG_NOTIFY);
841 // Àíèìèðîâàííàÿ òåêñòóðà:
842 if ByteBool(_textures[a].Anim) then
843 begin
844 if not CreateAnimTexture(_textures[a].Resource, FileName, True) then
845 begin
846 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s]));
847 CreateNullTexture(_textures[a].Resource);
848 end;
849 end
850 else // Îáû÷íàÿ òåêñòóðà:
851 if not CreateTexture(_textures[a].Resource, FileName, True) then
852 begin
853 g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s]));
854 CreateNullTexture(_textures[a].Resource);
855 end;
857 g_Game_StepLoading();
858 end;
859 end;
861 // Çàãðóçêà òðèããåðîâ:
862 gTriggerClientID := 0;
863 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
864 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS], 0, False);
865 triggers := MapReader.GetTriggers();
867 // Çàãðóçêà ïàíåëåé:
868 e_WriteLog(' Loading panels...', MSG_NOTIFY);
869 g_Game_SetLoadingText(_lc[I_LOAD_PANELS], 0, False);
870 panels := MapReader.GetPanels();
872 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì):
873 if triggers <> nil then
874 begin
875 e_WriteLog(' Setting up trigger table...', MSG_NOTIFY);
876 SetLength(TriggersTable, Length(triggers));
877 g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], High(TriggersTable), False);
879 for a := 0 to High(TriggersTable) do
880 begin
881 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè):
882 TriggersTable[a].TexturePanel := triggers[a].TexturePanel;
883 // Ëèôòû:
884 if triggers[a].TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then
885 TriggersTable[a].LiftPanel := TTriggerData(triggers[a].DATA).PanelID
886 else
887 TriggersTable[a].LiftPanel := -1;
888 // Äâåðè:
889 if triggers[a].TriggerType in [TRIGGER_OPENDOOR,
890 TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5,
891 TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
892 TriggersTable[a].DoorPanel := TTriggerData(triggers[a].DATA).PanelID
893 else
894 TriggersTable[a].DoorPanel := -1;
895 // Òóðåëü:
896 if triggers[a].TriggerType = TRIGGER_SHOT then
897 TriggersTable[a].ShotPanel := TTriggerData(triggers[a].DATA).ShotPanelID
898 else
899 TriggersTable[a].ShotPanel := -1;
901 g_Game_StepLoading();
902 end;
903 end;
905 // Ñîçäàåì ïàíåëè:
906 if panels <> nil then
907 begin
908 e_WriteLog(' Setting up trigger links...', MSG_NOTIFY);
909 g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], High(panels), False);
911 for a := 0 to High(panels) do
912 begin
913 SetLength(AddTextures, 0);
914 trigRef := False;
915 CurTex := -1;
916 if _textures <> nil then
917 begin
918 texture := _textures[panels[a].TextureNum];
919 ok := True;
920 end
921 else
922 ok := False;
924 if ok then
925 begin
926 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
927 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð:
928 ok := False;
929 if (TriggersTable <> nil) and (_textures <> nil) then
930 for b := 0 to High(TriggersTable) do
931 if (TriggersTable[b].TexturePanel = a)
932 or (TriggersTable[b].ShotPanel = a) then
933 begin
934 trigRef := True;
935 ok := True;
936 Break;
937 end;
938 end;
940 if ok then
941 begin // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
942 SetLength(s, 64);
943 CopyMemory(@s[1], @texture.Resource[0], 64);
944 // Èçìåðÿåì äëèíó:
945 Len := Length(s);
946 for c := Len downto 1 do
947 if s[c] <> #0 then
948 begin
949 Len := c;
950 Break;
951 end;
952 SetLength(s, Len);
954 // Ñïåö-òåêñòóðû çàïðåùåíû:
955 if g_Map_IsSpecialTexture(s) then
956 ok := False
957 else
958 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè:
959 ok := g_Texture_NumNameFindStart(s);
961 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
962 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #:
963 if ok then
964 begin
965 k := NNF_NAME_BEFORE;
966 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû:
967 while ok or (k = NNF_NAME_BEFORE) or
968 (k = NNF_NAME_EQUALS) do
969 begin
970 k := g_Texture_NumNameFindNext(TexName);
972 if (k = NNF_NAME_BEFORE) or
973 (k = NNF_NAME_AFTER) then
974 begin
975 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó:
976 if ByteBool(texture.Anim) then
977 begin // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
978 isAnim := True;
979 ok := CreateAnimTexture(TexName, FileName, False);
980 if not ok then
981 begin // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
982 isAnim := False;
983 ok := CreateTexture(TexName, FileName, False);
984 end;
985 end
986 else
987 begin // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
988 isAnim := False;
989 ok := CreateTexture(TexName, FileName, False);
990 if not ok then
991 begin // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
992 isAnim := True;
993 ok := CreateAnimTexture(TexName, FileName, False);
994 end;
995 end;
997 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè:
998 if ok then
999 begin
1000 for c := 0 to High(Textures) do
1001 if Textures[c].TextureName = TexName then
1002 begin
1003 SetLength(AddTextures, Length(AddTextures)+1);
1004 AddTextures[High(AddTextures)].Texture := c;
1005 AddTextures[High(AddTextures)].Anim := isAnim;
1006 Break;
1007 end;
1008 end;
1009 end
1010 else
1011 if k = NNF_NAME_EQUALS then
1012 begin
1013 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî:
1014 SetLength(AddTextures, Length(AddTextures)+1);
1015 AddTextures[High(AddTextures)].Texture := panels[a].TextureNum;
1016 AddTextures[High(AddTextures)].Anim := ByteBool(texture.Anim);
1017 CurTex := High(AddTextures);
1018 ok := True;
1019 end
1020 else // NNF_NO_NAME
1021 ok := False;
1022 end; // while ok...
1024 ok := True;
1025 end; // if ok - åñòü ñìåæíûå òåêñòóðû
1026 end; // if ok - ññûëàþòñÿ òðèããåðû
1028 if not ok then
1029 begin
1030 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó:
1031 SetLength(AddTextures, 1);
1032 AddTextures[0].Texture := panels[a].TextureNum;
1033 AddTextures[0].Anim := ByteBool(texture.Anim);
1034 CurTex := 0;
1035 end;
1037 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð:
1038 PanelID := CreatePanel(panels[a], AddTextures, CurTex, trigRef);
1040 // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID:
1041 if TriggersTable <> nil then
1042 for b := 0 to High(TriggersTable) do
1043 begin
1044 // Òðèããåð äâåðè/ëèôòà:
1045 if (TriggersTable[b].LiftPanel = a) or
1046 (TriggersTable[b].DoorPanel = a) then
1047 TTriggerData(triggers[b].DATA).PanelID := PanelID;
1048 // Òðèããåð ñìåíû òåêñòóðû:
1049 if TriggersTable[b].TexturePanel = a then
1050 triggers[b].TexturePanel := PanelID;
1051 // Òðèããåð "Òóðåëü":
1052 if TriggersTable[b].ShotPanel = a then
1053 TTriggerData(triggers[b].DATA).ShotPanelID := PanelID;
1054 end;
1056 g_Game_StepLoading();
1057 end;
1058 end;
1060 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû:
1061 if (triggers <> nil) and not gLoadGameMode then
1062 begin
1063 e_WriteLog(' Creating triggers...', MSG_NOTIFY);
1064 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_TRIGGERS], 0, False);
1065 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü:
1066 for a := 0 to High(triggers) do
1067 begin
1068 if triggers[a].TexturePanel <> -1 then
1069 b := panels[TriggersTable[a].TexturePanel].PanelType
1070 else
1071 b := 0;
1072 if (triggers[a].TriggerType = TRIGGER_SHOT) and
1073 (TTriggerData(triggers[a].DATA).ShotPanelID <> -1) then
1074 c := panels[TriggersTable[a].ShotPanel].PanelType
1075 else
1076 c := 0;
1077 CreateTrigger(triggers[a], b, c);
1078 end;
1079 end;
1081 // Çàãðóçêà ïðåäìåòîâ:
1082 e_WriteLog(' Loading triggers...', MSG_NOTIFY);
1083 g_Game_SetLoadingText(_lc[I_LOAD_ITEMS], 0, False);
1084 items := MapReader.GetItems();
1086 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû:
1087 if (items <> nil) and not gLoadGameMode then
1088 begin
1089 e_WriteLog(' Spawning items...', MSG_NOTIFY);
1090 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_ITEMS], 0, False);
1091 for a := 0 to High(items) do
1092 CreateItem(Items[a]);
1093 end;
1095 // Çàãðóçêà îáëàñòåé:
1096 e_WriteLog(' Loading areas...', MSG_NOTIFY);
1097 g_Game_SetLoadingText(_lc[I_LOAD_AREAS], 0, False);
1098 areas := MapReader.GetAreas();
1100 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè:
1101 if areas <> nil then
1102 begin
1103 e_WriteLog(' Creating areas...', MSG_NOTIFY);
1104 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_AREAS], 0, False);
1105 for a := 0 to High(areas) do
1106 CreateArea(areas[a]);
1107 end;
1109 // Çàãðóçêà ìîíñòðîâ:
1110 e_WriteLog(' Loading monsters...', MSG_NOTIFY);
1111 g_Game_SetLoadingText(_lc[I_LOAD_MONSTERS], 0, False);
1112 monsters := MapReader.GetMonsters();
1114 gTotalMonsters := 0;
1116 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ:
1117 if (monsters <> nil) and not gLoadGameMode then
1118 begin
1119 e_WriteLog(' Spawning monsters...', MSG_NOTIFY);
1120 g_Game_SetLoadingText(_lc[I_LOAD_CREATE_MONSTERS], 0, False);
1121 for a := 0 to High(monsters) do
1122 CreateMonster(monsters[a]);
1123 end;
1125 // Çàãðóçêà îïèñàíèÿ êàðòû:
1126 e_WriteLog(' Reading map info...', MSG_NOTIFY);
1127 g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
1128 Header := MapReader.GetMapHeader();
1130 MapReader.Free();
1132 with gMapInfo do
1133 begin
1134 Name := Header.MapName;
1135 Description := Header.MapDescription;
1136 Author := Header.MapAuthor;
1137 MusicName := Header.MusicName;
1138 SkyName := Header.SkyName;
1139 Height := Header.Height;
1140 Width := Header.Width;
1141 end;
1143 // Çàãðóçêà íåáà:
1144 if gMapInfo.SkyName <> '' then
1145 begin
1146 e_WriteLog(' Loading sky: ' + gMapInfo.SkyName, MSG_NOTIFY);
1147 g_Game_SetLoadingText(_lc[I_LOAD_SKY], 0, False);
1148 g_ProcessResourceStr(gMapInfo.SkyName, FileName, SectionName, ResName);
1150 if FileName <> '' then
1151 FileName := GameDir+'/wads/'+FileName
1152 else
1153 begin
1154 g_ProcessResourceStr(Res, @FileName2, nil, nil);
1155 FileName := FileName2;
1156 end;
1158 s := FileName+':'+SectionName+'/'+ResName;
1159 if g_Texture_CreateWAD(BackID, s) then
1160 begin
1161 g_Game_SetupScreenSize();
1162 end
1163 else
1164 g_FatalError(Format(_lc[I_GAME_ERROR_SKY], [s]));
1165 end;
1167 // Çàãðóçêà ìóçûêè:
1168 ok := False;
1169 if gMapInfo.MusicName <> '' then
1170 begin
1171 e_WriteLog(' Loading music: ' + gMapInfo.MusicName, MSG_NOTIFY);
1172 g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
1173 g_ProcessResourceStr(gMapInfo.MusicName, FileName, SectionName, ResName);
1175 if FileName <> '' then
1176 FileName := GameDir+'/wads/'+FileName
1177 else
1178 begin
1179 g_ProcessResourceStr(Res, @FileName2, nil, nil);
1180 FileName := FileName2;
1181 end;
1183 s := FileName+':'+SectionName+'/'+ResName;
1184 if g_Sound_CreateWADEx(gMapInfo.MusicName, s, True) then
1185 ok := True
1186 else
1187 g_FatalError(Format(_lc[I_GAME_ERROR_MUSIC], [s]));
1188 end;
1190 // Îñòàëüíûå óñòàíâêè:
1191 CreateDoorMap();
1192 CreateLiftMap();
1194 g_Items_Init();
1195 g_Weapon_Init();
1196 g_Monsters_Init();
1198 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
1199 if not gLoadGameMode then
1200 g_GFX_Init();
1202 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
1203 _textures := nil;
1204 panels := nil;
1205 items := nil;
1206 areas := nil;
1207 triggers := nil;
1208 TriggersTable := nil;
1209 AddTextures := nil;
1211 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
1212 if ok and (not gLoadGameMode) then
1213 begin
1214 gMusic.SetByName(gMapInfo.MusicName);
1215 gMusic.Play();
1216 end
1217 else
1218 gMusic.SetByName('');
1220 e_WriteLog('Done loading map.', MSG_NOTIFY);
1221 Result := True;
1222 end;
1224 function g_Map_GetMapInfo(Res: String): TMapInfo;
1225 var
1226 WAD: TWADEditor_1;
1227 MapReader: TMapReader_1;
1228 Header: TMapHeaderRec_1;
1229 FileName, SectionName, ResName: String;
1230 Data: Pointer;
1231 Len: Integer;
1232 begin
1233 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
1235 WAD := TWADEditor_1.Create();
1236 if not WAD.ReadFile(FileName) then
1237 begin
1238 WAD.Free();
1239 Exit;
1240 end;
1242 if not WAD.GetResource('', ResName, Data, Len) then
1243 begin
1244 WAD.Free();
1245 Exit;
1246 end;
1248 WAD.Free();
1250 MapReader := TMapReader_1.Create();
1252 if not MapReader.LoadMap(Data) then
1253 begin
1254 g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True);
1255 ZeroMemory(@Header, SizeOf(Header));
1256 Result.Name := _lc[I_GAME_ERROR_MAP_SELECT];
1257 Result.Description := _lc[I_GAME_ERROR_MAP_SELECT];
1258 end
1259 else
1260 begin
1261 Header := MapReader.GetMapHeader();
1262 Result.Name := Header.MapName;
1263 Result.Description := Header.MapDescription;
1264 end;
1266 FreeMem(Data);
1267 MapReader.Free();
1269 Result.Map := Res;
1270 Result.Author := Header.MapAuthor;
1271 Result.Height := Header.Height;
1272 Result.Width := Header.Width;
1273 end;
1275 function g_Map_GetMapsList(WADName: string): SArray;
1276 var
1277 WAD: TWADEditor_1;
1278 a: Integer;
1279 ResList: SArray;
1280 Data: Pointer;
1281 Len: Integer;
1282 Sign: Array [0..2] of Char;
1283 begin
1284 Result := nil;
1286 WAD := TWADEditor_1.Create();
1287 if not WAD.ReadFile(WADName) then
1288 begin
1289 WAD.Free();
1290 Exit;
1291 end;
1293 ResList := WAD.GetResourcesList('');
1295 if ResList <> nil then
1296 for a := 0 to High(ResList) do
1297 begin
1298 if not WAD.GetResource('', ResList[a], Data, Len) then Continue;
1299 CopyMemory(@Sign[0], Data, 3);
1300 FreeMem(Data);
1302 if Sign = MAP_SIGNATURE then
1303 begin
1304 SetLength(Result, Length(Result)+1);
1305 Result[High(Result)] := ResList[a];
1306 end;
1308 Sign := '';
1309 end;
1311 WAD.Free();
1312 end;
1314 function g_Map_Exist(Res: string): Boolean;
1315 var
1316 WAD: TWADEditor_1;
1317 FileName, SectionName, ResName: string;
1318 ResList: SArray;
1319 a: Integer;
1320 begin
1321 Result := False;
1323 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
1325 if Pos('.wad', LowerCase(FileName)) = 0 then FileName := FileName+'.wad';
1327 WAD := TWADEditor_1.Create;
1328 if not WAD.ReadFile(FileName) then
1329 begin
1330 WAD.Free();
1331 Exit;
1332 end;
1334 ResList := WAD.GetResourcesList('');
1335 WAD.Free();
1337 if ResList <> nil then
1338 for a := 0 to High(ResList) do if ResList[a] = ResName then
1339 begin
1340 Result := True;
1341 Exit;
1342 end;
1343 end;
1345 procedure g_Map_Free();
1346 var
1347 a: Integer;
1349 procedure FreePanelArray(var panels: TPanelArray);
1350 var
1351 i: Integer;
1353 begin
1354 if panels <> nil then
1355 begin
1356 for i := 0 to High(panels) do
1357 panels[i].Free();
1358 panels := nil;
1359 end;
1360 end;
1362 begin
1363 g_GFX_Free();
1364 g_Weapon_Free();
1365 g_Items_Free();
1366 g_Triggers_Free();
1367 g_Monsters_Free();
1369 RespawnPoints := nil;
1370 if FlagPoints[FLAG_RED] <> nil then
1371 begin
1372 Dispose(FlagPoints[FLAG_RED]);
1373 FlagPoints[FLAG_RED] := nil;
1374 end;
1375 if FlagPoints[FLAG_BLUE] <> nil then
1376 begin
1377 Dispose(FlagPoints[FLAG_BLUE]);
1378 FlagPoints[FLAG_BLUE] := nil;
1379 end;
1380 //DOMFlagPoints := nil;
1382 //gDOMFlags := nil;
1384 if Textures <> nil then
1385 begin
1386 for a := 0 to High(Textures) do
1387 if not g_Map_IsSpecialTexture(Textures[a].TextureName) then
1388 if Textures[a].Anim then
1389 g_Frames_DeleteByID(Textures[a].FramesID)
1390 else
1391 if Textures[a].TextureID <> TEXTURE_NONE then
1392 e_DeleteTexture(Textures[a].TextureID);
1394 Textures := nil;
1395 end;
1397 FreePanelArray(gWalls);
1398 FreePanelArray(gRenderBackgrounds);
1399 FreePanelArray(gRenderForegrounds);
1400 FreePanelArray(gWater);
1401 FreePanelArray(gAcid1);
1402 FreePanelArray(gAcid2);
1403 FreePanelArray(gSteps);
1404 FreePanelArray(gLifts);
1405 FreePanelArray(gBlockMon);
1407 if BackID <> DWORD(-1) then
1408 begin
1409 gBackSize.X := 0;
1410 gBackSize.Y := 0;
1411 e_DeleteTexture(BackID);
1412 BackID := DWORD(-1);
1413 end;
1415 g_Game_StopAllSounds(False);
1416 gMusic.FreeSound();
1417 g_Sound_Delete(gMapInfo.MusicName);
1419 gMapInfo.Name := '';
1420 gMapInfo.Description := '';
1421 gMapInfo.MusicName := '';
1422 gMapInfo.Height := 0;
1423 gMapInfo.Width := 0;
1425 gDoorMap := nil;
1426 gLiftMap := nil;
1427 end;
1429 procedure g_Map_Update();
1430 var
1431 a, d, j: Integer;
1432 m: Word;
1433 s: String;
1435 procedure UpdatePanelArray(var panels: TPanelArray);
1436 var
1437 i: Integer;
1439 begin
1440 if panels <> nil then
1441 for i := 0 to High(panels) do
1442 panels[i].Update();
1443 end;
1445 begin
1446 UpdatePanelArray(gWalls);
1447 UpdatePanelArray(gRenderBackgrounds);
1448 UpdatePanelArray(gRenderForegrounds);
1449 UpdatePanelArray(gWater);
1450 UpdatePanelArray(gAcid1);
1451 UpdatePanelArray(gAcid2);
1452 UpdatePanelArray(gSteps);
1454 if gGameSettings.GameMode = GM_CTF then
1455 begin
1456 for a := FLAG_RED to FLAG_BLUE do
1457 if not (gFlags[a].State in [FLAG_STATE_NONE, FLAG_STATE_CAPTURED]) then
1458 with gFlags[a] do
1459 begin
1460 if gFlags[a].Animation <> nil then
1461 gFlags[a].Animation.Update();
1463 m := g_Obj_Move(@Obj, True, True);
1465 if gTime mod (GAME_TICK*2) <> 0 then
1466 Continue;
1468 // Ñîïðîòèâëåíèå âîçäóõà:
1469 Obj.Vel.X := z_dec(Obj.Vel.X, 1);
1471 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó:
1472 if ((Count = 0) or ByteBool(m and MOVE_FALLOUT)) and g_Game_IsServer then
1473 begin
1474 g_Map_ResetFlag(a);
1475 gFlags[a].CaptureTime := 0;
1476 if a = FLAG_RED then
1477 s := _lc[I_PLAYER_FLAG_RED]
1478 else
1479 s := _lc[I_PLAYER_FLAG_BLUE];
1480 g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
1482 if g_Game_IsNet then
1483 MH_SEND_FlagEvent(FLAG_STATE_RETURNED, a, 0);
1484 Continue;
1485 end;
1487 if Count > 0 then
1488 Count := Count - 1;
1490 // Èãðîê áåðåò ôëàã:
1491 if gPlayers <> nil then
1492 begin
1493 j := Random(Length(gPlayers)) - 1;
1495 for d := 0 to High(gPlayers) do
1496 begin
1497 Inc(j);
1498 if j > High(gPlayers) then
1499 j := 0;
1501 if gPlayers[j] <> nil then
1502 if gPlayers[j].Live and
1503 g_Obj_Collide(@Obj, @gPlayers[j].Obj) then
1504 begin
1505 if gPlayers[j].GetFlag(a) then
1506 Break;
1507 end;
1508 end;
1509 end;
1510 end;
1511 end;
1512 end;
1514 procedure g_Map_DrawPanels(PanelType: Word);
1516 procedure DrawPanels(var panels: TPanelArray;
1517 drawDoors: Boolean = False);
1518 var
1519 a: Integer;
1521 begin
1522 if panels <> nil then
1523 for a := 0 to High(panels) do
1524 if not (drawDoors xor panels[a].Door) then
1525 panels[a].Draw();
1526 end;
1528 begin
1529 case PanelType of
1530 PANEL_WALL: DrawPanels(gWalls);
1531 PANEL_CLOSEDOOR: DrawPanels(gWalls, True);
1532 PANEL_BACK: DrawPanels(gRenderBackgrounds);
1533 PANEL_FORE: DrawPanels(gRenderForegrounds);
1534 PANEL_WATER: DrawPanels(gWater);
1535 PANEL_ACID1: DrawPanels(gAcid1);
1536 PANEL_ACID2: DrawPanels(gAcid2);
1537 PANEL_STEP: DrawPanels(gSteps);
1538 end;
1539 end;
1541 procedure g_Map_DrawBack(dx, dy: Integer);
1542 begin
1543 if gDrawBackGround and (BackID <> DWORD(-1)) then
1544 e_DrawSize(BackID, dx, dy, 0, False, False, gBackSize.X, gBackSize.Y)
1545 else
1546 e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
1547 end;
1549 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word;
1550 PanelType: Word; b1x3: Boolean): Boolean;
1551 var
1552 a, h: Integer;
1553 begin
1554 Result := False;
1556 if WordBool(PanelType and PANEL_WALL) then
1557 if gWalls <> nil then
1558 begin
1559 h := High(gWalls);
1561 for a := 0 to h do
1562 if gWalls[a].Enabled and
1563 g_Collide(X, Y, Width, Height,
1564 gWalls[a].X, gWalls[a].Y,
1565 gWalls[a].Width, gWalls[a].Height) then
1566 begin
1567 Result := True;
1568 Exit;
1569 end;
1570 end;
1572 if WordBool(PanelType and PANEL_WATER) then
1573 if gWater <> nil then
1574 begin
1575 h := High(gWater);
1577 for a := 0 to h do
1578 if g_Collide(X, Y, Width, Height,
1579 gWater[a].X, gWater[a].Y,
1580 gWater[a].Width, gWater[a].Height) then
1581 begin
1582 Result := True;
1583 Exit;
1584 end;
1585 end;
1587 if WordBool(PanelType and PANEL_ACID1) then
1588 if gAcid1 <> nil then
1589 begin
1590 h := High(gAcid1);
1592 for a := 0 to h do
1593 if g_Collide(X, Y, Width, Height,
1594 gAcid1[a].X, gAcid1[a].Y,
1595 gAcid1[a].Width, gAcid1[a].Height) then
1596 begin
1597 Result := True;
1598 Exit;
1599 end;
1600 end;
1602 if WordBool(PanelType and PANEL_ACID2) then
1603 if gAcid2 <> nil then
1604 begin
1605 h := High(gAcid2);
1607 for a := 0 to h do
1608 if g_Collide(X, Y, Width, Height,
1609 gAcid2[a].X, gAcid2[a].Y,
1610 gAcid2[a].Width, gAcid2[a].Height) then
1611 begin
1612 Result := True;
1613 Exit;
1614 end;
1615 end;
1617 if WordBool(PanelType and PANEL_STEP) then
1618 if gSteps <> nil then
1619 begin
1620 h := High(gSteps);
1622 for a := 0 to h do
1623 if g_Collide(X, Y, Width, Height,
1624 gSteps[a].X, gSteps[a].Y,
1625 gSteps[a].Width, gSteps[a].Height) then
1626 begin
1627 Result := True;
1628 Exit;
1629 end;
1630 end;
1632 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
1633 if gLifts <> nil then
1634 begin
1635 h := High(gLifts);
1637 for a := 0 to h do
1638 if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = 0)) or
1639 (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = 1)) or
1640 (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = 2)) or
1641 (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = 3))) and
1642 g_Collide(X, Y, Width, Height,
1643 gLifts[a].X, gLifts[a].Y,
1644 gLifts[a].Width, gLifts[a].Height) then
1645 begin
1646 Result := True;
1647 Exit;
1648 end;
1649 end;
1651 if WordBool(PanelType and PANEL_BLOCKMON) then
1652 if gBlockMon <> nil then
1653 begin
1654 h := High(gBlockMon);
1656 for a := 0 to h do
1657 if ( (not b1x3) or
1658 ((gBlockMon[a].Width + gBlockMon[a].Height) >= 64) ) and
1659 g_Collide(X, Y, Width, Height,
1660 gBlockMon[a].X, gBlockMon[a].Y,
1661 gBlockMon[a].Width, gBlockMon[a].Height) then
1662 begin
1663 Result := True;
1664 Exit;
1665 end;
1666 end;
1667 end;
1669 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
1670 var
1671 a, h: Integer;
1672 begin
1673 Result := TEXTURE_NONE;
1675 if gWater <> nil then
1676 begin
1677 h := High(gWater);
1679 for a := 0 to h do
1680 if g_Collide(X, Y, Width, Height,
1681 gWater[a].X, gWater[a].Y,
1682 gWater[a].Width, gWater[a].Height) then
1683 begin
1684 Result := gWater[a].GetTextureID();
1685 Exit;
1686 end;
1687 end;
1689 if gAcid1 <> nil then
1690 begin
1691 h := High(gAcid1);
1693 for a := 0 to h do
1694 if g_Collide(X, Y, Width, Height,
1695 gAcid1[a].X, gAcid1[a].Y,
1696 gAcid1[a].Width, gAcid1[a].Height) then
1697 begin
1698 Result := gAcid1[a].GetTextureID();
1699 Exit;
1700 end;
1701 end;
1703 if gAcid2 <> nil then
1704 begin
1705 h := High(gAcid2);
1707 for a := 0 to h do
1708 if g_Collide(X, Y, Width, Height,
1709 gAcid2[a].X, gAcid2[a].Y,
1710 gAcid2[a].Width, gAcid2[a].Height) then
1711 begin
1712 Result := gAcid2[a].GetTextureID();
1713 Exit;
1714 end;
1715 end;
1716 end;
1718 procedure g_Map_EnableWall(ID: DWORD);
1719 begin
1720 with gWalls[ID] do
1721 begin
1722 Enabled := True;
1723 g_Mark(X, Y, Width, Height, MARK_DOOR, True);
1725 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1726 end;
1727 end;
1729 procedure g_Map_DisableWall(ID: DWORD);
1730 begin
1731 with gWalls[ID] do
1732 begin
1733 Enabled := False;
1734 g_Mark(X, Y, Width, Height, MARK_DOOR, False);
1736 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1737 end;
1738 end;
1740 procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0);
1741 var
1742 tp: TPanel;
1743 begin
1744 case PanelType of
1745 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR:
1746 tp := gWalls[ID];
1747 PANEL_FORE:
1748 tp := gRenderForegrounds[ID];
1749 PANEL_BACK:
1750 tp := gRenderBackgrounds[ID];
1751 PANEL_WATER:
1752 tp := gWater[ID];
1753 PANEL_ACID1:
1754 tp := gAcid1[ID];
1755 PANEL_ACID2:
1756 tp := gAcid2[ID];
1757 PANEL_STEP:
1758 tp := gSteps[ID];
1759 else
1760 Exit;
1761 end;
1763 tp.NextTexture(AnimLoop);
1764 if g_Game_IsServer and g_Game_IsNet then
1765 MH_SEND_PanelTexture(PanelType, ID, AnimLoop);
1766 end;
1768 procedure g_Map_SetLift(ID: DWORD; t: Integer);
1769 begin
1770 if gLifts[ID].LiftType = t then
1771 Exit;
1773 with gLifts[ID] do
1774 begin
1775 LiftType := t;
1777 g_Mark(X, Y, Width, Height, MARK_LIFT, False);
1779 if LiftType = 0 then
1780 g_Mark(X, Y, Width, Height, MARK_LIFTUP, True)
1781 else if LiftType = 1 then
1782 g_Mark(X, Y, Width, Height, MARK_LIFTDOWN, True)
1783 else if LiftType = 2 then
1784 g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True)
1785 else if LiftType = 3 then
1786 g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True);
1788 if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
1789 end;
1790 end;
1792 function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean;
1793 var
1794 a: Integer;
1795 PointsArray: Array of TRespawnPoint;
1796 begin
1797 Result := False;
1798 SetLength(PointsArray, 0);
1800 if RespawnPoints = nil then
1801 Exit;
1803 for a := 0 to High(RespawnPoints) do
1804 if RespawnPoints[a].PointType = PointType then
1805 begin
1806 SetLength(PointsArray, Length(PointsArray)+1);
1807 PointsArray[High(PointsArray)] := RespawnPoints[a];
1808 end;
1810 if PointsArray = nil then
1811 Exit;
1813 RespawnPoint := PointsArray[Random(Length(PointsArray))];
1814 Result := True;
1815 end;
1817 function g_Map_GetPointCount(PointType: Byte): Word;
1818 var
1819 a: Integer;
1820 begin
1821 Result := 0;
1823 if RespawnPoints = nil then
1824 Exit;
1826 for a := 0 to High(RespawnPoints) do
1827 if RespawnPoints[a].PointType = PointType then
1828 Result := Result + 1;
1829 end;
1831 function g_Map_HaveFlagPoints(): Boolean;
1832 begin
1833 Result := (FlagPoints[FLAG_RED] <> nil) and (FlagPoints[FLAG_BLUE] <> nil);
1834 end;
1836 procedure g_Map_ResetFlag(Flag: Byte);
1837 begin
1838 with gFlags[Flag] do
1839 begin
1840 Obj.X := -1000;
1841 Obj.Y := -1000;
1842 Obj.Vel.X := 0;
1843 Obj.Vel.Y := 0;
1844 Direction := D_LEFT;
1845 State := FLAG_STATE_NONE;
1846 if FlagPoints[Flag] <> nil then
1847 begin
1848 Obj.X := FlagPoints[Flag]^.X;
1849 Obj.Y := FlagPoints[Flag]^.Y;
1850 Direction := FlagPoints[Flag]^.Direction;
1851 State := FLAG_STATE_NORMAL;
1852 end;
1853 Count := -1;
1854 end;
1855 end;
1857 procedure g_Map_DrawFlags();
1858 var
1859 i, dx: Integer;
1860 Mirror: TMirrorType;
1861 begin
1862 if gGameSettings.GameMode <> GM_CTF then
1863 Exit;
1865 for i := FLAG_RED to FLAG_BLUE do
1866 with gFlags[i] do
1867 if State <> FLAG_STATE_CAPTURED then
1868 begin
1869 if State = FLAG_STATE_NONE then
1870 continue;
1872 if Direction = D_LEFT then
1873 begin
1874 Mirror := M_HORIZONTAL;
1875 dx := -1;
1876 end
1877 else
1878 begin
1879 Mirror := M_NONE;
1880 dx := 1;
1881 end;
1883 Animation.Draw(Obj.X+dx, Obj.Y+1, Mirror);
1885 if g_debug_Frames then
1886 begin
1887 e_DrawQuad(Obj.X+Obj.Rect.X,
1888 Obj.Y+Obj.Rect.Y,
1889 Obj.X+Obj.Rect.X+Obj.Rect.Width-1,
1890 Obj.Y+Obj.Rect.Y+Obj.Rect.Height-1,
1891 0, 255, 0);
1892 end;
1893 end;
1894 end;
1896 procedure g_Map_SaveState(Var Mem: TBinMemoryWriter);
1897 var
1898 dw: DWORD;
1899 b: Byte;
1900 str: String;
1901 boo: Boolean;
1903 procedure SavePanelArray(var panels: TPanelArray);
1904 var
1905 PAMem: TBinMemoryWriter;
1906 i: Integer;
1907 begin
1908 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé:
1909 PAMem := TBinMemoryWriter.Create((Length(panels)+1) * 40);
1911 i := 0;
1912 while i < Length(panels) do
1913 begin
1914 if panels[i].SaveIt then
1915 begin
1916 // ID ïàíåëè:
1917 PAMem.WriteInt(i);
1918 // Ñîõðàíÿåì ïàíåëü:
1919 panels[i].SaveState(PAMem);
1920 end;
1921 Inc(i);
1922 end;
1924 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé:
1925 PAMem.SaveToMemory(Mem);
1926 PAMem.Free();
1927 end;
1929 procedure SaveFlag(flag: PFlag);
1930 begin
1931 // Ñèãíàòóðà ôëàãà:
1932 dw := FLAG_SIGNATURE; // 'FLAG'
1933 Mem.WriteDWORD(dw);
1934 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
1935 Mem.WriteByte(flag^.RespawnType);
1936 // Ñîñòîÿíèå ôëàãà:
1937 Mem.WriteByte(flag^.State);
1938 // Íàïðàâëåíèå ôëàãà:
1939 if flag^.Direction = D_LEFT then
1940 b := 1
1941 else // D_RIGHT
1942 b := 2;
1943 Mem.WriteByte(b);
1944 // Îáúåêò ôëàãà:
1945 Obj_SaveState(@flag^.Obj, Mem);
1946 end;
1948 begin
1949 Mem := TBinMemoryWriter.Create(1024 * 1024); // 1 MB
1951 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
1952 // Ñîõðàíÿåì ïàíåëè ñòåí è äâåðåé:
1953 SavePanelArray(gWalls);
1954 // Ñîõðàíÿåì ïàíåëè ôîíà:
1955 SavePanelArray(gRenderBackgrounds);
1956 // Ñîõðàíÿåì ïàíåëè ïåðåäíåãî ïëàíà:
1957 SavePanelArray(gRenderForegrounds);
1958 // Ñîõðàíÿåì ïàíåëè âîäû:
1959 SavePanelArray(gWater);
1960 // Ñîõðàíÿåì ïàíåëè êèñëîòû-1:
1961 SavePanelArray(gAcid1);
1962 // Ñîõðàíÿåì ïàíåëè êèñëîòû-2:
1963 SavePanelArray(gAcid2);
1964 // Ñîõðàíÿåì ïàíåëè ñòóïåíåé:
1965 SavePanelArray(gSteps);
1966 // Ñîõðàíÿåì ïàíåëè ëèôòîâ:
1967 SavePanelArray(gLifts);
1968 ///// /////
1970 ///// Ñîõðàíÿåì ìóçûêó: /////
1971 // Ñèãíàòóðà ìóçûêè:
1972 dw := MUSIC_SIGNATURE; // 'MUSI'
1973 Mem.WriteDWORD(dw);
1974 // Íàçâàíèå ìóçûêè:
1975 Assert(gMusic <> nil, 'g_Map_SaveState: gMusic = nil');
1976 if gMusic.NoMusic then
1977 str := ''
1978 else
1979 str := gMusic.Name;
1980 Mem.WriteString(str, 64);
1981 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
1982 dw := gMusic.GetPosition();
1983 Mem.WriteDWORD(dw);
1984 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
1985 boo := gMusic.SpecPause;
1986 Mem.WriteBoolean(boo);
1987 ///// /////
1989 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
1990 Mem.WriteInt(gTotalMonsters);
1991 ///// /////
1993 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
1994 if gGameSettings.GameMode = GM_CTF then
1995 begin
1996 // Ôëàã Êðàñíîé êîìàíäû:
1997 SaveFlag(@gFlags[FLAG_RED]);
1998 // Ôëàã Ñèíåé êîìàíäû:
1999 SaveFlag(@gFlags[FLAG_BLUE]);
2000 end;
2001 ///// /////
2003 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2004 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2005 begin
2006 // Î÷êè Êðàñíîé êîìàíäû:
2007 Mem.WriteSmallInt(gTeamStat[TEAM_RED].Goals);
2008 // Î÷êè Ñèíåé êîìàíäû:
2009 Mem.WriteSmallInt(gTeamStat[TEAM_BLUE].Goals);
2010 end;
2011 ///// /////
2012 end;
2014 procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
2015 var
2016 dw: DWORD;
2017 b: Byte;
2018 str: String;
2019 boo: Boolean;
2021 procedure LoadPanelArray(var panels: TPanelArray);
2022 var
2023 PAMem: TBinMemoryReader;
2024 i, id: Integer;
2025 begin
2026 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé:
2027 PAMem := TBinMemoryReader.Create();
2028 PAMem.LoadFromMemory(Mem);
2030 for i := 0 to Length(panels)-1 do
2031 if panels[i].SaveIt then
2032 begin
2033 // ID ïàíåëè:
2034 PAMem.ReadInt(id);
2035 if id <> i then
2036 begin
2037 raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel ID');
2038 end;
2039 // Çàãðóæàåì ïàíåëü:
2040 panels[i].LoadState(PAMem);
2041 end;
2043 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí:
2044 PAMem.Free();
2045 end;
2047 procedure LoadFlag(flag: PFlag);
2048 begin
2049 // Ñèãíàòóðà ôëàãà:
2050 Mem.ReadDWORD(dw);
2051 if dw <> FLAG_SIGNATURE then // 'FLAG'
2052 begin
2053 raise EBinSizeError.Create('g_Map_LoadState: LoadFlag: Wrong Flag Signature');
2054 end;
2055 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
2056 Mem.ReadByte(flag^.RespawnType);
2057 // Ñîñòîÿíèå ôëàãà:
2058 Mem.ReadByte(flag^.State);
2059 // Íàïðàâëåíèå ôëàãà:
2060 Mem.ReadByte(b);
2061 if b = 1 then
2062 flag^.Direction := D_LEFT
2063 else // b = 2
2064 flag^.Direction := D_RIGHT;
2065 // Îáúåêò ôëàãà:
2066 Obj_LoadState(@flag^.Obj, Mem);
2067 end;
2069 begin
2070 if Mem = nil then
2071 Exit;
2073 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
2074 // Çàãðóæàåì ïàíåëè ñòåí è äâåðåé:
2075 LoadPanelArray(gWalls);
2076 // Çàãðóæàåì ïàíåëè ôîíà:
2077 LoadPanelArray(gRenderBackgrounds);
2078 // Çàãðóæàåì ïàíåëè ïåðåäíåãî ïëàíà:
2079 LoadPanelArray(gRenderForegrounds);
2080 // Çàãðóæàåì ïàíåëè âîäû:
2081 LoadPanelArray(gWater);
2082 // Çàãðóæàåì ïàíåëè êèñëîòû-1:
2083 LoadPanelArray(gAcid1);
2084 // Çàãðóæàåì ïàíåëè êèñëîòû-2:
2085 LoadPanelArray(gAcid2);
2086 // Çàãðóæàåì ïàíåëè ñòóïåíåé:
2087 LoadPanelArray(gSteps);
2088 // Çàãðóæàåì ïàíåëè ëèôòîâ:
2089 LoadPanelArray(gLifts);
2090 ///// /////
2092 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé:
2093 g_GFX_Init();
2095 ///// Çàãðóæàåì ìóçûêó: /////
2096 // Ñèãíàòóðà ìóçûêè:
2097 Mem.ReadDWORD(dw);
2098 if dw <> MUSIC_SIGNATURE then // 'MUSI'
2099 begin
2100 raise EBinSizeError.Create('g_Map_LoadState: Wrong Music Signature');
2101 end;
2102 // Íàçâàíèå ìóçûêè:
2103 Assert(gMusic <> nil, 'g_Map_LoadState: gMusic = nil');
2104 Mem.ReadString(str);
2105 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
2106 Mem.ReadDWORD(dw);
2107 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
2108 Mem.ReadBoolean(boo);
2109 // Çàïóñêàåì ýòó ìóçûêó:
2110 gMusic.SetByName(str);
2111 gMusic.SpecPause := boo;
2112 gMusic.Play();
2113 gMusic.Pause(True);
2114 gMusic.SetPosition(dw);
2115 ///// /////
2117 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
2118 Mem.ReadInt(gTotalMonsters);
2119 ///// /////
2121 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
2122 if gGameSettings.GameMode = GM_CTF then
2123 begin
2124 // Ôëàã Êðàñíîé êîìàíäû:
2125 LoadFlag(@gFlags[FLAG_RED]);
2126 // Ôëàã Ñèíåé êîìàíäû:
2127 LoadFlag(@gFlags[FLAG_BLUE]);
2128 end;
2129 ///// /////
2131 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
2132 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
2133 begin
2134 // Î÷êè Êðàñíîé êîìàíäû:
2135 Mem.ReadSmallInt(gTeamStat[TEAM_RED].Goals);
2136 // Î÷êè Ñèíåé êîìàíäû:
2137 Mem.ReadSmallInt(gTeamStat[TEAM_BLUE].Goals);
2138 end;
2139 ///// /////
2140 end;
2142 end.