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
600 begin
601 {
602 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
603 begin
604 result := pan.Enabled; // stop if wall is enabled
605 exit;
606 end;
607 }
610 begin
611 // stop if the lift of the right type
612 result :=
617 exit;
620 result := true; // otherwise, stop anyway, 'cause `forEachAtPoint()` is guaranteed to call this only for correct panels
623 var
625 begin
628 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
633 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
638 begin
639 // slow
641 end
642 else
643 begin
644 // fast
651 begin
659 begin
666 var
675 begin
677 Exit;
685 begin
695 begin
701 // Íåò äâåðåé:
703 begin
705 Exit;
714 begin
723 begin
729 if {((gRenderWalls[PanelArray[b].RenderPanelID].TextureID = gRenderWalls[gDoorMap[m, c]].TextureID) or
730 gRenderWalls[PanelArray[b].RenderPanelID].Hide or gRenderWalls[gDoorMap[m, c]].Hide) and}
737 begin
743 Break;
754 var
762 begin
764 Exit;
770 begin
785 begin
793 begin
806 begin
816 Break;
831 function CreatePanel (PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer): Integer;
832 var
837 begin
869 //result := len;
875 begin
884 begin
897 var
902 begin
906 begin
907 // i found her!
908 //e_LogWritefln('texture ''%s'' already loaded (%s)', [RecName, result]);
909 exit;
914 if (BadTextNameHash <> nil) and BadTextNameHash.has(RecName) then exit; // don't do it again and again
916 {
917 if Textures <> nil then
918 begin
919 for a := 0 to High(Textures) do
920 begin
921 if (Textures[a].TextureName = RecName) then
922 begin // Òåêñòóðà ñ òàêèì èìåíåì óæå åñòü
923 e_LogWritefln('texture ''%s'' already loaded', [RecName]);
924 Result := a;
925 Exit;
926 end;
927 end;
928 end;
929 }
931 // Òåêñòóðû ñî ñïåöèàëüíûìè èìåíàìè (âîäà, ëàâà, êèñëîòà):
935 begin
939 begin
950 Exit;
953 // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
962 //txname := RecName;
963 {
964 if (WADName = Map) and WAD.GetResource(g_ExtractFilePathName(RecName), TextureData, ResLength) then
965 begin
966 FreeMem(TextureData);
967 RecName := 'COMMON\ALIEN';
968 end;
969 }
972 begin
975 begin
979 Exit;
981 e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height);
988 end
990 begin
991 //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING);
994 begin
996 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1006 var
1017 //imgfmt: string;
1020 begin
1024 begin
1025 // i found her!
1026 //e_LogWritefln('animated texture ''%s'' already loaded (%s)', [RecName, result]);
1027 exit;
1032 //e_LogWritefln('*** Loading animated texture "%s"', [RecName]);
1036 begin
1037 //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY);
1038 exit;
1041 // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
1045 try
1051 begin
1054 begin
1056 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
1059 exit;
1062 {TEST
1063 if WADName = Map then
1064 begin
1065 //FreeMem(TextureWAD);
1066 if not WAD.GetResource('COMMON/animation', TextureWAD, ResLength) then Halt(1);
1067 end;
1068 }
1073 begin
1076 exit;
1079 // ýòî ïòèöà? ýòî ñàìîë¸ò?
1082 begin
1083 // íåò, ýòî ñóïåðìåí!
1085 begin
1088 exit;
1091 // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
1093 begin
1096 exit;
1103 begin
1104 e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), TMsgType.Warning);
1106 exit;
1118 // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
1120 begin
1121 e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), TMsgType.Warning);
1123 exit;
1131 begin
1132 // Ñîçäàåì êàäðû àíèì. òåêñòóðû èç ïàìÿòè:
1133 if g_Frames_CreateMemory(@FramesID, '', TextureData, ResLength, _width, _height, _framecount, _backanimation) then
1134 begin
1143 end
1144 else
1145 begin
1148 begin
1154 end
1155 else
1156 begin
1157 // try animated image
1158 {
1159 imgfmt := DetermineMemoryFormat(TextureWAD, ResLength);
1160 if length(imgfmt) = 0 then
1161 begin
1162 e_WriteLog(Format('Animated texture file "%s" has unknown format', [RecName]), MSG_WARNING);
1163 exit;
1164 end;
1165 }
1169 begin
1170 e_WriteLog(Format('Animated texture file "%s" cannot be loaded', [RecName]), TMsgType.Warning);
1172 exit;
1175 begin
1178 exit;
1192 begin
1193 //writeln(' frame delay: ', GlobalMetadata.MetaItems[SMetaFrameDelay]);
1194 try
1198 // rounding ;-)
1204 except
1208 begin
1209 //writeln(' frame loop : ', GlobalMetadata.MetaItems[SMetaAnimationLoops]);
1210 try
1214 except
1217 //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
1218 //for f := 0 to high(ia) do writeln(' frame #', f, ': ', ia[f].width, 'x', ia[f].height);
1220 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);
1223 // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
1225 begin
1234 //writeln(' CREATED!');
1235 end
1236 else
1237 begin
1240 begin
1241 e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), TMsgType.Warning);
1246 finally
1257 begin
1262 Exit;
1269 var
1272 begin
1276 begin
1279 begin
1295 begin
1303 begin
1310 begin
1323 AREA_DOMFLAG:
1324 begin
1325 {SetLength(DOMFlagPoints, Length(DOMFlagPoints)+1);
1326 with DOMFlagPoints[High(DOMFlagPoints)] do
1327 begin
1328 X := Area.X;
1329 Y := Area.Y;
1330 Direction := TDirection(Area.Direction);
1331 end;
1333 g_Map_CreateFlag(DOMFlagPoints[High(DOMFlagPoints)], FLAG_DOM, FLAG_STATE_NORMAL);}
1338 function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer): Integer;
1339 var
1341 begin
1346 begin
1365 var
1368 begin
1373 begin
1374 mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
1377 begin
1379 begin
1381 begin
1382 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1395 var
1397 //tw: TStrTextWriter;
1398 begin
1402 begin
1404 begin
1405 //if (gTriggers[a].Data.MonsterID-1) = Integer(mon.StartID) then mon.AddTrigger(a);
1406 {
1407 tw := TStrTextWriter.Create();
1408 try
1409 gTriggers[a].trigData.writeTo(tw);
1410 e_LogWritefln('=== trigger #%s ==='#10'%s'#10'---', [a, tw.str]);
1411 finally
1412 tw.Free();
1413 end;
1414 }
1420 begin
1427 var
1429 begin
1433 else
1438 begin
1445 //var
1446 //textures: TTexturesRec1Array;
1447 //textures: TDynField;
1448 //trec: TDynRecord;
1449 //mapHeader: TMapHeaderRec_1;
1450 //i: integer;
1451 //resFile: String = '';
1452 begin
1458 (*
1459 {
1460 textures := GetTextures(map);
1461 for i := 0 to High(textures) do
1462 begin
1463 addResToExternalResList(resFile);
1464 end;
1465 }
1467 textures := map['texture'];
1468 if (textures <> nil) then
1469 begin
1470 for trec in textures do
1471 begin
1472 addResToExternalResList(resFile);
1473 end;
1474 end;
1476 textures := nil;
1477 *)
1479 //mapHeader := GetMapHeader(map);
1487 var
1494 var
1497 begin
1499 begin
1511 var
1515 begin
1516 //tag := panelTypeToTag(tag);
1518 begin
1522 begin
1523 {$IF DEFINED(D2F_DEBUG)}
1524 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);
1525 {$ENDIF}
1526 continue;
1544 // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
1546 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
1547 {
1548 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
1549 begin
1550 e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
1551 end;
1552 }
1553 {$ENDIF}
1557 begin
1571 e_LogWritefln('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]);
1580 //mapGrid := TPanelGrid.Create(0, 0, gMapInfo.Width, gMapInfo.Height);
1599 const
1602 type
1605 //TexturePanel: Integer;
1609 // texture pane;
1612 // "action" panel
1616 var
1618 //mapReader: TDynRecord = nil;
1639 //moveActive: Boolean;
1643 begin
1649 //gCurrentMap.Free();
1650 //gCurrentMap := nil;
1657 //mapReader := nil;
1660 try
1661 // Çàãðóçêà WAD (åñëè ó íàñ íåò óæå çàãðóæåíîé êàðòû)
1663 begin
1670 begin
1673 Exit;
1677 begin
1681 begin
1689 begin
1692 begin
1695 end else
1702 begin
1703 //k8: why loader ignores path here?
1706 begin
1709 Exit;
1716 begin
1719 exit;
1722 // Çàãðóçêà êàðòû:
1728 try
1730 except
1735 Exit;
1741 begin
1744 exit;
1746 end
1747 else
1748 begin
1752 //gCurrentMap := mapReader;
1756 // get all other lists here too
1763 // Çàãðóçêà îïèñàíèÿ êàðòû:
1768 begin
1778 // Çàãðóçêà òåêñòóð:
1780 // Äîáàâëåíèå òåêñòóð â Textures[]:
1782 begin
1786 // find used textures
1788 try
1790 begin
1792 begin
1800 begin
1803 begin
1806 end
1807 else
1808 begin
1809 {$IF DEFINED(D2F_DEBUG_TXLOAD)}
1811 {$ENDIF}
1812 //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY);
1814 begin
1815 // Àíèìèðîâàííàÿ òåêñòóðà
1818 end
1819 else
1820 begin
1821 // Îáû÷íàÿ òåêñòóðà
1831 finally
1835 // set panel tagInt to texture index
1837 begin
1839 begin
1847 // Çàãðóçêà òðèããåðîâ
1852 // Çàãðóçêà ïàíåëåé
1856 // check texture numbers for panels
1858 begin
1860 begin
1862 begin
1868 exit;
1873 // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
1875 begin
1877 //SetLength(TriggersTable, triggers.count);
1883 begin
1887 // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
1890 // action panel
1892 if (rec.trigRec <> nil) then pttit.actPanel := rec.trigRec.tgPanelRec else pttit.actPanel := nil;
1893 // set flag
1896 // update progress
1901 // Ñîçäàåì ïàíåëè
1903 begin
1909 begin
1911 //e_LogWritefln('PANSTART: pannum=%s', [pannum]);
1918 begin
1924 begin
1925 // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
1926 // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
1929 begin
1931 begin
1932 // e_LogWritefln('trigref for panel %s', [pannum]);
1939 begin
1940 // Åñòü ññûëêè òðèããåðîâ íà ýòó ïàíåëü
1943 // Ñïåö-òåêñòóðû çàïðåùåíû
1945 begin
1947 end
1948 else
1949 begin
1950 // Îïðåäåëÿåì íàëè÷èå è ïîëîæåíèå öèôð â êîíöå ñòðîêè
1954 // Åñëè ok, çíà÷èò åñòü öèôðû â êîíöå.
1955 // Çàãðóæàåì òåêñòóðû ñ îñòàëüíûìè #
1957 begin
1959 // Öèêë ïî èçìåíåíèþ èìåíè òåêñòóðû
1961 begin
1965 begin
1966 // Ïðîáóåì äîáàâèòü íîâóþ òåêñòóðó
1968 begin
1969 // Íà÷àëüíàÿ - àíèìèðîâàííàÿ, èùåì àíèìèðîâàííóþ
1971 //e_LogWritefln('000: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1973 //e_LogWritefln('001: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1975 begin
1976 // Íåò àíèìèðîâàííîé, èùåì îáû÷íóþ
1978 //e_LogWritefln('002: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1980 //e_LogWritefln('003: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1982 end
1983 else
1984 begin
1985 // Íà÷àëüíàÿ - îáû÷íàÿ, èùåì îáû÷íóþ
1987 //e_LogWritefln('004: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1989 //e_LogWritefln('005: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1991 begin
1992 // Íåò îáû÷íîé, èùåì àíèìèðîâàííóþ
1994 //e_LogWritefln('006: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
1996 //e_LogWritefln('007: pannum=%s; TexName=[%s]; FileName=[%s]', [pannum, TexName, FileName]);
2000 // Îíà ñóùåñòâóåò. Çàíîñèì åå ID â ñïèñîê ïàíåëè
2002 begin
2003 {
2004 for c := 0 to High(Textures) do
2005 begin
2006 if (Textures[c].TextureName = TexName) then
2007 begin
2008 SetLength(AddTextures, Length(AddTextures)+1);
2009 AddTextures[High(AddTextures)].Texture := c;
2010 AddTextures[High(AddTextures)].Anim := isAnim;
2011 break;
2012 end;
2013 end;
2014 }
2016 begin
2022 end
2023 else
2024 begin
2026 begin
2027 // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
2029 AddTextures[High(AddTextures)].Texture := rec.tagInt; // internal texture number, not map index
2033 end
2035 begin
2046 begin
2047 // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
2055 //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);
2057 //e_LogWritefln('PANADD: pannum=%s', [pannum]);
2059 // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID
2060 //e_LogWritefln('new panel; tcount=%s; curtex=%s', [Length(AddTextures), CurTex]);
2062 //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]);
2065 // setup lifts
2067 //moveStart := rec.moveStart;
2068 //moveEnd := rec.moveEnd;
2069 //moveActive := rec['move_active'].value;
2071 begin
2074 //e_LogWritefln('found moving panel ''%s'' (idx=%s; id=%s)', [rec.id, pannum, PanelID]);
2077 //e_LogWritefln('PANEND: pannum=%s', [pannum]);
2083 // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ
2085 begin
2086 if (TriggersTable[b].texPanel <> nil) then TriggersTable[b].texPanelIdx := TriggersTable[b].texPanel.userPanelId;
2087 if (TriggersTable[b].actPanel <> nil) then TriggersTable[b].actPanelIdx := TriggersTable[b].actPanel.userPanelId;
2090 // create map grid, init other grids (for monsters, for example)
2094 // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
2096 begin
2099 // Óêàçûâàåì òèï ïàíåëè, åñëè åñòü
2102 begin
2105 //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
2107 TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanelIdx, tgpid);
2111 //FIXME: use hashtable!
2113 begin
2115 begin
2119 begin
2124 // Çàãðóçêà ïðåäìåòîâ
2128 // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
2130 begin
2136 // Çàãðóçêà îáëàñòåé
2140 // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
2142 begin
2148 // Çàãðóçêà ìîíñòðîâ
2154 // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
2156 begin
2162 //gCurrentMap := mapReader; // this will be our current map now
2164 //mapReader := nil;
2166 // Çàãðóçêà íåáà
2168 begin
2173 if (FileName <> '') then FileName := GameDir+'/wads/'+FileName else FileName := g_ExtractWadName(Res);
2176 try
2179 begin
2181 end
2182 else
2183 begin
2186 finally
2191 // Çàãðóçêà ìóçûêè
2194 begin
2201 else
2202 begin
2209 else
2213 // Îñòàëüíûå óñòàíâêè
2221 // Åñëè íå LoadState, òî ñîçäàåì êàðòó ñòîëêíîâåíèé:
2224 // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
2233 // Âêëþ÷àåì ìóçûêó, åñëè ýòî íå çàãðóçêà:
2235 begin
2238 end
2239 else
2240 begin
2245 e_LogWritefln('map loaded in %s.%s milliseconds', [Integer(stt div 1000), Integer(stt mod 1000)]);
2247 finally
2249 //mapReader.Free();
2252 begin
2265 var
2268 //Header: TMapHeaderRec_1;
2272 begin
2278 begin
2280 Exit;
2283 //k8: it ignores path again
2285 begin
2287 Exit;
2292 try
2294 except
2297 exit;
2305 begin
2312 end
2313 else
2314 begin
2316 //ZeroMemory(@Header, SizeOf(Header));
2329 var
2333 begin
2337 begin
2339 Exit;
2343 begin
2345 begin
2354 var
2359 begin
2366 begin
2368 Exit;
2377 begin
2379 Exit;
2384 var
2388 var
2391 begin
2393 begin
2400 begin
2409 begin
2414 begin
2418 //DOMFlagPoints := nil;
2420 //gDOMFlags := nil;
2423 begin
2425 end
2426 else
2427 begin
2432 begin
2435 begin
2437 begin
2439 begin
2441 begin
2443 end
2444 else
2445 begin
2447 begin
2478 begin
2500 var
2506 var
2509 begin
2513 begin
2524 if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end;
2527 begin
2529 begin
2531 begin
2533 begin
2540 // Ñîïðîòèâëåíèå âîçäóõà
2543 // Òàéìàóò ïîòåðÿííîãî ôëàãà, ëèáî îí âûïàë çà êàðòó
2545 begin
2550 else
2556 Continue;
2561 // Èãðîê áåðåò ôëàã
2563 begin
2566 begin
2570 begin
2572 begin
2585 // old algo
2586 procedure g_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor);
2589 var
2591 begin
2593 begin
2594 // alas, no visible set
2596 begin
2602 begin
2616 // new algo
2618 (*
2619 function checker (pan: TPanel; tag: Integer): Boolean;
2620 begin
2621 result := false; // don't stop, ever
2622 if ((tag and GridTagDoor) <> 0) <> pan.Door then exit;
2623 gDrawPanelList.insert(pan);
2624 end;
2625 *)
2626 var
2630 begin
2632 //tagmask := panelTypeToTag(PanelType);
2633 //mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask);
2639 begin
2641 begin
2642 end
2643 else
2644 begin
2651 // list will be rendered in `g_game.DrawPlayer()`
2656 (*
2657 function checker (pan: TPanel; tag: Integer): Boolean;
2658 begin
2659 result := false; // don't stop, ever
2660 pan.DrawShadowVolume(lightX, lightY, radius);
2661 end;
2662 *)
2663 var
2667 begin
2668 //mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
2670 hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
2674 begin
2684 begin
2687 else
2693 var
2695 begin
2700 begin
2708 begin
2710 Exit;
2716 begin
2723 begin
2725 Exit;
2731 begin
2738 begin
2740 Exit;
2746 begin
2753 begin
2755 Exit;
2761 begin
2768 begin
2770 Exit;
2774 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then
2776 begin
2787 begin
2789 Exit;
2795 begin
2804 begin
2806 Exit;
2812 var
2816 var
2818 begin
2822 begin
2823 if g_Collide(X, Y, Width, Height, panels[a].X, panels[a].Y, panels[a].Width, panels[a].Height) then
2824 begin
2827 exit;
2832 begin
2842 function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
2843 const
2847 begin
2848 {
2849 if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
2850 begin
2851 result := pan.Enabled;
2852 exit;
2853 end;
2854 }
2857 begin
2858 result :=
2864 exit;
2868 begin
2869 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2870 exit;
2873 // other shit
2874 //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2878 var
2884 begin
2886 if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor);
2891 if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift;
2898 begin
2899 {if (Width = 1) and (Height = 1) then
2900 begin
2901 if ((tagmask and SlowMask) <> 0) then
2902 begin
2903 // slow
2904 result := (mapGrid.forEachAtPoint(X, Y, checker, tagmask) <> nil);
2905 end
2906 else
2907 begin
2908 // fast
2909 result := (mapGrid.forEachAtPoint(X, Y, nil, tagmask) <> nil);
2910 end;
2911 end
2912 else}
2913 begin
2916 begin
2917 // slow
2918 //result := (mapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask) <> nil);
2920 //if (hitcount = 0) then exit;
2923 begin
2926 begin
2927 result :=
2933 end
2935 begin
2936 result := ((not b1x3) or (pan.Width+pan.Height >= 64)); //and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
2937 end
2938 else
2939 begin
2940 // other shit
2947 end
2948 else
2949 begin
2950 // fast
2951 //result := (mapGrid.forEachInAABB(X, Y, Width, Height, nil, tagmask) <> nil);
2952 hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
2957 end
2958 else
2959 begin
2966 // returns `true` if we need to stop
2968 begin
2970 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
2971 // check priorities
2975 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
2977 // collision?
2978 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
2979 // yeah
2981 // water? water has the highest priority, so stop right here
2983 // acid2?
2985 // acid1?
2990 var
2991 cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
2992 //texid: DWORD;
2994 (*
2995 // slightly different from the old code, but meh...
2996 function checker (pan: TPanel; tag: Integer): Boolean;
2997 begin
2998 result := false; // don't stop, ever
2999 //if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
3000 // check priorities
3001 case cctype of
3002 0: if ((tag and GridTagWater) = 0) then exit; // allowed: water
3003 1: if ((tag and (GridTagWater or GridTagAcid1)) = 0) then exit; // allowed: water, acid1
3004 //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2
3005 end;
3006 // collision?
3007 //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit;
3008 // yeah
3009 texid := pan.GetTextureID();
3010 // water? water has the highest priority, so stop right here
3011 if ((tag and GridTagWater) <> 0) then begin cctype := 0; result := true; exit; end;
3012 // acid2?
3013 if ((tag and GridTagAcid2) <> 0) then cctype := 2;
3014 // acid1?
3015 if ((tag and GridTagAcid1) <> 0) then cctype := 1;
3016 end;
3017 *)
3018 var
3023 begin
3026 begin
3028 {
3029 if (Width = 1) and (Height = 1) then
3030 begin
3031 mapGrid.forEachAtPoint(X, Y, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3032 end
3033 else
3034 begin
3035 mapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3036 end;
3037 }
3039 hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
3043 begin
3050 //result := texid;
3051 end
3052 else
3053 begin
3060 procedure g_Map_EnableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_EnableWallGUID(gWalls[ID].guid); end;
3061 procedure g_Map_DisableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_DisableWallGUID(gWalls[ID].guid); end;
3062 procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); begin if (ID < Length(gLifts)) then g_Map_SetLiftGUID(gLifts[ID].guid, t); end;
3066 var
3068 begin
3069 //pan := gWalls[ID];
3078 //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
3079 //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor);
3081 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3082 // mark platform as interesting
3085 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
3086 //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);
3087 {$ENDIF}
3092 var
3094 begin
3095 //pan := gWalls[ID];
3104 //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
3106 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3107 // mark platform as interesting
3110 {$IFDEF MAP_DEBUG_ENABLED_FLAG}
3111 //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);
3112 {$ENDIF}
3117 var
3119 begin
3128 var
3130 begin
3131 //pan := gLifts[ID];
3139 begin
3143 //TODO: make separate lift tags, and change tag here
3152 //if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pguid);
3153 // mark platform as interesting
3160 var
3163 begin
3168 Exit;
3172 begin
3178 Exit;
3185 var
3187 begin
3191 Exit;
3199 begin
3204 begin
3206 begin
3214 begin
3225 var
3228 begin
3230 Exit;
3235 begin
3237 continue;
3240 begin
3243 end
3244 else
3245 begin
3253 begin
3265 var
3269 var
3271 begin
3272 // Ñîõðàíÿåì ïàíåëè
3278 var
3280 begin
3283 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3285 // Ñîñòîÿíèå ôëàãà
3287 // Íàïðàâëåíèå ôëàãà
3290 // Îáúåêò ôëàãà
3294 begin
3297 // Ñîõðàíÿåì ìóçûêó
3300 // Íàçâàíèå ìóçûêè
3304 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3306 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3309 ///// Ñîõðàíÿåì êîëè÷åñòâî ìîíñòðîâ: /////
3311 ///// /////
3313 //// Ñîõðàíÿåì ôëàãè, åñëè ýòî CTF: /////
3315 begin
3316 // Ôëàã Êðàñíîé êîìàíäû
3318 // Ôëàã Ñèíåé êîìàíäû
3321 ///// /////
3323 ///// Ñîõðàíÿåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3325 begin
3326 // Î÷êè Êðàñíîé êîìàíäû
3328 // Î÷êè Ñèíåé êîìàíäû
3331 ///// /////
3336 var
3342 var
3344 begin
3345 // Çàãðóæàåì ïàíåëè
3346 if (Length(panByGUID) <> utils.readLongInt(st)) then raise XStreamError.Create('invalid number of saved panels');
3348 begin
3355 var
3357 begin
3358 // Ñèãíàòóðà ôëàãà
3361 // Âðåìÿ ïåðåïîÿâëåíèÿ ôëàãà
3363 // Ñîñòîÿíèå ôëàãà
3365 // Íàïðàâëåíèå ôëàãà
3367 if (b = 1) then flag^.Direction := TDirection.D_LEFT else flag^.Direction := TDirection.D_RIGHT; // b = 2
3368 // Îáúåêò ôëàãà
3372 begin
3375 ///// Çàãðóæàåì ñïèñêè ïàíåëåé: /////
3377 ///// /////
3379 // Îáíîâëÿåì êàðòó ñòîëêíîâåíèé è ñåòêó
3381 //mapCreateGrid();
3383 ///// Çàãðóæàåì ìóçûêó: /////
3386 // Íàçâàíèå ìóçûêè
3389 // Ïîçèöèÿ ïðîèãðûâàíèÿ ìóçûêè
3391 // Ñòîèò ëè ìóçûêà íà ñïåö-ïàóçå
3393 // Çàïóñêàåì ýòó ìóçûêó
3399 ///// /////
3401 ///// Çàãðóæàåì êîëè÷åñòâî ìîíñòðîâ: /////
3403 ///// /////
3405 //// Çàãðóæàåì ôëàãè, åñëè ýòî CTF: /////
3407 begin
3408 // Ôëàã Êðàñíîé êîìàíäû
3410 // Ôëàã Ñèíåé êîìàíäû
3413 ///// /////
3415 ///// Çàãðóæàåì êîëè÷åñòâî ïîáåä, åñëè ýòî TDM/CTF: /////
3417 begin
3418 // Î÷êè Êðàñíîé êîìàíäû
3420 // Î÷êè Ñèíåé êîìàíäû
3423 ///// /////
3427 // trace liquid, stepping by `dx` and `dy`
3428 // return last seen liquid coords, and `false` if we're started outside of the liquid
3429 function g_Map_TraceLiquidNonPrecise (x, y, dx, dy: Integer; out topx, topy: Integer): Boolean;
3430 const
3432 begin
3435 // started outside of the liquid?
3436 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then begin result := false; exit; end;
3440 begin
3443 if (mapGrid.forEachAtPoint(x, y, nil, MaskLiquid) = nil) then exit; // out of the water, just exit
3450 begin