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
95 // returns panel or nil
96 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
97 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
99 // returns panel or nil
100 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
101 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
103 type
109 // trace liquid, stepping by `dx` and `dy`
110 // return last seen liquid coords, and `false` if we're started outside of the liquid
120 const
129 const
152 const
155 (* draw order:
156 PANEL_BACK
157 PANEL_STEP
158 PANEL_WALL
159 PANEL_CLOSEDOOR
160 PANEL_ACID1
161 PANEL_ACID2
162 PANEL_WATER
163 PANEL_FORE
164 *)
165 // sorted by draw priority
174 // the following are invisible
178 GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
181 var
190 //gDOMFlags: array of TFlag;
202 gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
210 type
213 var
217 implementation
219 uses
228 const
234 var
238 var
242 begin
244 try
247 except
252 begin
255 begin
256 //raise Exception.Create('cannot load "game.wad"');
258 end
259 else
260 begin
266 begin
267 //raise Exception.Create('cannot open "mapdef.txt"');
270 end
271 else
272 begin
276 try
279 raise Exception.Create(Format('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.line, pr.col, e.message]));
288 var
291 begin
299 if (PAnsiChar(data)[0] = 'M') and (PAnsiChar(data)[1] = 'A') and (PAnsiChar(data)[2] = 'P') and (PByte(data)[3] = 1) then
300 begin
301 // binary map
302 try
305 begin
309 exit;
313 end
314 else
315 begin
316 // text map
318 try
321 begin
326 exit;
334 var
341 var
344 begin
352 begin
355 Exit;
356 end
357 else
358 begin
361 Break;
365 // Íå ïåðåâåñòè â ÷èñëî:
367 Exit;
376 begin
378 begin
381 Exit;
387 Result := NNF_NAME_BEFORE
388 else
390 Result := NNF_NAME_AFTER
391 else
399 begin
409 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: result := GridTagLift; // gLifts -- this is for all lifts
417 var
419 begin
428 begin
429 if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
433 type
439 var
444 //DOMFlagPoints: Array of TFlagPoint;
448 begin
449 if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size);
451 // create sections
453 begin
462 begin
467 // wall index in `gWalls` or -1
468 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
469 var
471 begin
474 begin
477 end
478 else
479 begin
485 // returns panel or nil
486 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
487 var
489 begin
492 begin
495 end
496 else
497 begin
507 begin
508 {
509 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
510 begin
511 result := pan.Enabled; // stop if wall is enabled
512 exit;
513 end;
514 }
517 begin
518 // stop if the lift of the right type
519 result :=
524 exit;
527 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
530 var
532 begin
535 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
540 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
545 begin
546 // slow
548 end
549 else
550 begin
551 // fast
558 begin
566 begin
573 var
582 begin
584 Exit;
592 begin
602 begin
608 // Íåò äâåðåé:
610 begin
612 Exit;
621 begin
630 begin
636 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
637 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
644 begin
650 Break;
661 var
669 begin
671 Exit;
677 begin
692 begin
700 begin
713 begin
723 Break;
740 var
743 begin
749 PANEL_BACK:
751 PANEL_FORE:
753 PANEL_WATER:
755 PANEL_ACID1:
757 PANEL_ACID2:
759 PANEL_STEP:
763 PANEL_BLOCKMON:
765 else
766 Exit;
788 begin
793 begin
803 var
808 begin
816 Exit;
819 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
823 begin
827 begin
832 else
835 else
843 Exit;
846 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
853 else
859 {
860 if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
861 begin
862 FreeMem(TextureData);
863 RecName := 'COMMON\ALIEN';
864 end;
865 }
868 begin
871 Exit;
880 end
882 begin
883 //e_WriteLog(Format('SHIT! Error loading texture %s : %s : %s', [RecName, txname, g_ExtractFilePathName(RecName)]), MSG_WARNING);
885 begin
887 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
895 var
906 //imgfmt: string;
909 begin
912 //e_WriteLog(Format('*** Loading animated texture "%s"', [RecName]), MSG_NOTIFY);
914 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
918 try
921 else
927 begin
929 begin
931 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
933 exit;
936 {TEST
937 if WADName = Map then
938 begin
939 //FreeMem(TextureWAD);
940 if not WAD.GetResource('COMMON/animation', TextureWAD, ResLength) then Halt(1);
941 end;
942 }
947 begin
949 exit;
952 // ýòî ïòèöà? ýòî ñàìîë¸ò?
955 begin
956 // íåò, ýòî ñóïåðìåí!
958 begin
960 exit;
963 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
965 begin
967 exit;
974 begin
976 exit;
988 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
990 begin
991 e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), MSG_WARNING);
992 exit;
1000 begin
1001 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
1002 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength, _width, _height, _framecount, _backanimation) then
1003 begin
1011 end
1012 else
1013 begin
1017 end
1018 else
1019 begin
1020 // try animated image
1021 {
1022 imgfmt := DetermineMemoryFormat(TextureWAD, ResLength);
1023 if length(imgfmt) = 0 then
1024 begin
1025 e_WriteLog(Format('Animated texture file "%s" has unknown format', [RecName]), MSG_WARNING);
1026 exit;
1027 end;
1028 }
1032 begin
1034 exit;
1037 begin
1039 exit;
1053 begin
1054 //writeln(' frame delay: ', GlobalMetadata.MetaItems[SMetaFrameDelay]);
1055 try
1059 // rounding ;-)
1065 except
1069 begin
1070 //writeln(' frame loop : ', GlobalMetadata.MetaItems[SMetaAnimationLoops]);
1071 try
1075 except
1078 //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
1079 //for f := 0 to high(ia) do writeln(' frame #', f, ': ', ia[f].width, 'x', ia[f].height);
1081 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);
1084 // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
1086 begin
1094 //writeln(' CREATED!');
1095 end
1096 else
1097 begin
1098 if log then e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), MSG_WARNING);
1101 finally
1112 begin
1117 Exit;
1124 var
1127 begin
1131 begin
1134 begin
1150 begin
1158 begin
1165 begin
1178 AREA_DOMFLAG:
1179 begin
1180 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
1181 with DOMFlagPoints[High(DOMFlagPoints)] do
1182 begin
1183 X := Area.X;
1184 Y := Area.Y;
1185 Direction := TDirection(Area.Direction);
1186 end;
1188 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
1193 procedure CreateTrigger(Trigger: TDynRecord; atpanid, ashotpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word);
1194 var
1196 begin
1200 begin
1214 //Data.Default := Trigger.DATA;
1222 var
1225 begin
1230 begin
1231 mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
1234 begin
1236 begin
1238 begin
1239 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1252 var
1254 begin
1258 begin
1260 begin
1261 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1267 begin
1274 var
1276 begin
1280 else
1285 begin
1292 //var
1293 //textures: TTexturesRec1Array;
1294 //textures: TDynField;
1295 //trec: TDynRecord;
1296 //mapHeader: TMapHeaderRec_1;
1297 //i: integer;
1298 //resFile: String = '';
1299 begin
1305 (*
1306 {
1307 textures := GetTextures(map);
1308 for i := 0 to High(textures) do
1309 begin
1310 addResToExternalResList(resFile);
1311 end;
1312 }
1314 textures := map['texture'];
1315 if (textures <> nil) then
1316 begin
1317 for trec in textures do
1318 begin
1319 addResToExternalResList(resFile);
1320 end;
1321 end;
1323 textures := nil;
1324 *)
1326 //mapHeader := GetMapHeader(map);
1334 var
1341 var
1344 begin
1346 begin
1358 var
1362 begin
1363 //tag := panelTypeToTag(tag);
1365 begin
1369 begin
1370 {$IF DEFINED(D2F_DEBUG)}
1371 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);
1372 {$ENDIF}
1373 continue;
1391 // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
1393 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
1394 {
1395 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
1396 begin
1397 e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
1398 end;
1399 }
1400 {$ENDIF}
1404 begin
1418 e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]);
1427 //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height);
1446 const
1449 type
1452 //TexturePanel: Integer;
1463 var
1465 //MapReader: TMapReader_1;
1467 //Header: TMapHeaderRec_1;
1469 //_texnummap: array of Integer = nil; // `_textures` -> `Textures`
1478 //texture: TTextureRec_1;
1488 // key: panel index; value: `TriggersTable` index
1493 begin
1504 //FillChar(texture, SizeOf(texture), 0);
1507 try
1508 // Çàãðóçêà WAD:
1515 begin
1518 Exit;
1521 //k8: why loader ignores path here?
1524 begin
1527 Exit;
1533 begin
1536 exit;
1539 // Çàãðóçêà êàðòû:
1543 try
1545 except
1549 Exit;
1560 //_textures := GetTextures(mapReader);
1562 //_texnummap := nil;
1563 // get all other lists here too
1564 //panels := GetPanels(mapReader);
1566 //triggers := GetTriggers(mapReader);
1568 //items := GetItems(mapReader);
1570 //areas := GetAreas(mapReader);
1572 //monsters := GetMonsters(mapReader);
1575 // Çàãðóçêà îïèñàíèÿ êàðòû:
1578 //Header := GetMapHeader(mapReader);
1581 begin
1591 // Çàãðóçêà òåêñòóð:
1593 // Äîáàâëåíèå òåêñòóð â Textures[]:
1595 begin
1598 //SetLength(_texnummap, _textures.count);
1602 begin
1605 {$IF DEFINED(D2F_DEBUG_TXLOAD)}
1607 {$ENDIF}
1608 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
1610 begin
1611 // Àíèìèðîâàííàÿ òåêñòóðà
1614 end
1615 else
1616 begin
1617 // Îáû÷íàÿ òåêñòóðà
1623 //_texnummap[a] := ntn; // fix texture number
1628 // set panel tagInt to texture index
1630 begin
1632 begin
1639 // Çàãðóçêà òðèããåðîâ
1644 // Çàãðóçêà ïàíåëåé
1648 // check texture numbers for panels
1650 begin
1652 begin
1654 begin
1657 exit;
1662 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
1664 begin
1666 //SetLength(TriggersTable, triggers.count);
1670 begin
1682 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
1683 //if (rec.TexturePanel >= 0) and (pttit.texPan = nil) then e_WriteLog('error loading map: invalid texture panel index for trigger', MSG_WARNING);
1684 // Ëèôòû
1686 begin
1687 //pttit.LiftPanel := TTriggerData(rec.DATA).PanelID
1689 //if (rec.trigRec.trigPanelID >= 0) and (pttit.liftPan = nil) then e_WriteLog('error loading map: invalid lift panel index for trigger', MSG_WARNING);
1691 // Äâåðè
1692 if rec.TriggerType in [TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
1693 begin
1694 //pttit.DoorPanel := TTriggerData(rec.DATA).PanelID
1697 // Òóðåëü
1699 begin
1700 //pttit.ShotPanel := TTriggerData(rec.DATA).ShotPanelID
1704 // update hashes
1708 if (pttit.shotPan <> nil) then hashShotPan.put(rec.trigRec.tgShotPanelID, High(TriggersTable));
1714 // Ñîçäàåì ïàíåëè
1716 begin
1722 begin
1731 begin
1737 begin
1738 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
1739 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
1742 begin
1744 begin
1746 begin
1749 break;
1756 begin
1757 // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
1760 // Ñïåö-òåêñòóðû çàïðåùåíû
1762 begin
1764 end
1765 else
1766 begin
1767 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè
1771 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
1772 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #
1774 begin
1776 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû
1778 begin
1782 begin
1783 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó
1785 begin
1786 // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
1790 begin
1791 // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
1795 end
1796 else
1797 begin
1798 // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
1802 begin
1803 // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
1809 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè
1811 begin
1813 begin
1815 begin
1819 break;
1823 end
1824 else
1825 begin
1827 begin
1828 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
1830 //AddTextures[High(AddTextures)].Texture := _texnummap[rec.TextureNum]; //panels[a].TextureNum;
1835 end
1837 begin
1848 begin
1849 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
1857 //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);
1859 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð
1861 //e_LogWritefln('panel #%s of type %s got id #%s', [pannum, rec.PanelType, PanelID]);
1863 // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID
1869 (*
1870 if (TriggersTable <> nil) then
1871 begin
1872 for b := 0 to High(TriggersTable) do
1873 begin
1874 if (TriggersTable[b].texPan = rec) then TriggersTable[b].texPanIdx := PanelID;
1875 if (TriggersTable[b].liftPan = rec) then TriggersTable[b].LiftPanelIdx := PanelID;
1876 if (TriggersTable[b].doorPan = rec) then TriggersTable[b].DoorPanelIdx := PanelID;
1877 if (TriggersTable[b].shotPan = rec) then TriggersTable[b].ShotPanelIdx := PanelID;
1878 {
1879 // Òðèããåð äâåðè/ëèôòà
1880 if (TriggersTable[b].LiftPanel = pannum) or
1881 (TriggersTable[b].DoorPanel = pannum) then
1882 //TTriggerData(TriggersTable[b].trigrec.DATA).PanelID := PanelID;
1883 TriggersTable[b].trigrec.trigRec.trigPanelID := PanelID;
1884 // Òðèããåð ñìåíû òåêñòóðû
1885 if TriggersTable[b].texPanIdx = pannum then
1886 TriggersTable[b].trigrec.TexturePanel := PanelID;
1887 // Òðèããåð "Òóðåëü"
1888 if TriggersTable[b].ShotPanel = pannum then
1889 TriggersTable[b].trigrec.trigRec.trigShotPanelID := PanelID;
1890 }
1891 end;
1892 end;
1893 *)
1899 (*
1900 begin
1901 for b := 0 to High(TriggersTable) do
1902 begin
1903 // Òðèããåð äâåðè/ëèôòà
1904 if (TriggersTable[b].texPan <> nil) then e_LogWritefln('trigger #%s: textPan=%s; panidx=%s', [b, TriggersTable[b].texPanIdx, mapReader.panelIndex[TriggersTable[b].texPan]]);
1905 if (TriggersTable[b].liftPan <> nil) then e_LogWritefln('trigger #%s: liftPan=%s; panidx=%s', [b, TriggersTable[b].LiftPanelIdx, mapReader.panelIndex[TriggersTable[b].liftPan]]);
1906 if (TriggersTable[b].doorPan <> nil) then e_LogWritefln('trigger #%s: doorPan=%s; panidx=%s', [b, TriggersTable[b].DoorPanelIdx, mapReader.panelIndex[TriggersTable[b].doorPan]]);
1907 if (TriggersTable[b].shotPan <> nil) then e_LogWritefln('trigger #%s: shotPan=%s; panidx=%s', [b, TriggersTable[b].ShotPanelIdx, mapReader.panelIndex[TriggersTable[b].shotPan]]);
1908 end;
1909 end;
1910 *)
1912 // create map grid, init other grids (for monsters, for example)
1916 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
1918 begin
1921 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü
1924 begin
1926 if (TriggersTable[trignum].texPan <> nil) then b := TriggersTable[trignum].texPan.PanelType else b := 0;
1927 if (TriggersTable[trignum].shotPan <> nil) then c := TriggersTable[trignum].shotPan.PanelType else c := 0;
1928 (*
1929 if (rec.TexturePanel <> -1) then
1930 begin
1931 {
1932 if (TriggersTable[trignum].TexturePanel < 0) or (TriggersTable[trignum].TexturePanel >= panels.count) then
1933 begin
1934 e_WriteLog('error loading map: invalid panel index for trigger', MSG_FATALERROR);
1935 result := false;
1936 exit;
1937 end;
1938 }
1939 //b := panels[TriggersTable[a].TexturePanel].PanelType;
1940 //b := mapReader.panel[TriggersTable[trignum].texPanIdx].PanelType;
1941 assert(TriggersTable[trignum].texPanIdx >= 0);
1942 b := TriggersTable[trignum].texPanIdx;
1943 end
1944 else
1945 begin
1946 b := 0;
1947 end;
1948 e_LogWritefln('trigger #%s: type=%s; texPanIdx=%s; b=%s', [trignum, rec.TriggerType, TriggersTable[trignum].texPanIdx, b]);
1949 if (rec.TriggerType = TRIGGER_SHOT) then e_LogWritefln(' SHOT: shotpanidx=%s', [rec.trigRec.trigShotPanelID]);
1950 if (rec.TriggerType = TRIGGER_SHOT) and {(rec.trigRec.trigShotPanelID <> -1)} (TriggersTable[trignum].shotPan <> nil) then
1951 begin
1952 //c := panels[TriggersTable[a].ShotPanel].PanelType;
1953 //c := mapReader.panel[TriggersTable[trignum].ShotPanel].PanelType;
1954 assert(TriggersTable[trignum].ShotPanelIdx >= 0);
1955 c := TriggersTable[trignum].ShotPanelIdx;
1956 end
1957 else
1958 begin
1959 c := 0;
1960 end;
1961 *)
1962 //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
1963 CreateTrigger(rec, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx, Word(b), Word(c));
1967 // Çàãðóçêà ïðåäìåòîâ
1971 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
1973 begin
1979 // Çàãðóçêà îáëàñòåé
1983 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
1985 begin
1991 // Çàãðóçêà ìîíñòðîâ
1997 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
1999 begin
2005 //MapReader.Free();
2009 // Çàãðóçêà íåáà
2011 begin
2018 else
2019 begin
2025 begin
2027 end
2028 else
2032 // Çàãðóçêà ìóçûêè
2035 begin
2042 else
2043 begin
2050 else
2054 // Îñòàëüíûå óñòàíâêè
2062 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
2065 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
2074 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
2076 begin
2079 end
2080 else
2081 begin
2084 finally
2098 var
2101 //Header: TMapHeaderRec_1;
2105 begin
2111 begin
2113 Exit;
2116 //k8: it ignores path again
2118 begin
2120 Exit;
2125 {
2126 MapReader := TMapReader_1.Create();
2127 if not MapReader.LoadMap(Data) then
2128 begin
2129 g_Console_Add(Format(_lc[I_GAME_ERROR_MAP_LOAD], [Res]), True);
2130 ZeroMemory(@Header, SizeOf(Header));
2131 Result.Name := _lc[I_GAME_ERROR_MAP_SELECT];
2132 Result.Description := _lc[I_GAME_ERROR_MAP_SELECT];
2133 end
2134 else
2135 begin
2136 Header := MapReader.GetMapHeader();
2137 Result.Name := Header.MapName;
2138 Result.Description := Header.MapDescription;
2139 end;
2140 }
2141 try
2143 except
2148 //MapReader.Free();
2150 //if (mapReader <> nil) then Header := GetMapHeader(mapReader) else FillChar(Header, sizeof(Header), 0);
2151 //MapReader.Free();
2154 begin
2161 end
2162 else
2163 begin
2165 //ZeroMemory(@Header, SizeOf(Header));
2178 var
2182 begin
2186 begin
2188 Exit;
2192 begin
2194 begin
2203 var
2208 begin
2215 begin
2217 Exit;
2226 begin
2228 Exit;
2233 var
2237 var
2240 begin
2242 begin
2249 begin
2258 begin
2263 begin
2267 //DOMFlagPoints := nil;
2269 //gDOMFlags := nil;
2272 begin
2277 else
2295 begin
2319 var
2325 var
2328 begin
2334 begin
2344 begin
2348 begin
2355 Continue;
2357 // Ñîïðîòèâëåíèå âîçäóõà:
2360 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó:
2362 begin
2367 else
2373 Continue;
2379 // Èãðîê áåðåò ôëàã:
2381 begin
2385 begin
2393 begin
2395 Break;
2404 // old algo
2408 var
2410 begin
2412 begin
2413 // alas, no visible set
2415 begin
2421 begin
2435 // new algo
2439 begin
2445 begin
2447 //tagmask := panelTypeToTag(PanelType);
2449 // list will be rendered in `g_game.DrawPlayer()`
2456 begin
2461 begin
2462 mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
2467 begin
2470 else
2476 var
2478 begin
2483 begin
2491 begin
2493 Exit;
2499 begin
2506 begin
2508 Exit;
2514 begin
2521 begin
2523 Exit;
2529 begin
2536 begin
2538 Exit;
2544 begin
2551 begin
2553 Exit;
2557 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
2559 begin
2570 begin
2572 Exit;
2578 begin
2587 begin
2589 Exit;
2595 var
2599 var
2601 begin
2605 begin
2606 if g_Collide(X, Y, Width, Height, panels[a].X, panels[a].Y, panels[a].Width, panels[a].Height) then
2607 begin
2610 exit;
2615 begin
2625 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
2626 const
2629 begin
2630 {
2631 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
2632 begin
2633 result := pan.Enabled;
2634 exit;
2635 end;
2636 }
2639 begin
2640 result :=
2646 exit;
2650 begin
2651 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2652 exit;
2655 // other shit
2656 //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2660 var
2662 begin
2663 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
2668 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
2675 begin
2677 begin
2679 begin
2680 // slow
2682 end
2683 else
2684 begin
2685 // fast
2688 end
2689 else
2690 begin
2692 begin
2693 // slow
2695 end
2696 else
2697 begin
2698 // fast
2702 end
2703 else
2704 begin
2712 var
2713 cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
2716 // slightly different from the old code, but meh...
2718 begin
2720 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
2721 // check priorities
2725 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
2727 // collision?
2728 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
2729 // yeah
2731 // water? water has the highest priority, so stop right here
2733 // acid2?
2735 // acid1?
2739 begin
2742 begin
2745 begin
2747 end
2748 else
2749 begin
2750 mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
2753 end
2754 else
2755 begin
2763 var
2765 begin
2771 //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
2772 //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor);
2776 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2777 //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);
2778 {$ENDIF}
2782 var
2784 begin
2790 //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
2794 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2795 //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);
2796 {$ENDIF}
2800 var
2802 begin
2806 PANEL_FORE:
2808 PANEL_BACK:
2810 PANEL_WATER:
2812 PANEL_ACID1:
2814 PANEL_ACID2:
2816 PANEL_STEP:
2818 else
2819 Exit;
2828 begin
2830 Exit;
2833 begin
2837 //TODO: make separate lift tags, and change tag here
2853 var
2856 begin
2861 Exit;
2865 begin
2871 Exit;
2878 var
2880 begin
2884 Exit;
2892 begin
2897 begin
2899 begin
2907 begin
2918 var
2921 begin
2923 Exit;
2928 begin
2930 continue;
2933 begin
2936 end
2937 else
2938 begin
2946 begin
2957 var
2964 var
2967 begin
2968 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé:
2973 begin
2975 begin
2976 // ID ïàíåëè:
2978 // Ñîõðàíÿåì ïàíåëü:
2984 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé:
2990 begin
2991 // Ñèãíàòóðà ôëàãà:
2994 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
2996 // Ñîñòîÿíèå ôëàãà:
2998 // Íàïðàâëåíèå ôëàãà:
3004 // Îáúåêò ôëàãà:
3008 begin
3011 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
3012 // Ñîõðàíÿåì ïàíåëè ñòåí è äâåðåé:
3014 // Ñîõðàíÿåì ïàíåëè ôîíà:
3016 // Ñîõðàíÿåì ïàíåëè ïåðåäíåãî ïëàíà:
3018 // Ñîõðàíÿåì ïàíåëè âîäû:
3020 // Ñîõðàíÿåì ïàíåëè êèñëîòû-1:
3022 // Ñîõðàíÿåì ïàíåëè êèñëîòû-2:
3024 // Ñîõðàíÿåì ïàíåëè ñòóïåíåé:
3026 // Ñîõðàíÿåì ïàíåëè ëèôòîâ:
3028 ///// /////
3030 ///// Ñîõðàíÿåì ìóçûêó: /////
3031 // Ñèãíàòóðà ìóçûêè:
3034 // Íàçâàíèå ìóçûêè:
3038 else
3041 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
3044 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
3047 ///// /////
3049 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
3051 ///// /////
3053 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
3055 begin
3056 // Ôëàã Êðàñíîé êîìàíäû:
3058 // Ôëàã Ñèíåé êîìàíäû:
3061 ///// /////
3063 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3065 begin
3066 // Î÷êè Êðàñíîé êîìàíäû:
3068 // Î÷êè Ñèíåé êîìàíäû:
3071 ///// /////
3075 var
3082 var
3085 begin
3086 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé:
3091 begin
3093 begin
3094 // ID ïàíåëè:
3097 begin
3100 // Çàãðóæàåì ïàíåëü:
3102 if (panels[i].arrIdx <> i) then raise Exception.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel arrIdx');
3107 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí:
3112 begin
3113 // Ñèãíàòóðà ôëàãà:
3116 begin
3119 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà:
3121 // Ñîñòîÿíèå ôëàãà:
3123 // Íàïðàâëåíèå ôëàãà:
3129 // Îáúåêò ôëàãà:
3133 begin
3135 Exit;
3137 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
3138 // Çàãðóæàåì ïàíåëè ñòåí è äâåðåé:
3140 // Çàãðóæàåì ïàíåëè ôîíà:
3142 // Çàãðóæàåì ïàíåëè ïåðåäíåãî ïëàíà:
3144 // Çàãðóæàåì ïàíåëè âîäû:
3146 // Çàãðóæàåì ïàíåëè êèñëîòû-1:
3148 // Çàãðóæàåì ïàíåëè êèñëîòû-2:
3150 // Çàãðóæàåì ïàíåëè ñòóïåíåé:
3152 // Çàãðóæàåì ïàíåëè ëèôòîâ:
3154 ///// /////
3156 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó:
3158 //mapCreateGrid();
3160 ///// Çàãðóæàåì ìóçûêó: /////
3161 // Ñèãíàòóðà ìóçûêè:
3164 begin
3167 // Íàçâàíèå ìóçûêè:
3170 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè:
3172 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå:
3174 // Çàïóñêàåì ýòó ìóçûêó:
3180 ///// /////
3182 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
3184 ///// /////
3186 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
3188 begin
3189 // Ôëàã Êðàñíîé êîìàíäû:
3191 // Ôëàã Ñèíåé êîìàíäû:
3194 ///// /////
3196 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3198 begin
3199 // Î÷êè Êðàñíîé êîìàíäû:
3201 // Î÷êè Ñèíåé êîìàíäû:
3204 ///// /////
3208 var
3210 begin
3219 // trace liquid, stepping by `dx` and `dy`
3220 // return last seen liquid coords, and `false` if we're started outside of the liquid
3221 function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean;
3222 const
3224 begin
3227 // started outside of the liquid?
3228 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then begin result := false; exit; end;
3232 begin
3235 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then exit; // out of the water, just exit