1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 {$DEFINE MAP_DEBUG_ENABLED_FLAG}
20 interface
22 uses
26 type
68 procedure g_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor); // unaccelerated
80 // HACK!!!
103 // returns panel or nil
104 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
105 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
107 // returns panel or nil
108 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
109 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
111 type
117 // trace liquid, stepping by `dx` and `dy`
118 // return last seen liquid coords, and `false` if we're started outside of the liquid
122 // return `true` from `cb` to stop
140 const
149 const
172 const
175 (* draw order:
176 PANEL_BACK
177 PANEL_STEP
178 PANEL_WALL
179 PANEL_CLOSEDOOR
180 PANEL_ACID1
181 PANEL_ACID2
182 PANEL_WATER
183 PANEL_FORE
184 *)
185 // sorted by draw priority
194 // the following are invisible
201 GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
204 var
213 //gDOMFlags: array of TFlag;
226 gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
235 type
238 var
242 implementation
244 uses
253 const
259 var
263 // ////////////////////////////////////////////////////////////////////////// //
265 begin
266 //if (panByGUID = nil) or (not panByGUID.get(aguid, result)) then result := nil;
267 if (aguid >= 0) and (aguid < Length(panByGUID)) then result := panByGUID[aguid] else result := nil;
271 // return `true` from `cb` to stop
273 var
275 begin
279 begin
286 var
288 begin
290 begin
292 begin
299 // ////////////////////////////////////////////////////////////////////////// //
300 function g_Map_MinX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0 else result := 0; end;
301 function g_Map_MinY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0 else result := 0; end;
302 function g_Map_MaxX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0+mapGrid.gridWidth-1 else result := 0; end;
303 function g_Map_MaxY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0+mapGrid.gridHeight-1 else result := 0; end;
306 // ////////////////////////////////////////////////////////////////////////// //
307 var
312 var
316 begin
319 try
323 except
328 begin
331 begin
332 //raise Exception.Create('cannot load "game.wad"');
334 end
335 else
336 begin
341 try
343 begin
344 //raise Exception.Create('cannot open "mapdef.txt"');
347 end
348 else
349 begin
353 begin
359 try
361 except
363 raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [e.tokLine, e.tokCol, e.message]);
365 raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message]);
373 // ////////////////////////////////////////////////////////////////////////// //
375 var
377 begin
386 try
388 except
390 begin
394 exit;
397 begin
401 exit;
405 //e_LogWriteln('map parsed.');
409 // ////////////////////////////////////////////////////////////////////////// //
410 var
417 var
420 begin
428 begin
431 Exit;
432 end
433 else
434 begin
437 Break;
441 // Íå ïåðåâåñòè â ÷èñëî:
443 Exit;
452 begin
454 begin
457 Exit;
463 Result := NNF_NAME_BEFORE
464 else
466 Result := NNF_NAME_AFTER
467 else
474 // ////////////////////////////////////////////////////////////////////////// //
476 begin
486 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: result := GridTagLift; // gLifts -- this is for all lifts
494 var
496 begin
505 begin
506 if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
510 var
516 //DOMFlagPoints: Array of TFlagPoint;
520 begin
521 if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size);
523 // create sections
525 begin
534 begin
539 // wall index in `gWalls` or -1
540 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
541 var
543 begin
546 begin
549 end
550 else
551 begin
557 // returns panel or nil
558 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
559 var
561 begin
564 begin
567 end
568 else
569 begin
579 begin
580 {
581 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
582 begin
583 result := pan.Enabled; // stop if wall is enabled
584 exit;
585 end;
586 }
589 begin
590 // stop if the lift of the right type
591 result :=
596 exit;
599 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
602 var
604 begin
607 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
612 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
617 begin
618 // slow
620 end
621 else
622 begin
623 // fast
630 begin
638 begin
645 var
654 begin
656 Exit;
664 begin
674 begin
680 // Íåò äâåðåé:
682 begin
684 Exit;
693 begin
702 begin
708 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
709 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
716 begin
722 Break;
733 var
741 begin
743 Exit;
749 begin
764 begin
772 begin
785 begin
795 Break;
810 function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer): Integer;
811 var
816 begin
848 //result := len;
854 begin
863 begin
876 var
881 begin
885 begin
886 // i found her!
887 //e_LogWritefln('texture ''%s'' already loaded', [RecName]);
888 exit;
893 if (BadTextNameHash <> nil) and BadTextNameHash.has(RecName) then exit; // don't do it again and again
895 {
896 if Textures <> nil then
897 begin
898 for a := 0 to High(Textures) do
899 begin
900 if (Textures[a].TextureName = RecName) then
901 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
902 e_LogWritefln('texture ''%s'' already loaded', [RecName]);
903 Result := a;
904 Exit;
905 end;
906 end;
907 end;
908 }
910 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
914 begin
918 begin
929 Exit;
932 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
941 //txname := RecName;
942 {
943 if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
944 begin
945 FreeMem(TextureData);
946 RecName := 'COMMON\ALIEN';
947 end;
948 }
951 begin
954 begin
956 Exit;
958 e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height);
965 end
967 begin
968 //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING);
971 begin
973 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
983 var
994 //imgfmt: string;
997 begin
1001 begin
1002 // i found her!
1003 //e_LogWritefln('animated texture ''%s'' already loaded', [RecName]);
1004 exit;
1009 //e_LogWritefln('*** Loading animated texture "%s"', [RecName]);
1013 begin
1014 //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY);
1015 exit;
1018 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
1022 try
1028 begin
1031 begin
1033 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1036 exit;
1039 {TEST
1040 if WADName = Map then
1041 begin
1042 //FreeMem(TextureWAD);
1043 if not WAD.GetResource('COMMON/animation', TextureWAD, ResLength) then Halt(1);
1044 end;
1045 }
1050 begin
1053 exit;
1056 // ýòî ïòèöà? ýòî ñàìîë¸ò?
1059 begin
1060 // íåò, ýòî ñóïåðìåí!
1062 begin
1065 exit;
1068 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
1070 begin
1073 exit;
1080 begin
1081 e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), MSG_WARNING);
1083 exit;
1095 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
1097 begin
1098 e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), MSG_WARNING);
1100 exit;
1108 begin
1109 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
1110 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength, _width, _height, _framecount, _backanimation) then
1111 begin
1120 end
1121 else
1122 begin
1125 begin
1131 end
1132 else
1133 begin
1134 // try animated image
1135 {
1136 imgfmt := DetermineMemoryFormat(TextureWAD, ResLength);
1137 if length(imgfmt) = 0 then
1138 begin
1139 e_WriteLog(Format('Animated texture file "%s" has unknown format', [RecName]), MSG_WARNING);
1140 exit;
1141 end;
1142 }
1146 begin
1149 exit;
1152 begin
1155 exit;
1169 begin
1170 //writeln(' frame delay: ', GlobalMetadata.MetaItems[SMetaFrameDelay]);
1171 try
1175 // rounding ;-)
1181 except
1185 begin
1186 //writeln(' frame loop : ', GlobalMetadata.MetaItems[SMetaAnimationLoops]);
1187 try
1191 except
1194 //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
1195 //for f := 0 to high(ia) do writeln(' frame #', f, ': ', ia[f].width, 'x', ia[f].height);
1197 e_WriteLog(Format('Animated texture file "%s": %d frames (delay:%d; back:%d; frdelay:%d; frloop:%d), %dx%d', [RecName, length(ia), _speed, f, frdelay, frloop, _width, _height]), MSG_NOTIFY);
1200 // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
1202 begin
1211 //writeln(' CREATED!');
1212 end
1213 else
1214 begin
1217 begin
1223 finally
1234 begin
1239 Exit;
1246 var
1249 begin
1253 begin
1256 begin
1272 begin
1280 begin
1287 begin
1300 AREA_DOMFLAG:
1301 begin
1302 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
1303 with DOMFlagPoints[High(DOMFlagPoints)] do
1304 begin
1305 X := Area.X;
1306 Y := Area.Y;
1307 Direction := TDirection(Area.Direction);
1308 end;
1310 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
1315 function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word): Integer;
1316 var
1318 begin
1323 begin
1331 //TexturePanel := Trigger.TexturePanel;
1339 //trigShotPanelId := ashotpanid;
1340 //Data.Default := Trigger.DATA;
1347 var
1350 begin
1355 begin
1356 mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
1359 begin
1361 begin
1363 begin
1364 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1377 var
1379 //tw: TStrTextWriter;
1380 begin
1384 begin
1386 begin
1387 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1388 {
1389 tw := TStrTextWriter.Create();
1390 try
1391 gTriggers[a].trigData.writeTo(tw);
1392 e_LogWritefln('=== trigger #%s ==='#10'%s'#10'---', [a, tw.str]);
1393 finally
1394 tw.Free();
1395 end;
1396 }
1402 begin
1409 var
1411 begin
1415 else
1420 begin
1427 //var
1428 //textures: TTexturesRec1Array;
1429 //textures: TDynField;
1430 //trec: TDynRecord;
1431 //mapHeader: TMapHeaderRec_1;
1432 //i: integer;
1433 //resFile: String = '';
1434 begin
1440 (*
1441 {
1442 textures := GetTextures(map);
1443 for i := 0 to High(textures) do
1444 begin
1445 addResToExternalResList(resFile);
1446 end;
1447 }
1449 textures := map['texture'];
1450 if (textures <> nil) then
1451 begin
1452 for trec in textures do
1453 begin
1454 addResToExternalResList(resFile);
1455 end;
1456 end;
1458 textures := nil;
1459 *)
1461 //mapHeader := GetMapHeader(map);
1469 var
1476 var
1479 begin
1481 begin
1493 var
1497 begin
1498 //tag := panelTypeToTag(tag);
1500 begin
1504 begin
1505 {$IF DEFINED(D2F_DEBUG)}
1506 e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), MSG_NOTIFY);
1507 {$ENDIF}
1508 continue;
1526 // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
1528 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
1529 {
1530 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
1531 begin
1532 e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
1533 end;
1534 }
1535 {$ENDIF}
1539 begin
1553 e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]);
1562 //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height);
1581 const
1584 type
1587 //TexturePanel: Integer;
1591 // texture pane;
1594 // "action" panel
1598 var
1600 //mapReader: TDynRecord = nil;
1621 //moveActive: Boolean;
1624 begin
1628 //gCurrentMap.Free();
1629 //gCurrentMap := nil;
1636 //mapReader := nil;
1639 try
1640 // Çàãðóçêà WAD (åñëè ó íàñ íåò óæå çàãðóæåíîé êàðòû)
1642 begin
1649 begin
1652 Exit;
1655 //k8: why loader ignores path here?
1658 begin
1661 Exit;
1667 begin
1670 exit;
1673 // Çàãðóçêà êàðòû:
1679 try
1681 except
1686 Exit;
1692 begin
1695 exit;
1697 end
1698 else
1699 begin
1703 //gCurrentMap := mapReader;
1707 // get all other lists here too
1714 // Çàãðóçêà îïèñàíèÿ êàðòû:
1719 begin
1729 // Çàãðóçêà òåêñòóð:
1731 // Äîáàâëåíèå òåêñòóð â Textures[]:
1733 begin
1739 begin
1742 {$IF DEFINED(D2F_DEBUG_TXLOAD)}
1744 {$ENDIF}
1745 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
1747 begin
1748 // Àíèìèðîâàííàÿ òåêñòóðà
1751 end
1752 else
1753 begin
1754 // Îáû÷íàÿ òåêñòóðà
1764 // set panel tagInt to texture index
1766 begin
1768 begin
1775 // Çàãðóçêà òðèããåðîâ
1780 // Çàãðóçêà ïàíåëåé
1784 // check texture numbers for panels
1786 begin
1788 begin
1790 begin
1796 exit;
1801 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
1803 begin
1805 //SetLength(TriggersTable, triggers.count);
1811 begin
1815 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
1818 // action panel
1820 if (rec.trigRec <> nil) then pttit.actPanel := rec.trigRec.tgPanelRec else pttit.actPanel := nil;
1821 // set flag
1824 // update progress
1829 // Ñîçäàåì ïàíåëè
1831 begin
1837 begin
1839 //e_LogWritefln('PANSTART: pannum=%s', [pannum]);
1846 begin
1852 begin
1853 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
1854 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
1857 begin
1859 begin
1860 // e_LogWritefln('trigref for panel %s', [pannum]);
1867 begin
1868 // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
1871 // Ñïåö-òåêñòóðû çàïðåùåíû
1873 begin
1875 end
1876 else
1877 begin
1878 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè
1882 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
1883 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #
1885 begin
1887 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû
1889 begin
1893 begin
1894 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó
1896 begin
1897 // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
1899 //e_LogWritefln('000: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1901 //e_LogWritefln('001: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1903 begin
1904 // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
1906 //e_LogWritefln('002: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1908 //e_LogWritefln('003: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1910 end
1911 else
1912 begin
1913 // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
1915 //e_LogWritefln('004: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1917 //e_LogWritefln('005: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1919 begin
1920 // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
1922 //e_LogWritefln('006: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1924 //e_LogWritefln('007: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1928 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè
1930 begin
1931 {
1932 for c := 0 to High(Textures) do
1933 begin
1934 if (Textures[c].TextureName = TexName) then
1935 begin
1936 SetLength(AddTextures, Length(AddTextures)+1);
1937 AddTextures[High(AddTextures)].Texture := c;
1938 AddTextures[High(AddTextures)].Anim := isAnim;
1939 break;
1940 end;
1941 end;
1942 }
1944 begin
1950 end
1951 else
1952 begin
1954 begin
1955 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
1957 AddTextures[High(AddTextures)].Texture := rec.tagInt; // internal texture number, not map index
1961 end
1963 begin
1974 begin
1975 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
1983 //e_WriteLog(Format('panel #%d: TextureNum=%d; ht=%d; ht1=%d; atl=%d', [a, panels[a].TextureNum, High(mapTextureList), High(Textures), High(AddTextures)]), MSG_NOTIFY);
1985 //e_LogWritefln('PANADD: pannum=%s', [pannum]);
1987 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID
1989 //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]);
1992 // setup lifts
1994 //moveStart := rec.moveStart;
1995 //moveEnd := rec.moveEnd;
1996 //moveActive := rec['move_active'].value;
1998 begin
2001 //e_LogWritefln('found moving panel ''%s'' (idx=%s; id=%s)', [rec.id, pannum, PanelID]);
2004 //e_LogWritefln('PANEND: pannum=%s', [pannum]);
2010 // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ
2012 begin
2013 if (TriggersTable[b].texPanel <> nil) then TriggersTable[b].texPanelIdx := TriggersTable[b].texPanel.userPanelId;
2014 if (TriggersTable[b].actPanel <> nil) then TriggersTable[b].actPanelIdx := TriggersTable[b].actPanel.userPanelId;
2017 // create map grid, init other grids (for monsters, for example)
2021 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
2023 begin
2026 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü
2029 begin
2031 if (TriggersTable[trignum].texPanel <> nil) then b := TriggersTable[trignum].texPanel.PanelType else b := 0;
2032 if (TriggersTable[trignum].actPanel <> nil) then c := TriggersTable[trignum].actPanel.PanelType else c := 0;
2033 // we can have only one of those
2035 //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
2037 TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanelIdx, tgpid, Word(b), Word(c));
2041 //FIXME: use hashtable!
2043 begin
2045 begin
2049 begin
2054 // Çàãðóçêà ïðåäìåòîâ
2058 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
2060 begin
2066 // Çàãðóçêà îáëàñòåé
2070 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
2072 begin
2078 // Çàãðóçêà ìîíñòðîâ
2084 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
2086 begin
2092 //gCurrentMap := mapReader; // this will be our current map now
2094 //mapReader := nil;
2096 // Çàãðóçêà íåáà
2098 begin
2103 if (FileName <> '') then FileName := GameDir+'/wads/'+FileName else FileName := g_ExtractWadName(Res);
2106 try
2109 begin
2111 end
2112 else
2113 begin
2116 finally
2121 // Çàãðóçêà ìóçûêè
2124 begin
2131 else
2132 begin
2139 else
2143 // Îñòàëüíûå óñòàíâêè
2151 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
2154 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
2163 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
2165 begin
2168 end
2169 else
2170 begin
2175 e_LogWritefln('map loaded in %s.%s milliseconds', [Integer(stt div 1000), Integer(stt mod 1000)]);
2177 finally
2179 //mapReader.Free();
2182 begin
2195 var
2198 //Header: TMapHeaderRec_1;
2202 begin
2208 begin
2210 Exit;
2213 //k8: it ignores path again
2215 begin
2217 Exit;
2222 try
2224 except
2227 exit;
2235 begin
2242 end
2243 else
2244 begin
2246 //ZeroMemory(@Header, SizeOf(Header));
2259 var
2263 begin
2267 begin
2269 Exit;
2273 begin
2275 begin
2284 var
2289 begin
2296 begin
2298 Exit;
2307 begin
2309 Exit;
2314 var
2318 var
2321 begin
2323 begin
2330 begin
2339 begin
2344 begin
2348 //DOMFlagPoints := nil;
2350 //gDOMFlags := nil;
2353 begin
2355 end
2356 else
2357 begin
2362 begin
2365 begin
2367 begin
2369 begin
2371 begin
2373 end
2374 else
2375 begin
2377 begin
2408 begin
2430 var
2436 var
2439 begin
2443 begin
2454 if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end;
2457 begin
2459 begin
2461 begin
2463 begin
2470 // Ñîïðîòèâëåíèå âîçäóõà
2473 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó
2475 begin
2480 else
2486 Continue;
2491 // Èãðîê áåðåò ôëàã
2493 begin
2496 begin
2500 begin
2502 begin
2515 // old algo
2516 procedure g_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor);
2519 var
2521 begin
2523 begin
2524 // alas, no visible set
2526 begin
2532 begin
2546 // new algo
2550 begin
2556 begin
2558 //tagmask := panelTypeToTag(PanelType);
2560 // list will be rendered in `g_game.DrawPlayer()`
2567 begin
2572 begin
2573 mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
2578 begin
2581 else
2587 var
2589 begin
2594 begin
2602 begin
2604 Exit;
2610 begin
2617 begin
2619 Exit;
2625 begin
2632 begin
2634 Exit;
2640 begin
2647 begin
2649 Exit;
2655 begin
2662 begin
2664 Exit;
2668 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
2670 begin
2681 begin
2683 Exit;
2689 begin
2698 begin
2700 Exit;
2706 var
2710 var
2712 begin
2716 begin
2717 if g_Collide(X, Y, Width, Height, panels[a].X, panels[a].Y, panels[a].Width, panels[a].Height) then
2718 begin
2721 exit;
2726 begin
2736 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
2737 const
2740 begin
2741 {
2742 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
2743 begin
2744 result := pan.Enabled;
2745 exit;
2746 end;
2747 }
2750 begin
2751 result :=
2757 exit;
2761 begin
2762 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2763 exit;
2766 // other shit
2767 //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2771 var
2773 begin
2774 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
2779 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
2786 begin
2788 begin
2790 begin
2791 // slow
2793 end
2794 else
2795 begin
2796 // fast
2799 end
2800 else
2801 begin
2803 begin
2804 // slow
2806 end
2807 else
2808 begin
2809 // fast
2813 end
2814 else
2815 begin
2823 var
2824 cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
2827 // slightly different from the old code, but meh...
2829 begin
2831 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
2832 // check priorities
2836 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
2838 // collision?
2839 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
2840 // yeah
2842 // water? water has the highest priority, so stop right here
2844 // acid2?
2846 // acid1?
2850 begin
2853 begin
2856 begin
2858 end
2859 else
2860 begin
2861 mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
2864 end
2865 else
2866 begin
2873 procedure g_Map_EnableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_EnableWallGUID(gWalls[ID].guid); end;
2874 procedure g_Map_DisableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_DisableWallGUID(gWalls[ID].guid); end;
2875 procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); begin if (ID < Length(gLifts)) then g_Map_SetLiftGUID(gLifts[ID].guid, t); end;
2879 var
2881 begin
2882 //pan := gWalls[ID];
2891 //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
2892 //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor);
2894 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
2895 // mark platform as interesting
2898 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2899 //e_WriteLog(Format('ENABLE: wall #%d(%d) enabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
2900 {$ENDIF}
2905 var
2907 begin
2908 //pan := gWalls[ID];
2917 //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
2919 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
2920 // mark platform as interesting
2923 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2924 //e_WriteLog(Format('DISABLE: wall #%d(%d) disabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
2925 {$ENDIF}
2930 var
2932 begin
2935 {
2936 case PanelType of
2937 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: tp := gWalls[ID];
2938 PANEL_FORE: tp := gRenderForegrounds[ID];
2939 PANEL_BACK: tp := gRenderBackgrounds[ID];
2940 PANEL_WATER: tp := gWater[ID];
2941 PANEL_ACID1: tp := gAcid1[ID];
2942 PANEL_ACID2: tp := gAcid2[ID];
2943 PANEL_STEP: tp := gSteps[ID];
2944 else exit;
2945 end;
2946 }
2954 var
2956 begin
2957 //pan := gLifts[ID];
2965 begin
2969 //TODO: make separate lift tags, and change tag here
2978 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
2979 // mark platform as interesting
2986 var
2989 begin
2994 Exit;
2998 begin
3004 Exit;
3011 var
3013 begin
3017 Exit;
3025 begin
3030 begin
3032 begin
3040 begin
3051 var
3054 begin
3056 Exit;
3061 begin
3063 continue;
3066 begin
3069 end
3070 else
3071 begin
3079 begin
3091 var
3098 var
3101 begin
3102 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé
3105 // Ñîõðàíÿåì ïàíåëè
3106 //Mem.WriteInt(Length(panByGUID));
3109 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé
3115 begin
3116 // Ñèãíàòóðà ôëàãà
3119 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3121 // Ñîñòîÿíèå ôëàãà
3123 // Íàïðàâëåíèå ôëàãà
3126 // Îáúåêò ôëàãà
3130 begin
3133 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
3135 ///// /////
3137 ///// Ñîõðàíÿåì ìóçûêó: /////
3138 // Ñèãíàòóðà ìóçûêè:
3141 // Íàçâàíèå ìóçûêè:
3145 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3148 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3151 ///// /////
3153 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
3155 ///// /////
3157 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
3159 begin
3160 // Ôëàã Êðàñíîé êîìàíäû
3162 // Ôëàã Ñèíåé êîìàíäû
3165 ///// /////
3167 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3169 begin
3170 // Î÷êè Êðàñíîé êîìàíäû
3172 // Î÷êè Ñèíåé êîìàíäû
3175 ///// /////
3180 var
3187 var
3190 //count: LongInt;
3191 begin
3192 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé
3196 // Çàãðóæàåì ïàíåëè
3197 //PAMem.ReadInt(count);
3198 //if (count <> Length(panByGUID)) then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: invalid number of panels');
3199 //if (count <> Length(panByGUID)) then raise EBinSizeError.Create(Format('g_Map_LoadState: LoadPanelArray: invalid number of panels (%d : %d)', [count, Length(panByGUID)]));
3201 begin
3206 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí
3211 begin
3212 // Ñèãíàòóðà ôëàãà
3214 // 'FLAG'
3215 if dw <> FLAG_SIGNATURE then raise EBinSizeError.Create('g_Map_LoadState: LoadFlag: Wrong Flag Signature');
3216 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3218 // Ñîñòîÿíèå ôëàãà
3220 // Íàïðàâëåíèå ôëàãà
3223 // Îáúåêò ôëàãà
3227 begin
3230 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
3232 ///// /////
3234 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó
3236 //mapCreateGrid();
3238 ///// Çàãðóæàåì ìóçûêó: /////
3239 // Ñèãíàòóðà ìóçûêè
3241 // 'MUSI'
3242 if dw <> MUSIC_SIGNATURE then raise EBinSizeError.Create('g_Map_LoadState: Wrong Music Signature');
3243 // Íàçâàíèå ìóçûêè
3246 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3248 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3250 // Çàïóñêàåì ýòó ìóçûêó
3256 ///// /////
3258 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
3260 ///// /////
3262 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
3264 begin
3265 // Ôëàã Êðàñíîé êîìàíäû
3267 // Ôëàã Ñèíåé êîìàíäû
3270 ///// /////
3272 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3274 begin
3275 // Î÷êè Êðàñíîé êîìàíäû
3277 // Î÷êè Ñèíåé êîìàíäû
3280 ///// /////
3284 // trace liquid, stepping by `dx` and `dy`
3285 // return last seen liquid coords, and `false` if we're started outside of the liquid
3286 function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean;
3287 const
3289 begin
3292 // started outside of the liquid?
3293 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then begin result := false; exit; end;
3297 begin
3300 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then exit; // out of the water, just exit