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
27 type
69 procedure g_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor); // unaccelerated
81 // HACK!!!
104 // returns panel or nil
105 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
106 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
108 // returns panel or nil
109 // sets `ex` and `ey` to `x1` and `y1` when no hit was detected
110 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
112 type
118 // trace liquid, stepping by `dx` and `dy`
119 // return last seen liquid coords, and `false` if we're started outside of the liquid
123 // return `true` from `cb` to stop
141 const
150 const
173 const
176 (* draw order:
177 PANEL_BACK
178 PANEL_STEP
179 PANEL_WALL
180 PANEL_CLOSEDOOR
181 PANEL_ACID1
182 PANEL_ACID2
183 PANEL_WATER
184 PANEL_FORE
185 *)
186 // sorted by draw priority
195 // the following are invisible
202 GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
205 type
207 public
213 var
222 //gDOMFlags: array of TFlag;
235 gDrawPanelList: TBinHeapPanelDraw = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
245 type
248 var
252 implementation
254 uses
263 const
269 // ////////////////////////////////////////////////////////////////////////// //
271 begin
273 begin
275 end
276 else
277 begin
283 // ////////////////////////////////////////////////////////////////////////// //
284 var
288 // ////////////////////////////////////////////////////////////////////////// //
290 begin
291 //if (panByGUID = nil) or (not panByGUID.get(aguid, result)) then result := nil;
292 if (aguid >= 0) and (aguid < Length(panByGUID)) then result := panByGUID[aguid] else result := nil;
296 // return `true` from `cb` to stop
298 var
300 begin
304 begin
311 var
313 begin
315 begin
317 begin
324 // ////////////////////////////////////////////////////////////////////////// //
325 function g_Map_MinX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0 else result := 0; end;
326 function g_Map_MinY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0 else result := 0; end;
327 function g_Map_MaxX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0+mapGrid.gridWidth-1 else result := 0; end;
328 function g_Map_MaxY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0+mapGrid.gridHeight-1 else result := 0; end;
331 // ////////////////////////////////////////////////////////////////////////// //
332 var
337 var
341 begin
344 try
348 except
353 begin
356 begin
357 //raise Exception.Create('cannot load "game.wad"');
359 end
360 else
361 begin
366 try
368 begin
369 //raise Exception.Create('cannot open "mapdef.txt"');
372 end
373 else
374 begin
378 begin
384 try
386 except
388 raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [e.tokLine, e.tokCol, e.message]);
390 raise Exception.CreateFmt('ERROR in "mapdef.txt" at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message]);
398 // ////////////////////////////////////////////////////////////////////////// //
400 var
402 begin
411 try
413 except
415 begin
419 exit;
422 begin
426 exit;
430 //e_LogWriteln('map parsed.');
434 // ////////////////////////////////////////////////////////////////////////// //
435 var
442 var
445 begin
453 begin
456 Exit;
457 end
458 else
459 begin
462 Break;
466 // Íå ïåðåâåñòè â ÷èñëî:
468 Exit;
477 begin
479 begin
482 Exit;
488 Result := NNF_NAME_BEFORE
489 else
491 Result := NNF_NAME_AFTER
492 else
499 // ////////////////////////////////////////////////////////////////////////// //
501 begin
511 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: result := GridTagLift; // gLifts -- this is for all lifts
519 begin
526 begin
527 if (gDrawPanelList = nil) then gDrawPanelList := TBinHeapPanelDraw.Create() else gDrawPanelList.clear();
531 var
537 //DOMFlagPoints: Array of TFlagPoint;
541 begin
542 if (profMapCollision = nil) then profMapCollision := TProfiler.Create('COLSOLID', g_profile_history_size);
544 // create sections
546 begin
555 begin
560 // wall index in `gWalls` or -1
561 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
562 var
564 begin
567 begin
570 end
571 else
572 begin
578 // returns panel or nil
579 function g_Map_traceToNearest (x0, y0, x1, y1: Integer; tag: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
580 var
582 begin
585 begin
588 end
589 else
590 begin
598 begin
600 begin
601 // stop if the lift of the right type
602 result :=
607 exit;
609 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
615 begin
616 {
617 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
618 begin
619 result := pan.Enabled; // stop if wall is enabled
620 exit;
621 end;
622 }
625 begin
626 // stop if the lift of the right type
627 result :=
632 exit;
635 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
638 var
643 begin
646 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
651 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
658 begin
659 // slow
663 begin
668 end
669 else
670 begin
671 // fast
679 var
682 begin
685 //result := mapGrid.forEachAtPoint(x, y, nil, tagmask);
694 begin
701 var
710 begin
712 Exit;
720 begin
730 begin
736 // Íåò äâåðåé:
738 begin
740 Exit;
749 begin
758 begin
764 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
765 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
772 begin
778 Break;
789 var
797 begin
799 Exit;
805 begin
820 begin
828 begin
841 begin
851 Break;
866 function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer): Integer;
867 var
872 begin
904 //result := len;
910 begin
919 begin
932 var
937 begin
941 begin
942 // i found her!
943 //e_LogWritefln('texture ''%s'' already loaded (%s)', [RecName, result]);
944 exit;
949 if (BadTextNameHash <> nil) and BadTextNameHash.has(RecName) then exit; // don't do it again and again
951 {
952 if Textures <> nil then
953 begin
954 for a := 0 to High(Textures) do
955 begin
956 if (Textures[a].TextureName = RecName) then
957 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
958 e_LogWritefln('texture ''%s'' already loaded', [RecName]);
959 Result := a;
960 Exit;
961 end;
962 end;
963 end;
964 }
966 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
970 begin
974 begin
985 Exit;
988 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
997 //txname := RecName;
998 {
999 if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
1000 begin
1001 FreeMem(TextureData);
1002 RecName := 'COMMON\ALIEN';
1003 end;
1004 }
1007 begin
1010 begin
1014 Exit;
1016 e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height);
1023 end
1025 begin
1026 //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING);
1029 begin
1031 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1041 var
1052 //imgfmt: string;
1055 begin
1059 begin
1060 // i found her!
1061 //e_LogWritefln('animated texture ''%s'' already loaded (%s)', [RecName, result]);
1062 exit;
1067 //e_LogWritefln('*** Loading animated texture "%s"', [RecName]);
1071 begin
1072 //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY);
1073 exit;
1076 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
1080 try
1086 begin
1089 begin
1091 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1094 exit;
1097 {TEST
1098 if WADName = Map then
1099 begin
1100 //FreeMem(TextureWAD);
1101 if not WAD.GetResource('COMMON/animation', TextureWAD, ResLength) then Halt(1);
1102 end;
1103 }
1108 begin
1111 exit;
1114 // ýòî ïòèöà? ýòî ñàìîë¸ò?
1117 begin
1118 // íåò, ýòî ñóïåðìåí!
1120 begin
1123 exit;
1126 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
1128 begin
1131 exit;
1138 begin
1139 e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), TMsgType.Warning);
1141 exit;
1153 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
1155 begin
1156 e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), TMsgType.Warning);
1158 exit;
1166 begin
1167 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
1168 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength, _width, _height, _framecount, _backanimation) then
1169 begin
1178 end
1179 else
1180 begin
1183 begin
1189 end
1190 else
1191 begin
1192 // try animated image
1193 {
1194 imgfmt := DetermineMemoryFormat(TextureWAD, ResLength);
1195 if length(imgfmt) = 0 then
1196 begin
1197 e_WriteLog(Format('Animated texture file "%s" has unknown format', [RecName]), MSG_WARNING);
1198 exit;
1199 end;
1200 }
1204 begin
1205 e_WriteLog(Format('Animated texture file "%s" cannot be loaded', [RecName]), TMsgType.Warning);
1207 exit;
1210 begin
1213 exit;
1227 begin
1228 //writeln(' frame delay: ', GlobalMetadata.MetaItems[SMetaFrameDelay]);
1229 try
1233 // rounding ;-)
1239 except
1243 begin
1244 //writeln(' frame loop : ', GlobalMetadata.MetaItems[SMetaAnimationLoops]);
1245 try
1249 except
1252 //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
1253 //for f := 0 to high(ia) do writeln(' frame #', f, ': ', ia[f].width, 'x', ia[f].height);
1255 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]), TMsgType.Notify);
1258 // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
1260 begin
1269 //writeln(' CREATED!');
1270 end
1271 else
1272 begin
1275 begin
1276 e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), TMsgType.Warning);
1281 finally
1292 begin
1297 Exit;
1304 var
1307 begin
1311 begin
1314 begin
1330 begin
1338 begin
1345 begin
1358 AREA_DOMFLAG:
1359 begin
1360 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
1361 with DOMFlagPoints[High(DOMFlagPoints)] do
1362 begin
1363 X := Area.X;
1364 Y := Area.Y;
1365 Direction := TDirection(Area.Direction);
1366 end;
1368 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
1373 function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer): Integer;
1374 var
1376 begin
1381 begin
1400 var
1403 begin
1408 begin
1409 mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
1412 begin
1414 begin
1416 begin
1417 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1430 var
1432 //tw: TStrTextWriter;
1433 begin
1437 begin
1439 begin
1440 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1441 {
1442 tw := TStrTextWriter.Create();
1443 try
1444 gTriggers[a].trigData.writeTo(tw);
1445 e_LogWritefln('=== trigger #%s ==='#10'%s'#10'---', [a, tw.str]);
1446 finally
1447 tw.Free();
1448 end;
1449 }
1455 begin
1462 var
1464 begin
1468 else
1473 begin
1480 //var
1481 //textures: TTexturesRec1Array;
1482 //textures: TDynField;
1483 //trec: TDynRecord;
1484 //mapHeader: TMapHeaderRec_1;
1485 //i: integer;
1486 //resFile: String = '';
1487 begin
1493 (*
1494 {
1495 textures := GetTextures(map);
1496 for i := 0 to High(textures) do
1497 begin
1498 addResToExternalResList(resFile);
1499 end;
1500 }
1502 textures := map['texture'];
1503 if (textures <> nil) then
1504 begin
1505 for trec in textures do
1506 begin
1507 addResToExternalResList(resFile);
1508 end;
1509 end;
1511 textures := nil;
1512 *)
1514 //mapHeader := GetMapHeader(map);
1522 var
1529 var
1532 begin
1534 begin
1546 var
1550 begin
1551 //tag := panelTypeToTag(tag);
1553 begin
1557 begin
1558 {$IF DEFINED(D2F_DEBUG)}
1559 e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), TMsgType.Notify);
1560 {$ENDIF}
1561 continue;
1579 // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
1581 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
1582 {
1583 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
1584 begin
1585 e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
1586 end;
1587 }
1588 {$ENDIF}
1592 begin
1606 e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]);
1615 //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height);
1634 const
1637 type
1640 //TexturePanel: Integer;
1644 // texture pane;
1647 // "action" panel
1651 var
1653 //mapReader: TDynRecord = nil;
1674 //moveActive: Boolean;
1678 begin
1684 //gCurrentMap.Free();
1685 //gCurrentMap := nil;
1692 //mapReader := nil;
1695 try
1696 // Çàãðóçêà WAD (åñëè ó íàñ íåò óæå çàãðóæåíîé êàðòû)
1698 begin
1705 begin
1708 Exit;
1712 begin
1716 begin
1724 begin
1727 begin
1730 end else
1737 begin
1738 //k8: why loader ignores path here?
1741 begin
1744 Exit;
1751 begin
1754 exit;
1757 // Çàãðóçêà êàðòû:
1763 try
1765 except
1770 Exit;
1776 begin
1779 exit;
1781 end
1782 else
1783 begin
1787 //gCurrentMap := mapReader;
1791 // get all other lists here too
1798 // Çàãðóçêà îïèñàíèÿ êàðòû:
1803 begin
1813 // Çàãðóçêà òåêñòóð:
1815 // Äîáàâëåíèå òåêñòóð â Textures[]:
1817 begin
1821 // find used textures
1823 try
1825 begin
1827 begin
1835 begin
1838 begin
1841 end
1842 else
1843 begin
1844 {$IF DEFINED(D2F_DEBUG_TXLOAD)}
1846 {$ENDIF}
1847 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
1849 begin
1850 // Àíèìèðîâàííàÿ òåêñòóðà
1853 end
1854 else
1855 begin
1856 // Îáû÷íàÿ òåêñòóðà
1866 finally
1870 // set panel tagInt to texture index
1872 begin
1874 begin
1882 // Çàãðóçêà òðèããåðîâ
1887 // Çàãðóçêà ïàíåëåé
1891 // check texture numbers for panels
1893 begin
1895 begin
1897 begin
1903 exit;
1908 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
1910 begin
1912 //SetLength(TriggersTable, triggers.count);
1918 begin
1922 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
1925 // action panel
1927 if (rec.trigRec <> nil) then pttit.actPanel := rec.trigRec.tgPanelRec else pttit.actPanel := nil;
1928 // set flag
1931 // update progress
1936 // Ñîçäàåì ïàíåëè
1938 begin
1944 begin
1946 //e_LogWritefln('PANSTART: pannum=%s', [pannum]);
1953 begin
1959 begin
1960 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
1961 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
1964 begin
1966 begin
1967 // e_LogWritefln('trigref for panel %s', [pannum]);
1974 begin
1975 // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
1978 // Ñïåö-òåêñòóðû çàïðåùåíû
1980 begin
1982 end
1983 else
1984 begin
1985 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè
1989 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
1990 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #
1992 begin
1994 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû
1996 begin
2000 begin
2001 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó
2003 begin
2004 // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
2006 //e_LogWritefln('000: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2008 //e_LogWritefln('001: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2010 begin
2011 // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
2013 //e_LogWritefln('002: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2015 //e_LogWritefln('003: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2017 end
2018 else
2019 begin
2020 // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
2022 //e_LogWritefln('004: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2024 //e_LogWritefln('005: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2026 begin
2027 // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
2029 //e_LogWritefln('006: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2031 //e_LogWritefln('007: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2035 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè
2037 begin
2038 {
2039 for c := 0 to High(Textures) do
2040 begin
2041 if (Textures[c].TextureName = TexName) then
2042 begin
2043 SetLength(AddTextures, Length(AddTextures)+1);
2044 AddTextures[High(AddTextures)].Texture := c;
2045 AddTextures[High(AddTextures)].Anim := isAnim;
2046 break;
2047 end;
2048 end;
2049 }
2051 begin
2057 end
2058 else
2059 begin
2061 begin
2062 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
2064 AddTextures[High(AddTextures)].Texture := rec.tagInt; // internal texture number, not map index
2068 end
2070 begin
2081 begin
2082 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
2090 //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);
2092 //e_LogWritefln('PANADD: pannum=%s', [pannum]);
2094 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID
2095 //e_LogWritefln('new panel; tcount=%s; curtex=%s', [Length(AddTextures), CurTex]);
2097 //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]);
2100 // setup lifts
2102 //moveStart := rec.moveStart;
2103 //moveEnd := rec.moveEnd;
2104 //moveActive := rec['move_active'].value;
2106 begin
2109 //e_LogWritefln('found moving panel ''%s'' (idx=%s; id=%s)', [rec.id, pannum, PanelID]);
2112 //e_LogWritefln('PANEND: pannum=%s', [pannum]);
2118 // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ
2120 begin
2121 if (TriggersTable[b].texPanel <> nil) then TriggersTable[b].texPanelIdx := TriggersTable[b].texPanel.userPanelId;
2122 if (TriggersTable[b].actPanel <> nil) then TriggersTable[b].actPanelIdx := TriggersTable[b].actPanel.userPanelId;
2125 // create map grid, init other grids (for monsters, for example)
2129 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
2131 begin
2134 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü
2137 begin
2140 //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
2142 TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanelIdx, tgpid);
2146 //FIXME: use hashtable!
2148 begin
2150 begin
2154 begin
2159 // Çàãðóçêà ïðåäìåòîâ
2163 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
2165 begin
2171 // Çàãðóçêà îáëàñòåé
2175 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
2177 begin
2183 // Çàãðóçêà ìîíñòðîâ
2189 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
2191 begin
2197 //gCurrentMap := mapReader; // this will be our current map now
2199 //mapReader := nil;
2201 // Çàãðóçêà íåáà
2203 begin
2208 if (FileName <> '') then FileName := GameDir+'/wads/'+FileName else FileName := g_ExtractWadName(Res);
2211 try
2214 begin
2216 end
2217 else
2218 begin
2221 finally
2226 // Çàãðóçêà ìóçûêè
2229 begin
2236 else
2237 begin
2244 else
2248 // Îñòàëüíûå óñòàíâêè
2256 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
2259 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
2268 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
2270 begin
2273 end
2274 else
2275 begin
2280 e_LogWritefln('map loaded in %s.%s milliseconds', [Integer(stt div 1000), Integer(stt mod 1000)]);
2282 finally
2284 //mapReader.Free();
2287 begin
2300 var
2303 //Header: TMapHeaderRec_1;
2307 begin
2313 begin
2315 Exit;
2318 //k8: it ignores path again
2320 begin
2322 Exit;
2327 try
2329 except
2332 exit;
2340 begin
2347 end
2348 else
2349 begin
2351 //ZeroMemory(@Header, SizeOf(Header));
2364 var
2368 begin
2372 begin
2374 Exit;
2378 begin
2380 begin
2389 var
2394 begin
2401 begin
2403 Exit;
2412 begin
2414 Exit;
2419 var
2423 var
2426 begin
2428 begin
2435 begin
2444 begin
2449 begin
2453 //DOMFlagPoints := nil;
2455 //gDOMFlags := nil;
2458 begin
2460 end
2461 else
2462 begin
2467 begin
2470 begin
2472 begin
2474 begin
2476 begin
2478 end
2479 else
2480 begin
2482 begin
2513 begin
2535 var
2541 var
2544 begin
2548 begin
2559 if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end;
2562 begin
2564 begin
2566 begin
2568 begin
2575 // Ñîïðîòèâëåíèå âîçäóõà
2578 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó
2580 begin
2585 else
2591 Continue;
2596 // Èãðîê áåðåò ôëàã
2598 begin
2601 begin
2605 begin
2607 begin
2620 // old algo
2621 procedure g_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor);
2624 var
2626 begin
2628 begin
2629 // alas, no visible set
2631 begin
2637 begin
2651 // new algo
2653 (*
2654 function checker (pan: TPanel; tag: Integer): Boolean;
2655 begin
2656 result := false; // don't stop, ever
2657 if ((tag and GridTagDoor) <> 0) <> pan.Door then exit;
2658 gDrawPanelList.insert(pan);
2659 end;
2660 *)
2661 var
2665 begin
2667 //tagmask := panelTypeToTag(PanelType);
2668 //mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask);
2674 begin
2676 begin
2677 end
2678 else
2679 begin
2686 // list will be rendered in `g_game.DrawPlayer()`
2691 (*
2692 function checker (pan: TPanel; tag: Integer): Boolean;
2693 begin
2694 result := false; // don't stop, ever
2695 pan.DrawShadowVolume(lightX, lightY, radius);
2696 end;
2697 *)
2698 var
2702 begin
2703 //mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
2705 hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
2709 begin
2719 begin
2722 else
2728 var
2730 begin
2735 begin
2743 begin
2745 Exit;
2751 begin
2758 begin
2760 Exit;
2766 begin
2773 begin
2775 Exit;
2781 begin
2788 begin
2790 Exit;
2796 begin
2803 begin
2805 Exit;
2809 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
2811 begin
2822 begin
2824 Exit;
2830 begin
2839 begin
2841 Exit;
2847 var
2851 var
2853 begin
2857 begin
2858 if g_Collide(X, Y, Width, Height, panels[a].X, panels[a].Y, panels[a].Width, panels[a].Height) then
2859 begin
2862 exit;
2867 begin
2877 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
2878 const
2882 begin
2883 {
2884 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
2885 begin
2886 result := pan.Enabled;
2887 exit;
2888 end;
2889 }
2892 begin
2893 result :=
2899 exit;
2903 begin
2904 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2905 exit;
2908 // other shit
2909 //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2913 var
2919 begin
2921 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
2926 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
2933 begin
2934 {if (Width = 1) and (Height = 1) then
2935 begin
2936 if ((tagmask and SlowMask) <> 0) then
2937 begin
2938 // slow
2939 result := (mapGrid.forEachAtPoint(X, Y, checker, tagmask) <> nil);
2940 end
2941 else
2942 begin
2943 // fast
2944 result := (mapGrid.forEachAtPoint(X, Y, nil, tagmask) <> nil);
2945 end;
2946 end
2947 else}
2948 begin
2951 begin
2952 // slow
2953 //result := (mapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask) <> nil);
2955 //if (hitcount = 0) then exit;
2958 begin
2961 begin
2962 result :=
2968 end
2970 begin
2971 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2972 end
2973 else
2974 begin
2975 // other shit
2982 end
2983 else
2984 begin
2985 // fast
2986 //result := (mapGrid.forEachInAABB(X, Y, Width, Height, nil, tagmask) <> nil);
2987 hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
2992 end
2993 else
2994 begin
3001 // returns `true` if we need to stop
3003 begin
3005 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
3006 // check priorities
3010 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
3012 // collision?
3013 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
3014 // yeah
3016 // water? water has the highest priority, so stop right here
3018 // acid2?
3020 // acid1?
3025 var
3026 cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
3027 //texid: DWORD;
3029 (*
3030 // slightly different from the old code, but meh...
3031 function checker (pan: TPanel; tag: Integer): Boolean;
3032 begin
3033 result := false; // don't stop, ever
3034 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
3035 // check priorities
3036 case cctype of
3037 0: if ((tag and GridTagWater) = 0) then exit; // allowed: water
3038 1: if ((tag and (GridTagWater or GridTagAcid1)) = 0) then exit; // allowed: water, acid1
3039 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
3040 end;
3041 // collision?
3042 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
3043 // yeah
3044 texid := pan.GetTextureID();
3045 // water? water has the highest priority, so stop right here
3046 if ((tag and GridTagWater) <> 0) then begin cctype := 0; result := true; exit; end;
3047 // acid2?
3048 if ((tag and GridTagAcid2) <> 0) then cctype := 2;
3049 // acid1?
3050 if ((tag and GridTagAcid1) <> 0) then cctype := 1;
3051 end;
3052 *)
3053 var
3058 begin
3061 begin
3063 {
3064 if (Width = 1) and (Height = 1) then
3065 begin
3066 mapGrid.forEachAtPoint(X, Y, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3067 end
3068 else
3069 begin
3070 mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3071 end;
3072 }
3074 hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3078 begin
3085 //result := texid;
3086 end
3087 else
3088 begin
3095 procedure g_Map_EnableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_EnableWallGUID(gWalls[ID].guid); end;
3096 procedure g_Map_DisableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_DisableWallGUID(gWalls[ID].guid); end;
3097 procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); begin if (ID < Length(gLifts)) then g_Map_SetLiftGUID(gLifts[ID].guid, t); end;
3101 var
3103 begin
3104 //pan := gWalls[ID];
3113 //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
3114 //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor);
3116 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3117 // mark platform as interesting
3120 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
3121 //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);
3122 {$ENDIF}
3127 var
3129 begin
3130 //pan := gWalls[ID];
3139 //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
3141 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3142 // mark platform as interesting
3145 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
3146 //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);
3147 {$ENDIF}
3152 var
3154 begin
3163 var
3165 begin
3166 //pan := gLifts[ID];
3174 begin
3178 //TODO: make separate lift tags, and change tag here
3187 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3188 // mark platform as interesting
3195 var
3198 begin
3203 Exit;
3207 begin
3213 Exit;
3220 var
3222 begin
3226 Exit;
3234 begin
3239 begin
3241 begin
3249 begin
3260 var
3263 begin
3265 Exit;
3270 begin
3272 continue;
3275 begin
3278 end
3279 else
3280 begin
3288 begin
3300 var
3304 var
3306 begin
3307 // Ñîõðàíÿåì ïàíåëè
3313 var
3315 begin
3318 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3320 // Ñîñòîÿíèå ôëàãà
3322 // Íàïðàâëåíèå ôëàãà
3325 // Îáúåêò ôëàãà
3329 begin
3332 // Ñîõðàíÿåì ìóçûêó
3335 // Íàçâàíèå ìóçûêè
3339 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3341 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3344 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
3346 ///// /////
3348 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
3350 begin
3351 // Ôëàã Êðàñíîé êîìàíäû
3353 // Ôëàã Ñèíåé êîìàíäû
3356 ///// /////
3358 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3360 begin
3361 // Î÷êè Êðàñíîé êîìàíäû
3363 // Î÷êè Ñèíåé êîìàíäû
3366 ///// /////
3371 var
3377 var
3379 begin
3380 // Çàãðóæàåì ïàíåëè
3381 if (Length(panByGUID) <> utils.readLongInt(st)) then raise XStreamError.Create('invalid number of saved panels');
3383 begin
3390 var
3392 begin
3393 // Ñèãíàòóðà ôëàãà
3396 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3398 // Ñîñòîÿíèå ôëàãà
3400 // Íàïðàâëåíèå ôëàãà
3402 if (b = 1) then flag^.Direction := TDirection.D_LEFT else flag^.Direction := TDirection.D_RIGHT; // b = 2
3403 // Îáúåêò ôëàãà
3407 begin
3410 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
3412 ///// /////
3414 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó
3416 //mapCreateGrid();
3418 ///// Çàãðóæàåì ìóçûêó: /////
3421 // Íàçâàíèå ìóçûêè
3424 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3426 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3428 // Çàïóñêàåì ýòó ìóçûêó
3434 ///// /////
3436 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
3438 ///// /////
3440 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
3442 begin
3443 // Ôëàã Êðàñíîé êîìàíäû
3445 // Ôëàã Ñèíåé êîìàíäû
3448 ///// /////
3450 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3452 begin
3453 // Î÷êè Êðàñíîé êîìàíäû
3455 // Î÷êè Ñèíåé êîìàíäû
3458 ///// /////
3462 // trace liquid, stepping by `dx` and `dy`
3463 // return last seen liquid coords, and `false` if we're started outside of the liquid
3464 function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean;
3465 const
3467 begin
3470 // started outside of the liquid?
3471 //if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then begin result := false; exit; end;
3476 begin
3479 //if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then exit; // out of the water, just exit
3487 begin