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
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
362 raise Exception.Create(Format('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.line, pr.col, e.message]));
370 // ////////////////////////////////////////////////////////////////////////// //
372 var
375 begin
385 if (PAnsiChar(data)[0] = 'M') and (PAnsiChar(data)[1] = 'A') and (PAnsiChar(data)[2] = 'P') and (PByte(data)[3] = 1) then
386 begin
387 // binary map
388 try
389 //e_LogWriteln('parsing binary map...');
392 begin
396 exit;
400 end
401 else
402 begin
403 // text map
405 try
406 //e_LogWriteln('parsing text map...');
409 begin
414 exit;
419 //e_LogWriteln('map parsed.');
423 // ////////////////////////////////////////////////////////////////////////// //
424 var
431 var
434 begin
442 begin
445 Exit;
446 end
447 else
448 begin
451 Break;
455 // Íå ïåðåâåñòè â ÷èñëî:
457 Exit;
466 begin
468 begin
471 Exit;
477 Result := NNF_NAME_BEFORE
478 else
480 Result := NNF_NAME_AFTER
481 else
488 // ////////////////////////////////////////////////////////////////////////// //
490 begin
500 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: result := GridTagLift; // gLifts -- this is for all lifts
508 var
510 begin
519 begin
520 if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
524 var
530 //DOMFlagPoints: Array of TFlagPoint;
534 begin
535 if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size);
537 // create sections
539 begin
548 begin
553 // wall index in `gWalls` or -1
554 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
555 var
557 begin
560 begin
563 end
564 else
565 begin
571 // returns panel or nil
572 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
573 var
575 begin
578 begin
581 end
582 else
583 begin
593 begin
594 {
595 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
596 begin
597 result := pan.Enabled; // stop if wall is enabled
598 exit;
599 end;
600 }
603 begin
604 // stop if the lift of the right type
605 result :=
610 exit;
613 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
616 var
618 begin
621 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
626 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
631 begin
632 // slow
634 end
635 else
636 begin
637 // fast
644 begin
652 begin
659 var
668 begin
670 Exit;
678 begin
688 begin
694 // Íåò äâåðåé:
696 begin
698 Exit;
707 begin
716 begin
722 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
723 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
730 begin
736 Break;
747 var
755 begin
757 Exit;
763 begin
778 begin
786 begin
799 begin
809 Break;
824 function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; sav: Boolean): Integer;
825 var
830 begin
863 //result := len;
869 begin
878 begin
891 var
896 begin
900 begin
901 // i found her!
902 //e_LogWritefln('texture ''%s'' already loaded', [RecName]);
903 exit;
908 if (BadTextNameHash <> nil) and BadTextNameHash.has(RecName) then exit; // don't do it again and again
910 {
911 if Textures <> nil then
912 begin
913 for a := 0 to High(Textures) do
914 begin
915 if (Textures[a].TextureName = RecName) then
916 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
917 e_LogWritefln('texture ''%s'' already loaded', [RecName]);
918 Result := a;
919 Exit;
920 end;
921 end;
922 end;
923 }
925 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
929 begin
933 begin
944 Exit;
947 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
956 //txname := RecName;
957 {
958 if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
959 begin
960 FreeMem(TextureData);
961 RecName := 'COMMON\ALIEN';
962 end;
963 }
966 begin
969 begin
971 Exit;
973 e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height);
980 end
982 begin
983 //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING);
986 begin
988 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
998 var
1009 //imgfmt: string;
1012 begin
1016 begin
1017 // i found her!
1018 //e_LogWritefln('animated texture ''%s'' already loaded', [RecName]);
1019 exit;
1024 //e_LogWritefln('*** Loading animated texture "%s"', [RecName]);
1028 begin
1029 //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY);
1030 exit;
1033 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
1037 try
1043 begin
1046 begin
1048 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1051 exit;
1054 {TEST
1055 if WADName = Map then
1056 begin
1057 //FreeMem(TextureWAD);
1058 if not WAD.GetResource('COMMON/animation', TextureWAD, ResLength) then Halt(1);
1059 end;
1060 }
1065 begin
1068 exit;
1071 // ýòî ïòèöà? ýòî ñàìîë¸ò?
1074 begin
1075 // íåò, ýòî ñóïåðìåí!
1077 begin
1080 exit;
1083 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
1085 begin
1088 exit;
1095 begin
1096 e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), MSG_WARNING);
1098 exit;
1110 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
1112 begin
1113 e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), MSG_WARNING);
1115 exit;
1123 begin
1124 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
1125 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength, _width, _height, _framecount, _backanimation) then
1126 begin
1135 end
1136 else
1137 begin
1140 begin
1146 end
1147 else
1148 begin
1149 // try animated image
1150 {
1151 imgfmt := DetermineMemoryFormat(TextureWAD, ResLength);
1152 if length(imgfmt) = 0 then
1153 begin
1154 e_WriteLog(Format('Animated texture file "%s" has unknown format', [RecName]), MSG_WARNING);
1155 exit;
1156 end;
1157 }
1161 begin
1164 exit;
1167 begin
1170 exit;
1184 begin
1185 //writeln(' frame delay: ', GlobalMetadata.MetaItems[SMetaFrameDelay]);
1186 try
1190 // rounding ;-)
1196 except
1200 begin
1201 //writeln(' frame loop : ', GlobalMetadata.MetaItems[SMetaAnimationLoops]);
1202 try
1206 except
1209 //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
1210 //for f := 0 to high(ia) do writeln(' frame #', f, ': ', ia[f].width, 'x', ia[f].height);
1212 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);
1215 // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
1217 begin
1226 //writeln(' CREATED!');
1227 end
1228 else
1229 begin
1232 begin
1238 finally
1249 begin
1254 Exit;
1261 var
1264 begin
1268 begin
1271 begin
1287 begin
1295 begin
1302 begin
1315 AREA_DOMFLAG:
1316 begin
1317 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
1318 with DOMFlagPoints[High(DOMFlagPoints)] do
1319 begin
1320 X := Area.X;
1321 Y := Area.Y;
1322 Direction := TDirection(Area.Direction);
1323 end;
1325 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
1330 function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word): Integer;
1331 var
1333 begin
1338 begin
1346 //TexturePanel := Trigger.TexturePanel;
1354 //trigShotPanelId := ashotpanid;
1355 //Data.Default := Trigger.DATA;
1357 begin
1360 begin
1363 end
1364 else
1365 begin
1374 var
1377 begin
1382 begin
1383 mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
1386 begin
1388 begin
1390 begin
1391 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1404 var
1406 //tw: TStrTextWriter;
1407 begin
1411 begin
1413 begin
1414 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1415 {
1416 tw := TStrTextWriter.Create();
1417 try
1418 gTriggers[a].trigData.writeTo(tw);
1419 e_LogWritefln('=== trigger #%s ==='#10'%s'#10'---', [a, tw.str]);
1420 finally
1421 tw.Free();
1422 end;
1423 }
1429 begin
1436 var
1438 begin
1442 else
1447 begin
1454 //var
1455 //textures: TTexturesRec1Array;
1456 //textures: TDynField;
1457 //trec: TDynRecord;
1458 //mapHeader: TMapHeaderRec_1;
1459 //i: integer;
1460 //resFile: String = '';
1461 begin
1467 (*
1468 {
1469 textures := GetTextures(map);
1470 for i := 0 to High(textures) do
1471 begin
1472 addResToExternalResList(resFile);
1473 end;
1474 }
1476 textures := map['texture'];
1477 if (textures <> nil) then
1478 begin
1479 for trec in textures do
1480 begin
1481 addResToExternalResList(resFile);
1482 end;
1483 end;
1485 textures := nil;
1486 *)
1488 //mapHeader := GetMapHeader(map);
1496 var
1503 var
1506 begin
1508 begin
1520 var
1524 begin
1525 //tag := panelTypeToTag(tag);
1527 begin
1531 begin
1532 {$IF DEFINED(D2F_DEBUG)}
1533 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);
1534 {$ENDIF}
1535 continue;
1553 // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
1555 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
1556 {
1557 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
1558 begin
1559 e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
1560 end;
1561 }
1562 {$ENDIF}
1566 begin
1580 e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]);
1589 //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height);
1608 const
1611 type
1614 //TexturePanel: Integer;
1629 var
1652 //moveActive: Boolean;
1654 begin
1669 try
1670 // Çàãðóçêà WAD:
1677 begin
1680 Exit;
1683 //k8: why loader ignores path here?
1686 begin
1689 Exit;
1695 begin
1698 exit;
1701 // Çàãðóçêà êàðòû:
1707 try
1709 except
1713 Exit;
1719 begin
1721 exit;
1726 // get all other lists here too
1733 // Çàãðóçêà îïèñàíèÿ êàðòû:
1738 begin
1748 // Çàãðóçêà òåêñòóð:
1750 // Äîáàâëåíèå òåêñòóð â Textures[]:
1752 begin
1758 begin
1761 {$IF DEFINED(D2F_DEBUG_TXLOAD)}
1763 {$ENDIF}
1764 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
1766 begin
1767 // Àíèìèðîâàííàÿ òåêñòóðà
1770 end
1771 else
1772 begin
1773 // Îáû÷íàÿ òåêñòóðà
1783 // set panel tagInt to texture index
1785 begin
1787 begin
1794 // Çàãðóçêà òðèããåðîâ
1799 // Çàãðóçêà ïàíåëåé
1803 // check texture numbers for panels
1805 begin
1807 begin
1809 begin
1812 exit;
1817 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
1819 begin
1821 //SetLength(TriggersTable, triggers.count);
1825 begin
1829 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
1840 // Ëèôòû
1842 begin
1845 // Äâåðè
1846 if rec.TriggerType in [TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
1847 begin
1850 // Òóðåëü
1852 begin
1855 //
1857 begin
1871 // Ñîçäàåì ïàíåëè
1873 begin
1879 begin
1881 //e_LogWritefln('PANSTART: pannum=%s', [pannum]);
1889 begin
1895 begin
1896 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
1897 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
1900 begin
1901 {
1902 for b := 0 to High(TriggersTable) do
1903 begin
1904 if (TriggersTable[b].texPan = rec) or (TriggersTable[b].shotPan = rec) then
1905 begin
1906 trigRef := True;
1907 ok := True;
1908 break;
1909 end;
1910 end;
1911 }
1913 begin
1914 // e_LogWritefln('trigref for panel %s', [pannum]);
1922 begin
1923 // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
1926 // Ñïåö-òåêñòóðû çàïðåùåíû
1928 begin
1930 end
1931 else
1932 begin
1933 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè
1937 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
1938 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #
1940 begin
1942 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû
1944 begin
1948 begin
1949 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó
1951 begin
1952 // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
1954 //e_LogWritefln('000: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1956 //e_LogWritefln('001: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1958 begin
1959 // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
1961 //e_LogWritefln('002: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1963 //e_LogWritefln('003: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1965 end
1966 else
1967 begin
1968 // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
1970 //e_LogWritefln('004: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1972 //e_LogWritefln('005: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1974 begin
1975 // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
1977 //e_LogWritefln('006: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1979 //e_LogWritefln('007: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1983 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè
1985 begin
1986 {
1987 for c := 0 to High(Textures) do
1988 begin
1989 if (Textures[c].TextureName = TexName) then
1990 begin
1991 SetLength(AddTextures, Length(AddTextures)+1);
1992 AddTextures[High(AddTextures)].Texture := c;
1993 AddTextures[High(AddTextures)].Anim := isAnim;
1994 break;
1995 end;
1996 end;
1997 }
1999 begin
2005 end
2006 else
2007 begin
2009 begin
2010 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
2012 AddTextures[High(AddTextures)].Texture := rec.tagInt; // internal texture number, not map index
2016 end
2018 begin
2029 begin
2030 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
2038 //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);
2040 //e_LogWritefln('PANADD: pannum=%s', [pannum]);
2042 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID
2044 //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]);
2047 // setup lifts
2049 //moveStart := rec.moveStart;
2050 //moveEnd := rec.moveEnd;
2051 //moveActive := rec['move_active'].varvalue;
2053 begin
2056 //e_LogWritefln('found moving panel ''%s'' (idx=%s; id=%s)', [rec.id, pannum, PanelID]);
2059 //e_LogWritefln('PANEND: pannum=%s', [pannum]);
2065 // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ
2067 begin
2068 if (TriggersTable[b].texPan <> nil) then TriggersTable[b].texPanIdx := TriggersTable[b].texPan.userPanelId;
2069 if (TriggersTable[b].liftPan <> nil) then TriggersTable[b].LiftPanelIdx := TriggersTable[b].liftPan.userPanelId;
2070 if (TriggersTable[b].doorPan <> nil) then TriggersTable[b].DoorPanelIdx := TriggersTable[b].doorPan.userPanelId;
2071 if (TriggersTable[b].shotPan <> nil) then TriggersTable[b].ShotPanelIdx := TriggersTable[b].shotPan.userPanelId;
2072 if (TriggersTable[b].mplatPan <> nil) then TriggersTable[b].MPlatPanelIdx := TriggersTable[b].mplatPan.userPanelId;
2075 // create map grid, init other grids (for monsters, for example)
2079 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
2081 begin
2084 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü
2087 begin
2089 if (TriggersTable[trignum].texPan <> nil) then b := TriggersTable[trignum].texPan.PanelType else b := 0;
2090 if (TriggersTable[trignum].shotPan <> nil) then c := TriggersTable[trignum].shotPan.PanelType else c := 0;
2091 // we can have only one of those
2092 if (TriggersTable[trignum].LiftPanelIdx <> -1) then tgpid := TriggersTable[trignum].LiftPanelIdx
2093 else if (TriggersTable[trignum].DoorPanelIdx <> -1) then tgpid := TriggersTable[trignum].DoorPanelIdx
2094 else if (TriggersTable[trignum].ShotPanelIdx <> -1) then tgpid := TriggersTable[trignum].ShotPanelIdx
2095 else if (TriggersTable[trignum].MPlatPanelIdx <> -1) then tgpid := TriggersTable[trignum].MPlatPanelIdx
2097 //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
2099 TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c));
2103 //FIXME: use hashtable!
2105 begin
2107 begin
2111 begin
2116 // Çàãðóçêà ïðåäìåòîâ
2120 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
2122 begin
2128 // Çàãðóçêà îáëàñòåé
2132 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
2134 begin
2140 // Çàãðóçêà ìîíñòðîâ
2146 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
2148 begin
2158 // Çàãðóçêà íåáà
2160 begin
2167 else
2168 begin
2174 begin
2176 end
2177 else
2181 // Çàãðóçêà ìóçûêè
2184 begin
2191 else
2192 begin
2199 else
2203 // Îñòàëüíûå óñòàíâêè
2211 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
2214 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
2223 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
2225 begin
2228 end
2229 else
2230 begin
2235 e_LogWritefln('map loaded in %s.%s milliseconds', [Integer(stt div 1000), Integer(stt mod 1000)]);
2236 finally
2248 var
2251 //Header: TMapHeaderRec_1;
2255 begin
2261 begin
2263 Exit;
2266 //k8: it ignores path again
2268 begin
2270 Exit;
2275 try
2277 except
2280 exit;
2288 begin
2295 end
2296 else
2297 begin
2299 //ZeroMemory(@Header, SizeOf(Header));
2312 var
2316 begin
2320 begin
2322 Exit;
2326 begin
2328 begin
2337 var
2342 begin
2349 begin
2351 Exit;
2360 begin
2362 Exit;
2367 var
2371 var
2374 begin
2376 begin
2383 begin
2392 begin
2397 begin
2401 //DOMFlagPoints := nil;
2403 //gDOMFlags := nil;
2406 begin
2408 end
2409 else
2410 begin
2414 begin
2417 begin
2419 begin
2421 begin
2423 begin
2425 end
2426 else
2427 begin
2429 begin
2457 begin
2479 var
2485 var
2488 begin
2492 begin
2503 if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end;
2506 begin
2508 begin
2510 begin
2512 begin
2519 // Ñîïðîòèâëåíèå âîçäóõà
2522 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó
2524 begin
2529 else
2535 Continue;
2540 // Èãðîê áåðåò ôëàã
2542 begin
2545 begin
2549 begin
2551 begin
2564 // old algo
2568 var
2570 begin
2572 begin
2573 // alas, no visible set
2575 begin
2581 begin
2595 // new algo
2599 begin
2605 begin
2607 //tagmask := panelTypeToTag(PanelType);
2609 // list will be rendered in `g_game.DrawPlayer()`
2616 begin
2621 begin
2622 mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
2627 begin
2630 else
2636 var
2638 begin
2643 begin
2651 begin
2653 Exit;
2659 begin
2666 begin
2668 Exit;
2674 begin
2681 begin
2683 Exit;
2689 begin
2696 begin
2698 Exit;
2704 begin
2711 begin
2713 Exit;
2717 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
2719 begin
2730 begin
2732 Exit;
2738 begin
2747 begin
2749 Exit;
2755 var
2759 var
2761 begin
2765 begin
2766 if g_Collide(X, Y, Width, Height, panels[a].X, panels[a].Y, panels[a].Width, panels[a].Height) then
2767 begin
2770 exit;
2775 begin
2785 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
2786 const
2789 begin
2790 {
2791 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
2792 begin
2793 result := pan.Enabled;
2794 exit;
2795 end;
2796 }
2799 begin
2800 result :=
2806 exit;
2810 begin
2811 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2812 exit;
2815 // other shit
2816 //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2820 var
2822 begin
2823 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
2828 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
2835 begin
2837 begin
2839 begin
2840 // slow
2842 end
2843 else
2844 begin
2845 // fast
2848 end
2849 else
2850 begin
2852 begin
2853 // slow
2855 end
2856 else
2857 begin
2858 // fast
2862 end
2863 else
2864 begin
2872 var
2873 cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
2876 // slightly different from the old code, but meh...
2878 begin
2880 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
2881 // check priorities
2885 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
2887 // collision?
2888 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
2889 // yeah
2891 // water? water has the highest priority, so stop right here
2893 // acid2?
2895 // acid1?
2899 begin
2902 begin
2905 begin
2907 end
2908 else
2909 begin
2910 mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
2913 end
2914 else
2915 begin
2922 procedure g_Map_EnableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_EnableWallGUID(gWalls[ID].guid); end;
2923 procedure g_Map_DisableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_DisableWallGUID(gWalls[ID].guid); end;
2924 procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); begin if (ID < Length(gLifts)) then g_Map_SetLiftGUID(gLifts[ID].guid, t); end;
2928 var
2930 begin
2931 //pan := gWalls[ID];
2940 //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
2941 //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor);
2943 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState({gWalls[ID]}pan.PanelType, pguid);
2944 // mark platform as interesting
2947 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2948 //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);
2949 {$ENDIF}
2954 var
2956 begin
2957 //pan := gWalls[ID];
2966 //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
2968 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, pguid);
2969 // mark platform as interesting
2972 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
2973 //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);
2974 {$ENDIF}
2979 var
2981 begin
2984 {
2985 case PanelType of
2986 PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: tp := gWalls[ID];
2987 PANEL_FORE: tp := gRenderForegrounds[ID];
2988 PANEL_BACK: tp := gRenderBackgrounds[ID];
2989 PANEL_WATER: tp := gWater[ID];
2990 PANEL_ACID1: tp := gAcid1[ID];
2991 PANEL_ACID2: tp := gAcid2[ID];
2992 PANEL_STEP: tp := gSteps[ID];
2993 else exit;
2994 end;
2995 }
3003 var
3005 begin
3006 //pan := gLifts[ID];
3014 begin
3018 //TODO: make separate lift tags, and change tag here
3027 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, pguid);
3028 // mark platform as interesting
3035 var
3038 begin
3043 Exit;
3047 begin
3053 Exit;
3060 var
3062 begin
3066 Exit;
3074 begin
3079 begin
3081 begin
3089 begin
3100 var
3103 begin
3105 Exit;
3110 begin
3112 continue;
3115 begin
3118 end
3119 else
3120 begin
3128 begin
3140 var
3147 var
3150 begin
3151 // Ñîçäàåì íîâûé ñïèñîê ñîõðàíÿåìûõ ïàíåëåé
3155 begin
3157 begin
3158 // ID ïàíåëè
3159 //PAMem.WriteInt(i);
3160 // Ñîõðàíÿåì ïàíåëü
3165 // Ñîõðàíÿåì ýòîò ñïèñîê ïàíåëåé
3171 begin
3172 // Ñèãíàòóðà ôëàãà
3175 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3177 // Ñîñòîÿíèå ôëàãà
3179 // Íàïðàâëåíèå ôëàãà
3182 // Îáúåêò ôëàãà
3186 begin
3189 ///// Ñîõðàíÿåì ñïèñêè ïàíåëåé: /////
3191 ///// /////
3193 ///// Ñîõðàíÿåì ìóçûêó: /////
3194 // Ñèãíàòóðà ìóçûêè:
3197 // Íàçâàíèå ìóçûêè:
3201 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3204 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3207 ///// /////
3209 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
3211 ///// /////
3213 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
3215 begin
3216 // Ôëàã Êðàñíîé êîìàíäû
3218 // Ôëàã Ñèíåé êîìàíäû
3221 ///// /////
3223 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3225 begin
3226 // Î÷êè Êðàñíîé êîìàíäû
3228 // Î÷êè Ñèíåé êîìàíäû
3231 ///// /////
3236 var
3243 var
3246 begin
3247 // Çàãðóæàåì òåêóùèé ñïèñîê ïàíåëåé
3252 begin
3254 begin
3255 // ID ïàíåëè:
3256 //PAMem.ReadInt(id);
3257 {
3258 if id <> i then raise EBinSizeError.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel ID');
3259 }
3260 // Çàãðóæàåì ïàíåëü
3262 //if (panels[i].arrIdx <> i) then raise Exception.Create('g_Map_LoadState: LoadPanelArray: Wrong Panel arrIdx');
3267 // Ýòîò ñïèñîê ïàíåëåé çàãðóæåí
3272 begin
3273 // Ñèãíàòóðà ôëàãà
3275 // 'FLAG'
3276 if dw <> FLAG_SIGNATURE then raise EBinSizeError.Create('g_Map_LoadState: LoadFlag: Wrong Flag Signature');
3277 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3279 // Ñîñòîÿíèå ôëàãà
3281 // Íàïðàâëåíèå ôëàãà
3284 // Îáúåêò ôëàãà
3288 begin
3291 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
3293 ///// /////
3295 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó
3297 //mapCreateGrid();
3299 ///// Çàãðóæàåì ìóçûêó: /////
3300 // Ñèãíàòóðà ìóçûêè
3302 // 'MUSI'
3303 if dw <> MUSIC_SIGNATURE then raise EBinSizeError.Create('g_Map_LoadState: Wrong Music Signature');
3304 // Íàçâàíèå ìóçûêè
3307 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3309 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3311 // Çàïóñêàåì ýòó ìóçûêó
3317 ///// /////
3319 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
3321 ///// /////
3323 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
3325 begin
3326 // Ôëàã Êðàñíîé êîìàíäû
3328 // Ôëàã Ñèíåé êîìàíäû
3331 ///// /////
3333 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3335 begin
3336 // Î÷êè Êðàñíîé êîìàíäû
3338 // Î÷êè Ñèíåé êîìàíäû
3341 ///// /////
3345 // trace liquid, stepping by `dx` and `dy`
3346 // return last seen liquid coords, and `false` if we're started outside of the liquid
3347 function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean;
3348 const
3350 begin
3353 // started outside of the liquid?
3354 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then begin result := false; exit; end;
3358 begin
3361 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then exit; // out of the water, just exit