DEADSOFTWARE

don't be *too* smart: `swapInt()` should not do xor trick, 'cause we may pass the...
[d2df-sdl.git] / src / game / g_map.pas
index 577891f59bbd8ef187dfa536aa3b2406b22a8bdb..101c3c544d06658454afb94777d730c333832545 100644 (file)
@@ -125,6 +125,12 @@ procedure g_Map_ProfilersEnd ();
 
 function g_Map_ParseMap (data: Pointer; dataLen: Integer): TDynRecord;
 
+
+function g_Map_MinX (): Integer; inline;
+function g_Map_MinY (): Integer; inline;
+function g_Map_MaxX (): Integer; inline;
+function g_Map_MaxY (): Integer; inline;
+
 const
   NNF_NO_NAME         = 0;
   NNF_NAME_BEFORE     = 1;
@@ -183,6 +189,9 @@ const
   GridTagLift = 1 shl 8; // gLifts
   GridTagBlockMon = 1 shl 9; // gBlockMon
 
+  GridTagObstacle = (GridTagStep or GridTagWall or GridTagDoor);
+  GridTagLiquid = (GridTagAcid1 or GridTagAcid2 or GridTagWater);
+
   GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
 
 
@@ -253,10 +262,18 @@ begin
 end;
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+function g_Map_MinX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0 else result := 0; end;
+function g_Map_MinY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0 else result := 0; end;
+function g_Map_MaxX (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridX0+mapGrid.gridWidth-1 else result := 0; end;
+function g_Map_MaxY (): Integer; inline; begin if (mapGrid <> nil) then result := mapGrid.gridY0+mapGrid.gridHeight-1 else result := 0; end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 var
   dfmapdef: TDynMapDef = nil;
 
+
 procedure loadMapDefinition ();
 var
   pr: TTextParser = nil;
@@ -264,13 +281,15 @@ var
   WAD: TWADFile = nil;
 begin
   if (dfmapdef <> nil) then exit;
+
   try
     e_LogWritefln('parsing "mapdef.txt"...', []);
     st := openDiskFileRO(DataDir+'mapdef.txt');
+    e_LogWritefln('found local "%smapdef.txt"', [DataDir]);
   except
     st := nil;
-    e_LogWritefln('local "%smapdef.txt" not found', [DataDir]);
   end;
+
   if (st = nil) then
   begin
     WAD := TWADFile.Create();
@@ -285,15 +304,22 @@ begin
     end;
   end;
 
-  if (st = nil) then
-  begin
-    //raise Exception.Create('cannot open "mapdef.txt"');
-    e_LogWritefln('using default "mapdef.txt"...', [], MSG_WARNING);
-    pr := TStrTextParser.Create(defaultMapDef);
-  end
-  else
-  begin
-    pr := TFileTextParser.Create(st);
+  try
+    if (st = nil) then
+    begin
+      //raise Exception.Create('cannot open "mapdef.txt"');
+      e_LogWriteln('using default "mapdef.txt"...');
+      pr := TStrTextParser.Create(defaultMapDef);
+    end
+    else
+    begin
+      pr := TFileTextParser.Create(st);
+    end;
+  except on e: Exception do
+    begin
+      e_LogWritefln('something is VERY wrong here! -- ', [e.message]);
+      raise;
+    end;
   end;
 
   try
@@ -315,6 +341,8 @@ var
 begin
   result := nil;
   if (dataLen < 4) then exit;
+
+  if (dfmapdef = nil) then writeln('need to load mapdef');
   loadMapDefinition();
   if (dfmapdef = nil) then raise Exception.Create('internal map loader error');
 
@@ -324,6 +352,7 @@ begin
   begin
     // binary map
     try
+      //e_LogWriteln('parsing binary map...');
       result := dfmapdef.parseBinMap(wst);
     except on e: Exception do
       begin
@@ -340,10 +369,11 @@ begin
     // text map
     pr := TFileTextParser.Create(wst);
     try
+      //e_LogWriteln('parsing text map...');
       result := dfmapdef.parseMap(pr);
     except on e: Exception do
       begin
-        if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.line, pr.col, e.message])
+        if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message])
         else e_LogWritefln('ERROR: %s', [e.message]);
         pr.Free(); // will free `wst`
         result := nil;
@@ -352,6 +382,7 @@ begin
     end;
     pr.Free(); // will free `wst`
   end;
+  //e_LogWriteln('map parsed.');
 end;
 
 
@@ -1262,10 +1293,11 @@ begin
   end;
 end;
 
-procedure CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word);
+function CreateTrigger (amapIdx: Integer; Trigger: TDynRecord; atpanid, atrigpanid: Integer; fTexturePanel1Type, fTexturePanel2Type: Word): Integer;
 var
   _trigger: TTrigger;
 begin
+  result := -1;
   if g_Game_IsClient and not (Trigger.TriggerType in [TRIGGER_SOUND, TRIGGER_MUSIC]) then Exit;
 
   with _trigger do
@@ -1297,11 +1329,11 @@ begin
     end
     else
     begin
-      trigData := Trigger.trigRec.clone();
+      trigData := Trigger.trigRec.clone(nil);
     end;
   end;
 
-  g_Triggers_Create(_trigger);
+  result := Integer(g_Triggers_Create(_trigger));
 end;
 
 procedure CreateMonster(monster: TDynRecord);
@@ -1546,6 +1578,8 @@ type
   PTRec = ^TTRec;
   TTRec = record
     //TexturePanel: Integer;
+    tnum: Integer;
+    id: Integer;
     texPanIdx: Integer;
     LiftPanelIdx: Integer;
     DoorPanelIdx: Integer;
@@ -1582,6 +1616,7 @@ var
   stt: UInt64;
   moveSpeed{, moveStart, moveEnd}: TDFPoint;
   //moveActive: Boolean;
+  pan: TPanel;
 begin
   mapGrid.Free();
   mapGrid := nil;
@@ -1646,6 +1681,12 @@ begin
 
     FreeMem(Data);
 
+    if (mapReader = nil) then
+    begin
+      e_LogWritefln('invalid map file: ''%s''', [mapResName]);
+      exit;
+    end;
+
     generateExternalResourcesList(mapReader);
     mapTextureList := mapReader['texture'];
     // get all other lists here too
@@ -2020,7 +2061,21 @@ begin
         else if (TriggersTable[trignum].MPlatPanelIdx <> -1) then tgpid := TriggersTable[trignum].MPlatPanelIdx
         else tgpid := -1;
         //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
-        CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c));
+        TriggersTable[trignum].tnum := trignum;
+        TriggersTable[trignum].id := CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c));
+      end;
+    end;
+
+    //FIXME: use hashtable!
+    for pan in panByGUID do
+    begin
+      if (pan.endPosTrigId >= 0) and (pan.endPosTrigId < Length(TriggersTable)) then
+      begin
+        pan.endPosTrigId := TriggersTable[pan.endPosTrigId].id;
+      end;
+      if (pan.endSizeTrigId >= 0) and (pan.endSizeTrigId < Length(TriggersTable)) then
+      begin
+        pan.endSizeTrigId := TriggersTable[pan.endSizeTrigId].id;
       end;
     end;
 
@@ -2187,10 +2242,14 @@ begin
     mapReader := g_Map_ParseMap(Data, Len);
   except
     mapReader := nil;
+    FreeMem(Data);
+    exit;
   end;
 
   FreeMem(Data);
 
+  if (mapReader = nil) then exit;
+
   if (mapReader.Width > 0) and (mapReader.Height > 0) then
   begin
     Result.Name := mapReader.MapName;
@@ -2397,6 +2456,8 @@ var
   end;
 
 begin
+  if g_dbgpan_mplat_step then g_dbgpan_mplat_active := true;
+
   UpdatePanelArray(gWalls);
   UpdatePanelArray(gRenderBackgrounds);
   UpdatePanelArray(gRenderForegrounds);
@@ -2405,6 +2466,8 @@ begin
   UpdatePanelArray(gAcid2);
   UpdatePanelArray(gSteps);
 
+  if g_dbgpan_mplat_step then begin g_dbgpan_mplat_step := false; g_dbgpan_mplat_active := false; end;
+
   if gGameSettings.GameMode = GM_CTF then
   begin
     for a := FLAG_RED to FLAG_BLUE do
@@ -2450,7 +2513,7 @@ begin
               if j > High(gPlayers) then j := 0;
               if gPlayers[j] <> nil then
               begin
-                if gPlayers[j].Live and g_Obj_Collide(@Obj, @gPlayers[j].Obj) then
+                if gPlayers[j].alive and g_Obj_Collide(@Obj, @gPlayers[j].Obj) then
                 begin
                   if gPlayers[j].GetFlag(a) then Break;
                 end;