DEADSOFTWARE

trigger loading now works; map loading code cleanup
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Thu, 31 Aug 2017 21:57:20 +0000 (00:57 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 1 Sep 2017 00:33:55 +0000 (03:33 +0300)
src/game/g_holmes.pas
src/game/g_map.pas
src/game/g_triggers.pas
src/shared/MAPDEF.pas
src/shared/utils.pas
src/shared/xdynrec.pas

index 31417e6bdf6e655696131dfff775ac34649ada92..566cd19c61b5b5eddb211b79e43f625ee56d06d7 100644 (file)
@@ -968,7 +968,7 @@ procedure plrDebugDraw ();
       if (idx < 0) or (idx >= Length(parr)) then exit;
       pan := parr[idx];
       drawLine(
-        trig.x+trig.width div 2, trig.y+trig.height div 2,
+        trig.trigCenter.x, trig.trigCenter.y,
         pan.x+pan.width div 2, pan.y+pan.height div 2,
         255, 0, 255, 220);
     end;
@@ -982,6 +982,9 @@ procedure plrDebugDraw ();
     tx := trig.x+(trig.width-Length(tts)*6) div 2;
     darkenRect(tx-2, trig.y-10, Length(tts)*6+4, 10, 64);
     drawText6(tx, trig.y-9, tts, 255, 127, 0);
+    tx := trig.x+(trig.width-Length(trig.mapId)*6) div 2;
+    darkenRect(tx-2, trig.y-20, Length(trig.mapId)*6+4, 10, 64);
+    drawText6(tx, trig.y-19, trig.mapId, 255, 255, 0);
     case trig.TriggerType of
       TRIGGER_NONE: begin end;
       TRIGGER_EXIT: begin end;
@@ -992,15 +995,23 @@ procedure plrDebugDraw ();
       TRIGGER_DOOR5: begin drawPanelDest(gWalls, trig.trigPanelId); end;
       TRIGGER_CLOSETRAP: begin drawPanelDest(gWalls, trig.trigPanelId); end;
       TRIGGER_TRAP: begin drawPanelDest(gWalls, trig.trigPanelId); end;
-      TRIGGER_PRESS: begin end;
       TRIGGER_SECRET: begin end;
       TRIGGER_LIFTUP: begin drawPanelDest(gLifts, trig.trigPanelId); end;
       TRIGGER_LIFTDOWN: begin drawPanelDest(gLifts, trig.trigPanelId); end;
       TRIGGER_LIFT: begin drawPanelDest(gLifts, trig.trigPanelId); end;
       TRIGGER_TEXTURE: begin end;
-      TRIGGER_ON: begin end;
-      TRIGGER_OFF: begin end;
-      TRIGGER_ONOFF: begin end;
+      TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF, TRIGGER_PRESS:
+        begin
+        fillRect(
+          trig.trigData.trigTX, trig.trigData.trigTY,
+          trig.trigData.trigTWidth, trig.trigData.trigTHeight,
+          0, 255, 255, 42);
+        drawLine(
+          trig.trigCenter.x, trig.trigCenter.y,
+          trig.trigData.trigTX+trig.trigData.trigTWidth div 2,
+          trig.trigData.trigTY+trig.trigData.trigTHeight div 2,
+          255, 0, 255, 220);
+        end;
       TRIGGER_SOUND: begin end;
       TRIGGER_SPAWNMONSTER: begin end;
       TRIGGER_SPAWNITEM: begin end;
@@ -1238,10 +1249,27 @@ procedure cbAtcurDumpWalls ();
     result := false; // don't stop
     e_WriteLog(Format('wall #%d(%d); enabled=%d (%d); (%d,%d)-(%d,%d)', [pan.arrIdx, pan.proxyId, Integer(pan.Enabled), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.X, pan.Y, pan.Width, pan.Height]), MSG_NOTIFY);
   end;
+var
+  hasTrigs: Boolean = false;
+  f: Integer;
+  trig: PTrigger;
 begin
   e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY);
   mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, wallToggle, (GridTagWall or GridTagDoor));
   e_WriteLog('--- toggle wall ---', MSG_NOTIFY);
+  if showTriggers then
+  begin
+    for f := 0 to High(gTriggers) do
+    begin
+      trig := @gTriggers[f];
+      if (pmsCurMapX >= trig.x) and (pmsCurMapY >= trig.y) and (pmsCurMapX < trig.x+trig.width) and (pmsCurMapY < trig.y+trig.height) then
+      begin
+        if not hasTrigs then begin writeln('=== TRIGGERS ==='); hasTrigs := true; end;
+        writeln('trigger ''', trig.mapId, ''' of type ''', trigType2Str(trig.TriggerType), '''');
+      end;
+    end;
+    if hasTrigs then writeln('--- triggers ---');
+  end;
 end;
 
 procedure cbAtcurToggleWalls ();
index 6ae077b111553f4193f959550e7ac90774e1b670..6b64d8818ead94d6f3c925bd0dabfd68589e242f 100644 (file)
@@ -1198,11 +1198,12 @@ begin
 
   with _trigger do
   begin
+    mapId := Trigger.id;
     X := Trigger.X;
     Y := Trigger.Y;
     Width := Trigger.Width;
     Height := Trigger.Height;
-    Enabled := ByteBool(Trigger.Enabled);
+    Enabled := Trigger.Enabled;
     //TexturePanel := Trigger.TexturePanel;
     TexturePanel := atpanid;
     TexturePanelType := fTexturePanel1Type;
@@ -1213,7 +1214,18 @@ begin
     trigPanelId := atrigpanid;
     //trigShotPanelId := ashotpanid;
     //Data.Default := Trigger.DATA;
-    trigData := Trigger.trigRec.clone();
+    if (Trigger.trigRec = nil) then
+    begin
+      trigData := nil;
+      if (TriggerType <> TRIGGER_SECRET) then
+      begin
+        e_LogWritefln('trigger of type %s has no triggerdata; wtf?!', [TriggerType], MSG_WARNING);
+      end;
+    end
+    else
+    begin
+      trigData := Trigger.trigRec.clone();
+    end;
   end;
 
   g_Triggers_Create(_trigger);
@@ -1463,11 +1475,8 @@ type
   end;
 var
   WAD: TWADFile;
-  //MapReader: TMapReader_1;
   mapReader: TDynRecord = nil;
-  //Header: TMapHeaderRec_1;
-  _textures: TDynField = nil; //TTexturesRec1Array; tagInt: texture index
-  //_texnummap: array of Integer = nil; // `_textures` -> `Textures`
+  mapTextureList: TDynField = nil; //TTexturesRec1Array; tagInt: texture index
   panels: TDynField = nil; //TPanelsRec1Array;
   items: TDynField = nil; //TItemsRec1Array;
   monsters: TDynField = nil; //TMonsterRec1Array;
@@ -1476,7 +1485,6 @@ var
   b, c, k: Integer;
   PanelID: DWORD;
   AddTextures: TAddTextureArray;
-  //texture: TTextureRec_1;
   TriggersTable: array of TTRec;
   FileName, mapResName, s, TexName: String;
   Data: Pointer;
@@ -1486,11 +1494,6 @@ var
   rec, texrec: TDynRecord;
   pttit: PTRec;
   pannum, trignum, cnt, tgpid: Integer;
-  // key: panel index; value: `TriggersTable` index
-  hashTextPan: THashIntInt = nil;
-  hashLiftPan: THashIntInt = nil;
-  hashDoorPan: THashIntInt = nil;
-  hashShotPan: THashIntInt = nil;
 begin
   mapGrid.Free();
   mapGrid := nil;
@@ -1502,7 +1505,6 @@ begin
   gMapInfo.Map := Res;
   TriggersTable := nil;
   mapReader := nil;
-  //FillChar(texture, SizeOf(texture), 0);
 
   sfsGCDisable(); // temporary disable removing of temporary volumes
   try
@@ -1552,31 +1554,18 @@ begin
 
     FreeMem(Data);
 
-    hashTextPan := hashNewIntInt();
-    hashLiftPan := hashNewIntInt();
-    hashDoorPan := hashNewIntInt();
-    hashShotPan := hashNewIntInt();
-
-    generateExternalResourcesList(MapReader);
-    //_textures := GetTextures(mapReader);
-    _textures := mapReader['texture'];
-    //_texnummap := nil;
+    generateExternalResourcesList(mapReader);
+    mapTextureList := mapReader['texture'];
     // get all other lists here too
-    //panels := GetPanels(mapReader);
     panels := mapReader['panel'];
-    //triggers := GetTriggers(mapReader);
     triggers := mapReader['trigger'];
-    //items := GetItems(mapReader);
     items := mapReader['item'];
-    //areas := GetAreas(mapReader);
     areas := mapReader['area'];
-    //monsters := GetMonsters(mapReader);
     monsters := mapReader['monster'];
 
     // Çàãðóçêà îïèñàíèÿ êàðòû:
     e_WriteLog('  Reading map info...', MSG_NOTIFY);
     g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
-    //Header := GetMapHeader(mapReader);
 
     with gMapInfo do
     begin
@@ -1592,14 +1581,13 @@ begin
     // Çàãðóçêà òåêñòóð:
     g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], 0, False);
     // Äîáàâëåíèå òåêñòóð â Textures[]:
-    if (_textures <> nil) and (_textures.count > 0) then
+    if (mapTextureList <> nil) and (mapTextureList.count > 0) then
     begin
       e_WriteLog('  Loading textures:', MSG_NOTIFY);
-      g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], _textures.count-1, False);
-      //SetLength(_texnummap, _textures.count);
+      g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], mapTextureList.count-1, False);
 
       cnt := -1;
-      for rec in _textures do
+      for rec in mapTextureList do
       begin
         Inc(cnt);
         s := rec.Resource;
@@ -1621,8 +1609,7 @@ begin
         end;
         if (ntn < 0) then ntn := CreateNullTexture(rec.Resource);
 
-        //_texnummap[a] := ntn; // fix texture number
-        rec.tagInt := ntn;
+        rec.tagInt := ntn; // remember texture number
         g_Game_StepLoading();
       end;
 
@@ -1672,6 +1659,7 @@ begin
         SetLength(TriggersTable, Length(TriggersTable)+1);
         pttit := @TriggersTable[High(TriggersTable)];
         pttit.trigrec := rec;
+        // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
         pttit.texPan := mapReader.panel[rec.TexturePanel];
         pttit.liftPan := nil;
         pttit.doorPan := nil;
@@ -1680,34 +1668,22 @@ begin
         pttit.LiftPanelIdx := -1;
         pttit.DoorPanelIdx := -1;
         pttit.ShotPanelIdx := -1;
-        // Ñìåíà òåêñòóðû (âîçìîæíî, êíîïêè)
-        //if (rec.TexturePanel >= 0) and (pttit.texPan = nil) then e_WriteLog('error loading map: invalid texture panel index for trigger', MSG_WARNING);
         // Ëèôòû
         if rec.TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then
         begin
-          //pttit.LiftPanel := TTriggerData(rec.DATA).PanelID
           pttit.liftPan := mapReader.panel[rec.trigRec.tgPanelID];
-          //if (rec.trigRec.trigPanelID >= 0) and (pttit.liftPan = nil) then e_WriteLog('error loading map: invalid lift panel index for trigger', MSG_WARNING);
         end;
         // Äâåðè
         if rec.TriggerType in [TRIGGER_OPENDOOR, TRIGGER_CLOSEDOOR, TRIGGER_DOOR, TRIGGER_DOOR5, TRIGGER_CLOSETRAP, TRIGGER_TRAP] then
         begin
-          //pttit.DoorPanel := TTriggerData(rec.DATA).PanelID
           pttit.doorPan := mapReader.panel[rec.trigRec.tgPanelID];
         end;
         // Òóðåëü
         if (rec.TriggerType = TRIGGER_SHOT) then
         begin
-          //pttit.ShotPanel := TTriggerData(rec.DATA).ShotPanelID
           pttit.shotPan := mapReader.panel[rec.trigRec.tgShotPanelID];
         end;
 
-        // update hashes
-        if (pttit.texPan <> nil) then hashTextPan.put(rec.TexturePanel, High(TriggersTable));
-        if (pttit.liftPan <> nil) then hashLiftPan.put(rec.trigRec.tgPanelID, High(TriggersTable));
-        if (pttit.doorPan <> nil) then hashDoorPan.put(rec.trigRec.tgPanelID, High(TriggersTable));
-        if (pttit.shotPan <> nil) then hashShotPan.put(rec.trigRec.tgShotPanelID, High(TriggersTable));
-
         g_Game_StepLoading();
       end;
     end;
@@ -1728,7 +1704,7 @@ begin
         CurTex := -1;
         ok := false;
 
-        if (_textures <> nil) then
+        if (mapTextureList <> nil) then
         begin
           texrec := rec.TextureRec;
           ok := (texrec <> nil);
@@ -1739,7 +1715,7 @@ begin
           // Ñìîòðèì, ññûëàþòñÿ ëè íà ýòó ïàíåëü òðèããåðû.
           // Åñëè äà - òî íàäî ñîçäàòü åùå òåêñòóð
           ok := false;
-          if (TriggersTable <> nil) and (_textures <> nil) then
+          if (TriggersTable <> nil) and (mapTextureList <> nil) then
           begin
             for b := 0 to High(TriggersTable) do
             begin
@@ -1828,8 +1804,7 @@ begin
                 begin
                   // Çàíîñèì òåêóùóþ òåêñòóðó íà ñâîå ìåñòî
                   SetLength(AddTextures, Length(AddTextures)+1);
-                  //AddTextures[High(AddTextures)].Texture := _texnummap[rec.TextureNum]; //panels[a].TextureNum;
-                  AddTextures[High(AddTextures)].Texture := rec.tagInt; //panels[a].TextureNum;
+                  AddTextures[High(AddTextures)].Texture := rec.tagInt; // internal texture number, not map index
                   AddTextures[High(AddTextures)].Anim := texrec.Anim;
                   CurTex := High(AddTextures);
                   ok := true;
@@ -1849,66 +1824,32 @@ begin
         begin
           // Çàíîñèì òîëüêî òåêóùóþ òåêñòóðó
           SetLength(AddTextures, 1);
-          AddTextures[0].Texture := rec.tagInt; //panels[a].TextureNum;
+          AddTextures[0].Texture := rec.tagInt; // internal texture number, not map index
           AddTextures[0].Anim := false;
           if (texrec <> nil) then AddTextures[0].Anim := texrec.Anim;
           CurTex := 0;
         end;
 
-        //e_WriteLog(Format('panel #%d: TextureNum=%d; ht=%d; ht1=%d; atl=%d', [a, panels[a].TextureNum, High(_textures), High(Textures), High(AddTextures)]), MSG_NOTIFY);
+        //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);
 
         // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå íîìåð
         PanelID := CreatePanel(rec, AddTextures, CurTex, trigRef);
         //e_LogWritefln('panel #%s of type %s got id #%s', [pannum, rec.PanelType, PanelID]);
-
-        // Åñëè èñïîëüçóåòñÿ â òðèããåðàõ, òî ñòàâèì òî÷íûé ID
-        if hashTextPan.get(pannum, b) then TriggersTable[b].texPanIdx := PanelID;
-        if hashLiftPan.get(pannum, b) then TriggersTable[b].LiftPanelIdx := PanelID;
-        if hashDoorPan.get(pannum, b) then TriggersTable[b].DoorPanelIdx := PanelID;
-        if hashShotPan.get(pannum, b) then TriggersTable[b].ShotPanelIdx := PanelID;
-
-        (*
-        if (TriggersTable <> nil) then
-        begin
-          for b := 0 to High(TriggersTable) do
-          begin
-            if (TriggersTable[b].texPan = rec) then TriggersTable[b].texPanIdx := PanelID;
-            if (TriggersTable[b].liftPan = rec) then TriggersTable[b].LiftPanelIdx := PanelID;
-            if (TriggersTable[b].doorPan = rec) then TriggersTable[b].DoorPanelIdx := PanelID;
-            if (TriggersTable[b].shotPan = rec) then TriggersTable[b].ShotPanelIdx := PanelID;
-            {
-            // Òðèããåð äâåðè/ëèôòà
-            if (TriggersTable[b].LiftPanel = pannum) or
-               (TriggersTable[b].DoorPanel = pannum) then
-              //TTriggerData(TriggersTable[b].trigrec.DATA).PanelID := PanelID;
-              TriggersTable[b].trigrec.trigRec.trigPanelID := PanelID;
-            // Òðèããåð ñìåíû òåêñòóðû
-            if TriggersTable[b].texPanIdx = pannum then
-              TriggersTable[b].trigrec.TexturePanel := PanelID;
-            // Òðèããåð "Òóðåëü"
-            if TriggersTable[b].ShotPanel = pannum then
-              TriggersTable[b].trigrec.trigRec.trigShotPanelID := PanelID;
-            }
-          end;
-        end;
-        *)
+        // set 'gamePanelId' field to panel id
+        rec.gamePanelId := PanelID; // remember game panel id, we'll fix triggers later
 
         g_Game_StepLoading();
       end;
     end;
 
-    (*
+    // ×èíèì ID'û ïàíåëåé, êîòîðûå èñïîëüçóþòñÿ â òðèããåðàõ
+    for b := 0 to High(TriggersTable) do
     begin
-      for b := 0 to High(TriggersTable) do
-      begin
-        // Òðèããåð äâåðè/ëèôòà
-        if (TriggersTable[b].texPan <> nil) then e_LogWritefln('trigger #%s: textPan=%s; panidx=%s', [b, TriggersTable[b].texPanIdx, mapReader.panelIndex[TriggersTable[b].texPan]]);
-        if (TriggersTable[b].liftPan <> nil) then e_LogWritefln('trigger #%s: liftPan=%s; panidx=%s', [b, TriggersTable[b].LiftPanelIdx, mapReader.panelIndex[TriggersTable[b].liftPan]]);
-        if (TriggersTable[b].doorPan <> nil) then e_LogWritefln('trigger #%s: doorPan=%s; panidx=%s', [b, TriggersTable[b].DoorPanelIdx, mapReader.panelIndex[TriggersTable[b].doorPan]]);
-        if (TriggersTable[b].shotPan <> nil) then e_LogWritefln('trigger #%s: shotPan=%s; panidx=%s', [b, TriggersTable[b].ShotPanelIdx, mapReader.panelIndex[TriggersTable[b].shotPan]]);
-      end;
+      if (TriggersTable[b].texPan <> nil) then TriggersTable[b].texPanIdx := TriggersTable[b].texPan.gamePanelId;
+      if (TriggersTable[b].liftPan <> nil) then TriggersTable[b].LiftPanelIdx := TriggersTable[b].liftPan.gamePanelId;
+      if (TriggersTable[b].doorPan <> nil) then TriggersTable[b].DoorPanelIdx := TriggersTable[b].doorPan.gamePanelId;
+      if (TriggersTable[b].shotPan <> nil) then TriggersTable[b].ShotPanelIdx := TriggersTable[b].shotPan.gamePanelId;
     end;
-    *)
 
     // create map grid, init other grids (for monsters, for example)
     e_WriteLog('Creating map grid', MSG_NOTIFY);
@@ -1926,45 +1867,11 @@ begin
         Inc(trignum);
         if (TriggersTable[trignum].texPan <> nil) then b := TriggersTable[trignum].texPan.PanelType else b := 0;
         if (TriggersTable[trignum].shotPan <> nil) then c := TriggersTable[trignum].shotPan.PanelType else c := 0;
-        tgpid := -1;
+        // we can have only one of those
              if (TriggersTable[trignum].LiftPanelIdx <> -1) then tgpid := TriggersTable[trignum].LiftPanelIdx
         else if (TriggersTable[trignum].DoorPanelIdx <> -1) then tgpid := TriggersTable[trignum].DoorPanelIdx
         else if (TriggersTable[trignum].ShotPanelIdx <> -1) then tgpid := TriggersTable[trignum].ShotPanelIdx
         else tgpid := -1;
-        (*
-        if (rec.TexturePanel <> -1) then
-        begin
-          {
-          if (TriggersTable[trignum].TexturePanel < 0) or (TriggersTable[trignum].TexturePanel >= panels.count) then
-          begin
-            e_WriteLog('error loading map: invalid panel index for trigger', MSG_FATALERROR);
-            result := false;
-            exit;
-          end;
-          }
-          //b := panels[TriggersTable[a].TexturePanel].PanelType;
-          //b := mapReader.panel[TriggersTable[trignum].texPanIdx].PanelType;
-          assert(TriggersTable[trignum].texPanIdx >= 0);
-          b := TriggersTable[trignum].texPanIdx;
-        end
-        else
-        begin
-          b := 0;
-        end;
-        e_LogWritefln('trigger #%s: type=%s; texPanIdx=%s; b=%s', [trignum, rec.TriggerType, TriggersTable[trignum].texPanIdx, b]);
-        if (rec.TriggerType = TRIGGER_SHOT) then e_LogWritefln('  SHOT: shotpanidx=%s', [rec.trigRec.trigShotPanelID]);
-        if (rec.TriggerType = TRIGGER_SHOT) and {(rec.trigRec.trigShotPanelID <> -1)} (TriggersTable[trignum].shotPan <> nil) then
-        begin
-          //c := panels[TriggersTable[a].ShotPanel].PanelType;
-          //c := mapReader.panel[TriggersTable[trignum].ShotPanel].PanelType;
-          assert(TriggersTable[trignum].ShotPanelIdx >= 0);
-          c := TriggersTable[trignum].ShotPanelIdx;
-        end
-        else
-        begin
-          c := 0;
-        end;
-        *)
         //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]);
         CreateTrigger(rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c));
       end;
@@ -2008,8 +1915,7 @@ begin
       for rec in monsters do CreateMonster(rec);
     end;
 
-    //MapReader.Free();
-    gCurrentMap := mapReader;
+    gCurrentMap := mapReader; // this will be our current map now
     mapReader := nil;
 
     // Çàãðóçêà íåáà
@@ -2069,7 +1975,7 @@ begin
     if not gLoadGameMode then g_GFX_Init();
 
     // Ñáðîñ ëîêàëüíûõ ìàññèâîâ:
-    _textures := nil;
+    mapTextureList := nil;
     panels := nil;
     items := nil;
     areas := nil;
@@ -2090,20 +1996,17 @@ begin
   finally
     sfsGCEnable(); // enable releasing unused volumes
     mapReader.Free();
-    hashTextPan.Free();
-    hashLiftPan.Free();
-    hashDoorPan.Free();
-    hashShotPan.Free();
   end;
 
   e_WriteLog('Done loading map.', MSG_NOTIFY);
   Result := True;
 end;
 
+
 function g_Map_GetMapInfo(Res: String): TMapInfo;
 var
   WAD: TWADFile;
-  MapReader: TDynRecord;
+  mapReader: TDynRecord;
   //Header: TMapHeaderRec_1;
   FileName: String;
   Data: Pointer;
index edafecc999a259e828799a9e1d51d3bd5d59603e..064b3b6cebba673302668005eb580130f48e1789 100644 (file)
@@ -27,7 +27,9 @@ type
     UID:     Word;
     TimeOut: Word;
   end;
+  PTrigger = ^TTrigger;
   TTrigger = record
+  public
     ID:               DWORD;
     ClientID:         DWORD;
     TriggerType:      Byte;
@@ -60,12 +62,17 @@ type
     ShotAmmoCount:    Word;
     ShotReloadTime:   Integer;
 
+    mapId: AnsiString; // trigger id, from map
     //trigShotPanelId: Integer;
     trigPanelId: Integer;
 
     //TrigData:             TTriggerData;
     trigData: TDynRecord; // triggerdata; owned by trigger
 
+  public
+    function trigCenter (): TDFPoint; inline;
+
+  public
     property trigShotPanelId: Integer read trigPanelId write trigPanelId;
   end;
 
@@ -113,6 +120,13 @@ const
   TRIGGER_SIGNATURE = $52475254; // 'TRGR'
   TRAP_DAMAGE = 1000;
 
+
+function TTrigger.trigCenter (): TDFPoint; inline;
+begin
+  result := TDFPoint.Create(x+width div 2, y+height div 2);
+end;
+
+
 function FindTrigger(): DWORD;
 var
   i: Integer;
@@ -2106,6 +2120,7 @@ begin
   find_id := FindTrigger();
   gTriggers[find_id] := Trigger;
 
+  {
   writeln('trigger #', find_id, ': pos=(', Trigger.x, ',', Trigger.y, ')-(', Trigger.width, 'x', Trigger.height, ')',
     '; TexturePanel=', Trigger.TexturePanel,
     '; TexturePanelType=', Trigger.TexturePanelType,
@@ -2116,6 +2131,7 @@ begin
     '; trigPanelId=', Trigger.trigPanelId,
     '; trigShotPanelId=', Trigger.trigShotPanelId
     );
+  }
 
   with gTriggers[find_id] do
   begin
@@ -2666,7 +2682,6 @@ var
 begin
   for a := 0 to High(gTriggers) do
   begin
-    gTriggers[a].trigData.Free();
     if (gTriggers[a].TriggerType = TRIGGER_SOUND) then
     begin
       if g_Sound_Exists(gTriggers[a].trigData.trigSoundName) then
@@ -2679,6 +2694,7 @@ begin
     begin
       SetLength(gTriggers[a].Activators, 0);
     end;
+    gTriggers[a].trigData.Free();
   end;
 
   gTriggers := nil;
index a7137162c81c5be25db278bc34b11462913c11a9..ededbdd40c7f885f7d8ea932af4493002678f51d 100644 (file)
@@ -117,6 +117,11 @@ type
     {$INCLUDE mapdef_help.inc}
     function trigMonsterId (): Integer; inline;
 
+  private
+    // user fields
+    function getGamePanelId (): Integer; inline;
+    procedure setGamePanelId (v: Integer); inline;
+
   public
     property panel[idx: Integer]: TDynRecord read getPanelByIdx;
     property panelIndex[pan: TDynRecord]: Integer read getPanelIndex;
@@ -124,6 +129,8 @@ type
     property tgPanelID: Integer read getPanelId {write setPanelId};
     property tgShotPanelID: Integer read getPanelId {write setPanelId};
     property TexturePanel: Integer read getTexturePanel {write setTexturePanel}; // texturepanel, int
+    // user fields
+    property gamePanelId: Integer read getGamePanelId write setGamePanelId;
   end;
 
 implementation
@@ -136,6 +143,22 @@ uses
 constructor TDFPoint.Create (ax, ay: LongInt); begin X := ax; Y := ay; end;
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+function TDynRecordHelper.getGamePanelId (): Integer; inline;
+var
+  fld: TDynField;
+begin
+  fld := field['gamePanelId'];
+  if (fld = nil) or (fld.baseType <> TDynField.TType.TInt) then result := -1 else result := fld.ival;
+end;
+
+
+procedure TDynRecordHelper.setGamePanelId (v: Integer); inline;
+begin
+  setUserField('gamePanelId', Integer(v));
+end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 function TDynRecordHelper.getFieldWithType (const aname: AnsiString; atype: TDynField.TType): TDynField; inline;
 begin
index 6bfe7915453d93af3b465d0fb5b0a7fbd97e46df..1caa1f3338c12bb30327a45ac45a4abff404199b 100644 (file)
@@ -1247,6 +1247,7 @@ var
   fmtblen: Integer;
   pclen: Integer;
   pc: PAnsiChar;
+  ccname: ShortString;
 
   procedure writer (constref buf; len: SizeUInt);
   var
@@ -1646,15 +1647,17 @@ begin
         end;
       vtObject: // args[curarg].VObject.Classname (TObject)
         begin
-          if (sign <> '-') then indent(width-Length(args[curarg].VObject.Classname));
-          xwrite(args[curarg].VObject.Classname);
-          if (sign = '-') then indent(width-Length(args[curarg].VObject.Classname));
+          if (args[curarg].VObject <> nil) then ccname := args[curarg].VObject.Classname else ccname := '<nil>';
+          if (sign <> '-') then indent(width-Length(ccname));
+          xwrite(ccname);
+          if (sign = '-') then indent(width-Length(ccname));
         end;
       vtClass: // args[curarg].VClass.Classname (TClass)
         begin
-          if (sign <> '-') then indent(width-Length(args[curarg].VClass.Classname));
-          xwrite(args[curarg].VClass.Classname);
-          if (sign = '-') then indent(width-Length(args[curarg].VClass.Classname));
+          if (args[curarg].VClass <> nil) then ccname := args[curarg].VClass.Classname else ccname := '<nil>';
+          if (sign <> '-') then indent(width-Length(ccname));
+          xwrite(ccname);
+          if (sign = '-') then indent(width-Length(ccname));
         end;
       //vtPWideChar: begin end; // args[curarg].VPWideChar (PWideChar)
       vtAnsiString: // AnsiString(args[curarg].VAnsiString) (Pointer)
index 8ebac36188754ef6349bbb7bbc5147a1a0ccfe7a..ac55cf5d0360202e28589c97e5525e71253dc3e2 100644 (file)
@@ -110,6 +110,7 @@ type
     function addListItem (rec: TDynRecord): Boolean; inline;
 
   public
+    {
     type
       TListEnumerator = record
       private
@@ -121,6 +122,7 @@ type
         function getCurrent (): TDynRecord; inline;
         property Current: TDynRecord read getCurrent;
       end;
+    }
 
   public
     constructor Create (const aname: AnsiString; atype: TType);
@@ -145,7 +147,7 @@ type
 
     procedure setValue (const s: AnsiString);
 
-    function GetEnumerator (): TListEnumerator;
+    function GetEnumerator (): TDynRecList.TEnumerator; inline;
 
   public
     property pasname: AnsiString read mPasName;
@@ -245,6 +247,9 @@ type
     // number of records of the given instance
     function instanceCount (const typename: AnsiString): Integer;
 
+    procedure setUserField (const fldname: AnsiString; v: LongInt);
+    procedure setUserField (const fldname: AnsiString; v: AnsiString);
+
   public
     property id: AnsiString read mId; // for map parser
     property pasname: AnsiString read mPasName;
@@ -358,6 +363,7 @@ function StrEqu (const a, b: AnsiString): Boolean; inline; begin result := (a =
 
 
 // ////////////////////////////////////////////////////////////////////////// //
+{
 constructor TDynField.TListEnumerator.Create (alist: TDynRecList);
 begin
   mList := alist;
@@ -376,11 +382,13 @@ function TDynField.TListEnumerator.getCurrent (): TDynRecord; inline;
 begin
   result := mList[mCurIdx];
 end;
+}
 
 
-function TDynField.GetEnumerator (): TListEnumerator;
+function TDynField.GetEnumerator (): TDynRecList.TEnumerator; inline;
 begin
-  result := TListEnumerator.Create(mRVal);
+  //result := TListEnumerator.Create(mRVal);
+  if (mRVal <> nil) then result := mRVal.GetEnumerator else result := TDynRecList.TEnumerator.Create(nil, 0);
 end;
 
 
@@ -1927,6 +1935,56 @@ begin
 end;
 
 
+procedure TDynRecord.setUserField (const fldname: AnsiString; v: LongInt);
+var
+  fld: TDynField;
+begin
+  if (Length(fldname) = 0) then exit;
+  fld := field[fldname];
+  if (fld <> nil) then
+  begin
+    if (fld.mType <> fld.TType.TInt) or (fld.mEBS <> fld.TEBS.TNone) then
+    begin
+      raise Exception.Create(Format('invalid user field ''%s'' type', [fld.name]));
+    end;
+  end
+  else
+  begin
+    fld := TDynField.Create(fldname, fld.TType.TInt);
+    fld.mOwner := self;
+    fld.mIVal := v;
+    fld.mInternal := true;
+    fld.mDefined := true;
+    addField(fld);
+  end;
+end;
+
+
+procedure TDynRecord.setUserField (const fldname: AnsiString; v: AnsiString);
+var
+  fld: TDynField;
+begin
+  if (Length(fldname) = 0) then exit;
+  fld := field[fldname];
+  if (fld <> nil) then
+  begin
+    if (fld.mType <> fld.TType.TString) or (fld.mEBS <> fld.TEBS.TNone) then
+    begin
+      raise Exception.Create(Format('invalid user field ''%s'' type', [fld.name]));
+    end;
+  end
+  else
+  begin
+    fld := TDynField.Create(fldname, fld.TType.TString);
+    fld.mOwner := self;
+    fld.mSVal := v;
+    fld.mInternal := true;
+    fld.mDefined := true;
+    addField(fld);
+  end;
+end;
+
+
 procedure TDynRecord.parseDef (pr: TTextParser);
 var
   fld: TDynField;